]> git.saurik.com Git - cycript.git/blob - Library.mm
4213e5bc34a39123ab6aa851c985098ecb07df0c
[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 "cycript.hpp"
44
45 #include "sig/parse.hpp"
46 #include "sig/ffi_type.hpp"
47
48 #include "Pooling.hpp"
49 #include "Struct.hpp"
50
51 #include <unistd.h>
52
53 #include <CoreFoundation/CoreFoundation.h>
54 #include <CoreFoundation/CFLogUtilities.h>
55
56 #include <CFNetwork/CFNetwork.h>
57
58 #include <WebKit/WebScriptObject.h>
59
60 #include <sys/types.h>
61 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <sys/mman.h>
64
65 #include <iostream>
66 #include <ext/stdio_filebuf.h>
67 #include <set>
68 #include <map>
69
70 #include "Parser.hpp"
71 #include "Cycript.tab.hh"
72
73 #undef _assert
74 #undef _trace
75
76 #define _assert(test) do { \
77 if (!(test)) \
78 @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"_assert(%s):%s(%u):%s", #test, __FILE__, __LINE__, __FUNCTION__] userInfo:nil]; \
79 } while (false)
80
81 #define _trace() do { \
82 CFLog(kCFLogLevelNotice, CFSTR("_trace():%u"), __LINE__); \
83 } while (false)
84
85 static JSGlobalContextRef Context_;
86 static JSObjectRef System_;
87
88 static JSClassRef Functor_;
89 static JSClassRef Instance_;
90 static JSClassRef Pointer_;
91 static JSClassRef Selector_;
92
93 static JSObjectRef Array_;
94 static JSObjectRef Function_;
95
96 static JSStringRef name_;
97 static JSStringRef message_;
98 static JSStringRef length_;
99
100 static Class NSCFBoolean_;
101
102 static NSMutableDictionary *Bridge_;
103
104 struct Client {
105 CFHTTPMessageRef message_;
106 CFSocketRef socket_;
107 };
108
109 struct ptrData {
110 apr_pool_t *pool_;
111 void *value_;
112 sig::Type type_;
113
114 void *operator new(size_t size) {
115 apr_pool_t *pool;
116 apr_pool_create(&pool, NULL);
117 void *data(apr_palloc(pool, size));
118 reinterpret_cast<ptrData *>(data)->pool_ = pool;
119 return data;;
120 }
121
122 ptrData(void *value) :
123 value_(value)
124 {
125 }
126
127 virtual ~ptrData() {
128 }
129 };
130
131 struct ffiData : ptrData {
132 sig::Signature signature_;
133 ffi_cif cif_;
134
135 ffiData(const char *type, void (*value)()) :
136 ptrData(reinterpret_cast<void *>(value))
137 {
138 sig::Parse(pool_, &signature_, type);
139 sig::sig_ffi_cif(pool_, &sig::ObjectiveC, &signature_, &cif_);
140 }
141 };
142
143 struct ffoData : ffiData {
144 JSContextRef context_;
145 JSObjectRef function_;
146
147 ffoData(const char *type) :
148 ffiData(type, NULL)
149 {
150 }
151 };
152
153 struct selData : ptrData {
154 selData(SEL value) :
155 ptrData(value)
156 {
157 }
158
159 SEL GetValue() const {
160 return reinterpret_cast<SEL>(value_);
161 }
162 };
163
164 struct jocData : ptrData {
165 bool transient_;
166
167 jocData(id value, bool transient) :
168 ptrData(value)
169 {
170 }
171
172 virtual ~jocData() {
173 if (!transient_)
174 [GetValue() release];
175 }
176
177 id GetValue() const {
178 return reinterpret_cast<id>(value_);
179 }
180 };
181
182 JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient = true) {
183 if (!transient)
184 object = [object retain];
185 jocData *data(new jocData(object, transient));
186 return JSObjectMake(context, Instance_, data);
187 }
188
189 const char *CYPoolCString(apr_pool_t *pool, NSString *value) {
190 if (pool == NULL)
191 return [value UTF8String];
192 else {
193 size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
194 char *string(new(pool) char[size]);
195 if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding])
196 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"[NSString getCString:maxLength:encoding:] == NO" userInfo:nil];
197 return string;
198 }
199 }
200
201 JSValueRef CYCastJSValue(JSContextRef context, bool value) {
202 return JSValueMakeBoolean(context, value);
203 }
204
205 JSValueRef CYCastJSValue(JSContextRef context, double value) {
206 return JSValueMakeNumber(context, value);
207 }
208
209 #define CYCastJSValue_(Type_) \
210 JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \
211 return JSValueMakeNumber(context, static_cast<double>(value)); \
212 }
213
214 CYCastJSValue_(int)
215 CYCastJSValue_(unsigned int)
216 CYCastJSValue_(long int)
217 CYCastJSValue_(long unsigned int)
218 CYCastJSValue_(long long int)
219 CYCastJSValue_(long long unsigned int)
220
221 JSValueRef CYJSUndefined(JSContextRef context) {
222 return JSValueMakeUndefined(context);
223 }
224
225 @interface NSMethodSignature (Cycript)
226 - (NSString *) _typeString;
227 @end
228
229 @interface NSObject (Cycript)
230 - (bool) cy$isUndefined;
231 - (NSString *) cy$toJSON;
232 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context;
233 @end
234
235 @interface NSString (Cycript)
236 - (void *) cy$symbol;
237 @end
238
239 @interface NSNumber (Cycript)
240 - (void *) cy$symbol;
241 @end
242
243 @implementation NSObject (Cycript)
244
245 - (bool) cy$isUndefined {
246 return false;
247 }
248
249 - (NSString *) cy$toJSON {
250 return [self description];
251 }
252
253 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context {
254 return CYMakeInstance(context, self);
255 }
256
257 @end
258
259 @implementation WebUndefined (Cycript)
260
261 - (bool) cy$isUndefined {
262 return true;
263 }
264
265 - (NSString *) cy$toJSON {
266 return @"undefined";
267 }
268
269 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context {
270 return CYJSUndefined(context);
271 }
272
273 @end
274
275 @implementation NSNull (Cycript)
276
277 - (NSString *) cy$toJSON {
278 return @"null";
279 }
280
281 @end
282
283 @implementation NSArray (Cycript)
284
285 - (NSString *) cy$toJSON {
286 NSMutableString *json([[[NSMutableString alloc] init] autorelease]);
287 [json appendString:@"["];
288
289 bool comma(false);
290 for (id object in self) {
291 if (comma)
292 [json appendString:@","];
293 else
294 comma = true;
295 if (![object cy$isUndefined])
296 [json appendString:[object cy$toJSON]];
297 else {
298 [json appendString:@","];
299 comma = false;
300 }
301 }
302
303 [json appendString:@"]"];
304 return json;
305 }
306
307 @end
308
309 @implementation NSDictionary (Cycript)
310
311 - (NSString *) cy$toJSON {
312 NSMutableString *json([[[NSMutableString alloc] init] autorelease]);
313 [json appendString:@"({"];
314
315 bool comma(false);
316 for (id key in self) {
317 if (comma)
318 [json appendString:@","];
319 else
320 comma = true;
321 [json appendString:[key cy$toJSON]];
322 [json appendString:@":"];
323 NSObject *object([self objectForKey:key]);
324 [json appendString:[object cy$toJSON]];
325 }
326
327 [json appendString:@"})"];
328 return json;
329 }
330
331 @end
332
333 @implementation NSNumber (Cycript)
334
335 - (NSString *) cy$toJSON {
336 return [self class] != NSCFBoolean_ ? [self stringValue] : [self boolValue] ? @"true" : @"false";
337 }
338
339 - (JSValueRef) cy$JSValueInContext:(JSContextRef)context {
340 return [self class] != NSCFBoolean_ ? CYCastJSValue(context, [self doubleValue]) : CYCastJSValue(context, [self boolValue]);
341 }
342
343 - (void *) cy$symbol {
344 return [self pointerValue];
345 }
346
347 @end
348
349 @implementation NSString (Cycript)
350
351 - (NSString *) cy$toJSON {
352 CFMutableStringRef json(CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef) self));
353
354 CFStringFindAndReplace(json, CFSTR("\\"), CFSTR("\\\\"), CFRangeMake(0, CFStringGetLength(json)), 0);
355 CFStringFindAndReplace(json, CFSTR("\""), CFSTR("\\\""), CFRangeMake(0, CFStringGetLength(json)), 0);
356 CFStringFindAndReplace(json, CFSTR("\t"), CFSTR("\\t"), CFRangeMake(0, CFStringGetLength(json)), 0);
357 CFStringFindAndReplace(json, CFSTR("\r"), CFSTR("\\r"), CFRangeMake(0, CFStringGetLength(json)), 0);
358 CFStringFindAndReplace(json, CFSTR("\n"), CFSTR("\\n"), CFRangeMake(0, CFStringGetLength(json)), 0);
359
360 CFStringInsert(json, 0, CFSTR("\""));
361 CFStringAppend(json, CFSTR("\""));
362
363 return [reinterpret_cast<const NSString *>(json) autorelease];
364 }
365
366 - (void *) cy$symbol {
367 CYPool pool;
368 return dlsym(RTLD_DEFAULT, CYPoolCString(pool, self));
369 }
370
371 @end
372
373 @interface CYJSObject : NSDictionary {
374 JSObjectRef object_;
375 JSContextRef context_;
376 }
377
378 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context;
379
380 - (NSUInteger) count;
381 - (id) objectForKey:(id)key;
382 - (NSEnumerator *) keyEnumerator;
383 - (void) setObject:(id)object forKey:(id)key;
384 - (void) removeObjectForKey:(id)key;
385
386 @end
387
388 @interface CYJSArray : NSArray {
389 JSObjectRef object_;
390 JSContextRef context_;
391 }
392
393 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context;
394
395 - (NSUInteger) count;
396 - (id) objectAtIndex:(NSUInteger)index;
397
398 @end
399
400 CYRange WordStartRange_(0x1000000000LLU,0x7fffffe87fffffeLLU); // A-Za-z_$
401 CYRange WordEndRange_(0x3ff001000000000LLU,0x7fffffe87fffffeLLU); // A-Za-z_$0-9
402
403 JSGlobalContextRef CYGetJSContext() {
404 return Context_;
405 }
406
407 #define CYCatch \
408 @catch (id error) { \
409 NSLog(@"e:%@", error); \
410 CYThrow(context, error, exception); \
411 return NULL; \
412 }
413
414 void CYThrow(JSContextRef context, JSValueRef value);
415
416 apr_status_t CYPoolRelease_(void *data) {
417 id object(reinterpret_cast<id>(data));
418 [object release];
419 return APR_SUCCESS;
420 }
421
422 id CYPoolRelease(apr_pool_t *pool, id object) {
423 if (pool == NULL)
424 return [object autorelease];
425 else {
426 apr_pool_cleanup_register(pool, object, &CYPoolRelease_, &apr_pool_cleanup_null);
427 return object;
428 }
429 }
430
431 id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) {
432 if (JSValueIsObjectOfClass(context, object, Instance_)) {
433 jocData *data(reinterpret_cast<jocData *>(JSObjectGetPrivate(object)));
434 return data->GetValue();
435 }
436
437 JSValueRef exception(NULL);
438 bool array(JSValueIsInstanceOfConstructor(context, object, Array_, &exception));
439 CYThrow(context, exception);
440 id value(array ? [CYJSArray alloc] : [CYJSObject alloc]);
441 return CYPoolRelease(pool, [value initWithJSObject:object inContext:context]);
442 }
443
444 JSStringRef CYCopyJSString(id value) {
445 return value == NULL ? NULL : JSStringCreateWithCFString(reinterpret_cast<CFStringRef>([value description]));
446 }
447
448 JSStringRef CYCopyJSString(const char *value) {
449 return value == NULL ? NULL : JSStringCreateWithUTF8CString(value);
450 }
451
452 JSStringRef CYCopyJSString(JSStringRef value) {
453 return value == NULL ? NULL : JSStringRetain(value);
454 }
455
456 JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) {
457 if (JSValueIsNull(context, value))
458 return NULL;
459 JSValueRef exception(NULL);
460 JSStringRef string(JSValueToStringCopy(context, value, &exception));
461 CYThrow(context, exception);
462 return string;
463 }
464
465 class CYJSString {
466 private:
467 JSStringRef string_;
468
469 void Clear_() {
470 JSStringRelease(string_);
471 }
472
473 public:
474 CYJSString(const CYJSString &rhs) :
475 string_(CYCopyJSString(rhs.string_))
476 {
477 }
478
479 template <typename Arg0_>
480 CYJSString(Arg0_ arg0) :
481 string_(CYCopyJSString(arg0))
482 {
483 }
484
485 template <typename Arg0_, typename Arg1_>
486 CYJSString(Arg0_ arg0, Arg1_ arg1) :
487 string_(CYCopyJSString(arg0, arg1))
488 {
489 }
490
491 CYJSString &operator =(const CYJSString &rhs) {
492 Clear_();
493 string_ = CYCopyJSString(rhs.string_);
494 return *this;
495 }
496
497 ~CYJSString() {
498 Clear_();
499 }
500
501 void Clear() {
502 Clear_();
503 string_ = NULL;
504 }
505
506 operator JSStringRef() const {
507 return string_;
508 }
509 };
510
511 CFStringRef CYCopyCFString(JSStringRef value) {
512 return JSStringCopyCFString(kCFAllocatorDefault, value);
513 }
514
515 CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) {
516 return CYCopyCFString(CYJSString(context, value));
517 }
518
519 double CYCastDouble(JSContextRef context, JSValueRef value) {
520 JSValueRef exception(NULL);
521 double number(JSValueToNumber(context, value, &exception));
522 CYThrow(context, exception);
523 return number;
524 }
525
526 CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) {
527 double number(CYCastDouble(context, value));
528 return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number);
529 }
530
531 NSString *CYCastNSString(apr_pool_t *pool, JSStringRef value) {
532 return CYPoolRelease(pool, reinterpret_cast<const NSString *>(CYCopyCFString(value)));
533 }
534
535 bool CYCastBool(JSContextRef context, JSValueRef value) {
536 return JSValueToBoolean(context, value);
537 }
538
539 CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) {
540 CFTypeRef object;
541 bool copy;
542
543 switch (JSType type = JSValueGetType(context, value)) {
544 case kJSTypeUndefined:
545 object = [WebUndefined undefined];
546 copy = false;
547 break;
548
549 case kJSTypeNull:
550 return NULL;
551 break;
552
553 case kJSTypeBoolean:
554 object = CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse;
555 copy = false;
556 break;
557
558 case kJSTypeNumber:
559 object = CYCopyCFNumber(context, value);
560 copy = true;
561 break;
562
563 case kJSTypeString:
564 object = CYCopyCFString(context, value);
565 copy = true;
566 break;
567
568 case kJSTypeObject:
569 // XXX: this might could be more efficient
570 object = (CFTypeRef) CYCastNSObject(pool, context, (JSObjectRef) value);
571 copy = false;
572 break;
573
574 default:
575 @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"JSValueGetType() == 0x%x", type] userInfo:nil];
576 break;
577 }
578
579 if (cast != copy)
580 return object;
581 else if (copy)
582 return CYPoolRelease(pool, (id) object);
583 else
584 return CFRetain(object);
585 }
586
587 CFTypeRef CYCastCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
588 return CYCFType(pool, context, value, true);
589 }
590
591 CFTypeRef CYCopyCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
592 return CYCFType(pool, context, value, false);
593 }
594
595 NSArray *CYCastNSArray(JSPropertyNameArrayRef names) {
596 CYPool pool;
597 size_t size(JSPropertyNameArrayGetCount(names));
598 NSMutableArray *array([NSMutableArray arrayWithCapacity:size]);
599 for (size_t index(0); index != size; ++index)
600 [array addObject:CYCastNSString(pool, JSPropertyNameArrayGetNameAtIndex(names, index))];
601 return array;
602 }
603
604 id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
605 return reinterpret_cast<const NSObject *>(CYCastCFType(pool, context, value));
606 }
607
608 void CYThrow(JSContextRef context, JSValueRef value) {
609 if (value == NULL)
610 return;
611 @throw CYCastNSObject(NULL, context, value);
612 }
613
614 JSValueRef CYJSNull(JSContextRef context) {
615 return JSValueMakeNull(context);
616 }
617
618 JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value) {
619 return value == NULL ? CYJSNull(context) : JSValueMakeString(context, value);
620 }
621
622 JSValueRef CYCastJSValue(JSContextRef context, const char *value) {
623 return CYCastJSValue(context, CYJSString(value));
624 }
625
626 JSValueRef CYCastJSValue(JSContextRef context, id value) {
627 return value == nil ? CYJSNull(context) : [value cy$JSValueInContext:context];
628 }
629
630 JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) {
631 JSValueRef exception(NULL);
632 JSObjectRef object(JSValueToObject(context, value, &exception));
633 CYThrow(context, exception);
634 return object;
635 }
636
637 JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, JSStringRef name) {
638 JSValueRef exception(NULL);
639 JSValueRef value(JSObjectGetProperty(context, object, name, &exception));
640 CYThrow(context, exception);
641 return value;
642 }
643
644 void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value) {
645 JSValueRef exception(NULL);
646 JSObjectSetProperty(context, object, name, value, kJSPropertyAttributeNone, &exception);
647 CYThrow(context, exception);
648 }
649
650 void CYThrow(JSContextRef context, id error, JSValueRef *exception) {
651 *exception = CYCastJSValue(context, error);
652 }
653
654 @implementation CYJSObject
655
656 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context {
657 if ((self = [super init]) != nil) {
658 object_ = object;
659 context_ = context;
660 } return self;
661 }
662
663 - (NSUInteger) count {
664 JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
665 size_t size(JSPropertyNameArrayGetCount(names));
666 JSPropertyNameArrayRelease(names);
667 return size;
668 }
669
670 - (id) objectForKey:(id)key {
671 return CYCastNSObject(NULL, context_, CYGetProperty(context_, object_, CYJSString(key))) ?: [NSNull null];
672 }
673
674 - (NSEnumerator *) keyEnumerator {
675 JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_));
676 NSEnumerator *enumerator([CYCastNSArray(names) objectEnumerator]);
677 JSPropertyNameArrayRelease(names);
678 return enumerator;
679 }
680
681 - (void) setObject:(id)object forKey:(id)key {
682 CYSetProperty(context_, object_, CYJSString(key), CYCastJSValue(context_, object));
683 }
684
685 - (void) removeObjectForKey:(id)key {
686 JSValueRef exception(NULL);
687 // XXX: this returns a bool... throw exception, or ignore?
688 JSObjectDeleteProperty(context_, object_, CYJSString(key), &exception);
689 CYThrow(context_, exception);
690 }
691
692 @end
693
694 @implementation CYJSArray
695
696 - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context {
697 if ((self = [super init]) != nil) {
698 object_ = object;
699 context_ = context;
700 } return self;
701 }
702
703 - (NSUInteger) count {
704 return CYCastDouble(context_, CYGetProperty(context_, object_, length_));
705 }
706
707 - (id) objectAtIndex:(NSUInteger)index {
708 JSValueRef exception(NULL);
709 JSValueRef value(JSObjectGetPropertyAtIndex(context_, object_, index, &exception));
710 CYThrow(context_, exception);
711 return CYCastNSObject(NULL, context_, value) ?: [NSNull null];
712 }
713
714 @end
715
716 CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value) { _pooled
717 id object(CYCastNSObject(NULL, context, value));
718 return reinterpret_cast<CFStringRef>([(object == nil ? @"null" : [object cy$toJSON]) retain]);
719 }
720
721 const char *CYPoolJSONString(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
722 NSString *json((NSString *) CYCopyJSONString(context, value));
723 const char *string(CYPoolCString(pool, json));
724 [json release];
725 return string;
726 }
727
728 static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
729 switch (type) {
730 case kCFSocketDataCallBack:
731 CFDataRef data(reinterpret_cast<CFDataRef>(value));
732 Client *client(reinterpret_cast<Client *>(info));
733
734 if (client->message_ == NULL)
735 client->message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
736
737 if (!CFHTTPMessageAppendBytes(client->message_, CFDataGetBytePtr(data), CFDataGetLength(data)))
738 CFLog(kCFLogLevelError, CFSTR("CFHTTPMessageAppendBytes()"));
739 else if (CFHTTPMessageIsHeaderComplete(client->message_)) {
740 CFURLRef url(CFHTTPMessageCopyRequestURL(client->message_));
741 Boolean absolute;
742 CFStringRef path(CFURLCopyStrictPath(url, &absolute));
743 CFRelease(client->message_);
744
745 CFStringRef code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault, path, CFSTR("")));
746 CFRelease(path);
747
748 JSStringRef script(JSStringCreateWithCFString(code));
749 CFRelease(code);
750
751 JSValueRef result(JSEvaluateScript(CYGetJSContext(), script, NULL, NULL, 0, NULL));
752 JSStringRelease(script);
753
754 CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1));
755 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8"));
756
757 CFStringRef json(CYCopyJSONString(CYGetJSContext(), result));
758 CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL));
759 CFRelease(json);
760
761 CFStringRef length(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(body)));
762 CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), length);
763 CFRelease(length);
764
765 CFHTTPMessageSetBody(response, body);
766 CFRelease(body);
767
768 CFDataRef serialized(CFHTTPMessageCopySerializedMessage(response));
769 CFRelease(response);
770
771 CFSocketSendData(socket, NULL, serialized, 0);
772 CFRelease(serialized);
773
774 CFRelease(url);
775 }
776 break;
777 }
778 }
779
780 static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) {
781 switch (type) {
782 case kCFSocketAcceptCallBack:
783 Client *client(new Client());
784
785 client->message_ = NULL;
786
787 CFSocketContext context;
788 context.version = 0;
789 context.info = client;
790 context.retain = NULL;
791 context.release = NULL;
792 context.copyDescription = NULL;
793
794 client->socket_ = CFSocketCreateWithNative(kCFAllocatorDefault, *reinterpret_cast<const CFSocketNativeHandle *>(value), kCFSocketDataCallBack, &OnData, &context);
795
796 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, client->socket_, 0), kCFRunLoopDefaultMode);
797 break;
798 }
799 }
800
801 static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
802 @try {
803 CYPool pool;
804 NSString *name(CYCastNSString(pool, property));
805 NSLog(@"get:%@", name);
806 return NULL;
807 } CYCatch
808 }
809
810 static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) {
811 @try {
812 CYPool pool;
813 NSString *name(CYCastNSString(pool, property));
814 NSLog(@"set:%@", name);
815 return false;
816 } CYCatch
817 }
818
819 static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
820 @try {
821 CYPool pool;
822 NSString *name(CYCastNSString(pool, property));
823 NSLog(@"delete:%@", name);
824 return false;
825 } CYCatch
826 }
827
828 static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
829 @try {
830 jocData *data(reinterpret_cast<jocData *>(JSObjectGetPrivate(object)));
831 return CYMakeInstance(context, [data->GetValue() alloc]);
832 } CYCatch
833 }
834
835 JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) {
836 selData *data(new selData(sel));
837 return JSObjectMake(context, Selector_, data);
838 }
839
840 JSObjectRef CYMakePointer(JSContextRef context, void *pointer) {
841 ptrData *data(new ptrData(pointer));
842 return JSObjectMake(context, Pointer_, data);
843 }
844
845 static void Pointer_finalize(JSObjectRef object) {
846 ptrData *data(reinterpret_cast<ptrData *>(JSObjectGetPrivate(object)));
847 data->~ptrData();
848 apr_pool_destroy(data->pool_);
849 }
850
851 JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) {
852 ffiData *data(new ffiData(type, function));
853 return JSObjectMake(context, Functor_, data);
854 }
855
856 const char *CYPoolCString(apr_pool_t *pool, JSStringRef value) {
857 if (pool == NULL)
858 return [CYCastNSString(NULL, value) UTF8String];
859 else {
860 size_t size(JSStringGetMaximumUTF8CStringSize(value));
861 char *string(new(pool) char[size]);
862 JSStringGetUTF8CString(value, string, size);
863 return string;
864 }
865 }
866
867 const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
868 if (JSValueIsNull(context, value))
869 return NULL;
870 return CYPoolCString(pool, CYJSString(context, value));
871 }
872
873 // XXX: this macro is unhygenic
874 #define CYCastCString(context, value) ({ \
875 char *utf8; \
876 if (value == NULL) \
877 utf8 = NULL; \
878 else if (JSStringRef string = CYCopyJSString(context, value)) { \
879 size_t size(JSStringGetMaximumUTF8CStringSize(string)); \
880 utf8 = reinterpret_cast<char *>(alloca(size)); \
881 JSStringGetUTF8CString(string, utf8, size); \
882 JSStringRelease(string); \
883 } else \
884 utf8 = NULL; \
885 utf8; \
886 })
887
888 SEL CYCastSEL(JSContextRef context, JSValueRef value) {
889 if (JSValueIsNull(context, value))
890 return NULL;
891 else if (JSValueIsObjectOfClass(context, value, Selector_)) {
892 selData *data(reinterpret_cast<selData *>(JSObjectGetPrivate((JSObjectRef) value)));
893 return reinterpret_cast<SEL>(data->value_);
894 } else
895 return sel_registerName(CYCastCString(context, value));
896 }
897
898 void *CYCastPointer_(JSContextRef context, JSValueRef value) {
899 switch (JSValueGetType(context, value)) {
900 case kJSTypeNull:
901 return NULL;
902 case kJSTypeString:
903 return dlsym(RTLD_DEFAULT, CYCastCString(context, value));
904 case kJSTypeObject:
905 if (JSValueIsObjectOfClass(context, value, Pointer_)) {
906 ptrData *data(reinterpret_cast<ptrData *>(JSObjectGetPrivate((JSObjectRef) value)));
907 return data->value_;
908 }
909 default:
910 return reinterpret_cast<void *>(static_cast<uintptr_t>(CYCastDouble(context, value)));
911 }
912 }
913
914 template <typename Type_>
915 _finline Type_ CYCastPointer(JSContextRef context, JSValueRef value) {
916 return reinterpret_cast<Type_>(CYCastPointer_(context, value));
917 }
918
919 void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *data, JSValueRef value) {
920 switch (type->primitive) {
921 case sig::boolean_P:
922 *reinterpret_cast<bool *>(data) = JSValueToBoolean(context, value);
923 break;
924
925 #define CYPoolFFI_(primitive, native) \
926 case sig::primitive ## _P: \
927 *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \
928 break;
929
930 CYPoolFFI_(uchar, unsigned char)
931 CYPoolFFI_(char, char)
932 CYPoolFFI_(ushort, unsigned short)
933 CYPoolFFI_(short, short)
934 CYPoolFFI_(ulong, unsigned long)
935 CYPoolFFI_(long, long)
936 CYPoolFFI_(uint, unsigned int)
937 CYPoolFFI_(int, int)
938 CYPoolFFI_(ulonglong, unsigned long long)
939 CYPoolFFI_(longlong, long long)
940 CYPoolFFI_(float, float)
941 CYPoolFFI_(double, double)
942
943 case sig::object_P:
944 case sig::typename_P:
945 *reinterpret_cast<id *>(data) = CYCastNSObject(pool, context, value);
946 break;
947
948 case sig::selector_P:
949 *reinterpret_cast<SEL *>(data) = CYCastSEL(context, value);
950 break;
951
952 case sig::pointer_P:
953 *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
954 break;
955
956 case sig::string_P:
957 *reinterpret_cast<const char **>(data) = CYPoolCString(pool, context, value);
958 break;
959
960 case sig::struct_P:
961 goto fail;
962
963 case sig::void_P:
964 break;
965
966 default: fail:
967 NSLog(@"CYPoolFFI(%c)\n", type->primitive);
968 _assert(false);
969 }
970 }
971
972 JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) {
973 JSValueRef value;
974
975 switch (type->primitive) {
976 case sig::boolean_P:
977 value = CYCastJSValue(context, *reinterpret_cast<bool *>(data));
978 break;
979
980 #define CYFromFFI_(primitive, native) \
981 case sig::primitive ## _P: \
982 value = CYCastJSValue(context, *reinterpret_cast<native *>(data)); \
983 break;
984
985 CYFromFFI_(uchar, unsigned char)
986 CYFromFFI_(char, char)
987 CYFromFFI_(ushort, unsigned short)
988 CYFromFFI_(short, short)
989 CYFromFFI_(ulong, unsigned long)
990 CYFromFFI_(long, long)
991 CYFromFFI_(uint, unsigned int)
992 CYFromFFI_(int, int)
993 CYFromFFI_(ulonglong, unsigned long long)
994 CYFromFFI_(longlong, long long)
995 CYFromFFI_(float, float)
996 CYFromFFI_(double, double)
997
998 case sig::object_P:
999 value = CYCastJSValue(context, *reinterpret_cast<id *>(data));
1000 break;
1001
1002 case sig::typename_P:
1003 value = CYMakeInstance(context, *reinterpret_cast<Class *>(data));
1004 break;
1005
1006 case sig::selector_P:
1007 if (SEL sel = *reinterpret_cast<SEL *>(data))
1008 value = CYMakeSelector(context, sel);
1009 else goto null;
1010 break;
1011
1012 case sig::pointer_P:
1013 if (void *pointer = *reinterpret_cast<void **>(data))
1014 value = CYMakePointer(context, pointer);
1015 else goto null;
1016 break;
1017
1018 case sig::string_P:
1019 if (char *utf8 = *reinterpret_cast<char **>(data))
1020 value = CYCastJSValue(context, utf8);
1021 else goto null;
1022 break;
1023
1024 case sig::struct_P:
1025 goto fail;
1026
1027 case sig::void_P:
1028 value = CYJSUndefined(context);
1029 break;
1030
1031 null:
1032 value = CYJSNull(context);
1033 break;
1034
1035 default: fail:
1036 NSLog(@"CYFromFFI(%c)\n", type->primitive);
1037 _assert(false);
1038 }
1039
1040 return value;
1041 }
1042
1043 static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) {
1044 @try {
1045 if (count != signature->count - 1)
1046 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi function" userInfo:nil];
1047
1048 CYPool pool;
1049 void *values[count];
1050
1051 for (unsigned index(0); index != count; ++index) {
1052 sig::Element *element(&signature->elements[index + 1]);
1053 // XXX: alignment?
1054 values[index] = new(pool) uint8_t[cif->arg_types[index]->size];
1055 CYPoolFFI(pool, context, element->type, values[index], arguments[index]);
1056 }
1057
1058 uint8_t value[cif->rtype->size];
1059 ffi_call(cif, function, value, values);
1060
1061 return CYFromFFI(context, signature->elements[0].type, value);
1062 } CYCatch
1063 }
1064
1065 void Closure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
1066 NSLog(@"Closure()");
1067 ffoData *data(reinterpret_cast<ffoData *>(arg));
1068
1069 JSContextRef context(data->context_);
1070
1071 size_t count(data->cif_.nargs);
1072 JSValueRef values[count];
1073
1074 for (size_t index(0); index != count; ++index)
1075 values[index] = CYFromFFI(context, data->signature_.elements[1 + index].type, arguments[index]);
1076
1077 JSValueRef exception(NULL);
1078 JSValueRef value(JSObjectCallAsFunction(context, data->function_, NULL, count, values, &exception));
1079 CYThrow(context, exception);
1080
1081 CYPoolFFI(NULL, context, data->signature_.elements[0].type, result, value);
1082 }
1083
1084 JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) {
1085 // XXX: in case of exceptions this will leak
1086 ffoData *data(new ffoData(type));
1087
1088 ffi_closure *closure;
1089 _syscall(closure = (ffi_closure *) mmap(
1090 NULL, sizeof(ffi_closure),
1091 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
1092 -1, 0
1093 ));
1094
1095 ffi_status status(ffi_prep_closure(closure, &data->cif_, &Closure_, data));
1096 _assert(status == FFI_OK);
1097
1098 _syscall(mprotect(closure, sizeof(*closure), PROT_READ | PROT_EXEC));
1099
1100 data->value_ = closure;
1101
1102 data->context_ = CYGetJSContext();
1103 data->function_ = function;
1104
1105 return JSObjectMake(context, Functor_, data);
1106 }
1107
1108 static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
1109 @try {
1110 CYPool pool;
1111 NSString *name(CYCastNSString(pool, property));
1112 if (Class _class = NSClassFromString(name))
1113 return CYMakeInstance(context, _class);
1114 if (NSMutableArray *entry = [Bridge_ objectForKey:name])
1115 switch ([[entry objectAtIndex:0] intValue]) {
1116 case 0:
1117 return JSEvaluateScript(CYGetJSContext(), CYJSString([entry objectAtIndex:1]), NULL, NULL, 0, NULL);
1118 case 1:
1119 return CYMakeFunctor(context, reinterpret_cast<void (*)()>([name cy$symbol]), CYPoolCString(pool, [entry objectAtIndex:1]));
1120 case 2:
1121 sig::Signature signature;
1122 sig::Parse(pool, &signature, CYPoolCString(pool, [entry objectAtIndex:1]));
1123 return CYFromFFI(context, signature.elements[0].type, [name cy$symbol]);
1124 }
1125 return NULL;
1126 } CYCatch
1127 }
1128
1129 bool stret(ffi_type *ffi_type) {
1130 return ffi_type->type == FFI_TYPE_STRUCT && (
1131 ffi_type->size > OBJC_MAX_STRUCT_BY_VALUE ||
1132 struct_forward_array[ffi_type->size] != 0
1133 );
1134 }
1135
1136 extern "C" {
1137 int *_NSGetArgc(void);
1138 char ***_NSGetArgv(void);
1139 int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
1140 }
1141
1142 static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1143 @try {
1144 NSLog(@"%s", CYCastCString(context, arguments[0]));
1145 return CYJSUndefined(context);
1146 } CYCatch
1147 }
1148
1149 static JSValueRef CYApplicationMain(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1150 @try {
1151 CYPool pool;
1152 NSString *name(CYCastNSObject(pool, context, arguments[0]));
1153 int argc(*_NSGetArgc());
1154 char **argv(*_NSGetArgv());
1155 for (int i(0); i != argc; ++i)
1156 NSLog(@"argv[%i]=%s", i, argv[i]);
1157 _pooled
1158 return CYCastJSValue(context, UIApplicationMain(argc, argv, name, name));
1159 } CYCatch
1160 }
1161
1162 static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1163 const char *type;
1164
1165 CYPool pool;
1166
1167 @try {
1168 if (count < 2)
1169 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"too few arguments to objc_msgSend" userInfo:nil];
1170
1171 id self(CYCastNSObject(pool, context, arguments[0]));
1172 if (self == nil)
1173 return CYJSNull(context);
1174
1175 SEL _cmd(CYCastSEL(context, arguments[1]));
1176
1177 Class _class(object_getClass(self));
1178 if (Method method = class_getInstanceMethod(_class, _cmd))
1179 type = method_getTypeEncoding(method);
1180 else { _pooled
1181 NSMethodSignature *method([self methodSignatureForSelector:_cmd]);
1182 if (method == nil)
1183 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil];
1184 type = CYPoolCString(pool, [method _typeString]);
1185 }
1186 } CYCatch
1187
1188 sig::Signature signature;
1189 sig::Parse(pool, &signature, type);
1190
1191 ffi_cif cif;
1192 sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
1193
1194 void (*function)() = stret(cif.rtype) ? reinterpret_cast<void (*)()>(&objc_msgSend_stret) : reinterpret_cast<void (*)()>(&objc_msgSend);
1195 return CYCallFunction(context, count, arguments, exception, &signature, &cif, function);
1196 }
1197
1198 static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1199 JSValueRef setup[count + 2];
1200 setup[0] = _this;
1201 setup[1] = object;
1202 memmove(setup + 2, arguments, sizeof(JSValueRef) * count);
1203 return $objc_msgSend(context, NULL, NULL, count + 2, setup, exception);
1204 }
1205
1206 static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1207 ffiData *data(reinterpret_cast<ffiData *>(JSObjectGetPrivate(object)));
1208 return CYCallFunction(context, count, arguments, exception, &data->signature_, &data->cif_, reinterpret_cast<void (*)()>(data->value_));
1209 }
1210
1211 JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1212 @try {
1213 if (count != 1)
1214 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector constructor" userInfo:nil];
1215 const char *name(CYCastCString(context, arguments[0]));
1216 return CYMakeSelector(context, sel_registerName(name));
1217 } CYCatch
1218 }
1219
1220 JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1221 @try {
1222 if (count != 2)
1223 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Functor constructor" userInfo:nil];
1224 const char *type(CYCastCString(context, arguments[1]));
1225 JSValueRef exception(NULL);
1226 if (JSValueIsInstanceOfConstructor(context, arguments[0], Function_, &exception)) {
1227 JSObjectRef function(CYCastJSObject(context, arguments[0]));
1228 return CYMakeFunctor(context, function, type);
1229 } else if (exception != NULL) {
1230 return NULL;
1231 } else {
1232 void (*function)()(CYCastPointer<void (*)()>(context, arguments[0]));
1233 return CYMakeFunctor(context, function, type);
1234 }
1235 } CYCatch
1236 }
1237
1238 JSValueRef Pointer_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
1239 ptrData *data(reinterpret_cast<ptrData *>(JSObjectGetPrivate(object)));
1240 return CYCastJSValue(context, reinterpret_cast<uintptr_t>(data->value_));
1241 }
1242
1243 JSValueRef Selector_getProperty_prototype(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
1244 return Function_;
1245 }
1246
1247 static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled
1248 @try {
1249 jocData *data(reinterpret_cast<jocData *>(JSObjectGetPrivate(_this)));
1250 return CYCastJSValue(context, CYJSString([data->GetValue() description]));
1251 } CYCatch
1252 }
1253
1254 static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1255 @try {
1256 selData *data(reinterpret_cast<selData *>(JSObjectGetPrivate(_this)));
1257 return CYCastJSValue(context, sel_getName(data->GetValue()));
1258 } CYCatch
1259 }
1260
1261 static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
1262 @try {
1263 if (count != 2)
1264 @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector.type" userInfo:nil];
1265 CYPool pool;
1266 selData *data(reinterpret_cast<selData *>(JSObjectGetPrivate(_this)));
1267 Class _class(CYCastNSObject(pool, context, arguments[0]));
1268 bool instance(CYCastBool(context, arguments[1]));
1269 SEL sel(data->GetValue());
1270 if (Method method = (*(instance ? &class_getInstanceMethod : class_getClassMethod))(_class, sel))
1271 return CYCastJSValue(context, method_getTypeEncoding(method));
1272 else if (NSString *type = [Bridge_ objectForKey:CYPoolRelease(pool, [[NSString alloc] initWithFormat:@":%s", sel_getName(sel)])])
1273 return CYCastJSValue(context, CYJSString(type));
1274 else
1275 return CYJSNull(context);
1276 } CYCatch
1277 }
1278
1279 static JSStaticValue Pointer_staticValues[2] = {
1280 {"value", &Pointer_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete},
1281 {NULL, NULL, NULL, 0}
1282 };
1283
1284 /*static JSStaticValue Selector_staticValues[2] = {
1285 {"prototype", &Selector_getProperty_prototype, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete},
1286 {NULL, NULL, NULL, 0}
1287 };*/
1288
1289 static JSStaticFunction Instance_staticFunctions[2] = {
1290 {"toString", &Instance_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
1291 {NULL, NULL, 0}
1292 };
1293
1294 static JSStaticFunction Selector_staticFunctions[3] = {
1295 {"toString", &Selector_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
1296 {"type", &Selector_callAsFunction_type, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
1297 {NULL, NULL, 0}
1298 };
1299
1300 CYDriver::CYDriver(const std::string &filename) :
1301 state_(CYClear),
1302 data_(NULL),
1303 size_(0),
1304 filename_(filename),
1305 source_(NULL)
1306 {
1307 ScannerInit();
1308 }
1309
1310 CYDriver::~CYDriver() {
1311 ScannerDestroy();
1312 }
1313
1314 void cy::parser::error(const cy::parser::location_type &location, const std::string &message) {
1315 CYDriver::Error error;
1316 error.location_ = location;
1317 error.message_ = message;
1318 driver.errors_.push_back(error);
1319 }
1320
1321 void CYSetArgs(int argc, const char *argv[]) {
1322 JSContextRef context(CYGetJSContext());
1323 JSValueRef args[argc];
1324 for (int i(0); i != argc; ++i)
1325 args[i] = CYCastJSValue(context, argv[i]);
1326 JSValueRef exception(NULL);
1327 JSObjectRef array(JSObjectMakeArray(context, argc, args, &exception));
1328 CYThrow(context, exception);
1329 CYSetProperty(context, System_, CYJSString("args"), array);
1330 }
1331
1332 MSInitialize { _pooled
1333 apr_initialize();
1334
1335 NSCFBoolean_ = objc_getClass("NSCFBoolean");
1336
1337 pid_t pid(getpid());
1338
1339 struct sockaddr_in address;
1340 address.sin_len = sizeof(address);
1341 address.sin_family = AF_INET;
1342 address.sin_addr.s_addr = INADDR_ANY;
1343 address.sin_port = htons(10000 + pid);
1344
1345 CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 *>(&address), sizeof(address)));
1346
1347 CFSocketSignature signature;
1348 signature.protocolFamily = AF_INET;
1349 signature.socketType = SOCK_STREAM;
1350 signature.protocol = IPPROTO_TCP;
1351 signature.address = data;
1352
1353 CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL));
1354 CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode);
1355
1356 JSClassDefinition definition;
1357
1358 definition = kJSClassDefinitionEmpty;
1359 definition.className = "Pointer";
1360 definition.staticValues = Pointer_staticValues;
1361 definition.finalize = &Pointer_finalize;
1362 Pointer_ = JSClassCreate(&definition);
1363
1364 definition = kJSClassDefinitionEmpty;
1365 definition.className = "Functor";
1366 definition.parentClass = Pointer_;
1367 definition.callAsFunction = &Functor_callAsFunction;
1368 Functor_ = JSClassCreate(&definition);
1369
1370 definition = kJSClassDefinitionEmpty;
1371 definition.className = "Selector";
1372 definition.parentClass = Pointer_;
1373 //definition.staticValues = Selector_staticValues;
1374 definition.staticFunctions = Selector_staticFunctions;
1375 definition.callAsFunction = &Selector_callAsFunction;
1376 Selector_ = JSClassCreate(&definition);
1377
1378 definition = kJSClassDefinitionEmpty;
1379 definition.className = "Instance";
1380 definition.parentClass = Pointer_;
1381 definition.staticFunctions = Instance_staticFunctions;
1382 definition.getProperty = &Instance_getProperty;
1383 definition.setProperty = &Instance_setProperty;
1384 definition.deleteProperty = &Instance_deleteProperty;
1385 definition.callAsConstructor = &Instance_callAsConstructor;
1386 Instance_ = JSClassCreate(&definition);
1387
1388 definition = kJSClassDefinitionEmpty;
1389 definition.getProperty = &Global_getProperty;
1390 JSClassRef Global(JSClassCreate(&definition));
1391
1392 JSGlobalContextRef context(JSGlobalContextCreate(Global));
1393 Context_ = context;
1394
1395 JSObjectRef global(JSContextGetGlobalObject(context));
1396
1397 CYSetProperty(context, global, CYJSString("Selector"), JSObjectMakeConstructor(context, Selector_, &Selector_new));
1398 CYSetProperty(context, global, CYJSString("Functor"), JSObjectMakeConstructor(context, Functor_, &Functor_new));
1399
1400 CYSetProperty(context, global, CYJSString("CYApplicationMain"), JSObjectMakeFunctionWithCallback(context, CYJSString("CYApplicationMain"), &CYApplicationMain));
1401 CYSetProperty(context, global, CYJSString("objc_msgSend"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_msgSend"), &$objc_msgSend));
1402
1403 System_ = JSObjectMake(context, NULL, NULL);
1404 CYSetProperty(context, global, CYJSString("system"), System_);
1405 CYSetProperty(context, System_, CYJSString("args"), CYJSNull(context));
1406 CYSetProperty(context, System_, CYJSString("global"), global);
1407
1408 CYSetProperty(context, System_, CYJSString("print"), JSObjectMakeFunctionWithCallback(context, CYJSString("print"), &System_print));
1409
1410 Bridge_ = [[NSMutableDictionary dictionaryWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain];
1411
1412 name_ = JSStringCreateWithUTF8CString("name");
1413 message_ = JSStringCreateWithUTF8CString("message");
1414 length_ = JSStringCreateWithUTF8CString("length");
1415
1416 Array_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array")));
1417 Function_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function")));
1418 }