1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2015  Jay Freeman (saurik) 
   5 /* GNU Affero General Public License, Version 3 {{{ */ 
   7  * This program is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU Affero General Public License as published by 
   9  * the Free Software Foundation, either version 3 of the License, or 
  10  * (at your option) any later version. 
  12  * This program is distributed in the hope that it will be useful, 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU Affero General Public License for more details. 
  17  * You should have received a copy of the GNU Affero General Public License 
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  22 #include "cycript.hpp" 
  39 #include "sig/parse.hpp" 
  40 #include "sig/ffi_type.hpp" 
  45 #include "Execute.hpp" 
  46 #include "Internal.hpp" 
  47 #include "JavaScript.hpp" 
  48 #include "Pooling.hpp" 
  51 static std::vector
<CYHook 
*> &GetHooks() { 
  52     static std::vector
<CYHook 
*> hooks
; 
  56 CYRegisterHook::CYRegisterHook(CYHook 
*hook
) { 
  57     GetHooks().push_back(hook
); 
  60 /* JavaScript Properties {{{ */ 
  61 bool CYHasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
) { 
  62     return JSObjectHasProperty(context
, object
, name
); 
  65 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, size_t index
) { 
  66     return _jsccall(JSObjectGetPropertyAtIndex
, context
, object
, index
); 
  69 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
) { 
  70     return _jsccall(JSObjectGetProperty
, context
, object
, name
); 
  73 void CYSetProperty(JSContextRef context
, JSObjectRef object
, size_t index
, JSValueRef value
) { 
  74     _jsccall(JSObjectSetPropertyAtIndex
, context
, object
, index
, value
); 
  77 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef value
, JSPropertyAttributes attributes
) { 
  78     _jsccall(JSObjectSetProperty
, context
, object
, name
, value
, attributes
); 
  81 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef (*callback
)(JSContextRef
, JSObjectRef
, JSObjectRef
, size_t, const JSValueRef
[], JSValueRef 
*), JSPropertyAttributes attributes
) { 
  82     CYSetProperty(context
, object
, name
, JSObjectMakeFunctionWithCallback(context
, name
, callback
), attributes
); 
  85 void CYSetPrototype(JSContextRef context
, JSObjectRef object
, JSValueRef value
) { 
  86     JSObjectSetPrototype(context
, object
, value
); 
  87     _assert(CYIsStrictEqual(context
, JSObjectGetPrototype(context
, object
), value
)); 
  90 /* JavaScript Strings {{{ */ 
  91 JSStringRef 
CYCopyJSString(const char *value
) { 
  92     return value 
== NULL 
? NULL 
: JSStringCreateWithUTF8CString(value
); 
  95 JSStringRef 
CYCopyJSString(JSStringRef value
) { 
  96     return value 
== NULL 
? NULL 
: JSStringRetain(value
); 
  99 JSStringRef 
CYCopyJSString(CYUTF8String value
) { 
 100     // XXX: this is very wrong; it needs to convert to UTF16 and then create from there 
 101     return CYCopyJSString(value
.data
); 
 104 JSStringRef 
CYCopyJSString(JSContextRef context
, JSValueRef value
) { 
 105     if (JSValueIsNull(context
, value
)) 
 107     return _jsccall(JSValueToStringCopy
, context
, value
); 
 110 static CYUTF16String 
CYCastUTF16String(JSStringRef value
) { 
 111     return CYUTF16String(JSStringGetCharactersPtr(value
), JSStringGetLength(value
)); 
 114 CYUTF8String 
CYPoolUTF8String(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 115     return CYPoolUTF8String(pool
, CYCastUTF16String(value
)); 
 118 const char *CYPoolCString(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 119     CYUTF8String 
utf8(CYPoolUTF8String(pool
, context
, value
)); 
 120     _assert(memchr(utf8
.data
, '\0', utf8
.size
) == NULL
); 
 124 const char *CYPoolCString(CYPool 
&pool
, JSContextRef context
, JSValueRef value
) { 
 125     return JSValueIsNull(context
, value
) ? NULL 
: CYPoolCString(pool
, context
, CYJSString(context
, value
)); 
 128 /* Index Offsets {{{ */ 
 129 size_t CYGetIndex(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 130     return CYGetIndex(CYPoolUTF8String(pool
, context
, value
)); 
 134 static JSClassRef All_
; 
 135 static JSClassRef Context_
; 
 137 static JSClassRef Global_
; 
 138 static JSClassRef Pointer_
; 
 139 static JSClassRef Struct_
; 
 144 JSStringRef length_s
; 
 145 JSStringRef message_s
; 
 148 JSStringRef prototype_s
; 
 150 JSStringRef splice_s
; 
 151 JSStringRef toCYON_s
; 
 152 JSStringRef toJSON_s
; 
 153 JSStringRef toPointer_s
; 
 154 JSStringRef toString_s
; 
 157 static JSStringRef Result_
; 
 159 void CYFinalize(JSObjectRef object
) { 
 160     CYData 
*internal(reinterpret_cast<CYData 
*>(JSObjectGetPrivate(object
))); 
 161     _assert(internal
->count_ 
!= _not(unsigned)); 
 162     if (--internal
->count_ 
== 0) 
 166 void Structor_(CYPool 
&pool
, sig::Type 
*&type
) { 
 168         type
->primitive 
== sig::pointer_P 
&& 
 169         type
->data
.data
.type
->primitive 
== sig::struct_P 
&& 
 170         type
->data
.data
.type
->name 
!= NULL 
&& 
 171         strcmp(type
->data
.data
.type
->name
, "_objc_class") == 0 
 173         type
->primitive 
= sig::typename_P
; 
 174         type
->data
.data
.type 
= NULL
; 
 178     if (type
->primitive 
!= sig::struct_P 
|| type
->name 
== NULL
) 
 181     size_t length(strlen(type
->name
)); 
 182     char keyed
[length 
+ 2]; 
 183     memcpy(keyed 
+ 1, type
->name
, length 
+ 1); 
 185     static const char *modes 
= "34"; 
 186     for (size_t i(0); i 
!= 2; ++i
) { 
 190         if (CYBridgeEntry 
*entry 
= CYBridgeHash(keyed
, length 
+ 1)) 
 193                     sig::Parse(pool
, &type
->data
.signature
, entry
->value_
, &Structor_
); 
 197                     sig::Signature signature
; 
 198                     sig::Parse(pool
, &signature
, entry
->value_
, &Structor_
); 
 199                     type 
= signature
.elements
[0].type
; 
 205 JSClassRef 
Type_privateData::Class_
; 
 210     JSGlobalContextRef context_
; 
 212     Context(JSGlobalContextRef context
) : 
 221     Type_privateData 
*type_
; 
 224     Pointer(void *value
, JSContextRef context
, JSObjectRef owner
, size_t length
, sig::Type 
*type
) : 
 225         CYOwned(value
, context
, owner
), 
 226         type_(new(*pool_
) Type_privateData(type
)), 
 232 struct Struct_privateData 
: 
 235     Type_privateData 
*type_
; 
 237     Struct_privateData(JSContextRef context
, JSObjectRef owner
) : 
 238         CYOwned(NULL
, context
, owner
) 
 243 JSObjectRef 
CYMakeStruct(JSContextRef context
, void *data
, sig::Type 
*type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 244     Struct_privateData 
*internal(new Struct_privateData(context
, owner
)); 
 245     CYPool 
&pool(*internal
->pool_
); 
 246     Type_privateData 
*typical(new(pool
) Type_privateData(type
, ffi
)); 
 247     internal
->type_ 
= typical
; 
 250         internal
->value_ 
= data
; 
 252         size_t size(typical
->GetFFI()->size
); 
 253         void *copy(internal
->pool_
->malloc
<void>(size
)); 
 254         memcpy(copy
, data
, size
); 
 255         internal
->value_ 
= copy
; 
 258     return JSObjectMake(context
, Struct_
, internal
); 
 261 static void *CYCastSymbol(const char *name
) { 
 262     for (CYHook 
*hook 
: GetHooks()) 
 263         if (hook
->CastSymbol 
!= NULL
) 
 264             if (void *value 
= (*hook
->CastSymbol
)(name
)) 
 266     return dlsym(RTLD_DEFAULT
, name
); 
 269 JSValueRef 
CYCastJSValue(JSContextRef context
, bool value
) { 
 270     return JSValueMakeBoolean(context
, value
); 
 273 JSValueRef 
CYCastJSValue(JSContextRef context
, double value
) { 
 274     return JSValueMakeNumber(context
, value
); 
 277 #define CYCastJSValue_(Type_) \ 
 278     JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \ 
 279         return JSValueMakeNumber(context, static_cast<double>(value)); \ 
 283 CYCastJSValue_(unsigned int) 
 284 CYCastJSValue_(long int) 
 285 CYCastJSValue_(long unsigned int) 
 286 CYCastJSValue_(long long int) 
 287 CYCastJSValue_(long long unsigned int) 
 289 JSValueRef 
CYJSUndefined(JSContextRef context
) { 
 290     return JSValueMakeUndefined(context
); 
 293 double CYCastDouble(JSContextRef context
, JSValueRef value
) { 
 294     return _jsccall(JSValueToNumber
, context
, value
); 
 297 bool CYCastBool(JSContextRef context
, JSValueRef value
) { 
 298     return JSValueToBoolean(context
, value
); 
 301 JSValueRef 
CYJSNull(JSContextRef context
) { 
 302     return JSValueMakeNull(context
); 
 305 JSValueRef 
CYCastJSValue(JSContextRef context
, JSStringRef value
) { 
 306     return value 
== NULL 
? CYJSNull(context
) : JSValueMakeString(context
, value
); 
 309 JSValueRef 
CYCastJSValue(JSContextRef context
, const char *value
) { 
 310     return CYCastJSValue(context
, CYJSString(value
)); 
 313 JSObjectRef 
CYCastJSObject(JSContextRef context
, JSValueRef value
) { 
 314     return _jsccall(JSValueToObject
, context
, value
); 
 317 JSValueRef 
CYCallAsFunction(JSContextRef context
, JSObjectRef function
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[]) { 
 318     return _jsccall(JSObjectCallAsFunction
, context
, function
, _this
, count
, arguments
); 
 321 bool CYIsCallable(JSContextRef context
, JSValueRef value
) { 
 322     return value 
!= NULL 
&& JSValueIsObject(context
, value
) && JSObjectIsFunction(context
, (JSObjectRef
) value
); 
 325 bool CYIsEqual(JSContextRef context
, JSValueRef lhs
, JSValueRef rhs
) { 
 326     return _jsccall(JSValueIsEqual
, context
, lhs
, rhs
); 
 329 bool CYIsStrictEqual(JSContextRef context
, JSValueRef lhs
, JSValueRef rhs
) { 
 330     return JSValueIsStrictEqual(context
, lhs
, rhs
); 
 333 size_t CYArrayLength(JSContextRef context
, JSObjectRef array
) { 
 334     return CYCastDouble(context
, CYGetProperty(context
, array
, length_s
)); 
 337 JSValueRef 
CYArrayGet(JSContextRef context
, JSObjectRef array
, size_t index
) { 
 338     return _jsccall(JSObjectGetPropertyAtIndex
, context
, array
, index
); 
 341 void CYArrayPush(JSContextRef context
, JSObjectRef array
, JSValueRef value
) { 
 342     JSValueRef arguments
[1]; 
 343     arguments
[0] = value
; 
 344     JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array_prototype"))); 
 345     _jsccall(JSObjectCallAsFunction
, context
, CYCastJSObject(context
, CYGetProperty(context
, Array
, push_s
)), array
, 1, arguments
); 
 348 static JSValueRef 
System_print(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 353         printf("%s\n", CYPoolCString(pool
, context
, arguments
[0])); 
 356     return CYJSUndefined(context
); 
 359 static void (*JSSynchronousGarbageCollectForDebugging$
)(JSContextRef
); 
 361 _visible 
void CYGarbageCollect(JSContextRef context
) { 
 362     (JSSynchronousGarbageCollectForDebugging$ 
?: &JSGarbageCollect
)(context
); 
 365 static JSValueRef 
Cycript_compile_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 367     std::stringstream 
value(CYPoolCString(pool
, context
, arguments
[0])); 
 368     CYUTF8String 
code(CYPoolCode(pool
, value
)); 
 369     return CYCastJSValue(context
, CYJSString(code
)); 
 370 } CYCatch_(NULL
, "SyntaxError") } 
 372 static JSValueRef 
Cycript_gc_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 373     CYGarbageCollect(context
); 
 374     return CYJSUndefined(context
); 
 377 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, std::set
<void *> &objects
, JSValueRef 
*exception
) { CYTry 
{ 
 378     switch (JSType type 
= JSValueGetType(context
, value
)) { 
 379         case kJSTypeUndefined
: 
 384             return CYCastBool(context
, value
) ? "true" : "false"; 
 386         case kJSTypeNumber
: { 
 387             std::ostringstream str
; 
 388             CYNumerify(str
, CYCastDouble(context
, value
)); 
 389             std::string 
value(str
.str()); 
 390             return pool
.strmemdup(value
.c_str(), value
.size()); 
 393         case kJSTypeString
: { 
 394             std::ostringstream str
; 
 395             CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, value
))); 
 396             CYStringify(str
, string
.data
, string
.size
); 
 397             std::string 
value(str
.str()); 
 398             return pool
.strmemdup(value
.c_str(), value
.size()); 
 402             return CYPoolCCYON(pool
, context
, (JSObjectRef
) value
, objects
); 
 404             throw CYJSError(context
, "JSValueGetType() == 0x%x", type
); 
 408 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, std::set
<void *> &objects
) { 
 409     return _jsccall(CYPoolCCYON
, pool
, context
, value
, objects
); 
 412 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, std::set
<void *> *objects
) { 
 414         return CYPoolCCYON(pool
, context
, value
, *objects
); 
 416         std::set
<void *> objects
; 
 417         return CYPoolCCYON(pool
, context
, value
, objects
); 
 421 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSObjectRef object
, std::set
<void *> &objects
) { 
 422     JSValueRef 
toCYON(CYGetProperty(context
, object
, toCYON_s
)); 
 423     if (CYIsCallable(context
, toCYON
)) { 
 424         // XXX: this needs to be abstracted behind some kind of function 
 425         JSValueRef arguments
[1] = {CYCastJSValue(context
, reinterpret_cast<uintptr_t>(&objects
))}; 
 426         JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toCYON
, object
, 1, arguments
)); 
 427         _assert(value 
!= NULL
); 
 428         return CYPoolCString(pool
, context
, value
); 
 431     JSValueRef 
toJSON(CYGetProperty(context
, object
, toJSON_s
)); 
 432     if (CYIsCallable(context
, toJSON
)) { 
 433         JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 434         return _jsccall(CYPoolCCYON
, pool
, context
, CYCallAsFunction(context
, (JSObjectRef
) toJSON
, object
, 1, arguments
), objects
); 
 437     if (JSObjectIsFunction(context
, object
)) { 
 438         JSValueRef 
toString(CYGetProperty(context
, object
, toString_s
)); 
 439         if (CYIsCallable(context
, toString
)) { 
 440             JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 441             JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toString
, object
, 1, arguments
)); 
 442             _assert(value 
!= NULL
); 
 443             return CYPoolCString(pool
, context
, value
); 
 447     _assert(objects
.insert(object
).second
); 
 449     std::ostringstream str
; 
 453     // XXX: this is, sadly, going to leak 
 454     JSPropertyNameArrayRef 
names(JSObjectCopyPropertyNames(context
, object
)); 
 458     for (size_t index(0), count(JSPropertyNameArrayGetCount(names
)); index 
!= count
; ++index
) { 
 464         JSStringRef 
name(JSPropertyNameArrayGetNameAtIndex(names
, index
)); 
 465         CYUTF8String 
string(CYPoolUTF8String(pool
, context
, name
)); 
 470             CYStringify(str
, string
.data
, string
.size
); 
 475             JSValueRef 
value(CYGetProperty(context
, object
, name
)); 
 476             str 
<< CYPoolCCYON(pool
, context
, value
, objects
); 
 477         } catch (const CYException 
&error
) { 
 482     JSPropertyNameArrayRelease(names
); 
 486     std::string 
string(str
.str()); 
 487     return pool
.strmemdup(string
.c_str(), string
.size()); 
 490 std::set
<void *> *CYCastObjects(JSContextRef context
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[]) { 
 493     return CYCastPointer
<std::set
<void *> *>(context
, arguments
[0]); 
 496 static JSValueRef 
Array_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 497     std::set
<void *> *objects(CYCastObjects(context
, _this
, count
, arguments
)); 
 498     // XXX: this is horribly inefficient 
 499     std::set
<void *> backup
; 
 504     std::ostringstream str
; 
 508     JSValueRef 
length(CYGetProperty(context
, _this
, length_s
)); 
 511     for (size_t index(0), count(CYCastDouble(context
, length
)); index 
!= count
; ++index
) { 
 518             JSValueRef 
value(CYGetProperty(context
, _this
, index
)); 
 519             if (!JSValueIsUndefined(context
, value
)) 
 520                 str 
<< CYPoolCCYON(pool
, context
, value
, *objects
); 
 525         } catch (const CYException 
&error
) { 
 532     std::string 
value(str
.str()); 
 533     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 536 static JSValueRef 
Error_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 538     std::ostringstream str
; 
 540     str 
<< "new " << CYPoolUTF8String(pool
, context
, CYJSString(context
, CYGetProperty(context
, _this
, name_s
))) << "("; 
 542     CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, CYGetProperty(context
, _this
, message_s
)))); 
 543     CYStringify(str
, string
.data
, string
.size
); 
 547     std::string 
value(str
.str()); 
 548     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 551 static JSValueRef 
String_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 553     std::ostringstream str
; 
 555     CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, _this
))); 
 556     CYStringify(str
, string
.data
, string
.size
); 
 558     std::string 
value(str
.str()); 
 559     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 562 JSObjectRef 
CYMakePointer(JSContextRef context
, void *pointer
, size_t length
, sig::Type 
*type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 563     Pointer 
*internal(new Pointer(pointer
, context
, owner
, length
, type
)); 
 564     return JSObjectMake(context
, Pointer_
, internal
); 
 567 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, void (*function
)(), const sig::Signature 
&signature
) { 
 568     return JSObjectMake(context
, Functor_
, new cy::Functor(signature
, function
)); 
 571 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, const char *symbol
, const char *encoding
, void **cache
) { 
 572     cy::Functor 
*internal
; 
 574         internal 
= reinterpret_cast<cy::Functor 
*>(*cache
); 
 576         void (*function
)()(reinterpret_cast<void (*)()>(CYCastSymbol(symbol
))); 
 577         if (function 
== NULL
) 
 580         internal 
= new cy::Functor(encoding
, function
); 
 585     return JSObjectMake(context
, Functor_
, internal
); 
 588 static bool CYGetOffset(CYPool 
&pool
, JSContextRef context
, JSStringRef value
, ssize_t 
&index
) { 
 589     return CYGetOffset(CYPoolCString(pool
, context
, value
), index
); 
 592 void *CYCastPointer_(JSContextRef context
, JSValueRef value
) { 
 595     else switch (JSValueGetType(context
, value
)) { 
 598         case kJSTypeObject
: { 
 599             JSObjectRef 
object((JSObjectRef
) value
); 
 600             if (JSValueIsObjectOfClass(context
, value
, Pointer_
)) { 
 601                 Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 602                 return internal
->value_
; 
 604             JSValueRef 
toPointer(CYGetProperty(context
, object
, toPointer_s
)); 
 605             if (CYIsCallable(context
, toPointer
)) { 
 606                 JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toPointer
, object
, 0, NULL
)); 
 607                 _assert(value 
!= NULL
); 
 608                 return CYCastPointer_(context
, value
); 
 611             double number(CYCastDouble(context
, value
)); 
 612             if (std::isnan(number
)) 
 613                 throw CYJSError(context
, "cannot convert value to pointer"); 
 614             return reinterpret_cast<void *>(static_cast<uintptr_t>(static_cast<long long>(number
))); 
 618 void CYPoolFFI(CYPool 
*pool
, JSContextRef context
, sig::Type 
*type
, ffi_type 
*ffi
, void *data
, JSValueRef value
) { 
 619     switch (type
->primitive
) { 
 621             *reinterpret_cast<bool *>(data
) = JSValueToBoolean(context
, value
); 
 624 #define CYPoolFFI_(primitive, native) \ 
 625         case sig::primitive ## _P: \ 
 626             *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \ 
 629         CYPoolFFI_(uchar
, unsigned char) 
 630         CYPoolFFI_(char, char) 
 631         CYPoolFFI_(ushort
, unsigned short) 
 632         CYPoolFFI_(short, short) 
 633         CYPoolFFI_(ulong
, unsigned long) 
 634         CYPoolFFI_(long, long) 
 635         CYPoolFFI_(uint
, unsigned int) 
 637         CYPoolFFI_(ulonglong
, unsigned long long) 
 638         CYPoolFFI_(longlong
, long long) 
 639         CYPoolFFI_(float, float) 
 640         CYPoolFFI_(double, double) 
 643             uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 644             JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 645             for (size_t index(0); index 
!= type
->data
.data
.size
; ++index
) { 
 646                 ffi_type 
*field(ffi
->elements
[index
]); 
 649                 if (aggregate 
== NULL
) 
 652                     rhs 
= CYGetProperty(context
, aggregate
, index
); 
 653                     if (JSValueIsUndefined(context
, rhs
)) 
 654                         throw CYJSError(context
, "unable to extract array value"); 
 657                 CYPoolFFI(pool
, context
, type
->data
.data
.type
, field
, base
, rhs
); 
 664             *reinterpret_cast<void **>(data
) = CYCastPointer
<void *>(context
, value
); 
 668             _assert(pool 
!= NULL
); 
 669             *reinterpret_cast<const char **>(data
) = CYPoolCString(*pool
, context
, value
); 
 672         case sig::struct_P
: { 
 673             uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 674             JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 675             for (size_t index(0); index 
!= type
->data
.signature
.count
; ++index
) { 
 676                 sig::Element 
*element(&type
->data
.signature
.elements
[index
]); 
 677                 ffi_type 
*field(ffi
->elements
[index
]); 
 680                 if (aggregate 
== NULL
) 
 683                     rhs 
= CYGetProperty(context
, aggregate
, index
); 
 684                     if (JSValueIsUndefined(context
, rhs
)) { 
 685                         if (element
->name 
!= NULL
) 
 686                             rhs 
= CYGetProperty(context
, aggregate
, CYJSString(element
->name
)); 
 689                         if (JSValueIsUndefined(context
, rhs
)) undefined
: 
 690                             throw CYJSError(context
, "unable to extract structure value"); 
 694                 CYPoolFFI(pool
, context
, element
->type
, field
, base
, rhs
); 
 704             for (CYHook 
*hook 
: GetHooks()) 
 705                 if (hook
->PoolFFI 
!= NULL
) 
 706                     if ((*hook
->PoolFFI
)(pool
, context
, type
, ffi
, data
, value
)) 
 709             CYThrow("unimplemented signature code: '%c''\n", type
->primitive
); 
 713 JSValueRef 
CYFromFFI(JSContextRef context
, sig::Type 
*type
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) { 
 714     switch (type
->primitive
) { 
 716             return CYCastJSValue(context
, *reinterpret_cast<bool *>(data
)); 
 718 #define CYFromFFI_(primitive, native) \ 
 719         case sig::primitive ## _P: \ 
 720             return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \ 
 722         CYFromFFI_(uchar, unsigned char) 
 723         CYFromFFI_(char, char) 
 724         CYFromFFI_(ushort
, unsigned short) 
 725         CYFromFFI_(short, short) 
 726         CYFromFFI_(ulong
, unsigned long) 
 727         CYFromFFI_(long, long) 
 728         CYFromFFI_(uint
, unsigned int) 
 730         CYFromFFI_(ulonglong
, unsigned long long) 
 731         CYFromFFI_(longlong
, long long) 
 732         CYFromFFI_(float, float) 
 733         CYFromFFI_(double, double) 
 736             if (void *pointer 
= data
) 
 737                 return CYMakePointer(context
, pointer
, type
->data
.data
.size
, type
->data
.data
.type
, NULL
, owner
); 
 741             if (void *pointer 
= *reinterpret_cast<void **>(data
)) 
 742                 return CYMakePointer(context
, pointer
, _not(size_t), type
->data
.data
.type
, NULL
, owner
); 
 746             if (char *utf8 
= *reinterpret_cast<char **>(data
)) 
 747                 return CYCastJSValue(context
, utf8
); 
 751             return CYMakeStruct(context
, data
, type
, ffi
, owner
); 
 753             return CYJSUndefined(context
); 
 756             return CYJSNull(context
); 
 758             for (CYHook 
*hook 
: GetHooks()) 
 759                 if (hook
->FromFFI 
!= NULL
) 
 760                     if (JSValueRef value 
= (*hook
->FromFFI
)(context
, type
, ffi
, data
, initialize
, owner
)) 
 763             CYThrow("unimplemented signature code: '%c''\n", type
->primitive
); 
 767 void CYExecuteClosure(ffi_cif 
*cif
, void *result
, void **arguments
, void *arg
) { 
 768     Closure_privateData 
*internal(reinterpret_cast<Closure_privateData 
*>(arg
)); 
 770     JSContextRef 
context(internal
->context_
); 
 772     size_t count(internal
->cif_
.nargs
); 
 773     JSValueRef values
[count
]; 
 775     for (size_t index(0); index 
!= count
; ++index
) 
 776         values
[index
] = CYFromFFI(context
, internal
->signature_
.elements
[1 + index
].type
, internal
->cif_
.arg_types
[index
], arguments
[index
]); 
 778     JSValueRef 
value(internal
->adapter_(context
, count
, values
, internal
->function_
)); 
 779     CYPoolFFI(NULL
, context
, internal
->signature_
.elements
[0].type
, internal
->cif_
.rtype
, result
, value
); 
 782 static JSValueRef 
FunctionAdapter_(JSContextRef context
, size_t count
, JSValueRef values
[], JSObjectRef function
) { 
 783     return CYCallAsFunction(context
, function
, NULL
, count
, values
); 
 786 Closure_privateData 
*CYMakeFunctor_(JSContextRef context
, JSObjectRef function
, const sig::Signature 
&signature
, JSValueRef (*adapter
)(JSContextRef
, size_t, JSValueRef
[], JSObjectRef
)) { 
 787     // XXX: in case of exceptions this will leak 
 788     // XXX: in point of fact, this may /need/ to leak :( 
 789     Closure_privateData 
*internal(new Closure_privateData(context
, function
, adapter
, signature
)); 
 791 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 
 793     ffi_closure 
*writable(reinterpret_cast<ffi_closure 
*>(ffi_closure_alloc(sizeof(ffi_closure
), &executable
))); 
 795     ffi_status 
status(ffi_prep_closure_loc(writable
, &internal
->cif_
, &CYExecuteClosure
, internal
, executable
)); 
 796     _assert(status 
== FFI_OK
); 
 798     internal
->value_ 
= executable
; 
 800     ffi_closure 
*closure((ffi_closure 
*) _syscall(mmap( 
 801         NULL
, sizeof(ffi_closure
), 
 802         PROT_READ 
| PROT_WRITE
, MAP_ANON 
| MAP_PRIVATE
, 
 806     ffi_status 
status(ffi_prep_closure(closure
, &internal
->cif_
, &CYExecuteClosure
, internal
)); 
 807     _assert(status 
== FFI_OK
); 
 809     _syscall(mprotect(closure
, sizeof(*closure
), PROT_READ 
| PROT_EXEC
)); 
 811     internal
->value_ 
= closure
; 
 817 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSObjectRef function
, const sig::Signature 
&signature
) { 
 818     Closure_privateData 
*internal(CYMakeFunctor_(context
, function
, signature
, &FunctionAdapter_
)); 
 819     JSObjectRef 
object(JSObjectMake(context
, Functor_
, internal
)); 
 820     // XXX: see above notes about needing to leak 
 821     JSValueProtect(CYGetJSContext(context
), object
); 
 825 JSValueRef 
CYGetCachedValue(JSContextRef context
, JSStringRef name
) { 
 826     return CYGetProperty(context
, CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
)), name
); 
 829 JSObjectRef 
CYGetCachedObject(JSContextRef context
, JSStringRef name
) { 
 830     return CYCastJSObject(context
, CYGetCachedValue(context
, name
)); 
 833 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSValueRef value
, const sig::Signature 
&signature
) { 
 834     JSObjectRef 
Function(CYGetCachedObject(context
, CYJSString("Function"))); 
 836     bool function(_jsccall(JSValueIsInstanceOfConstructor
, context
, value
, Function
)); 
 838         JSObjectRef 
function(CYCastJSObject(context
, value
)); 
 839         return CYMakeFunctor(context
, function
, signature
); 
 841         void (*function
)()(CYCastPointer
<void (*)()>(context
, value
)); 
 842         return CYMakeFunctor(context
, function
, signature
); 
 846 static bool Index_(CYPool 
&pool
, JSContextRef context
, Struct_privateData 
*internal
, JSStringRef property
, ssize_t 
&index
, uint8_t *&base
) { 
 847     Type_privateData 
*typical(internal
->type_
); 
 848     sig::Type 
*type(typical
->type_
); 
 852     const char *name(CYPoolCString(pool
, context
, property
)); 
 853     size_t length(strlen(name
)); 
 854     double number(CYCastDouble(name
, length
)); 
 856     size_t count(type
->data
.signature
.count
); 
 858     if (std::isnan(number
)) { 
 859         if (property 
== NULL
) 
 862         sig::Element 
*elements(type
->data
.signature
.elements
); 
 864         for (size_t local(0); local 
!= count
; ++local
) { 
 865             sig::Element 
*element(&elements
[local
]); 
 866             if (element
->name 
!= NULL 
&& strcmp(name
, element
->name
) == 0) { 
 874         index 
= static_cast<ssize_t
>(number
); 
 875         if (index 
!= number 
|| index 
< 0 || static_cast<size_t>(index
) >= count
) 
 880     ffi_type 
**elements(typical
->GetFFI()->elements
); 
 882     base 
= reinterpret_cast<uint8_t *>(internal
->value_
); 
 883     for (ssize_t 
local(0); local 
!= index
; ++local
) 
 884         base 
+= elements
[local
]->size
; 
 889 static JSValueRef 
Pointer_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 891     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 893     if (JSStringIsEqual(property
, length_s
)) 
 894         return internal
->length_ 
== _not(size_t) ? CYJSUndefined(context
) : CYCastJSValue(context
, internal
->length_
); 
 896     Type_privateData 
*typical(internal
->type_
); 
 897     if (typical
->type_ 
== NULL
) 
 899     sig::Type 
&type(*typical
->type_
); 
 902     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
 904     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
 907     if (type
.primitive 
== sig::function_P
) 
 908         return CYMakeFunctor(context
, reinterpret_cast<void (*)()>(internal
->value_
), type
.data
.signature
); 
 910     ffi_type 
*ffi(typical
->GetFFI()); 
 912     uint8_t *base(reinterpret_cast<uint8_t *>(internal
->value_
)); 
 913     base 
+= ffi
->size 
* offset
; 
 915     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
 916     return CYFromFFI(context
, &type
, ffi
, base
, false, owner
); 
 919 static bool Pointer_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 921     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 922     Type_privateData 
*typical(internal
->type_
); 
 924     if (typical
->type_ 
== NULL
) 
 928     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
 930     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
 933     ffi_type 
*ffi(typical
->GetFFI()); 
 935     uint8_t *base(reinterpret_cast<uint8_t *>(internal
->value_
)); 
 936     base 
+= ffi
->size 
* offset
; 
 938     CYPoolFFI(NULL
, context
, typical
->type_
, ffi
, base
, value
); 
 942 static JSValueRef Struct_callAsFunction_$
cya(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 943     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(_this
))); 
 944     Type_privateData 
*typical(internal
->type_
); 
 945     return CYMakePointer(context
, internal
->value_
, _not(size_t), typical
->type_
, typical
->ffi_
, _this
); 
 948 static JSValueRef 
Struct_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 950     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 951     Type_privateData 
*typical(internal
->type_
); 
 956     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
 959     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
 961     return CYFromFFI(context
, typical
->type_
->data
.signature
.elements
[index
].type
, typical
->GetFFI()->elements
[index
], base
, false, owner
); 
 964 static bool Struct_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 966     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 967     Type_privateData 
*typical(internal
->type_
); 
 972     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
 975     CYPoolFFI(NULL
, context
, typical
->type_
->data
.signature
.elements
[index
].type
, typical
->GetFFI()->elements
[index
], base
, value
); 
 979 static void Struct_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
 980     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 981     Type_privateData 
*typical(internal
->type_
); 
 982     sig::Type 
*type(typical
->type_
); 
 987     size_t count(type
->data
.signature
.count
); 
 988     sig::Element 
*elements(type
->data
.signature
.elements
); 
 992     for (size_t index(0); index 
!= count
; ++index
) { 
 994         name 
= elements
[index
].name
; 
 997             sprintf(number
, "%zu", index
); 
1001         JSPropertyNameAccumulatorAddName(names
, CYJSString(name
)); 
1005 void CYCallFunction(CYPool 
&pool
, JSContextRef context
, ffi_cif 
*cif
, void (*function
)(), void *value
, void **values
) { 
1006     ffi_call(cif
, function
, value
, values
); 
1009 JSValueRef 
CYCallFunction(CYPool 
&pool
, JSContextRef context
, size_t setups
, void *setup
[], size_t count
, const JSValueRef arguments
[], bool initialize
, sig::Signature 
*signature
, ffi_cif 
*cif
, void (*function
)()) { 
1010     if (setups 
+ count 
!= signature
->count 
- 1) 
1011         throw CYJSError(context
, "incorrect number of arguments to ffi function"); 
1013     size_t size(setups 
+ count
); 
1015     memcpy(values
, setup
, sizeof(void *) * setups
); 
1017     for (size_t index(setups
); index 
!= size
; ++index
) { 
1018         sig::Element 
*element(&signature
->elements
[index 
+ 1]); 
1019         ffi_type 
*ffi(cif
->arg_types
[index
]); 
1021         values
[index
] = new(pool
) uint8_t[ffi
->size
]; 
1022         CYPoolFFI(&pool
, context
, element
->type
, ffi
, values
[index
], arguments
[index 
- setups
]); 
1025     uint8_t value
[cif
->rtype
->size
]; 
1027     void (*call
)(CYPool 
&, JSContextRef
, ffi_cif 
*, void (*)(), void *, void **) = &CYCallFunction
; 
1028     // XXX: this only supports one hook, but it is a bad idea anyway 
1029     for (CYHook 
*hook 
: GetHooks()) 
1030         if (hook
->CallFunction 
!= NULL
) 
1031             call 
= hook
->CallFunction
; 
1033     call(pool
, context
, cif
, function
, value
, values
); 
1034     return CYFromFFI(context
, signature
->elements
[0].type
, cif
->rtype
, value
, initialize
); 
1037 static JSValueRef 
Functor_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1039     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(object
))); 
1040     return CYCallFunction(pool
, context
, 0, NULL
, count
, arguments
, false, &internal
->signature_
, &internal
->cif_
, internal
->GetValue()); 
1043 JSObjectRef 
CYMakeType(JSContextRef context
, const char *encoding
) { 
1044     Type_privateData 
*internal(new Type_privateData(encoding
)); 
1045     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
1048 JSObjectRef 
CYMakeType(JSContextRef context
, sig::Type 
*type
) { 
1049     Type_privateData 
*internal(new Type_privateData(type
)); 
1050     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
1053 JSObjectRef 
CYMakeType(JSContextRef context
, sig::Signature 
*signature
) { 
1060     type
.primitive 
= sig::function_P
; 
1061     sig::Copy(pool
, type
.data
.signature
, *signature
); 
1063     return CYMakeType(context
, &type
); 
1066 static bool All_hasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
) { 
1067     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1068     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1069     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1071     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1072         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) 
1073             if (CYHasProperty(context
, space
, property
)) 
1077     CYUTF8String 
name(CYPoolUTF8String(pool
, context
, property
)); 
1079     size_t length(name
.size
); 
1080     char keyed
[length 
+ 2]; 
1081     memcpy(keyed 
+ 1, name
.data
, length 
+ 1); 
1083     static const char *modes 
= "0124"; 
1084     for (size_t i(0); i 
!= 4; ++i
) { 
1085         keyed
[0] = modes
[i
]; 
1086         if (CYBridgeHash(keyed
, length 
+ 1) != NULL
) 
1093 static JSValueRef 
All_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1094     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1095     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1096     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1098     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1099         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) 
1100             if (JSValueRef value 
= CYGetProperty(context
, space
, property
)) 
1101                 if (!JSValueIsUndefined(context
, value
)) 
1105     CYUTF8String 
name(CYPoolUTF8String(pool
, context
, property
)); 
1107     size_t length(name
.size
); 
1108     char keyed
[length 
+ 2]; 
1109     memcpy(keyed 
+ 1, name
.data
, length 
+ 1); 
1111     static const char *modes 
= "0124"; 
1112     for (size_t i(0); i 
!= 4; ++i
) { 
1113         char mode(modes
[i
]); 
1116         if (CYBridgeEntry 
*entry 
= CYBridgeHash(keyed
, length 
+ 1)) 
1119                     return JSEvaluateScript(CYGetJSContext(context
), CYJSString(entry
->value_
), NULL
, NULL
, 0, NULL
); 
1122                     return CYMakeFunctor(context
, name
.data
, entry
->value_
, &entry
->cache_
); 
1125                     if (void *symbol 
= CYCastSymbol(name
.data
)) { 
1126                         // XXX: this is horrendously inefficient 
1127                         sig::Signature signature
; 
1128                         sig::Parse(pool
, &signature
, entry
->value_
, &Structor_
); 
1130                         sig::sig_ffi_cif(pool
, &sig::ObjectiveC
, &signature
, &cif
); 
1131                         return CYFromFFI(context
, signature
.elements
[0].type
, cif
.rtype
, symbol
); 
1134                 // XXX: implement case 3 
1136                     return CYMakeType(context
, entry
->value_
); 
1143 static void All_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
1144     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1145     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1146     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1148     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1149         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) { 
1150             JSPropertyNameArrayRef 
subset(JSObjectCopyPropertyNames(context
, space
)); 
1151             for (size_t index(0), count(JSPropertyNameArrayGetCount(subset
)); index 
!= count
; ++index
) 
1152                 JSPropertyNameAccumulatorAddName(names
, JSPropertyNameArrayGetNameAtIndex(subset
, index
)); 
1153             JSPropertyNameArrayRelease(subset
); 
1157 static JSObjectRef 
Pointer_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1159         throw CYJSError(context
, "incorrect number of arguments to Pointer constructor"); 
1163     void *value(CYCastPointer
<void *>(context
, arguments
[0])); 
1164     const char *type(CYPoolCString(pool
, context
, arguments
[1])); 
1166     sig::Signature signature
; 
1167     sig::Parse(pool
, &signature
, type
, &Structor_
); 
1169     return CYMakePointer(context
, value
, _not(size_t), signature
.elements
[0].type
, NULL
, NULL
); 
1172 static JSObjectRef 
Type_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1174         throw CYJSError(context
, "incorrect number of arguments to Type constructor"); 
1176     const char *type(CYPoolCString(pool
, context
, arguments
[0])); 
1177     return CYMakeType(context
, type
); 
1180 static JSValueRef Type_callAsFunction_$
With(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], sig::Primitive primitive
, JSValueRef 
*exception
) { CYTry 
{ 
1181     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1189     type
.primitive 
= primitive
; 
1190     type
.data
.signature
.elements 
= new(pool
) sig::Element
[1 + count
]; 
1191     type
.data
.signature
.count 
= 1 + count
; 
1193     type
.data
.signature
.elements
[0].name 
= NULL
; 
1194     type
.data
.signature
.elements
[0].type 
= internal
->type_
; 
1195     type
.data
.signature
.elements
[0].offset 
= _not(size_t); 
1197     for (size_t i(0); i 
!= count
; ++i
) { 
1198         sig::Element 
&element(type
.data
.signature
.elements
[i 
+ 1]); 
1199         element
.name 
= NULL
; 
1200         element
.offset 
= _not(size_t); 
1202         JSObjectRef 
object(CYCastJSObject(context
, arguments
[i
])); 
1203         _assert(JSValueIsObjectOfClass(context
, object
, Type_privateData::Class_
)); 
1204         Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1206         element
.type 
= internal
->type_
; 
1209     return CYMakeType(context
, &type
); 
1212 static JSValueRef 
Type_callAsFunction_arrayOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1214         throw CYJSError(context
, "incorrect number of arguments to Type.arrayOf"); 
1215     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1218     size_t index(CYGetIndex(pool
, context
, CYJSString(context
, arguments
[0]))); 
1219     if (index 
== _not(size_t)) 
1220         throw CYJSError(context
, "invalid array size used with Type.arrayOf"); 
1226     type
.primitive 
= sig::array_P
; 
1227     type
.data
.data
.type 
= internal
->type_
; 
1228     type
.data
.data
.size 
= index
; 
1230     return CYMakeType(context
, &type
); 
1233 static JSValueRef 
Type_callAsFunction_blockWith(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1234     return Type_callAsFunction_$
With(context
, object
, _this
, count
, arguments
, sig::block_P
, exception
); 
1237 static JSValueRef 
Type_callAsFunction_constant(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1239         throw CYJSError(context
, "incorrect number of arguments to Type.constant"); 
1240     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1242     sig::Type 
type(*internal
->type_
); 
1243     type
.flags 
|= JOC_TYPE_CONST
; 
1244     return CYMakeType(context
, &type
); 
1247 static JSValueRef 
Type_callAsFunction_long(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1249         throw CYJSError(context
, "incorrect number of arguments to Type.long"); 
1250     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1252     sig::Type 
type(*internal
->type_
); 
1254     switch (type
.primitive
) { 
1255         case sig::short_P
: type
.primitive 
= sig::int_P
; break; 
1256         case sig::int_P
: type
.primitive 
= sig::long_P
; break; 
1257         case sig::long_P
: type
.primitive 
= sig::longlong_P
; break; 
1258         default: throw CYJSError(context
, "invalid type argument to Type.long"); 
1261     return CYMakeType(context
, &type
); 
1264 static JSValueRef 
Type_callAsFunction_short(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1266         throw CYJSError(context
, "incorrect number of arguments to Type.short"); 
1267     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1269     sig::Type 
type(*internal
->type_
); 
1271     switch (type
.primitive
) { 
1272         case sig::int_P
: type
.primitive 
= sig::short_P
; break; 
1273         case sig::long_P
: type
.primitive 
= sig::int_P
; break; 
1274         case sig::longlong_P
: type
.primitive 
= sig::long_P
; break; 
1275         default: throw CYJSError(context
, "invalid type argument to Type.short"); 
1278     return CYMakeType(context
, &type
); 
1281 static JSValueRef 
Type_callAsFunction_signed(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1283         throw CYJSError(context
, "incorrect number of arguments to Type.signed"); 
1284     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1286     sig::Type 
type(*internal
->type_
); 
1288     switch (type
.primitive
) { 
1289         case sig::char_P
: case sig::uchar_P
: type
.primitive 
= sig::char_P
; break; 
1290         case sig::short_P
: case sig::ushort_P
: type
.primitive 
= sig::short_P
; break; 
1291         case sig::int_P
: case sig::uint_P
: type
.primitive 
= sig::int_P
; break; 
1292         case sig::long_P
: case sig::ulong_P
: type
.primitive 
= sig::long_P
; break; 
1293         case sig::longlong_P
: case sig::ulonglong_P
: type
.primitive 
= sig::longlong_P
; break; 
1294         default: throw CYJSError(context
, "invalid type argument to Type.signed"); 
1297     return CYMakeType(context
, &type
); 
1300 static JSValueRef 
Type_callAsFunction_unsigned(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1302         throw CYJSError(context
, "incorrect number of arguments to Type.unsigned"); 
1303     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1305     sig::Type 
type(*internal
->type_
); 
1307     switch (type
.primitive
) { 
1308         case sig::char_P
: case sig::uchar_P
: type
.primitive 
= sig::uchar_P
; break; 
1309         case sig::short_P
: case sig::ushort_P
: type
.primitive 
= sig::ushort_P
; break; 
1310         case sig::int_P
: case sig::uint_P
: type
.primitive 
= sig::uint_P
; break; 
1311         case sig::long_P
: case sig::ulong_P
: type
.primitive 
= sig::ulong_P
; break; 
1312         case sig::longlong_P
: case sig::ulonglong_P
: type
.primitive 
= sig::ulonglong_P
; break; 
1313         default: throw CYJSError(context
, "invalid type argument to Type.unsigned"); 
1316     return CYMakeType(context
, &type
); 
1319 static JSValueRef 
Type_callAsFunction_functionWith(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1320     return Type_callAsFunction_$
With(context
, object
, _this
, count
, arguments
, sig::function_P
, exception
); 
1323 static JSValueRef 
Type_callAsFunction_pointerTo(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1325         throw CYJSError(context
, "incorrect number of arguments to Type.pointerTo"); 
1326     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1331     if (internal
->type_
->primitive 
== sig::char_P
) { 
1332         type
.flags 
= internal
->type_
->flags
; 
1333         type
.primitive 
= sig::string_P
; 
1334         type
.data
.data
.type 
= NULL
; 
1335         type
.data
.data
.size 
= 0; 
1338         type
.primitive 
= sig::pointer_P
; 
1339         type
.data
.data
.type 
= internal
->type_
; 
1340         type
.data
.data
.size 
= 0; 
1343     return CYMakeType(context
, &type
); 
1346 static JSValueRef 
Type_callAsFunction_withName(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1348         throw CYJSError(context
, "incorrect number of arguments to Type.withName"); 
1349     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1352     const char *name(CYPoolCString(pool
, context
, arguments
[0])); 
1354     sig::Type 
type(*internal
->type_
); 
1356     return CYMakeType(context
, &type
); 
1359 static JSValueRef 
Type_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1361         throw CYJSError(context
, "incorrect number of arguments to type cast function"); 
1362     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1364     if (internal
->type_
->primitive 
== sig::function_P
) 
1365         return CYMakeFunctor(context
, arguments
[0], internal
->type_
->data
.signature
); 
1367     sig::Type 
*type(internal
->type_
); 
1368     ffi_type 
*ffi(internal
->GetFFI()); 
1370     uint8_t value
[ffi
->size
]; 
1372     CYPoolFFI(&pool
, context
, type
, ffi
, value
, arguments
[0]); 
1373     return CYFromFFI(context
, type
, ffi
, value
); 
1376 static JSObjectRef 
Type_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1378         throw CYJSError(context
, "incorrect number of arguments to Type allocator"); 
1379     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1381     sig::Type 
*type(internal
->type_
); 
1384     if (type
->primitive 
!= sig::array_P
) 
1385         length 
= _not(size_t); 
1387         length 
= type
->data
.data
.size
; 
1388         type 
= type
->data
.data
.type
; 
1391     void *value(calloc(1, internal
->GetFFI()->size
)); 
1392     return CYMakePointer(context
, value
, length
, type
, NULL
, NULL
); 
1395 static JSObjectRef 
Functor_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1397         throw CYJSError(context
, "incorrect number of arguments to Functor constructor"); 
1399     const char *encoding(CYPoolCString(pool
, context
, arguments
[1])); 
1400     sig::Signature signature
; 
1401     sig::Parse(pool
, &signature
, encoding
, &Structor_
); 
1402     return CYMakeFunctor(context
, arguments
[0], signature
); 
1405 static JSValueRef 
CYValue_callAsFunction_valueOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1406     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1407     return CYCastJSValue(context
, reinterpret_cast<uintptr_t>(internal
->value_
)); 
1410 static JSValueRef 
CYValue_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1411     return CYValue_callAsFunction_valueOf(context
, object
, _this
, count
, arguments
, exception
); 
1414 static JSValueRef 
CYValue_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1415     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1417     sprintf(string
, "%p", internal
->value_
); 
1418     return CYCastJSValue(context
, string
); 
1421 static JSValueRef 
Pointer_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1422     std::set
<void *> *objects(CYCastObjects(context
, _this
, count
, arguments
)); 
1424     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(_this
))); 
1425     if (internal
->length_ 
!= _not(size_t)) { 
1426         JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array_prototype"))); 
1427         JSObjectRef 
toCYON(CYCastJSObject(context
, CYGetProperty(context
, Array
, toCYON_s
))); 
1428         return CYCallAsFunction(context
, toCYON
, _this
, count
, arguments
); 
1429     } else if (internal
->type_
->type_ 
== NULL
) pointer
: { 
1431         sprintf(string
, "%p", internal
->value_
); 
1432         return CYCastJSValue(context
, string
); 
1434         JSValueRef 
value(CYGetProperty(context
, _this
, cyi_s
)); 
1435         if (JSValueIsUndefined(context
, value
)) 
1438         return CYCastJSValue(context
, pool
.strcat("&", CYPoolCCYON(pool
, context
, value
, objects
), NULL
)); 
1439     } catch (const CYException 
&e
) { 
1444 static JSValueRef 
Pointer_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1445     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
1446     return CYMakeType(context
, internal
->type_
->type_
); 
1449 static JSValueRef 
Functor_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1450     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(object
))); 
1451     return CYMakeType(context
, &internal
->signature_
); 
1454 static JSValueRef 
Type_getProperty_alignment(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1455     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1456     return CYCastJSValue(context
, internal
->GetFFI()->alignment
); 
1459 static JSValueRef 
Type_getProperty_name(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1460     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1461     return CYCastJSValue(context
, internal
->type_
->name
); 
1464 static JSValueRef 
Type_getProperty_size(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1465     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1466     return CYCastJSValue(context
, internal
->GetFFI()->size
); 
1469 static JSValueRef 
Type_callAsFunction_toString(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1470     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1472     const char *type(sig::Unparse(pool
, internal
->type_
)); 
1473     return CYCastJSValue(context
, CYJSString(type
)); 
1476 static JSValueRef 
Type_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1477     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1481     CYOutput 
output(out
, options
); 
1482     (new(pool
) CYEncodedType(Decode(pool
, internal
->type_
)))->Output(output
, CYNoFlags
); 
1483     return CYCastJSValue(context
, CYJSString(out
.str().c_str())); 
1486 static JSValueRef 
Type_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1487     return Type_callAsFunction_toString(context
, object
, _this
, count
, arguments
, exception
); 
1490 static JSStaticFunction Pointer_staticFunctions
[4] = { 
1491     {"toCYON", &Pointer_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1492     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1493     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1497 static JSStaticValue Pointer_staticValues
[2] = { 
1498     {"type", &Pointer_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1499     {NULL
, NULL
, NULL
, 0} 
1502 static JSStaticFunction Struct_staticFunctions
[2] = { 
1503     {"$cya", &Struct_callAsFunction_$cya
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1507 static JSStaticFunction Functor_staticFunctions
[4] = { 
1508     {"toCYON", &CYValue_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1509     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1510     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1515     JSStaticFunction 
const * const Functor::StaticFunctions 
= Functor_staticFunctions
; 
1518 static JSStaticValue Functor_staticValues
[2] = { 
1519     {"type", &Functor_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1520     {NULL
, NULL
, NULL
, 0} 
1524     JSStaticValue 
const * const Functor::StaticValues 
= Functor_staticValues
; 
1527 static JSStaticValue Type_staticValues
[4] = { 
1528     {"alignment", &Type_getProperty_alignment
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1529     {"name", &Type_getProperty_name
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1530     {"size", &Type_getProperty_size
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1531     {NULL
, NULL
, NULL
, 0} 
1534 static JSStaticFunction Type_staticFunctions
[14] = { 
1535     {"arrayOf", &Type_callAsFunction_arrayOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1536     {"blockWith", &Type_callAsFunction_blockWith
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1537     {"constant", &Type_callAsFunction_constant
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1538     {"functionWith", &Type_callAsFunction_functionWith
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1539     {"long", &Type_callAsFunction_long
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1540     {"pointerTo", &Type_callAsFunction_pointerTo
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1541     {"short", &Type_callAsFunction_short
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1542     {"signed", &Type_callAsFunction_signed
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1543     {"withName", &Type_callAsFunction_withName
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1544     {"toCYON", &Type_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1545     {"toJSON", &Type_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1546     {"toString", &Type_callAsFunction_toString
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1547     {"unsigned", &Type_callAsFunction_unsigned
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1551 static JSObjectRef (*JSObjectMakeArray$
)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*); 
1553 _visible 
void CYSetArgs(int argc
, const char *argv
[]) { 
1554     JSContextRef 
context(CYGetJSContext()); 
1555     JSValueRef args
[argc
]; 
1556     for (int i(0); i 
!= argc
; ++i
) 
1557         args
[i
] = CYCastJSValue(context
, argv
[i
]); 
1560     if (JSObjectMakeArray$ 
!= NULL
) 
1561         array 
= _jsccall(*JSObjectMakeArray$
, context
, argc
, args
); 
1563         JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array"))); 
1564         JSValueRef 
value(CYCallAsFunction(context
, Array
, NULL
, argc
, args
)); 
1565         array 
= CYCastJSObject(context
, value
); 
1568     JSObjectRef 
System(CYGetCachedObject(context
, CYJSString("System"))); 
1569     CYSetProperty(context
, System
, CYJSString("args"), array
); 
1572 JSObjectRef 
CYGetGlobalObject(JSContextRef context
) { 
1573     return JSContextGetGlobalObject(context
); 
1576 // XXX: this is neither exceptin safe nor even terribly sane 
1577 class ExecutionHandle 
{ 
1579     JSContextRef context_
; 
1580     std::vector
<void *> handles_
; 
1583     ExecutionHandle(JSContextRef context
) : 
1586         handles_
.resize(GetHooks().size()); 
1587         for (size_t i(0); i 
!= GetHooks().size(); ++i
) { 
1588             CYHook 
*hook(GetHooks()[i
]); 
1589             if (hook
->ExecuteStart 
!= NULL
) 
1590                 handles_
[i
] = (*hook
->ExecuteStart
)(context_
); 
1596     ~ExecutionHandle() { 
1597         for (size_t i(GetHooks().size()); i 
!= 0; --i
) { 
1598             CYHook 
*hook(GetHooks()[i
-1]); 
1599             if (hook
->ExecuteEnd 
!= NULL
) 
1600                 (*hook
->ExecuteEnd
)(context_
, handles_
[i
-1]); 
1605 static volatile bool cancel_
; 
1607 static bool CYShouldTerminate(JSContextRef context
, void *arg
) { 
1611 _visible 
const char *CYExecute(JSContextRef context
, CYPool 
&pool
, CYUTF8String code
) { 
1612     ExecutionHandle 
handle(context
); 
1615     if (&JSContextGroupSetExecutionTimeLimit 
!= NULL
) 
1616         JSContextGroupSetExecutionTimeLimit(JSContextGetGroup(context
), 0.5, &CYShouldTerminate
, NULL
); 
1619         JSValueRef 
result(_jsccall(JSEvaluateScript
, context
, CYJSString(code
), NULL
, NULL
, 0)); 
1620         if (JSValueIsUndefined(context
, result
)) 
1623         std::set
<void *> objects
; 
1624         const char *json(_jsccall(CYPoolCCYON
, pool
, context
, result
, objects
)); 
1625         CYSetProperty(context
, CYGetGlobalObject(context
), Result_
, result
); 
1628     } catch (const CYException 
&error
) { 
1629         return pool
.strcat("throw ", error
.PoolCString(pool
), NULL
); 
1633 _visible 
void CYCancel() { 
1637 static bool initialized_ 
= false; 
1639 void CYInitializeDynamic() { 
1641         initialized_ 
= true; 
1644     JSObjectMakeArray$ 
= reinterpret_cast<JSObjectRef (*)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*)>(dlsym(RTLD_DEFAULT
, "JSObjectMakeArray")); 
1645     JSSynchronousGarbageCollectForDebugging$ 
= reinterpret_cast<void (*)(JSContextRef
)>(dlsym(RTLD_DEFAULT
, "JSSynchronousGarbageCollectForDebugging")); 
1647     JSClassDefinition definition
; 
1649     definition 
= kJSClassDefinitionEmpty
; 
1650     definition
.className 
= "All"; 
1651     definition
.hasProperty 
= &All_hasProperty
; 
1652     definition
.getProperty 
= &All_getProperty
; 
1653     definition
.getPropertyNames 
= &All_getPropertyNames
; 
1654     All_ 
= JSClassCreate(&definition
); 
1656     definition 
= kJSClassDefinitionEmpty
; 
1657     definition
.className 
= "Context"; 
1658     definition
.finalize 
= &CYFinalize
; 
1659     Context_ 
= JSClassCreate(&definition
); 
1661     definition 
= kJSClassDefinitionEmpty
; 
1662     definition
.className 
= "Functor"; 
1663     definition
.staticFunctions 
= cy::Functor::StaticFunctions
; 
1664     definition
.staticValues 
= Functor_staticValues
; 
1665     definition
.callAsFunction 
= &Functor_callAsFunction
; 
1666     definition
.finalize 
= &CYFinalize
; 
1667     Functor_ 
= JSClassCreate(&definition
); 
1669     definition 
= kJSClassDefinitionEmpty
; 
1670     definition
.className 
= "Pointer"; 
1671     definition
.staticFunctions 
= Pointer_staticFunctions
; 
1672     definition
.staticValues 
= Pointer_staticValues
; 
1673     definition
.getProperty 
= &Pointer_getProperty
; 
1674     definition
.setProperty 
= &Pointer_setProperty
; 
1675     definition
.finalize 
= &CYFinalize
; 
1676     Pointer_ 
= JSClassCreate(&definition
); 
1678     definition 
= kJSClassDefinitionEmpty
; 
1679     definition
.className 
= "Struct"; 
1680     definition
.staticFunctions 
= Struct_staticFunctions
; 
1681     definition
.getProperty 
= &Struct_getProperty
; 
1682     definition
.setProperty 
= &Struct_setProperty
; 
1683     definition
.getPropertyNames 
= &Struct_getPropertyNames
; 
1684     definition
.finalize 
= &CYFinalize
; 
1685     Struct_ 
= JSClassCreate(&definition
); 
1687     definition 
= kJSClassDefinitionEmpty
; 
1688     definition
.className 
= "Type"; 
1689     definition
.staticValues 
= Type_staticValues
; 
1690     definition
.staticFunctions 
= Type_staticFunctions
; 
1691     definition
.callAsFunction 
= &Type_callAsFunction
; 
1692     definition
.callAsConstructor 
= &Type_callAsConstructor
; 
1693     definition
.finalize 
= &CYFinalize
; 
1694     Type_privateData::Class_ 
= JSClassCreate(&definition
); 
1696     definition 
= kJSClassDefinitionEmpty
; 
1697     definition
.className 
= "Global"; 
1698     //definition.getProperty = &Global_getProperty; 
1699     Global_ 
= JSClassCreate(&definition
); 
1701     Array_s 
= JSStringCreateWithUTF8CString("Array"); 
1702     cy_s 
= JSStringCreateWithUTF8CString("$cy"); 
1703     cyi_s 
= JSStringCreateWithUTF8CString("$cyi"); 
1704     length_s 
= JSStringCreateWithUTF8CString("length"); 
1705     message_s 
= JSStringCreateWithUTF8CString("message"); 
1706     name_s 
= JSStringCreateWithUTF8CString("name"); 
1707     pop_s 
= JSStringCreateWithUTF8CString("pop"); 
1708     prototype_s 
= JSStringCreateWithUTF8CString("prototype"); 
1709     push_s 
= JSStringCreateWithUTF8CString("push"); 
1710     splice_s 
= JSStringCreateWithUTF8CString("splice"); 
1711     toCYON_s 
= JSStringCreateWithUTF8CString("toCYON"); 
1712     toJSON_s 
= JSStringCreateWithUTF8CString("toJSON"); 
1713     toPointer_s 
= JSStringCreateWithUTF8CString("toPointer"); 
1714     toString_s 
= JSStringCreateWithUTF8CString("toString"); 
1715     weak_s 
= JSStringCreateWithUTF8CString("weak"); 
1717     Result_ 
= JSStringCreateWithUTF8CString("_"); 
1719     for (CYHook 
*hook 
: GetHooks()) 
1720         if (hook
->Initialize 
!= NULL
) 
1721             (*hook
->Initialize
)(); 
1724 void CYThrow(JSContextRef context
, JSValueRef value
) { 
1726         throw CYJSError(context
, value
); 
1729 const char *CYJSError::PoolCString(CYPool 
&pool
) const { 
1730     std::set
<void *> objects
; 
1731     // XXX: this used to be CYPoolCString 
1732     return CYPoolCCYON(pool
, context_
, value_
, objects
); 
1735 JSValueRef 
CYJSError::CastJSValue(JSContextRef context
, const char *name
) const { 
1736     // XXX: what if the context is different? or the name? I dunno. ("epic" :/) 
1740 JSValueRef 
CYCastJSError(JSContextRef context
, const char *name
, const char *message
) { 
1741     JSObjectRef 
Error(CYGetCachedObject(context
, CYJSString(name
))); 
1742     JSValueRef arguments
[1] = {CYCastJSValue(context
, message
)}; 
1743     return _jsccall(JSObjectCallAsConstructor
, context
, Error
, 1, arguments
); 
1746 JSValueRef 
CYPoolError::CastJSValue(JSContextRef context
, const char *name
) const { 
1747     return CYCastJSError(context
, name
, message_
); 
1750 CYJSError::CYJSError(JSContextRef context
, const char *format
, ...) { 
1751     _assert(context 
!= NULL
); 
1756     va_start(args
, format
); 
1757     // XXX: there might be a beter way to think about this 
1758     const char *message(pool
.vsprintf(64, format
, args
)); 
1761     value_ 
= CYCastJSError(context
, "Error", message
); 
1764 JSGlobalContextRef 
CYGetJSContext(JSContextRef context
) { 
1765     return reinterpret_cast<Context 
*>(JSObjectGetPrivate(CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
))))->context_
; 
1768 void *CYMapFile(const char *path
, size_t *psize
) { 
1769     int fd(_syscall_(open(path
, O_RDONLY
), 1, ENOENT
)); 
1774     _syscall(fstat(fd
, &stat
)); 
1775     size_t size(stat
.st_size
); 
1780     _syscall(base 
= mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, 0)); 
1782     _syscall(close(fd
)); 
1786 static JSValueRef 
require(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1787     _assert(count 
== 1); 
1791     _assert(dladdr(reinterpret_cast<void *>(&require
), &addr
) != 0); 
1792     char *lib(pool
.strdup(addr
.dli_fname
)); 
1794     char *slash(strrchr(lib
, '/')); 
1795     _assert(slash 
!= NULL
); 
1798     CYJSString 
property("exports"); 
1801     const char *name(CYPoolCString(pool
, context
, arguments
[0])); 
1802     const char *path(pool
.strcat(lib
, "/cycript0.9/", name
, ".cy", NULL
)); 
1804     CYJSString 
key(path
); 
1805     JSObjectRef 
modules(CYGetCachedObject(context
, CYJSString("modules"))); 
1806     JSValueRef 
cache(CYGetProperty(context
, modules
, key
)); 
1808     if (!JSValueIsUndefined(context
, cache
)) 
1809         module = CYCastJSObject(context
, cache
); 
1812         code
.data 
= reinterpret_cast<char *>(CYMapFile(path
, &code
.size
)); 
1814         if (code
.data 
== NULL
) { 
1815             if (strchr(name
, '/') == NULL 
&& ( 
1817                 dlopen(pool
.strcat("/System/Library/Frameworks/", name
, ".framework/", name
, NULL
), RTLD_LAZY 
| RTLD_GLOBAL
) != NULL 
|| 
1818                 dlopen(pool
.strcat("/System/Library/PrivateFrameworks/", name
, ".framework/", name
, NULL
), RTLD_LAZY 
| RTLD_GLOBAL
) != NULL 
|| 
1821                 return CYJSUndefined(NULL
); 
1823             CYThrow("Can't find module: %s", name
); 
1826         module = JSObjectMake(context
, NULL
, NULL
); 
1827         CYSetProperty(context
, modules
, key
, module); 
1829         JSObjectRef 
exports(JSObjectMake(context
, NULL
, NULL
)); 
1830         CYSetProperty(context
, module, property
, exports
); 
1832         std::stringstream wrap
; 
1833         wrap 
<< "(function (exports, require, module) { " << code 
<< "\n});"; 
1834         code 
= CYPoolCode(pool
, wrap
); 
1836         JSValueRef 
value(_jsccall(JSEvaluateScript
, context
, CYJSString(code
), NULL
, NULL
, 0)); 
1837         JSObjectRef 
function(CYCastJSObject(context
, value
)); 
1839         JSValueRef arguments
[3] = { exports
, JSObjectMakeFunctionWithCallback(context
, CYJSString("require"), &require
), module }; 
1840         CYCallAsFunction(context
, function
, NULL
, 3, arguments
); 
1843     return CYGetProperty(context
, module, property
); 
1846 extern "C" void CYDestroyWeak(JSWeakObjectMapRef weak
, void *data
) { 
1849 extern "C" void CYSetupContext(JSGlobalContextRef context
) { 
1850     CYInitializeDynamic(); 
1852     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1854     JSObjectRef 
cy(JSObjectMake(context
, Context_
, new Context(context
))); 
1855     CYSetProperty(context
, global
, cy_s
, cy
, kJSPropertyAttributeDontEnum
); 
1857 /* Cache Globals {{{ */ 
1858     JSObjectRef 
Array(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Array")))); 
1859     CYSetProperty(context
, cy
, CYJSString("Array"), Array
); 
1861     JSObjectRef 
Array_prototype(CYCastJSObject(context
, CYGetProperty(context
, Array
, prototype_s
))); 
1862     CYSetProperty(context
, cy
, CYJSString("Array_prototype"), Array_prototype
); 
1864     JSObjectRef 
Boolean(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Boolean")))); 
1865     CYSetProperty(context
, cy
, CYJSString("Boolean"), Boolean
); 
1867     JSObjectRef 
Boolean_prototype(CYCastJSObject(context
, CYGetProperty(context
, Boolean
, prototype_s
))); 
1868     CYSetProperty(context
, cy
, CYJSString("Boolean_prototype"), Boolean_prototype
); 
1870     JSObjectRef 
Error(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Error")))); 
1871     CYSetProperty(context
, cy
, CYJSString("Error"), Error
); 
1873     JSObjectRef 
Error_prototype(CYCastJSObject(context
, CYGetProperty(context
, Error
, prototype_s
))); 
1874     CYSetProperty(context
, cy
, CYJSString("Error_prototype"), Error_prototype
); 
1876     JSObjectRef 
Function(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Function")))); 
1877     CYSetProperty(context
, cy
, CYJSString("Function"), Function
); 
1879     JSObjectRef 
Function_prototype(CYCastJSObject(context
, CYGetProperty(context
, Function
, prototype_s
))); 
1880     CYSetProperty(context
, cy
, CYJSString("Function_prototype"), Function_prototype
); 
1882     JSObjectRef 
Number(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Number")))); 
1883     CYSetProperty(context
, cy
, CYJSString("Number"), Number
); 
1885     JSObjectRef 
Number_prototype(CYCastJSObject(context
, CYGetProperty(context
, Number
, prototype_s
))); 
1886     CYSetProperty(context
, cy
, CYJSString("Number_prototype"), Number_prototype
); 
1888     JSObjectRef 
Object(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Object")))); 
1889     CYSetProperty(context
, cy
, CYJSString("Object"), Object
); 
1891     JSObjectRef 
Object_prototype(CYCastJSObject(context
, CYGetProperty(context
, Object
, prototype_s
))); 
1892     CYSetProperty(context
, cy
, CYJSString("Object_prototype"), Object_prototype
); 
1894     JSObjectRef 
String(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("String")))); 
1895     CYSetProperty(context
, cy
, CYJSString("String"), String
); 
1897     JSObjectRef 
String_prototype(CYCastJSObject(context
, CYGetProperty(context
, String
, prototype_s
))); 
1898     CYSetProperty(context
, cy
, CYJSString("String_prototype"), String_prototype
); 
1900     JSObjectRef 
SyntaxError(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("SyntaxError")))); 
1901     CYSetProperty(context
, cy
, CYJSString("SyntaxError"), SyntaxError
); 
1904     CYSetProperty(context
, Array_prototype
, toCYON_s
, &Array_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
1905     CYSetProperty(context
, Error_prototype
, toCYON_s
, &Error_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
1906     CYSetProperty(context
, String_prototype
, toCYON_s
, &String_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
1908     JSObjectRef 
cycript(JSObjectMake(context
, NULL
, NULL
)); 
1909     CYSetProperty(context
, global
, CYJSString("Cycript"), cycript
); 
1910     CYSetProperty(context
, cycript
, CYJSString("compile"), &Cycript_compile_callAsFunction
); 
1911     CYSetProperty(context
, cycript
, CYJSString("gc"), &Cycript_gc_callAsFunction
); 
1913     JSObjectRef 
Functor(JSObjectMakeConstructor(context
, Functor_
, &Functor_new
)); 
1914     CYSetPrototype(context
, CYCastJSObject(context
, CYGetProperty(context
, Functor
, prototype_s
)), Function_prototype
); 
1915     CYSetProperty(context
, cycript
, CYJSString("Functor"), Functor
); 
1917     CYSetProperty(context
, cycript
, CYJSString("Pointer"), JSObjectMakeConstructor(context
, Pointer_
, &Pointer_new
)); 
1918     CYSetProperty(context
, cycript
, CYJSString("Type"), JSObjectMakeConstructor(context
, Type_privateData::Class_
, &Type_new
)); 
1920     JSObjectRef 
modules(JSObjectMake(context
, NULL
, NULL
)); 
1921     CYSetProperty(context
, cy
, CYJSString("modules"), modules
); 
1923     JSObjectRef 
all(JSObjectMake(context
, All_
, NULL
)); 
1924     CYSetProperty(context
, cycript
, CYJSString("all"), all
); 
1926     JSObjectRef 
alls(_jsccall(JSObjectCallAsConstructor
, context
, Array
, 0, NULL
)); 
1927     CYSetProperty(context
, cycript
, CYJSString("alls"), alls
); 
1930         JSObjectRef 
last(NULL
), curr(global
); 
1932         goto next
; for (JSValueRef next
;;) { 
1933             if (JSValueIsNull(context
, next
)) 
1936             curr 
= CYCastJSObject(context
, next
); 
1938             next 
= JSObjectGetPrototype(context
, curr
); 
1941         CYSetPrototype(context
, last
, all
); 
1944     JSObjectRef 
System(JSObjectMake(context
, NULL
, NULL
)); 
1945     CYSetProperty(context
, cy
, CYJSString("System"), System
); 
1947     CYSetProperty(context
, all
, CYJSString("require"), &require
, kJSPropertyAttributeDontEnum
); 
1949     CYSetProperty(context
, global
, CYJSString("system"), System
); 
1950     CYSetProperty(context
, System
, CYJSString("args"), CYJSNull(context
)); 
1951     //CYSetProperty(context, System, CYJSString("global"), global); 
1952     CYSetProperty(context
, System
, CYJSString("print"), &System_print
); 
1955     if (&JSWeakObjectMapCreate 
!= NULL
) { 
1956         JSWeakObjectMapRef 
weak(JSWeakObjectMapCreate(context
, NULL
, &CYDestroyWeak
)); 
1957         CYSetProperty(context
, cy
, weak_s
, CYCastJSValue(context
, reinterpret_cast<uintptr_t>(weak
))); 
1961     if (CYBridgeEntry 
*entry 
= CYBridgeHash("1dlerror", 8)) 
1962         entry
->cache_ 
= new cy::Functor(entry
->value_
, reinterpret_cast<void (*)()>(&dlerror
)); 
1964     for (CYHook 
*hook 
: GetHooks()) 
1965         if (hook
->SetupContext 
!= NULL
) 
1966             (*hook
->SetupContext
)(context
); 
1968     CYArrayPush(context
, alls
, cycript
); 
1971 static JSGlobalContextRef context_
; 
1973 _visible JSGlobalContextRef 
CYGetJSContext() { 
1974     CYInitializeDynamic(); 
1976     if (context_ 
== NULL
) { 
1977         context_ 
= JSGlobalContextCreate(Global_
); 
1978         CYSetupContext(context_
); 
1984 _visible 
void CYDestroyContext() { 
1985     if (context_ 
== NULL
) 
1987     JSGlobalContextRelease(context_
);