1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2013  Jay Freeman (saurik) 
   5 /* GNU General Public License, Version 3 {{{ */ 
   7  * Cycript is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU General Public License as published 
   9  * by the Free Software Foundation, either version 3 of the License, 
  10  * or (at your option) any later version. 
  12  * Cycript is distributed in the hope that it will be useful, but 
  13  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU General Public License for more details. 
  17  * You should have received a copy of the GNU General Public License 
  18  * along with Cycript.  If not, see <http://www.gnu.org/licenses/>. 
  22 #include "Internal.hpp" 
  26 #include "cycript.hpp" 
  28 #include "sig/parse.hpp" 
  29 #include "sig/ffi_type.hpp" 
  31 #include "Pooling.hpp" 
  32 #include "Execute.hpp" 
  44 #include "Cycript.tab.hh" 
  47 #include "JavaScript.hpp" 
  50 struct CYHooks 
*hooks_
; 
  52 /* JavaScript Properties {{{ */ 
  53 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, size_t index
) { 
  54     JSValueRef 
exception(NULL
); 
  55     JSValueRef 
value(JSObjectGetPropertyAtIndex(context
, object
, index
, &exception
)); 
  56     CYThrow(context
, exception
); 
  60 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
) { 
  61     JSValueRef 
exception(NULL
); 
  62     JSValueRef 
value(JSObjectGetProperty(context
, object
, name
, &exception
)); 
  63     CYThrow(context
, exception
); 
  67 void CYSetProperty(JSContextRef context
, JSObjectRef object
, size_t index
, JSValueRef value
) { 
  68     JSValueRef 
exception(NULL
); 
  69     JSObjectSetPropertyAtIndex(context
, object
, index
, value
, &exception
); 
  70     CYThrow(context
, exception
); 
  73 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef value
, JSPropertyAttributes attributes
) { 
  74     JSValueRef 
exception(NULL
); 
  75     JSObjectSetProperty(context
, object
, name
, value
, attributes
, &exception
); 
  76     CYThrow(context
, exception
); 
  79 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef (*callback
)(JSContextRef
, JSObjectRef
, JSObjectRef
, size_t, const JSValueRef
[], JSValueRef 
*), JSPropertyAttributes attributes
) { 
  80     CYSetProperty(context
, object
, name
, JSObjectMakeFunctionWithCallback(context
, name
, callback
), attributes
); 
  83 /* JavaScript Strings {{{ */ 
  84 JSStringRef 
CYCopyJSString(const char *value
) { 
  85     return value 
== NULL 
? NULL 
: JSStringCreateWithUTF8CString(value
); 
  88 JSStringRef 
CYCopyJSString(JSStringRef value
) { 
  89     return value 
== NULL 
? NULL 
: JSStringRetain(value
); 
  92 JSStringRef 
CYCopyJSString(CYUTF8String value
) { 
  93     // XXX: this is very wrong; it needs to convert to UTF16 and then create from there 
  94     return CYCopyJSString(value
.data
); 
  97 JSStringRef 
CYCopyJSString(JSContextRef context
, JSValueRef value
) { 
  98     if (JSValueIsNull(context
, value
)) 
 100     JSValueRef 
exception(NULL
); 
 101     JSStringRef 
string(JSValueToStringCopy(context
, value
, &exception
)); 
 102     CYThrow(context
, exception
); 
 106 static CYUTF16String 
CYCastUTF16String(JSStringRef value
) { 
 107     return CYUTF16String(JSStringGetCharactersPtr(value
), JSStringGetLength(value
)); 
 110 CYUTF8String 
CYPoolUTF8String(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 111     return CYPoolUTF8String(pool
, CYCastUTF16String(value
)); 
 114 const char *CYPoolCString(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 115     CYUTF8String 
utf8(CYPoolUTF8String(pool
, context
, value
)); 
 116     _assert(memchr(utf8
.data
, '\0', utf8
.size
) == NULL
); 
 120 const char *CYPoolCString(CYPool 
&pool
, JSContextRef context
, JSValueRef value
) { 
 121     return JSValueIsNull(context
, value
) ? NULL 
: CYPoolCString(pool
, context
, CYJSString(context
, value
)); 
 124 /* Index Offsets {{{ */ 
 125 size_t CYGetIndex(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 126     return CYGetIndex(CYPoolUTF8String(pool
, context
, value
)); 
 130 static JSClassRef All_
; 
 131 static JSClassRef Context_
; 
 133 static JSClassRef Global_
; 
 134 static JSClassRef Pointer_
; 
 135 static JSClassRef Struct_
; 
 139 JSStringRef length_s
; 
 140 JSStringRef message_s
; 
 143 JSStringRef prototype_s
; 
 145 JSStringRef splice_s
; 
 146 JSStringRef toCYON_s
; 
 147 JSStringRef toJSON_s
; 
 148 JSStringRef toPointer_s
; 
 149 JSStringRef toString_s
; 
 151 static JSStringRef Result_
; 
 153 void CYFinalize(JSObjectRef object
) { 
 154     CYData 
*internal(reinterpret_cast<CYData 
*>(JSObjectGetPrivate(object
))); 
 155     _assert(internal
->count_ 
!= _not(unsigned)); 
 156     if (--internal
->count_ 
== 0) 
 160 void Structor_(CYPool 
&pool
, sig::Type 
*&type
) { 
 162         type
->primitive 
== sig::pointer_P 
&& 
 163         type
->data
.data
.type 
!= NULL 
&& 
 164         type
->data
.data
.type
->primitive 
== sig::struct_P 
&& 
 165         type
->data
.data
.type
->name 
!= NULL 
&& 
 166         strcmp(type
->data
.data
.type
->name
, "_objc_class") == 0 
 168         type
->primitive 
= sig::typename_P
; 
 169         type
->data
.data
.type 
= NULL
; 
 173     if (type
->primitive 
!= sig::struct_P 
|| type
->name 
== NULL
) 
 176     size_t length(strlen(type
->name
)); 
 177     char keyed
[length 
+ 2]; 
 178     memcpy(keyed 
+ 1, type
->name
, length 
+ 1); 
 180     static const char *modes 
= "34"; 
 181     for (size_t i(0); i 
!= 2; ++i
) { 
 185         if (CYBridgeEntry 
*entry 
= CYBridgeHash(keyed
, length 
+ 1)) 
 188                     sig::Parse(pool
, &type
->data
.signature
, entry
->value_
, &Structor_
); 
 192                     sig::Signature signature
; 
 193                     sig::Parse(pool
, &signature
, entry
->value_
, &Structor_
); 
 194                     type 
= signature
.elements
[0].type
; 
 200 JSClassRef 
Type_privateData::Class_
; 
 205     JSGlobalContextRef context_
; 
 207     Context(JSGlobalContextRef context
) : 
 216     Type_privateData 
*type_
; 
 219     Pointer(void *value
, JSContextRef context
, JSObjectRef owner
, size_t length
, sig::Type 
*type
) : 
 220         CYOwned(value
, context
, owner
), 
 221         type_(new(*pool_
) Type_privateData(type
)), 
 227 struct Struct_privateData 
: 
 230     Type_privateData 
*type_
; 
 232     Struct_privateData(JSContextRef context
, JSObjectRef owner
) : 
 233         CYOwned(NULL
, context
, owner
) 
 238 typedef std::map
<const char *, Type_privateData 
*, CYCStringLess
> TypeMap
; 
 239 static TypeMap Types_
; 
 241 JSObjectRef 
CYMakeStruct(JSContextRef context
, void *data
, sig::Type 
*type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 242     Struct_privateData 
*internal(new Struct_privateData(context
, owner
)); 
 243     CYPool 
&pool(*internal
->pool_
); 
 244     Type_privateData 
*typical(new(pool
) Type_privateData(type
, ffi
)); 
 245     internal
->type_ 
= typical
; 
 248         internal
->value_ 
= data
; 
 250         size_t size(typical
->GetFFI()->size
); 
 251         void *copy(internal
->pool_
->malloc
<void>(size
)); 
 252         memcpy(copy
, data
, size
); 
 253         internal
->value_ 
= copy
; 
 256     return JSObjectMake(context
, Struct_
, internal
); 
 259 static void *CYCastSymbol(const char *name
) { 
 260     return dlsym(RTLD_DEFAULT
, name
); 
 263 JSValueRef 
CYCastJSValue(JSContextRef context
, bool value
) { 
 264     return JSValueMakeBoolean(context
, value
); 
 267 JSValueRef 
CYCastJSValue(JSContextRef context
, double value
) { 
 268     return JSValueMakeNumber(context
, value
); 
 271 #define CYCastJSValue_(Type_) \ 
 272     JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \ 
 273         return JSValueMakeNumber(context, static_cast<double>(value)); \ 
 277 CYCastJSValue_(unsigned int) 
 278 CYCastJSValue_(long int) 
 279 CYCastJSValue_(long unsigned int) 
 280 CYCastJSValue_(long long int) 
 281 CYCastJSValue_(long long unsigned int) 
 283 JSValueRef 
CYJSUndefined(JSContextRef context
) { 
 284     return JSValueMakeUndefined(context
); 
 287 double CYCastDouble(JSContextRef context
, JSValueRef value
) { 
 288     JSValueRef 
exception(NULL
); 
 289     double number(JSValueToNumber(context
, value
, &exception
)); 
 290     CYThrow(context
, exception
); 
 294 bool CYCastBool(JSContextRef context
, JSValueRef value
) { 
 295     return JSValueToBoolean(context
, value
); 
 298 JSValueRef 
CYJSNull(JSContextRef context
) { 
 299     return JSValueMakeNull(context
); 
 302 JSValueRef 
CYCastJSValue(JSContextRef context
, JSStringRef value
) { 
 303     return value 
== NULL 
? CYJSNull(context
) : JSValueMakeString(context
, value
); 
 306 JSValueRef 
CYCastJSValue(JSContextRef context
, const char *value
) { 
 307     return CYCastJSValue(context
, CYJSString(value
)); 
 310 JSObjectRef 
CYCastJSObject(JSContextRef context
, JSValueRef value
) { 
 311     JSValueRef 
exception(NULL
); 
 312     JSObjectRef 
object(JSValueToObject(context
, value
, &exception
)); 
 313     CYThrow(context
, exception
); 
 317 JSValueRef 
CYCallAsFunction(JSContextRef context
, JSObjectRef function
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[]) { 
 318     JSValueRef 
exception(NULL
); 
 319     JSValueRef 
value(JSObjectCallAsFunction(context
, function
, _this
, count
, arguments
, &exception
)); 
 320     CYThrow(context
, exception
); 
 324 bool CYIsCallable(JSContextRef context
, JSValueRef value
) { 
 325     return value 
!= NULL 
&& JSValueIsObject(context
, value
) && JSObjectIsFunction(context
, (JSObjectRef
) value
); 
 328 static JSValueRef 
System_print(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 333         printf("%s\n", CYPoolCString(pool
, context
, arguments
[0])); 
 336     return CYJSUndefined(context
); 
 339 static size_t Nonce_(0); 
 341 static JSValueRef $
cyq(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 343     const char *name(pool
.strcat(CYPoolCString(pool
, context
, arguments
[0]), pool
.itoa(Nonce_
++), NULL
)); 
 344     return CYCastJSValue(context
, name
); 
 347 static JSValueRef 
Cycript_gc_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 348     JSGarbageCollect(context
); 
 349     return CYJSUndefined(context
); 
 352 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 353     switch (JSType type 
= JSValueGetType(context
, value
)) { 
 354         case kJSTypeUndefined
: 
 359             return CYCastBool(context
, value
) ? "true" : "false"; 
 361         case kJSTypeNumber
: { 
 362             std::ostringstream str
; 
 363             CYNumerify(str
, CYCastDouble(context
, value
)); 
 364             std::string 
value(str
.str()); 
 365             return pool
.strmemdup(value
.c_str(), value
.size()); 
 368         case kJSTypeString
: { 
 369             std::ostringstream str
; 
 370             CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, value
))); 
 371             CYStringify(str
, string
.data
, string
.size
); 
 372             std::string 
value(str
.str()); 
 373             return pool
.strmemdup(value
.c_str(), value
.size()); 
 377             return CYPoolCCYON(pool
, context
, (JSObjectRef
) value
); 
 379             throw CYJSError(context
, "JSValueGetType() == 0x%x", type
); 
 383 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
) { 
 384     JSValueRef 
exception(NULL
); 
 385     const char *cyon(CYPoolCCYON(pool
, context
, value
, &exception
)); 
 386     CYThrow(context
, exception
); 
 390 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSObjectRef object
) { 
 391     JSValueRef 
toCYON(CYGetProperty(context
, object
, toCYON_s
)); 
 392     if (CYIsCallable(context
, toCYON
)) { 
 393         JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toCYON
, object
, 0, NULL
)); 
 394         _assert(value 
!= NULL
); 
 395         return CYPoolCString(pool
, context
, value
); 
 398     JSValueRef 
toJSON(CYGetProperty(context
, object
, toJSON_s
)); 
 399     if (CYIsCallable(context
, toJSON
)) { 
 400         JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 401         JSValueRef 
exception(NULL
); 
 402         const char *cyon(CYPoolCCYON(pool
, context
, CYCallAsFunction(context
, (JSObjectRef
) toJSON
, object
, 1, arguments
), &exception
)); 
 403         CYThrow(context
, exception
); 
 407     if (JSObjectIsFunction(context
, object
)) { 
 408         JSValueRef 
toString(CYGetProperty(context
, object
, toString_s
)); 
 409         if (CYIsCallable(context
, toString
)) { 
 410             JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 411             JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toString
, object
, 1, arguments
)); 
 412             _assert(value 
!= NULL
); 
 413             return CYPoolCString(pool
, context
, value
); 
 417     std::ostringstream str
; 
 421     // XXX: this is, sadly, going to leak 
 422     JSPropertyNameArrayRef 
names(JSObjectCopyPropertyNames(context
, object
)); 
 426     for (size_t index(0), count(JSPropertyNameArrayGetCount(names
)); index 
!= count
; ++index
) { 
 427         JSStringRef 
name(JSPropertyNameArrayGetNameAtIndex(names
, index
)); 
 428         JSValueRef 
value(CYGetProperty(context
, object
, name
)); 
 435         CYUTF8String 
string(CYPoolUTF8String(pool
, context
, name
)); 
 439             CYStringify(str
, string
.data
, string
.size
); 
 441         str 
<< ':' << CYPoolCCYON(pool
, context
, value
); 
 446     JSPropertyNameArrayRelease(names
); 
 448     std::string 
string(str
.str()); 
 449     return pool
.strmemdup(string
.c_str(), string
.size()); 
 452 static JSValueRef 
Array_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 454     std::ostringstream str
; 
 458     JSValueRef 
length(CYGetProperty(context
, _this
, length_s
)); 
 461     for (size_t index(0), count(CYCastDouble(context
, length
)); index 
!= count
; ++index
) { 
 462         JSValueRef 
value(CYGetProperty(context
, _this
, index
)); 
 469         if (!JSValueIsUndefined(context
, value
)) 
 470             str 
<< CYPoolCCYON(pool
, context
, value
); 
 479     std::string 
value(str
.str()); 
 480     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 483 static JSValueRef 
String_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 485     std::ostringstream str
; 
 487     CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, _this
))); 
 488     CYStringify(str
, string
.data
, string
.size
); 
 490     std::string 
value(str
.str()); 
 491     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 494 JSObjectRef 
CYMakePointer(JSContextRef context
, void *pointer
, size_t length
, sig::Type 
*type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 495     Pointer 
*internal(new Pointer(pointer
, context
, owner
, length
, type
)); 
 496     return JSObjectMake(context
, Pointer_
, internal
); 
 499 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, void (*function
)(), const char *type
) { 
 500     return JSObjectMake(context
, Functor_
, new cy::Functor(type
, function
)); 
 503 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, const char *symbol
, const char *type
, void **cache
) { 
 504     cy::Functor 
*internal
; 
 506         internal 
= reinterpret_cast<cy::Functor 
*>(*cache
); 
 508         void (*function
)()(reinterpret_cast<void (*)()>(CYCastSymbol(symbol
))); 
 509         if (function 
== NULL
) 
 512         internal 
= new cy::Functor(type
, function
); 
 517     return JSObjectMake(context
, Functor_
, internal
); 
 520 static bool CYGetOffset(CYPool 
&pool
, JSContextRef context
, JSStringRef value
, ssize_t 
&index
) { 
 521     return CYGetOffset(CYPoolCString(pool
, context
, value
), index
); 
 524 void *CYCastPointer_(JSContextRef context
, JSValueRef value
) { 
 525     switch (JSValueGetType(context
, value
)) { 
 528         case kJSTypeObject
: { 
 529             JSObjectRef 
object((JSObjectRef
) value
); 
 530             if (JSValueIsObjectOfClass(context
, value
, Pointer_
)) { 
 531                 Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 532                 return internal
->value_
; 
 534             JSValueRef 
toPointer(CYGetProperty(context
, object
, toPointer_s
)); 
 535             if (CYIsCallable(context
, toPointer
)) { 
 536                 JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toPointer
, object
, 0, NULL
)); 
 537                 _assert(value 
!= NULL
); 
 538                 return CYCastPointer_(context
, value
); 
 541             double number(CYCastDouble(context
, value
)); 
 542             if (std::isnan(number
)) 
 543                 throw CYJSError(context
, "cannot convert value to pointer"); 
 544             return reinterpret_cast<void *>(static_cast<uintptr_t>(static_cast<long long>(number
))); 
 548 void CYPoolFFI(CYPool 
*pool
, JSContextRef context
, sig::Type 
*type
, ffi_type 
*ffi
, void *data
, JSValueRef value
) { 
 549     switch (type
->primitive
) { 
 551             *reinterpret_cast<bool *>(data
) = JSValueToBoolean(context
, value
); 
 554 #define CYPoolFFI_(primitive, native) \ 
 555         case sig::primitive ## _P: \ 
 556             *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \ 
 559         CYPoolFFI_(uchar
, unsigned char) 
 560         CYPoolFFI_(char, char) 
 561         CYPoolFFI_(ushort
, unsigned short) 
 562         CYPoolFFI_(short, short) 
 563         CYPoolFFI_(ulong
, unsigned long) 
 564         CYPoolFFI_(long, long) 
 565         CYPoolFFI_(uint
, unsigned int) 
 567         CYPoolFFI_(ulonglong
, unsigned long long) 
 568         CYPoolFFI_(longlong
, long long) 
 569         CYPoolFFI_(float, float) 
 570         CYPoolFFI_(double, double) 
 573             uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 574             JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 575             for (size_t index(0); index 
!= type
->data
.data
.size
; ++index
) { 
 576                 ffi_type 
*field(ffi
->elements
[index
]); 
 579                 if (aggregate 
== NULL
) 
 582                     rhs 
= CYGetProperty(context
, aggregate
, index
); 
 583                     if (JSValueIsUndefined(context
, rhs
)) 
 584                         throw CYJSError(context
, "unable to extract array value"); 
 587                 CYPoolFFI(pool
, context
, type
->data
.data
.type
, field
, base
, rhs
); 
 594             *reinterpret_cast<void **>(data
) = CYCastPointer
<void *>(context
, value
); 
 598             _assert(pool 
!= NULL
); 
 599             *reinterpret_cast<const char **>(data
) = CYPoolCString(*pool
, context
, value
); 
 602         case sig::struct_P
: { 
 603             uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 604             JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 605             for (size_t index(0); index 
!= type
->data
.signature
.count
; ++index
) { 
 606                 sig::Element 
*element(&type
->data
.signature
.elements
[index
]); 
 607                 ffi_type 
*field(ffi
->elements
[index
]); 
 610                 if (aggregate 
== NULL
) 
 613                     rhs 
= CYGetProperty(context
, aggregate
, index
); 
 614                     if (JSValueIsUndefined(context
, rhs
)) { 
 615                         if (element
->name 
!= NULL
) 
 616                             rhs 
= CYGetProperty(context
, aggregate
, CYJSString(element
->name
)); 
 619                         if (JSValueIsUndefined(context
, rhs
)) undefined
: 
 620                             throw CYJSError(context
, "unable to extract structure value"); 
 624                 CYPoolFFI(pool
, context
, element
->type
, field
, base
, rhs
); 
 634             if (hooks_ 
!= NULL 
&& hooks_
->PoolFFI 
!= NULL
) 
 635                 if ((*hooks_
->PoolFFI
)(pool
, context
, type
, ffi
, data
, value
)) 
 638             CYThrow("unimplemented signature code: '%c''\n", type
->primitive
); 
 642 JSValueRef 
CYFromFFI(JSContextRef context
, sig::Type 
*type
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) { 
 643     switch (type
->primitive
) { 
 645             return CYCastJSValue(context
, *reinterpret_cast<bool *>(data
)); 
 647 #define CYFromFFI_(primitive, native) \ 
 648         case sig::primitive ## _P: \ 
 649             return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \ 
 651         CYFromFFI_(uchar, unsigned char) 
 652         CYFromFFI_(char, char) 
 653         CYFromFFI_(ushort
, unsigned short) 
 654         CYFromFFI_(short, short) 
 655         CYFromFFI_(ulong
, unsigned long) 
 656         CYFromFFI_(long, long) 
 657         CYFromFFI_(uint
, unsigned int) 
 659         CYFromFFI_(ulonglong
, unsigned long long) 
 660         CYFromFFI_(longlong
, long long) 
 661         CYFromFFI_(float, float) 
 662         CYFromFFI_(double, double) 
 665             if (void *pointer 
= data
) 
 666                 return CYMakePointer(context
, pointer
, type
->data
.data
.size
, type
->data
.data
.type
, NULL
, owner
); 
 670             if (void *pointer 
= *reinterpret_cast<void **>(data
)) 
 671                 return CYMakePointer(context
, pointer
, _not(size_t), type
->data
.data
.type
, NULL
, owner
); 
 675             if (char *utf8 
= *reinterpret_cast<char **>(data
)) 
 676                 return CYCastJSValue(context
, utf8
); 
 680             return CYMakeStruct(context
, data
, type
, ffi
, owner
); 
 682             return CYJSUndefined(context
); 
 685             return CYJSNull(context
); 
 687             if (hooks_ 
!= NULL 
&& hooks_
->FromFFI 
!= NULL
) 
 688                 if (JSValueRef value 
= (*hooks_
->FromFFI
)(context
, type
, ffi
, data
, initialize
, owner
)) 
 691             CYThrow("unimplemented signature code: '%c''\n", type
->primitive
); 
 695 void CYExecuteClosure(ffi_cif 
*cif
, void *result
, void **arguments
, void *arg
, JSValueRef (*adapter
)(JSContextRef
, size_t, JSValueRef
[], JSObjectRef
)) { 
 696     Closure_privateData 
*internal(reinterpret_cast<Closure_privateData 
*>(arg
)); 
 698     JSContextRef 
context(internal
->context_
); 
 700     size_t count(internal
->cif_
.nargs
); 
 701     JSValueRef values
[count
]; 
 703     for (size_t index(0); index 
!= count
; ++index
) 
 704         values
[index
] = CYFromFFI(context
, internal
->signature_
.elements
[1 + index
].type
, internal
->cif_
.arg_types
[index
], arguments
[index
]); 
 706     JSValueRef 
value(adapter(context
, count
, values
, internal
->function_
)); 
 707     CYPoolFFI(NULL
, context
, internal
->signature_
.elements
[0].type
, internal
->cif_
.rtype
, result
, value
); 
 710 static JSValueRef 
FunctionAdapter_(JSContextRef context
, size_t count
, JSValueRef values
[], JSObjectRef function
) { 
 711     return CYCallAsFunction(context
, function
, NULL
, count
, values
); 
 714 static void FunctionClosure_(ffi_cif 
*cif
, void *result
, void **arguments
, void *arg
) { 
 715     CYExecuteClosure(cif
, result
, arguments
, arg
, &FunctionAdapter_
); 
 718 Closure_privateData 
*CYMakeFunctor_(JSContextRef context
, JSObjectRef function
, const char *type
, void (*callback
)(ffi_cif 
*, void *, void **, void *)) { 
 719     // XXX: in case of exceptions this will leak 
 720     // XXX: in point of fact, this may /need/ to leak :( 
 721     Closure_privateData 
*internal(new Closure_privateData(context
, function
, type
)); 
 723 #if defined(__APPLE__) && defined(__arm__) 
 725     ffi_closure 
*writable(reinterpret_cast<ffi_closure 
*>(ffi_closure_alloc(sizeof(ffi_closure
), &executable
))); 
 727     ffi_status 
status(ffi_prep_closure_loc(writable
, &internal
->cif_
, callback
, internal
, executable
)); 
 728     _assert(status 
== FFI_OK
); 
 730     internal
->value_ 
= executable
; 
 732     ffi_closure 
*closure((ffi_closure 
*) _syscall(mmap( 
 733         NULL
, sizeof(ffi_closure
), 
 734         PROT_READ 
| PROT_WRITE
, MAP_ANON 
| MAP_PRIVATE
, 
 738     ffi_status 
status(ffi_prep_closure(closure
, &internal
->cif_
, callback
, internal
)); 
 739     _assert(status 
== FFI_OK
); 
 741     _syscall(mprotect(closure
, sizeof(*closure
), PROT_READ 
| PROT_EXEC
)); 
 743     internal
->value_ 
= closure
; 
 749 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSObjectRef function
, const char *type
) { 
 750     Closure_privateData 
*internal(CYMakeFunctor_(context
, function
, type
, &FunctionClosure_
)); 
 751     JSObjectRef 
object(JSObjectMake(context
, Functor_
, internal
)); 
 752     // XXX: see above notes about needing to leak 
 753     JSValueProtect(CYGetJSContext(context
), object
); 
 757 JSObjectRef 
CYGetCachedObject(JSContextRef context
, JSStringRef name
) { 
 758     return CYCastJSObject(context
, CYGetProperty(context
, CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
)), name
)); 
 761 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSValueRef value
, const char *type
) { 
 762     JSObjectRef 
Function(CYGetCachedObject(context
, CYJSString("Function"))); 
 764     JSValueRef 
exception(NULL
); 
 765     bool function(JSValueIsInstanceOfConstructor(context
, value
, Function
, &exception
)); 
 766     CYThrow(context
, exception
); 
 769         JSObjectRef 
function(CYCastJSObject(context
, value
)); 
 770         return CYMakeFunctor(context
, function
, type
); 
 772         void (*function
)()(CYCastPointer
<void (*)()>(context
, value
)); 
 773         return CYMakeFunctor(context
, function
, type
); 
 777 static bool Index_(CYPool 
&pool
, JSContextRef context
, Struct_privateData 
*internal
, JSStringRef property
, ssize_t 
&index
, uint8_t *&base
) { 
 778     Type_privateData 
*typical(internal
->type_
); 
 779     sig::Type 
*type(typical
->type_
); 
 783     const char *name(CYPoolCString(pool
, context
, property
)); 
 784     size_t length(strlen(name
)); 
 785     double number(CYCastDouble(name
, length
)); 
 787     size_t count(type
->data
.signature
.count
); 
 789     if (std::isnan(number
)) { 
 790         if (property 
== NULL
) 
 793         sig::Element 
*elements(type
->data
.signature
.elements
); 
 795         for (size_t local(0); local 
!= count
; ++local
) { 
 796             sig::Element 
*element(&elements
[local
]); 
 797             if (element
->name 
!= NULL 
&& strcmp(name
, element
->name
) == 0) { 
 805         index 
= static_cast<ssize_t
>(number
); 
 806         if (index 
!= number 
|| index 
< 0 || static_cast<size_t>(index
) >= count
) 
 811     ffi_type 
**elements(typical
->GetFFI()->elements
); 
 813     base 
= reinterpret_cast<uint8_t *>(internal
->value_
); 
 814     for (ssize_t 
local(0); local 
!= index
; ++local
) 
 815         base 
+= elements
[local
]->size
; 
 820 static JSValueRef 
Pointer_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 822     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 824     if (JSStringIsEqual(property
, length_s
)) 
 825         return internal
->length_ 
== _not(size_t) ? CYJSUndefined(context
) : CYCastJSValue(context
, internal
->length_
); 
 827     Type_privateData 
*typical(internal
->type_
); 
 829     if (typical
->type_ 
== NULL
) 
 833     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
 835     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
 838     ffi_type 
*ffi(typical
->GetFFI()); 
 840     uint8_t *base(reinterpret_cast<uint8_t *>(internal
->value_
)); 
 841     base 
+= ffi
->size 
* offset
; 
 843     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
 844     return CYFromFFI(context
, typical
->type_
, ffi
, base
, false, owner
); 
 847 static bool Pointer_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 849     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 850     Type_privateData 
*typical(internal
->type_
); 
 852     if (typical
->type_ 
== NULL
) 
 856     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
 858     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
 861     ffi_type 
*ffi(typical
->GetFFI()); 
 863     uint8_t *base(reinterpret_cast<uint8_t *>(internal
->value_
)); 
 864     base 
+= ffi
->size 
* offset
; 
 866     CYPoolFFI(NULL
, context
, typical
->type_
, ffi
, base
, value
); 
 870 static JSValueRef Struct_callAsFunction_$
cya(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 871     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(_this
))); 
 872     Type_privateData 
*typical(internal
->type_
); 
 873     return CYMakePointer(context
, internal
->value_
, _not(size_t), typical
->type_
, typical
->ffi_
, _this
); 
 876 static JSValueRef 
Struct_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 878     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 879     Type_privateData 
*typical(internal
->type_
); 
 884     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
 887     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
 889     return CYFromFFI(context
, typical
->type_
->data
.signature
.elements
[index
].type
, typical
->GetFFI()->elements
[index
], base
, false, owner
); 
 892 static bool Struct_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 894     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 895     Type_privateData 
*typical(internal
->type_
); 
 900     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
 903     CYPoolFFI(NULL
, context
, typical
->type_
->data
.signature
.elements
[index
].type
, typical
->GetFFI()->elements
[index
], base
, value
); 
 907 static void Struct_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
 908     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 909     Type_privateData 
*typical(internal
->type_
); 
 910     sig::Type 
*type(typical
->type_
); 
 915     size_t count(type
->data
.signature
.count
); 
 916     sig::Element 
*elements(type
->data
.signature
.elements
); 
 920     for (size_t index(0); index 
!= count
; ++index
) { 
 922         name 
= elements
[index
].name
; 
 925             sprintf(number
, "%zu", index
); 
 929         JSPropertyNameAccumulatorAddName(names
, CYJSString(name
)); 
 933 JSValueRef 
CYCallFunction(CYPool 
&pool
, JSContextRef context
, size_t setups
, void *setup
[], size_t count
, const JSValueRef arguments
[], bool initialize
, JSValueRef 
*exception
, sig::Signature 
*signature
, ffi_cif 
*cif
, void (*function
)()) { CYTry 
{ 
 934     if (setups 
+ count 
!= signature
->count 
- 1) 
 935         throw CYJSError(context
, "incorrect number of arguments to ffi function"); 
 937     size_t size(setups 
+ count
); 
 939     memcpy(values
, setup
, sizeof(void *) * setups
); 
 941     for (size_t index(setups
); index 
!= size
; ++index
) { 
 942         sig::Element 
*element(&signature
->elements
[index 
+ 1]); 
 943         ffi_type 
*ffi(cif
->arg_types
[index
]); 
 945         values
[index
] = new(pool
) uint8_t[ffi
->size
]; 
 946         CYPoolFFI(&pool
, context
, element
->type
, ffi
, values
[index
], arguments
[index 
- setups
]); 
 949     uint8_t value
[cif
->rtype
->size
]; 
 951     if (hooks_ 
!= NULL 
&& hooks_
->CallFunction 
!= NULL
) 
 952         (*hooks_
->CallFunction
)(context
, cif
, function
, value
, values
); 
 954         ffi_call(cif
, function
, value
, values
); 
 956     return CYFromFFI(context
, signature
->elements
[0].type
, cif
->rtype
, value
, initialize
); 
 959 static JSValueRef 
Functor_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 961     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(object
))); 
 962     return CYCallFunction(pool
, context
, 0, NULL
, count
, arguments
, false, exception
, &internal
->signature_
, &internal
->cif_
, internal
->GetValue()); 
 965 JSObjectRef 
CYMakeType(JSContextRef context
, const char *type
) { 
 966     Type_privateData 
*internal(new Type_privateData(type
)); 
 967     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
 970 JSObjectRef 
CYMakeType(JSContextRef context
, sig::Type 
*type
) { 
 971     Type_privateData 
*internal(new Type_privateData(type
)); 
 972     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
 975 static JSValueRef 
All_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 976     JSObjectRef 
global(CYGetGlobalObject(context
)); 
 977     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
 978     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
 980     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
 981         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) 
 982             if (JSValueRef value 
= CYGetProperty(context
, space
, property
)) 
 983                 if (!JSValueIsUndefined(context
, value
)) 
 987     CYUTF8String 
name(CYPoolUTF8String(pool
, context
, property
)); 
 989     size_t length(name
.size
); 
 990     char keyed
[length 
+ 2]; 
 991     memcpy(keyed 
+ 1, name
.data
, length 
+ 1); 
 993     static const char *modes 
= "0124"; 
 994     for (size_t i(0); i 
!= 4; ++i
) { 
 998         if (CYBridgeEntry 
*entry 
= CYBridgeHash(keyed
, length 
+ 1)) 
1001                     return JSEvaluateScript(CYGetJSContext(context
), CYJSString(entry
->value_
), NULL
, NULL
, 0, NULL
); 
1004                     return CYMakeFunctor(context
, name
.data
, entry
->value_
, &entry
->cache_
); 
1007                     if (void *symbol 
= CYCastSymbol(name
.data
)) { 
1008                         // XXX: this is horrendously inefficient 
1009                         sig::Signature signature
; 
1010                         sig::Parse(pool
, &signature
, entry
->value_
, &Structor_
); 
1012                         sig::sig_ffi_cif(pool
, &sig::ObjectiveC
, &signature
, &cif
); 
1013                         return CYFromFFI(context
, signature
.elements
[0].type
, cif
.rtype
, symbol
); 
1016                 // XXX: implement case 3 
1018                     return CYMakeType(context
, entry
->value_
); 
1025 static void All_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
1026     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1027     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1028     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1030     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1031         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) { 
1032             JSPropertyNameArrayRef 
subset(JSObjectCopyPropertyNames(context
, space
)); 
1033             for (size_t index(0), count(JSPropertyNameArrayGetCount(subset
)); index 
!= count
; ++index
) 
1034                 JSPropertyNameAccumulatorAddName(names
, JSPropertyNameArrayGetNameAtIndex(subset
, index
)); 
1035             JSPropertyNameArrayRelease(subset
); 
1039 static JSObjectRef 
Pointer_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1041         throw CYJSError(context
, "incorrect number of arguments to Pointer constructor"); 
1045     void *value(CYCastPointer
<void *>(context
, arguments
[0])); 
1046     const char *type(CYPoolCString(pool
, context
, arguments
[1])); 
1048     sig::Signature signature
; 
1049     sig::Parse(pool
, &signature
, type
, &Structor_
); 
1051     return CYMakePointer(context
, value
, _not(size_t), signature
.elements
[0].type
, NULL
, NULL
); 
1054 static JSObjectRef 
Type_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1056         throw CYJSError(context
, "incorrect number of arguments to Type constructor"); 
1058     const char *type(CYPoolCString(pool
, context
, arguments
[0])); 
1059     return CYMakeType(context
, type
); 
1062 static JSValueRef 
Type_callAsFunction_arrayOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1064         throw CYJSError(context
, "incorrect number of arguments to Type.arrayOf"); 
1065     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1068     size_t index(CYGetIndex(pool
, context
, CYJSString(context
, arguments
[0]))); 
1069     if (index 
== _not(size_t)) 
1070         throw CYJSError(context
, "invalid array size used with Type.arrayOf"); 
1076     type
.primitive 
= sig::array_P
; 
1077     type
.data
.data
.type 
= internal
->type_
; 
1078     type
.data
.data
.size 
= index
; 
1080     return CYMakeType(context
, &type
); 
1083 static JSValueRef 
Type_callAsFunction_constant(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1085         throw CYJSError(context
, "incorrect number of arguments to Type.constant"); 
1086     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1088     sig::Type 
type(*internal
->type_
); 
1089     type
.flags 
|= JOC_TYPE_CONST
; 
1090     return CYMakeType(context
, &type
); 
1093 static JSValueRef 
Type_callAsFunction_pointerTo(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1095         throw CYJSError(context
, "incorrect number of arguments to Type.pointerTo"); 
1096     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1102     type
.primitive 
= sig::pointer_P
; 
1103     type
.data
.data
.type 
= internal
->type_
; 
1104     type
.data
.data
.size 
= 0; 
1106     return CYMakeType(context
, &type
); 
1109 static JSValueRef 
Type_callAsFunction_withName(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1111         throw CYJSError(context
, "incorrect number of arguments to Type.withName"); 
1112     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1115     const char *name(CYPoolCString(pool
, context
, arguments
[0])); 
1117     sig::Type 
type(*internal
->type_
); 
1119     return CYMakeType(context
, &type
); 
1122 static JSValueRef 
Type_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1124         throw CYJSError(context
, "incorrect number of arguments to type cast function"); 
1125     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1127     sig::Type 
*type(internal
->type_
); 
1128     ffi_type 
*ffi(internal
->GetFFI()); 
1130     uint8_t value
[ffi
->size
]; 
1132     CYPoolFFI(&pool
, context
, type
, ffi
, value
, arguments
[0]); 
1133     return CYFromFFI(context
, type
, ffi
, value
); 
1136 static JSObjectRef 
Type_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1138         throw CYJSError(context
, "incorrect number of arguments to Type allocator"); 
1139     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1141     sig::Type 
*type(internal
->type_
); 
1144     if (type
->primitive 
!= sig::array_P
) 
1145         length 
= _not(size_t); 
1147         length 
= type
->data
.data
.size
; 
1148         type 
= type
->data
.data
.type
; 
1151     void *value(malloc(internal
->GetFFI()->size
)); 
1152     return CYMakePointer(context
, value
, length
, type
, NULL
, NULL
); 
1155 static JSObjectRef 
Functor_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1157         throw CYJSError(context
, "incorrect number of arguments to Functor constructor"); 
1159     const char *type(CYPoolCString(pool
, context
, arguments
[1])); 
1160     return CYMakeFunctor(context
, arguments
[0], type
); 
1163 static JSValueRef 
CYValue_callAsFunction_valueOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1164     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1165     return CYCastJSValue(context
, reinterpret_cast<uintptr_t>(internal
->value_
)); 
1168 static JSValueRef 
CYValue_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1169     return CYValue_callAsFunction_valueOf(context
, object
, _this
, count
, arguments
, exception
); 
1172 static JSValueRef 
CYValue_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1173     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1175     sprintf(string
, "%p", internal
->value_
); 
1176     return CYCastJSValue(context
, string
); 
1179 static JSValueRef 
Pointer_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1180     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(_this
))); 
1181     if (internal
->length_ 
!= _not(size_t)) { 
1182         JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array_prototype"))); 
1183         JSObjectRef 
toCYON(CYCastJSObject(context
, CYGetProperty(context
, Array
, toCYON_s
))); 
1184         return CYCallAsFunction(context
, toCYON
, _this
, count
, arguments
); 
1187         sprintf(string
, "%p", internal
->value_
); 
1188         return CYCastJSValue(context
, string
); 
1192 static JSValueRef 
Type_getProperty_alignment(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { 
1193     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1194     return CYCastJSValue(context
, internal
->GetFFI()->alignment
); 
1197 static JSValueRef 
Type_getProperty_name(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { 
1198     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1199     return CYCastJSValue(context
, internal
->type_
->name
); 
1202 static JSValueRef 
Type_getProperty_size(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { 
1203     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1204     return CYCastJSValue(context
, internal
->GetFFI()->size
); 
1207 static JSValueRef 
Type_callAsFunction_toString(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1208     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1210     const char *type(sig::Unparse(pool
, internal
->type_
)); 
1211     return CYCastJSValue(context
, CYJSString(type
)); 
1214 static JSValueRef 
Type_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1215     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1217     const char *type(sig::Unparse(pool
, internal
->type_
)); 
1218     std::ostringstream str
; 
1219     CYStringify(str
, type
, strlen(type
)); 
1220     char *cyon(pool
.strcat("new Type(", str
.str().c_str(), ")", NULL
)); 
1221     return CYCastJSValue(context
, CYJSString(cyon
)); 
1224 static JSValueRef 
Type_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1225     return Type_callAsFunction_toString(context
, object
, _this
, count
, arguments
, exception
); 
1228 static JSStaticFunction Pointer_staticFunctions
[4] = { 
1229     {"toCYON", &Pointer_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1230     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1231     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1235 static JSStaticFunction Struct_staticFunctions
[2] = { 
1236     {"$cya", &Struct_callAsFunction_$cya
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1240 static JSStaticFunction Functor_staticFunctions
[4] = { 
1241     {"toCYON", &CYValue_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1242     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1243     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1248     JSStaticFunction 
const * const Functor::StaticFunctions 
= Functor_staticFunctions
; 
1251 static JSStaticValue Type_staticValues
[4] = { 
1252     {"alignment", &Type_getProperty_alignment
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1253     {"name", &Type_getProperty_name
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1254     {"size", &Type_getProperty_size
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1255     {NULL
, NULL
, NULL
, 0} 
1258 static JSStaticFunction Type_staticFunctions
[8] = { 
1259     {"arrayOf", &Type_callAsFunction_arrayOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1260     {"constant", &Type_callAsFunction_constant
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1261     {"pointerTo", &Type_callAsFunction_pointerTo
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1262     {"withName", &Type_callAsFunction_withName
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1263     {"toCYON", &Type_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1264     {"toJSON", &Type_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1265     {"toString", &Type_callAsFunction_toString
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1269 static JSObjectRef (*JSObjectMakeArray$
)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*); 
1271 void CYSetArgs(int argc
, const char *argv
[]) { 
1272     JSContextRef 
context(CYGetJSContext()); 
1273     JSValueRef args
[argc
]; 
1274     for (int i(0); i 
!= argc
; ++i
) 
1275         args
[i
] = CYCastJSValue(context
, argv
[i
]); 
1278     if (JSObjectMakeArray$ 
!= NULL
) { 
1279         JSValueRef 
exception(NULL
); 
1280         array 
= (*JSObjectMakeArray$
)(context
, argc
, args
, &exception
); 
1281         CYThrow(context
, exception
); 
1283         JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array"))); 
1284         JSValueRef 
value(CYCallAsFunction(context
, Array
, NULL
, argc
, args
)); 
1285         array 
= CYCastJSObject(context
, value
); 
1288     JSObjectRef 
System(CYGetCachedObject(context
, CYJSString("System"))); 
1289     CYSetProperty(context
, System
, CYJSString("args"), array
); 
1292 JSObjectRef 
CYGetGlobalObject(JSContextRef context
) { 
1293     return JSContextGetGlobalObject(context
); 
1296 const char *CYExecute(CYPool 
&pool
, CYUTF8String code
) { 
1297     JSContextRef 
context(CYGetJSContext()); 
1298     JSValueRef 
exception(NULL
), result
; 
1301     if (hooks_ 
!= NULL 
&& hooks_
->ExecuteStart 
!= NULL
) 
1302         handle 
= (*hooks_
->ExecuteStart
)(context
); 
1309         result 
= JSEvaluateScript(context
, CYJSString(code
), NULL
, NULL
, 0, &exception
); 
1310     } catch (const char *error
) { 
1314     if (exception 
!= NULL
) error
: 
1315         return CYPoolCString(pool
, context
, CYJSString(context
, exception
)); 
1317     if (JSValueIsUndefined(context
, result
)) 
1321         json 
= CYPoolCCYON(pool
, context
, result
, &exception
); 
1322     } catch (const char *error
) { 
1326     if (exception 
!= NULL
) 
1329     CYSetProperty(context
, CYGetGlobalObject(context
), Result_
, result
); 
1331     if (hooks_ 
!= NULL 
&& hooks_
->ExecuteEnd 
!= NULL
) 
1332         (*hooks_
->ExecuteEnd
)(context
, handle
); 
1336 extern "C" void CydgetSetupContext(JSGlobalContextRef context
) { 
1337     CYSetupContext(context
); 
1340 static bool initialized_ 
= false; 
1342 void CYInitializeDynamic() { 
1344         initialized_ 
= true; 
1347     JSObjectMakeArray$ 
= reinterpret_cast<JSObjectRef (*)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*)>(dlsym(RTLD_DEFAULT
, "JSObjectMakeArray")); 
1349     JSClassDefinition definition
; 
1351     definition 
= kJSClassDefinitionEmpty
; 
1352     definition
.className 
= "All"; 
1353     definition
.getProperty 
= &All_getProperty
; 
1354     definition
.getPropertyNames 
= &All_getPropertyNames
; 
1355     All_ 
= JSClassCreate(&definition
); 
1357     definition 
= kJSClassDefinitionEmpty
; 
1358     definition
.className 
= "Context"; 
1359     definition
.finalize 
= &CYFinalize
; 
1360     Context_ 
= JSClassCreate(&definition
); 
1362     definition 
= kJSClassDefinitionEmpty
; 
1363     definition
.className 
= "Functor"; 
1364     definition
.staticFunctions 
= cy::Functor::StaticFunctions
; 
1365     definition
.callAsFunction 
= &Functor_callAsFunction
; 
1366     definition
.finalize 
= &CYFinalize
; 
1367     Functor_ 
= JSClassCreate(&definition
); 
1369     definition 
= kJSClassDefinitionEmpty
; 
1370     definition
.className 
= "Pointer"; 
1371     definition
.staticFunctions 
= Pointer_staticFunctions
; 
1372     definition
.getProperty 
= &Pointer_getProperty
; 
1373     definition
.setProperty 
= &Pointer_setProperty
; 
1374     definition
.finalize 
= &CYFinalize
; 
1375     Pointer_ 
= JSClassCreate(&definition
); 
1377     definition 
= kJSClassDefinitionEmpty
; 
1378     definition
.className 
= "Struct"; 
1379     definition
.staticFunctions 
= Struct_staticFunctions
; 
1380     definition
.getProperty 
= &Struct_getProperty
; 
1381     definition
.setProperty 
= &Struct_setProperty
; 
1382     definition
.getPropertyNames 
= &Struct_getPropertyNames
; 
1383     definition
.finalize 
= &CYFinalize
; 
1384     Struct_ 
= JSClassCreate(&definition
); 
1386     definition 
= kJSClassDefinitionEmpty
; 
1387     definition
.className 
= "Type"; 
1388     definition
.staticValues 
= Type_staticValues
; 
1389     definition
.staticFunctions 
= Type_staticFunctions
; 
1390     definition
.callAsFunction 
= &Type_callAsFunction
; 
1391     definition
.callAsConstructor 
= &Type_callAsConstructor
; 
1392     definition
.finalize 
= &CYFinalize
; 
1393     Type_privateData::Class_ 
= JSClassCreate(&definition
); 
1395     definition 
= kJSClassDefinitionEmpty
; 
1396     definition
.className 
= "Global"; 
1397     //definition.getProperty = &Global_getProperty; 
1398     Global_ 
= JSClassCreate(&definition
); 
1400     Array_s 
= JSStringCreateWithUTF8CString("Array"); 
1401     cy_s 
= JSStringCreateWithUTF8CString("$cy"); 
1402     length_s 
= JSStringCreateWithUTF8CString("length"); 
1403     message_s 
= JSStringCreateWithUTF8CString("message"); 
1404     name_s 
= JSStringCreateWithUTF8CString("name"); 
1405     pop_s 
= JSStringCreateWithUTF8CString("pop"); 
1406     prototype_s 
= JSStringCreateWithUTF8CString("prototype"); 
1407     push_s 
= JSStringCreateWithUTF8CString("push"); 
1408     splice_s 
= JSStringCreateWithUTF8CString("splice"); 
1409     toCYON_s 
= JSStringCreateWithUTF8CString("toCYON"); 
1410     toJSON_s 
= JSStringCreateWithUTF8CString("toJSON"); 
1411     toPointer_s 
= JSStringCreateWithUTF8CString("toPointer"); 
1412     toString_s 
= JSStringCreateWithUTF8CString("toString"); 
1414     Result_ 
= JSStringCreateWithUTF8CString("_"); 
1416     if (hooks_ 
!= NULL 
&& hooks_
->Initialize 
!= NULL
) 
1417         (*hooks_
->Initialize
)(); 
1420 void CYThrow(JSContextRef context
, JSValueRef value
) { 
1422         throw CYJSError(context
, value
); 
1425 const char *CYJSError::PoolCString(CYPool 
&pool
) const { 
1426     // XXX: this used to be CYPoolCString 
1427     return CYPoolCCYON(pool
, context_
, value_
); 
1430 JSValueRef 
CYJSError::CastJSValue(JSContextRef context
) const { 
1431     // XXX: what if the context is different? 
1435 JSValueRef 
CYCastJSError(JSContextRef context
, const char *message
) { 
1436     JSObjectRef 
Error(CYGetCachedObject(context
, CYJSString("Error"))); 
1438     JSValueRef arguments
[1] = {CYCastJSValue(context
, message
)}; 
1440     JSValueRef 
exception(NULL
); 
1441     JSValueRef 
value(JSObjectCallAsConstructor(context
, Error
, 1, arguments
, &exception
)); 
1442     CYThrow(context
, exception
); 
1447 JSValueRef 
CYPoolError::CastJSValue(JSContextRef context
) const { 
1448     return CYCastJSError(context
, message_
); 
1451 CYJSError::CYJSError(JSContextRef context
, const char *format
, ...) { 
1452     _assert(context 
!= NULL
); 
1457     va_start(args
, format
); 
1458     // XXX: there might be a beter way to think about this 
1459     const char *message(pool
.vsprintf(64, format
, args
)); 
1462     value_ 
= CYCastJSError(context
, message
); 
1465 JSGlobalContextRef 
CYGetJSContext(JSContextRef context
) { 
1466     return reinterpret_cast<Context 
*>(JSObjectGetPrivate(CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
))))->context_
; 
1469 extern "C" void CYSetupContext(JSGlobalContextRef context
) { 
1470     JSValueRef 
exception(NULL
); 
1472     CYInitializeDynamic(); 
1474     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1476     JSObjectRef 
cy(JSObjectMake(context
, Context_
, new Context(context
))); 
1477     CYSetProperty(context
, global
, cy_s
, cy
, kJSPropertyAttributeDontEnum
); 
1479 /* Cache Globals {{{ */ 
1480     JSObjectRef 
Array(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Array")))); 
1481     CYSetProperty(context
, cy
, CYJSString("Array"), Array
); 
1483     JSObjectRef 
Array_prototype(CYCastJSObject(context
, CYGetProperty(context
, Array
, prototype_s
))); 
1484     CYSetProperty(context
, cy
, CYJSString("Array_prototype"), Array_prototype
); 
1486     JSObjectRef 
Error(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Error")))); 
1487     CYSetProperty(context
, cy
, CYJSString("Error"), Error
); 
1489     JSObjectRef 
Function(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Function")))); 
1490     CYSetProperty(context
, cy
, CYJSString("Function"), Function
); 
1492     JSObjectRef 
Function_prototype(CYCastJSObject(context
, CYGetProperty(context
, Function
, prototype_s
))); 
1493     CYSetProperty(context
, cy
, CYJSString("Function_prototype"), Function_prototype
); 
1495     JSObjectRef 
Object(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Object")))); 
1496     CYSetProperty(context
, cy
, CYJSString("Object"), Object
); 
1498     JSObjectRef 
Object_prototype(CYCastJSObject(context
, CYGetProperty(context
, Object
, prototype_s
))); 
1499     CYSetProperty(context
, cy
, CYJSString("Object_prototype"), Object_prototype
); 
1501     JSObjectRef 
String(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("String")))); 
1502     CYSetProperty(context
, cy
, CYJSString("String"), String
); 
1504     JSObjectRef 
String_prototype(CYCastJSObject(context
, CYGetProperty(context
, String
, prototype_s
))); 
1505     CYSetProperty(context
, cy
, CYJSString("String_prototype"), String_prototype
); 
1508     CYSetProperty(context
, Array_prototype
, toCYON_s
, &Array_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
1509     CYSetProperty(context
, String_prototype
, toCYON_s
, &String_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
1511     JSObjectRef 
cycript(JSObjectMake(context
, NULL
, NULL
)); 
1512     CYSetProperty(context
, global
, CYJSString("Cycript"), cycript
); 
1513     CYSetProperty(context
, cycript
, CYJSString("gc"), &Cycript_gc_callAsFunction
); 
1515     JSObjectRef 
Functor(JSObjectMakeConstructor(context
, Functor_
, &Functor_new
)); 
1516     JSObjectSetPrototype(context
, CYCastJSObject(context
, CYGetProperty(context
, Functor
, prototype_s
)), Function_prototype
); 
1517     CYSetProperty(context
, cycript
, CYJSString("Functor"), Functor
); 
1519     CYSetProperty(context
, cycript
, CYJSString("Pointer"), JSObjectMakeConstructor(context
, Pointer_
, &Pointer_new
)); 
1520     CYSetProperty(context
, cycript
, CYJSString("Type"), JSObjectMakeConstructor(context
, Type_privateData::Class_
, &Type_new
)); 
1522     JSObjectRef 
all(JSObjectMake(context
, All_
, NULL
)); 
1523     CYSetProperty(context
, cycript
, CYJSString("all"), all
); 
1525     JSObjectRef 
alls(JSObjectCallAsConstructor(context
, Array
, 0, NULL
, &exception
)); 
1526     CYThrow(context
, exception
); 
1527     CYSetProperty(context
, cycript
, CYJSString("alls"), alls
); 
1530         JSObjectRef 
last(NULL
), curr(global
); 
1532         goto next
; for (JSValueRef next
;;) { 
1533             if (JSValueIsNull(context
, next
)) 
1536             curr 
= CYCastJSObject(context
, next
); 
1538             next 
= JSObjectGetPrototype(context
, curr
); 
1541         JSObjectSetPrototype(context
, last
, all
); 
1544     CYSetProperty(context
, global
, CYJSString("$cyq"), &$cyq
, kJSPropertyAttributeDontEnum
); 
1546     JSObjectRef 
System(JSObjectMake(context
, NULL
, NULL
)); 
1547     CYSetProperty(context
, cy
, CYJSString("System"), System
); 
1549     CYSetProperty(context
, global
, CYJSString("system"), System
); 
1550     CYSetProperty(context
, System
, CYJSString("args"), CYJSNull(context
)); 
1551     //CYSetProperty(context, System, CYJSString("global"), global); 
1552     CYSetProperty(context
, System
, CYJSString("print"), &System_print
); 
1554     if (CYBridgeEntry 
*entry 
= CYBridgeHash("1dlerror", 8)) 
1555         entry
->cache_ 
= new cy::Functor(entry
->value_
, reinterpret_cast<void (*)()>(&dlerror
)); 
1557     if (hooks_ 
!= NULL 
&& hooks_
->SetupContext 
!= NULL
) 
1558         (*hooks_
->SetupContext
)(context
); 
1560     CYArrayPush(context
, alls
, cycript
); 
1563 JSGlobalContextRef 
CYGetJSContext() { 
1564     CYInitializeDynamic(); 
1566     static JSGlobalContextRef context_
; 
1568     if (context_ 
== NULL
) { 
1569         context_ 
= JSGlobalContextCreate(Global_
); 
1570         CYSetupContext(context_
);