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" 
  41 #include "sig/parse.hpp" 
  42 #include "sig/ffi_type.hpp" 
  47 #include "Execute.hpp" 
  48 #include "Internal.hpp" 
  49 #include "JavaScript.hpp" 
  50 #include "Pooling.hpp" 
  53 const char *sqlite3_column_string(sqlite3_stmt 
*stmt
, int n
) { 
  54     return reinterpret_cast<const char *>(sqlite3_column_text(stmt
, n
)); 
  57 char *sqlite3_column_pooled(CYPool 
&pool
, sqlite3_stmt 
*stmt
, int n
) { 
  58     if (const char *value 
= sqlite3_column_string(stmt
, n
)) 
  59         return pool
.strdup(value
); 
  63 static std::vector
<CYHook 
*> &GetHooks() { 
  64     static std::vector
<CYHook 
*> hooks
; 
  68 CYRegisterHook::CYRegisterHook(CYHook 
*hook
) { 
  69     GetHooks().push_back(hook
); 
  72 /* JavaScript Properties {{{ */ 
  73 bool CYHasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
) { 
  74     return JSObjectHasProperty(context
, object
, name
); 
  77 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, size_t index
) { 
  78     return _jsccall(JSObjectGetPropertyAtIndex
, context
, object
, index
); 
  81 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
) { 
  82     return _jsccall(JSObjectGetProperty
, context
, object
, name
); 
  85 void CYSetProperty(JSContextRef context
, JSObjectRef object
, size_t index
, JSValueRef value
) { 
  86     _jsccall(JSObjectSetPropertyAtIndex
, context
, object
, index
, value
); 
  89 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef value
, JSPropertyAttributes attributes
) { 
  90     _jsccall(JSObjectSetProperty
, context
, object
, name
, value
, attributes
); 
  93 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef (*callback
)(JSContextRef
, JSObjectRef
, JSObjectRef
, size_t, const JSValueRef
[], JSValueRef 
*), JSPropertyAttributes attributes
) { 
  94     CYSetProperty(context
, object
, name
, JSObjectMakeFunctionWithCallback(context
, name
, callback
), attributes
); 
  97 void CYSetPrototype(JSContextRef context
, JSObjectRef object
, JSValueRef value
) { 
  98     JSObjectSetPrototype(context
, object
, value
); 
  99     _assert(CYIsStrictEqual(context
, JSObjectGetPrototype(context
, object
), value
)); 
 102 /* JavaScript Strings {{{ */ 
 103 JSStringRef 
CYCopyJSString(const char *value
) { 
 104     return value 
== NULL 
? NULL 
: JSStringCreateWithUTF8CString(value
); 
 107 JSStringRef 
CYCopyJSString(JSStringRef value
) { 
 108     return value 
== NULL 
? NULL 
: JSStringRetain(value
); 
 111 JSStringRef 
CYCopyJSString(CYUTF8String value
) { 
 112     if (memchr(value
.data
, '\0', value
.size
) != NULL
) { 
 114         return CYCopyJSString(CYPoolUTF16String(pool
, value
)); 
 115     } else if (value
.data
[value
.size
] != '\0') { 
 117         return CYCopyJSString(pool
.strmemdup(value
.data
, value
.size
)); 
 119         return CYCopyJSString(value
.data
); 
 123 JSStringRef 
CYCopyJSString(CYUTF16String value
) { 
 124     return JSStringCreateWithCharacters(value
.data
, value
.size
); 
 127 JSStringRef 
CYCopyJSString(JSContextRef context
, JSValueRef value
) { 
 128     if (JSValueIsNull(context
, value
)) 
 130     return _jsccall(JSValueToStringCopy
, context
, value
); 
 133 static CYUTF16String 
CYCastUTF16String(JSStringRef value
) { 
 134     return CYUTF16String(JSStringGetCharactersPtr(value
), JSStringGetLength(value
)); 
 137 CYUTF8String 
CYPoolUTF8String(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 138     return CYPoolUTF8String(pool
, CYCastUTF16String(value
)); 
 141 const char *CYPoolCString(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 142     CYUTF8String 
utf8(CYPoolUTF8String(pool
, context
, value
)); 
 143     _assert(memchr(utf8
.data
, '\0', utf8
.size
) == NULL
); 
 147 const char *CYPoolCString(CYPool 
&pool
, JSContextRef context
, JSValueRef value
) { 
 148     return JSValueIsNull(context
, value
) ? NULL 
: CYPoolCString(pool
, context
, CYJSString(context
, value
)); 
 151 /* Index Offsets {{{ */ 
 152 size_t CYGetIndex(CYPool 
&pool
, JSContextRef context
, JSStringRef value
) { 
 153     return CYGetIndex(CYPoolUTF8String(pool
, context
, value
)); 
 157 static JSObjectRef (*JSObjectMakeArray$
)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*); 
 159 static JSObjectRef 
CYObjectMakeArray(JSContextRef context
, size_t length
, const JSValueRef values
[]) { 
 160     if (JSObjectMakeArray$ 
!= NULL
) 
 161         return _jsccall(*JSObjectMakeArray$
, context
, length
, values
); 
 163         JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array"))); 
 164         JSValueRef 
value(CYCallAsFunction(context
, Array
, NULL
, length
, values
)); 
 165         return CYCastJSObject(context
, value
); 
 169 static JSClassRef All_
; 
 170 static JSClassRef Context_
; 
 171 static JSClassRef CArray_
; 
 172 static JSClassRef CString_
; 
 174 static JSClassRef Global_
; 
 175 static JSClassRef Pointer_
; 
 176 static JSClassRef Struct_
; 
 181 JSStringRef length_s
; 
 182 JSStringRef message_s
; 
 185 JSStringRef prototype_s
; 
 187 JSStringRef splice_s
; 
 188 JSStringRef toCYON_s
; 
 189 JSStringRef toJSON_s
; 
 190 JSStringRef toPointer_s
; 
 191 JSStringRef toString_s
; 
 194 static sqlite3 
*database_
; 
 196 static JSStringRef Result_
; 
 198 void CYFinalize(JSObjectRef object
) { 
 199     CYData 
*internal(reinterpret_cast<CYData 
*>(JSObjectGetPrivate(object
))); 
 200     _assert(internal
->count_ 
!= _not(unsigned)); 
 201     if (--internal
->count_ 
== 0) 
 205 sig::Type 
*Structor_(CYPool 
&pool
, sig::Aggregate 
*aggregate
) { 
 210 JSClassRef 
Type_privateData::Class_
; 
 215     JSGlobalContextRef context_
; 
 217     Context(JSGlobalContextRef context
) : 
 226     Type_privateData 
*type_
; 
 229     CArray(void *value
, JSContextRef context
, JSObjectRef owner
, size_t length
, const sig::Type 
&type
, ffi_type 
*ffi
) : 
 230         CYOwned(value
, context
, owner
), 
 231         type_(new(*pool_
) Type_privateData(type
, ffi
)), 
 240     CString(char *value
, JSContextRef context
, JSObjectRef owner
) : 
 241         CYOwned(value
, context
, owner
) 
 249     Type_privateData 
*type_
; 
 251     Pointer(void *value
, JSContextRef context
, JSObjectRef owner
, const sig::Type 
&type
) : 
 252         CYOwned(value
, context
, owner
), 
 253         type_(new(*pool_
) Type_privateData(type
)) 
 257     Pointer(void *value
, JSContextRef context
, JSObjectRef owner
, const char *encoding
) : 
 258         CYOwned(value
, context
, owner
), 
 259         type_(new(*pool_
) Type_privateData(encoding
)) 
 264 struct Struct_privateData 
: 
 267     Type_privateData 
*type_
; 
 269     Struct_privateData(void *value
, JSContextRef context
, JSObjectRef owner
, const sig::Type 
&type
, ffi_type 
*ffi
) : 
 270         CYOwned(value
, context
, owner
), 
 271         type_(new(*pool_
) Type_privateData(type
, ffi
)) 
 276 JSObjectRef 
CYMakeCArray(JSContextRef context
, void *data
, size_t length
, const sig::Type 
&type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 277     CArray 
*internal(new CArray(data
, context
, owner
, length
, type
, ffi
)); 
 280         size_t size(ffi
->size 
* length
); 
 281         void *copy(internal
->pool_
->malloc
<void>(size
, ffi
->alignment
)); 
 282         memcpy(copy
, internal
->value_
, size
); 
 283         internal
->value_ 
= copy
; 
 286     return JSObjectMake(context
, CArray_
, internal
); 
 289 JSObjectRef 
CYMakeCString(JSContextRef context
, char *pointer
, JSObjectRef owner
) { 
 290     CString 
*internal(new CString(pointer
, context
, owner
)); 
 292         internal
->value_ 
= internal
->pool_
->strdup(static_cast<const char *>(internal
->value_
)); 
 293     return JSObjectMake(context
, CString_
, internal
); 
 296 JSObjectRef 
CYMakeStruct(JSContextRef context
, void *data
, const sig::Type 
&type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 297     Struct_privateData 
*internal(new Struct_privateData(data
, context
, owner
, type
, ffi
)); 
 300         size_t size(ffi
->size
); 
 301         void *copy(internal
->pool_
->malloc
<void>(size
, ffi
->alignment
)); 
 302         memcpy(copy
, internal
->value_
, size
); 
 303         internal
->value_ 
= copy
; 
 306     return JSObjectMake(context
, Struct_
, internal
); 
 309 static void *CYCastSymbol(const char *name
) { 
 310     for (CYHook 
*hook 
: GetHooks()) 
 311         if (hook
->CastSymbol 
!= NULL
) 
 312             if (void *value 
= (*hook
->CastSymbol
)(name
)) 
 314     return dlsym(RTLD_DEFAULT
, name
); 
 317 JSValueRef 
CYCastJSValue(JSContextRef context
, bool value
) { 
 318     return JSValueMakeBoolean(context
, value
); 
 321 JSValueRef 
CYCastJSValue(JSContextRef context
, double value
) { 
 322     return JSValueMakeNumber(context
, value
); 
 325 #define CYCastJSValue_(Type_) \ 
 326     JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \ 
 327         _assert(static_cast<Type_>(static_cast<double>(value)) == value); \ 
 328         return JSValueMakeNumber(context, static_cast<double>(value)); \ 
 331 CYCastJSValue_(signed short int) 
 332 CYCastJSValue_(unsigned short int) 
 333 CYCastJSValue_(signed int) 
 334 CYCastJSValue_(unsigned int) 
 335 CYCastJSValue_(signed long int) 
 336 CYCastJSValue_(unsigned long int) 
 337 CYCastJSValue_(signed long long int) 
 338 CYCastJSValue_(unsigned long long int) 
 340 JSValueRef 
CYJSUndefined(JSContextRef context
) { 
 341     return JSValueMakeUndefined(context
); 
 344 double CYCastDouble(JSContextRef context
, JSValueRef value
) { 
 345     return _jsccall(JSValueToNumber
, context
, value
); 
 348 bool CYCastBool(JSContextRef context
, JSValueRef value
) { 
 349     return JSValueToBoolean(context
, value
); 
 352 JSValueRef 
CYJSNull(JSContextRef context
) { 
 353     return JSValueMakeNull(context
); 
 356 JSValueRef 
CYCastJSValue(JSContextRef context
, JSStringRef value
) { 
 357     return value 
== NULL 
? CYJSNull(context
) : JSValueMakeString(context
, value
); 
 360 JSValueRef 
CYCastJSValue(JSContextRef context
, const char *value
) { 
 361     return CYCastJSValue(context
, CYJSString(value
)); 
 364 JSObjectRef 
CYCastJSObject(JSContextRef context
, JSValueRef value
) { 
 365     return _jsccall(JSValueToObject
, context
, value
); 
 368 JSValueRef 
CYCallAsFunction(JSContextRef context
, JSObjectRef function
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[]) { 
 369     return _jsccall(JSObjectCallAsFunction
, context
, function
, _this
, count
, arguments
); 
 372 bool CYIsCallable(JSContextRef context
, JSValueRef value
) { 
 373     return value 
!= NULL 
&& JSValueIsObject(context
, value
) && JSObjectIsFunction(context
, (JSObjectRef
) value
); 
 376 bool CYIsEqual(JSContextRef context
, JSValueRef lhs
, JSValueRef rhs
) { 
 377     return _jsccall(JSValueIsEqual
, context
, lhs
, rhs
); 
 380 bool CYIsStrictEqual(JSContextRef context
, JSValueRef lhs
, JSValueRef rhs
) { 
 381     return JSValueIsStrictEqual(context
, lhs
, rhs
); 
 384 size_t CYArrayLength(JSContextRef context
, JSObjectRef array
) { 
 385     return CYCastDouble(context
, CYGetProperty(context
, array
, length_s
)); 
 388 JSValueRef 
CYArrayGet(JSContextRef context
, JSObjectRef array
, size_t index
) { 
 389     return _jsccall(JSObjectGetPropertyAtIndex
, context
, array
, index
); 
 392 void CYArrayPush(JSContextRef context
, JSObjectRef array
, size_t length
, const JSValueRef arguments
[]) { 
 393     JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array_prototype"))); 
 394     _jsccall(JSObjectCallAsFunction
, context
, CYCastJSObject(context
, CYGetProperty(context
, Array
, push_s
)), array
, length
, arguments
); 
 397 void CYArrayPush(JSContextRef context
, JSObjectRef array
, JSValueRef value
) { 
 398     return CYArrayPush(context
, array
, 1, &value
); 
 401 template <size_t Size_
> 
 402 class CYArrayBuilder 
{ 
 404     JSContextRef context_
; 
 407     JSValueRef values_
[Size_
]; 
 411             array_ 
= CYObjectMakeArray(context_
, size_
, values_
); 
 413             CYArrayPush(context_
, array_
, size_
, values_
); 
 417     CYArrayBuilder(JSContextRef context
, JSObjectRef 
&array
) : 
 428     void operator ()(JSValueRef value
) { 
 429         if (size_ 
== Size_
) { 
 434         values_
[size_
++] = value
; 
 438 static JSValueRef 
System_print(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 445         CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, arguments
[0]))); 
 446         fwrite(string
.data
, string
.size
, 1, file
); 
 450     return CYJSUndefined(context
); 
 453 static void (*JSSynchronousGarbageCollectForDebugging$
)(JSContextRef
); 
 455 _visible 
void CYGarbageCollect(JSContextRef context
) { 
 456     (JSSynchronousGarbageCollectForDebugging$ 
?: &JSGarbageCollect
)(context
); 
 459 static JSValueRef 
Cycript_compile_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 461     CYUTF8String 
before(CYPoolUTF8String(pool
, context
, CYJSString(context
, arguments
[0]))); 
 462     std::stringbuf 
value(std::string(before
.data
, before
.size
)); 
 463     CYUTF8String 
after(CYPoolCode(pool
, value
)); 
 464     return CYCastJSValue(context
, CYJSString(after
)); 
 465 } CYCatch_(NULL
, "SyntaxError") } 
 467 static JSValueRef 
Cycript_gc_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 468     CYGarbageCollect(context
); 
 469     return CYJSUndefined(context
); 
 472 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, std::set
<void *> &objects
, JSValueRef 
*exception
) { CYTry 
{ 
 473     switch (JSType type 
= JSValueGetType(context
, value
)) { 
 474         case kJSTypeUndefined
: 
 479             return CYCastBool(context
, value
) ? "true" : "false"; 
 481         case kJSTypeNumber
: { 
 482             std::ostringstream str
; 
 483             CYNumerify(str
, CYCastDouble(context
, value
)); 
 484             std::string 
value(str
.str()); 
 485             return pool
.strmemdup(value
.c_str(), value
.size()); 
 488         case kJSTypeString
: { 
 489             std::ostringstream str
; 
 490             CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, value
))); 
 491             CYStringify(str
, string
.data
, string
.size
); 
 492             std::string 
value(str
.str()); 
 493             return pool
.strmemdup(value
.c_str(), value
.size()); 
 497             return CYPoolCCYON(pool
, context
, (JSObjectRef
) value
, objects
); 
 499             throw CYJSError(context
, "JSValueGetType() == 0x%x", type
); 
 503 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, std::set
<void *> &objects
) { 
 504     return _jsccall(CYPoolCCYON
, pool
, context
, value
, objects
); 
 507 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSValueRef value
, std::set
<void *> *objects
) { 
 509         return CYPoolCCYON(pool
, context
, value
, *objects
); 
 511         std::set
<void *> objects
; 
 512         return CYPoolCCYON(pool
, context
, value
, objects
); 
 516 const char *CYPoolCCYON(CYPool 
&pool
, JSContextRef context
, JSObjectRef object
, std::set
<void *> &objects
) { 
 517     JSValueRef 
toCYON(CYGetProperty(context
, object
, toCYON_s
)); 
 518     if (CYIsCallable(context
, toCYON
)) { 
 519         // XXX: this needs to be abstracted behind some kind of function 
 520         JSValueRef arguments
[1] = {CYCastJSValue(context
, reinterpret_cast<uintptr_t>(&objects
))}; 
 521         JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toCYON
, object
, 1, arguments
)); 
 522         _assert(value 
!= NULL
); 
 523         return CYPoolCString(pool
, context
, value
); 
 526     JSValueRef 
toJSON(CYGetProperty(context
, object
, toJSON_s
)); 
 527     if (CYIsCallable(context
, toJSON
)) { 
 528         JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 529         return _jsccall(CYPoolCCYON
, pool
, context
, CYCallAsFunction(context
, (JSObjectRef
) toJSON
, object
, 1, arguments
), objects
); 
 532     if (JSObjectIsFunction(context
, object
)) { 
 533         JSValueRef 
toString(CYGetProperty(context
, object
, toString_s
)); 
 534         if (CYIsCallable(context
, toString
)) { 
 535             JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 536             JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toString
, object
, 1, arguments
)); 
 537             _assert(value 
!= NULL
); 
 538             return CYPoolCString(pool
, context
, value
); 
 542     _assert(objects
.insert(object
).second
); 
 544     std::ostringstream str
; 
 548     // XXX: this is, sadly, going to leak 
 549     JSPropertyNameArrayRef 
names(JSObjectCopyPropertyNames(context
, object
)); 
 553     for (size_t index(0), count(JSPropertyNameArrayGetCount(names
)); index 
!= count
; ++index
) { 
 559         JSStringRef 
name(JSPropertyNameArrayGetNameAtIndex(names
, index
)); 
 560         CYUTF8String 
string(CYPoolUTF8String(pool
, context
, name
)); 
 565             CYStringify(str
, string
.data
, string
.size
); 
 570             JSValueRef 
value(CYGetProperty(context
, object
, name
)); 
 571             str 
<< CYPoolCCYON(pool
, context
, value
, objects
); 
 572         } catch (const CYException 
&error
) { 
 577     JSPropertyNameArrayRelease(names
); 
 581     std::string 
string(str
.str()); 
 582     return pool
.strmemdup(string
.c_str(), string
.size()); 
 585 std::set
<void *> *CYCastObjects(JSContextRef context
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[]) { 
 588     return CYCastPointer
<std::set
<void *> *>(context
, arguments
[0]); 
 591 static JSValueRef 
Array_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 592     std::set
<void *> *objects(CYCastObjects(context
, _this
, count
, arguments
)); 
 593     // XXX: this is horribly inefficient 
 594     std::set
<void *> backup
; 
 599     std::ostringstream str
; 
 603     JSValueRef 
length(CYGetProperty(context
, _this
, length_s
)); 
 606     for (size_t index(0), count(CYCastDouble(context
, length
)); index 
!= count
; ++index
) { 
 613             JSValueRef 
value(CYGetProperty(context
, _this
, index
)); 
 614             if (!JSValueIsUndefined(context
, value
)) 
 615                 str 
<< CYPoolCCYON(pool
, context
, value
, *objects
); 
 620         } catch (const CYException 
&error
) { 
 627     std::string 
value(str
.str()); 
 628     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 631 static JSValueRef 
String_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 633     std::ostringstream str
; 
 635     CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, _this
))); 
 636     CYStringify(str
, string
.data
, string
.size
); 
 638     std::string 
value(str
.str()); 
 639     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 642 JSObjectRef 
CYMakePointer(JSContextRef context
, void *pointer
, const sig::Type 
&type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 643     Pointer 
*internal(new Pointer(pointer
, context
, owner
, type
)); 
 644     return JSObjectMake(context
, Pointer_
, internal
); 
 647 JSObjectRef 
CYMakePointer(JSContextRef context
, void *pointer
, const char *encoding
, JSObjectRef owner
) { 
 648     Pointer 
*internal(new Pointer(pointer
, context
, owner
, encoding
)); 
 649     return JSObjectMake(context
, Pointer_
, internal
); 
 652 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, void (*function
)(), const sig::Signature 
&signature
) { 
 653     return JSObjectMake(context
, Functor_
, new cy::Functor(signature
, function
)); 
 656 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, const char *symbol
, const char *encoding
) { 
 657     void (*function
)()(reinterpret_cast<void (*)()>(CYCastSymbol(symbol
))); 
 658     if (function 
== NULL
) 
 661     cy::Functor 
*internal(new cy::Functor(encoding
, function
)); 
 663     return JSObjectMake(context
, Functor_
, internal
); 
 666 static bool CYGetOffset(CYPool 
&pool
, JSContextRef context
, JSStringRef value
, ssize_t 
&index
) { 
 667     return CYGetOffset(CYPoolCString(pool
, context
, value
), index
); 
 670 void *CYCastPointer_(JSContextRef context
, JSValueRef value
, bool *guess
) { 
 673     else switch (JSValueGetType(context
, value
)) { 
 676         case kJSTypeObject
: { 
 677             JSObjectRef 
object((JSObjectRef
) value
); 
 678             if (JSValueIsObjectOfClass(context
, value
, Pointer_
)) { 
 679                 Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 680                 return internal
->value_
; 
 682             JSValueRef 
toPointer(CYGetProperty(context
, object
, toPointer_s
)); 
 683             if (CYIsCallable(context
, toPointer
)) { 
 684                 JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toPointer
, object
, 0, NULL
)); 
 685                 _assert(value 
!= NULL
); 
 686                 return CYCastPointer_(context
, value
, guess
); 
 692             double number(CYCastDouble(context
, value
)); 
 693             if (!std::isnan(number
)) 
 694                 return reinterpret_cast<void *>(static_cast<uintptr_t>(static_cast<long long>(number
))); 
 696                 throw CYJSError(context
, "cannot convert value to pointer"); 
 706 // XXX: this is somehow not quite a template :/ 
 709 void Primitive
<bool>::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 710     *reinterpret_cast<bool *>(data
) = JSValueToBoolean(context
, value
); 
 713 #define CYPoolFFI_(Type_) \ 
 715 void Primitive<Type_>::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { \ 
 716     *reinterpret_cast<Type_ *>(data) = CYCastDouble(context, value); \ 
 722 CYPoolFFI_(signed char) 
 723 CYPoolFFI_(signed int) 
 724 CYPoolFFI_(signed long int) 
 725 CYPoolFFI_(signed long long int) 
 726 CYPoolFFI_(signed short int) 
 727 CYPoolFFI_(unsigned char) 
 728 CYPoolFFI_(unsigned int) 
 729 CYPoolFFI_(unsigned long int) 
 730 CYPoolFFI_(unsigned long long int) 
 731 CYPoolFFI_(unsigned short int) 
 733 void Void::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 737 void Unknown::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 741 void String::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 743     *reinterpret_cast<const char **>(data
) = CYCastPointer
<const char *>(context
, value
, &guess
); 
 744     if (guess 
&& pool 
!= NULL
) 
 745         *reinterpret_cast<const char **>(data
) = CYPoolCString(*pool
, context
, value
); 
 748 void Bits::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 752 void Pointer::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 753     *reinterpret_cast<void **>(data
) = CYCastPointer
<void *>(context
, value
); 
 756 void Array::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 757     uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 758     JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 759     for (size_t index(0); index 
!= size
; ++index
) { 
 760         ffi_type 
*field(ffi
->elements
[index
]); 
 763         if (aggregate 
== NULL
) 
 766             rhs 
= CYGetProperty(context
, aggregate
, index
); 
 767             if (JSValueIsUndefined(context
, rhs
)) 
 768                 throw CYJSError(context
, "unable to extract array value"); 
 771         type
.PoolFFI(pool
, context
, field
, base
, rhs
); 
 776 void Aggregate::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 779     uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 780     JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 781     for (size_t index(0); index 
!= signature
.count
; ++index
) { 
 782         sig::Element 
*element(&signature
.elements
[index
]); 
 783         ffi_type 
*field(ffi
->elements
[index
]); 
 786         if (aggregate 
== NULL
) 
 789             rhs 
= CYGetProperty(context
, aggregate
, index
); 
 790             if (JSValueIsUndefined(context
, rhs
)) { 
 791                 if (element
->name 
!= NULL
) 
 792                     rhs 
= CYGetProperty(context
, aggregate
, CYJSString(element
->name
)); 
 795                 if (JSValueIsUndefined(context
, rhs
)) undefined
: 
 796                     throw CYJSError(context
, "unable to extract structure value"); 
 800         element
->type
->PoolFFI(pool
, context
, field
, base
, rhs
); 
 805 void Function::PoolFFI(CYPool 
*pool
, JSContextRef context
, ffi_type 
*ffi
, void *data
, JSValueRef value
) const { 
 809 #define CYFromFFI_(Type_) \ 
 811 JSValueRef Primitive<Type_>::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { \ 
 812     return CYCastJSValue(context, *reinterpret_cast<Type_ *>(data)); \ 
 819 CYFromFFI_(signed char) 
 820 CYFromFFI_(signed int) 
 821 CYFromFFI_(signed long int) 
 822 CYFromFFI_(signed long long int) 
 823 CYFromFFI_(signed short int) 
 824 CYFromFFI_(unsigned char) 
 825 CYFromFFI_(unsigned int) 
 826 CYFromFFI_(unsigned long int) 
 827 CYFromFFI_(unsigned long long int) 
 828 CYFromFFI_(unsigned short int) 
 830 JSValueRef 
Void::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 831     return CYJSUndefined(context
); 
 834 JSValueRef 
Unknown::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 838 JSValueRef 
String::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 839     if (char *value 
= *reinterpret_cast<char **>(data
)) 
 840         return CYMakeCString(context
, value
, owner
); 
 841     return CYJSNull(context
); 
 844 JSValueRef 
Bits::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 848 JSValueRef 
Pointer::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 849     if (void *value 
= *reinterpret_cast<void **>(data
)) 
 850         return CYMakePointer(context
, value
, type
, NULL
, owner
); 
 851     return CYJSNull(context
); 
 854 JSValueRef 
Array::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 855     return CYMakeCArray(context
, data
, size
, type
, ffi
->elements
[0], owner
); 
 858 JSValueRef 
Aggregate::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 859     return CYMakeStruct(context
, data
, *this, ffi
, owner
); 
 862 JSValueRef 
Function::FromFFI(JSContextRef context
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) const { 
 863     return CYMakeFunctor(context
, reinterpret_cast<void (*)()>(data
), signature
); 
 868 void CYExecuteClosure(ffi_cif 
*cif
, void *result
, void **arguments
, void *arg
) { 
 869     Closure_privateData 
*internal(reinterpret_cast<Closure_privateData 
*>(arg
)); 
 871     JSContextRef 
context(internal
->context_
); 
 873     size_t count(internal
->cif_
.nargs
); 
 874     JSValueRef values
[count
]; 
 876     for (size_t index(0); index 
!= count
; ++index
) 
 877         values
[index
] = internal
->signature_
.elements
[1 + index
].type
->FromFFI(context
, internal
->cif_
.arg_types
[index
], arguments
[index
]); 
 879     JSValueRef 
value(internal
->adapter_(context
, count
, values
, internal
->function_
)); 
 880     if (internal
->cif_
.rtype 
!= &ffi_type_void
) 
 881         internal
->signature_
.elements
[0].type
->PoolFFI(NULL
, context
, internal
->cif_
.rtype
, result
, value
); 
 884 static JSValueRef 
FunctionAdapter_(JSContextRef context
, size_t count
, JSValueRef values
[], JSObjectRef function
) { 
 885     return CYCallAsFunction(context
, function
, NULL
, count
, values
); 
 888 Closure_privateData 
*CYMakeFunctor_(JSContextRef context
, JSObjectRef function
, const sig::Signature 
&signature
, JSValueRef (*adapter
)(JSContextRef
, size_t, JSValueRef
[], JSObjectRef
)) { 
 889     // XXX: in case of exceptions this will leak 
 890     // XXX: in point of fact, this may /need/ to leak :( 
 891     Closure_privateData 
*internal(new Closure_privateData(context
, function
, adapter
, signature
)); 
 893 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) 
 895     ffi_closure 
*writable(reinterpret_cast<ffi_closure 
*>(ffi_closure_alloc(sizeof(ffi_closure
), &executable
))); 
 897     ffi_status 
status(ffi_prep_closure_loc(writable
, &internal
->cif_
, &CYExecuteClosure
, internal
, executable
)); 
 898     _assert(status 
== FFI_OK
); 
 900     internal
->value_ 
= executable
; 
 902     ffi_closure 
*closure((ffi_closure 
*) _syscall(mmap( 
 903         NULL
, sizeof(ffi_closure
), 
 904         PROT_READ 
| PROT_WRITE
, MAP_ANON 
| MAP_PRIVATE
, 
 908     ffi_status 
status(ffi_prep_closure(closure
, &internal
->cif_
, &CYExecuteClosure
, internal
)); 
 909     _assert(status 
== FFI_OK
); 
 911     _syscall(mprotect(closure
, sizeof(*closure
), PROT_READ 
| PROT_EXEC
)); 
 913     internal
->value_ 
= closure
; 
 919 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSObjectRef function
, const sig::Signature 
&signature
) { 
 920     Closure_privateData 
*internal(CYMakeFunctor_(context
, function
, signature
, &FunctionAdapter_
)); 
 921     JSObjectRef 
object(JSObjectMake(context
, Functor_
, internal
)); 
 922     // XXX: see above notes about needing to leak 
 923     JSValueProtect(CYGetJSContext(context
), object
); 
 927 JSValueRef 
CYGetCachedValue(JSContextRef context
, JSStringRef name
) { 
 928     return CYGetProperty(context
, CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
)), name
); 
 931 JSObjectRef 
CYGetCachedObject(JSContextRef context
, JSStringRef name
) { 
 932     return CYCastJSObject(context
, CYGetCachedValue(context
, name
)); 
 935 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSValueRef value
, const sig::Signature 
&signature
) { 
 936     JSObjectRef 
Function(CYGetCachedObject(context
, CYJSString("Function"))); 
 938     bool function(_jsccall(JSValueIsInstanceOfConstructor
, context
, value
, Function
)); 
 940         JSObjectRef 
function(CYCastJSObject(context
, value
)); 
 941         return CYMakeFunctor(context
, function
, signature
); 
 943         void (*function
)()(CYCastPointer
<void (*)()>(context
, value
)); 
 944         return CYMakeFunctor(context
, function
, signature
); 
 948 static JSValueRef 
CString_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 950     CString 
*internal(reinterpret_cast<CString 
*>(JSObjectGetPrivate(object
))); 
 951     char *string(static_cast<char *>(internal
->value_
)); 
 954     if (!CYGetOffset(pool
, context
, property
, offset
)) 
 957     return CYCastJSValue(context
, CYJSString(CYUTF8String(&string
[offset
], 1))); 
 960 static bool CString_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 962     CString 
*internal(reinterpret_cast<CString 
*>(JSObjectGetPrivate(object
))); 
 963     char *string(static_cast<char *>(internal
->value_
)); 
 966     if (!CYGetOffset(pool
, context
, property
, offset
)) 
 969     const char *data(CYPoolCString(pool
, context
, value
)); 
 970     string
[offset
] = *data
; 
 974 static bool Index_(CYPool 
&pool
, JSContextRef context
, Struct_privateData 
*internal
, JSStringRef property
, ssize_t 
&index
, uint8_t *&base
) { 
 975     Type_privateData 
*typical(internal
->type_
); 
 976     sig::Aggregate 
*type(static_cast<sig::Aggregate 
*>(typical
->type_
)); 
 980     const char *name(CYPoolCString(pool
, context
, property
)); 
 981     size_t length(strlen(name
)); 
 982     double number(CYCastDouble(name
, length
)); 
 984     size_t count(type
->signature
.count
); 
 986     if (std::isnan(number
)) { 
 987         if (property 
== NULL
) 
 990         sig::Element 
*elements(type
->signature
.elements
); 
 992         for (size_t local(0); local 
!= count
; ++local
) { 
 993             sig::Element 
*element(&elements
[local
]); 
 994             if (element
->name 
!= NULL 
&& strcmp(name
, element
->name
) == 0) { 
1002         index 
= static_cast<ssize_t
>(number
); 
1003         if (index 
!= number 
|| index 
< 0 || static_cast<size_t>(index
) >= count
) 
1008     ffi_type 
**elements(typical
->GetFFI()->elements
); 
1011     for (ssize_t 
local(0); local 
!= index
; ++local
) { 
1012         offset 
+= elements
[local
]->size
; 
1013         CYAlign(offset
, elements
[local 
+ 1]->alignment
); 
1016     base 
= reinterpret_cast<uint8_t *>(internal
->value_
) + offset
; 
1020 static void *Offset_(CYPool 
&pool
, JSContextRef context
, JSStringRef property
, void *data
, ffi_type 
*ffi
) { 
1022     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
1024     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
1026     return reinterpret_cast<uint8_t *>(data
) + ffi
->size 
* offset
; 
1029 static JSValueRef 
Offset_getProperty(CYPool 
&pool
, JSContextRef context
, JSStringRef property
, void *data
, Type_privateData 
*typical
, JSObjectRef owner
) { 
1030     ffi_type 
*ffi(typical
->GetFFI()); 
1031     void *base(Offset_(pool
, context
, property
, data
, ffi
)); 
1034     return typical
->type_
->FromFFI(context
, ffi
, base
, false, owner
); 
1037 static bool Offset_setProperty(CYPool 
&pool
, JSContextRef context
, JSStringRef property
, void *data
, Type_privateData 
*typical
, JSValueRef value
) { 
1038     ffi_type 
*ffi(typical
->GetFFI()); 
1039     void *base(Offset_(pool
, context
, property
, data
, ffi
)); 
1043     typical
->type_
->PoolFFI(NULL
, context
, ffi
, base
, value
); 
1047 static JSValueRef 
CArray_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1049     CArray 
*internal(reinterpret_cast<CArray 
*>(JSObjectGetPrivate(object
))); 
1050     if (JSStringIsEqual(property
, length_s
)) 
1051         return CYCastJSValue(context
, internal
->length_
); 
1052     Type_privateData 
*typical(internal
->type_
); 
1053     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
1054     return Offset_getProperty(pool
, context
, property
, internal
->value_
, typical
, owner
); 
1057 static bool CArray_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
1059     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
1060     Type_privateData 
*typical(internal
->type_
); 
1061     return Offset_setProperty(pool
, context
, property
, internal
->value_
, typical
, value
); 
1064 static JSValueRef 
Pointer_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1066     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
1068     Type_privateData 
*typical(internal
->type_
); 
1070     if (sig::Function 
*function 
= dynamic_cast<sig::Function 
*>(typical
->type_
)) { 
1071         if (!JSStringIsEqualToUTF8CString(property
, "$cyi")) 
1073         return CYMakeFunctor(context
, reinterpret_cast<void (*)()>(internal
->value_
), function
->signature
); 
1076     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
1077     return Offset_getProperty(pool
, context
, property
, internal
->value_
, typical
, owner
); 
1080 static bool Pointer_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
1082     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
1083     Type_privateData 
*typical(internal
->type_
); 
1084     return Offset_setProperty(pool
, context
, property
, internal
->value_
, typical
, value
); 
1087 static JSValueRef Struct_callAsFunction_$
cya(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1088     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(_this
))); 
1089     Type_privateData 
*typical(internal
->type_
); 
1090     return CYMakePointer(context
, internal
->value_
, *typical
->type_
, typical
->ffi_
, _this
); 
1093 static JSValueRef 
Struct_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1094     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
1095     return CYMakeType(context
, *internal
->type_
->type_
); 
1098 static JSValueRef 
Struct_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1100     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
1101     Type_privateData 
*typical(internal
->type_
); 
1102     sig::Aggregate 
*type(static_cast<sig::Aggregate 
*>(typical
->type_
)); 
1107     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
1110     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
1112     return type
->signature
.elements
[index
].type
->FromFFI(context
, typical
->GetFFI()->elements
[index
], base
, false, owner
); 
1115 static bool Struct_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
1117     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
1118     Type_privateData 
*typical(internal
->type_
); 
1119     sig::Aggregate 
*type(static_cast<sig::Aggregate 
*>(typical
->type_
)); 
1124     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
1127     type
->signature
.elements
[index
].type
->PoolFFI(NULL
, context
, typical
->GetFFI()->elements
[index
], base
, value
); 
1131 static void Struct_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
1132     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
1133     Type_privateData 
*typical(internal
->type_
); 
1134     sig::Aggregate 
*type(static_cast<sig::Aggregate 
*>(typical
->type_
)); 
1139     size_t count(type
->signature
.count
); 
1140     sig::Element 
*elements(type
->signature
.elements
); 
1144     for (size_t index(0); index 
!= count
; ++index
) { 
1146         name 
= elements
[index
].name
; 
1149             sprintf(number
, "%zu", index
); 
1153         JSPropertyNameAccumulatorAddName(names
, CYJSString(name
)); 
1157 void CYCallFunction(CYPool 
&pool
, JSContextRef context
, ffi_cif 
*cif
, void (*function
)(), void *value
, void **values
) { 
1158     ffi_call(cif
, function
, value
, values
); 
1161 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
)()) { 
1162     if (setups 
+ count 
!= signature
->count 
- 1) 
1163         throw CYJSError(context
, "incorrect number of arguments to ffi function"); 
1165     size_t size(setups 
+ count
); 
1167     memcpy(values
, setup
, sizeof(void *) * setups
); 
1169     for (size_t index(setups
); index 
!= size
; ++index
) { 
1170         sig::Element 
*element(&signature
->elements
[index 
+ 1]); 
1171         ffi_type 
*ffi(cif
->arg_types
[index
]); 
1172         values
[index
] = pool
.malloc
<uint8_t>(ffi
->size
, ffi
->alignment
); 
1173         element
->type
->PoolFFI(&pool
, context
, ffi
, values
[index
], arguments
[index 
- setups
]); 
1176     uint8_t value
[cif
->rtype
->size
]; 
1178     void (*call
)(CYPool 
&, JSContextRef
, ffi_cif 
*, void (*)(), void *, void **) = &CYCallFunction
; 
1179     // XXX: this only supports one hook, but it is a bad idea anyway 
1180     for (CYHook 
*hook 
: GetHooks()) 
1181         if (hook
->CallFunction 
!= NULL
) 
1182             call 
= hook
->CallFunction
; 
1184     call(pool
, context
, cif
, function
, value
, values
); 
1185     return signature
->elements
[0].type
->FromFFI(context
, cif
->rtype
, value
, initialize
); 
1188 static JSValueRef 
Functor_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1190     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(object
))); 
1191     return CYCallFunction(pool
, context
, 0, NULL
, count
, arguments
, false, &internal
->signature_
, &internal
->cif_
, internal
->GetValue()); 
1194 static JSValueRef 
Pointer_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1195     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
1196     if (dynamic_cast<sig::Function 
*>(internal
->type_
->type_
) == NULL
) 
1197         throw CYJSError(context
, "cannot call a pointer to non-function"); 
1198     JSObjectRef 
functor(CYCastJSObject(context
, CYGetProperty(context
, object
, cyi_s
))); 
1199     return CYCallAsFunction(context
, functor
, _this
, count
, arguments
); 
1202 JSObjectRef 
CYMakeType(JSContextRef context
, const sig::Type 
&type
) { 
1203     Type_privateData 
*internal(new Type_privateData(type
)); 
1204     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
1207 JSObjectRef 
CYMakeType(JSContextRef context
, sig::Signature 
*signature
) { 
1210     sig::Copy(pool
, type
.signature
, *signature
); 
1211     return CYMakeType(context
, type
); 
1214 extern "C" bool CYBridgeHash(CYPool 
&pool
, CYUTF8String name
, const char *&code
, unsigned &flags
) { 
1215     sqlite3_stmt 
*statement
; 
1217     _sqlcall(sqlite3_prepare(database_
, 
1219             "\"cache\".\"code\", " 
1220             "\"cache\".\"flags\" " 
1223             " \"cache\".\"system\" & " CY_SYSTEM 
" == " CY_SYSTEM 
" and" 
1224             " \"cache\".\"name\" = ?" 
1226     , -1, &statement
, NULL
)); 
1228     _sqlcall(sqlite3_bind_text(statement
, 1, name
.data
, name
.size
, SQLITE_STATIC
)); 
1231     if (_sqlcall(sqlite3_step(statement
)) == SQLITE_DONE
) 
1235         code 
= sqlite3_column_pooled(pool
, statement
, 0); 
1236         flags 
= sqlite3_column_int(statement
, 1); 
1239     _sqlcall(sqlite3_finalize(statement
)); 
1243 static bool All_hasProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
) { 
1244     if (JSStringIsEqualToUTF8CString(property
, "errno")) 
1247     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1248     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1249     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1251     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1252         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) 
1253             if (CYHasProperty(context
, space
, property
)) 
1259     if (CYBridgeHash(pool
, CYPoolUTF8String(pool
, context
, property
), code
, flags
)) 
1265 static JSValueRef 
All_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1266     if (JSStringIsEqualToUTF8CString(property
, "errno")) 
1267         return CYCastJSValue(context
, errno
); 
1269     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1270     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1271     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1273     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1274         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) 
1275             if (JSValueRef value 
= CYGetProperty(context
, space
, property
)) 
1276                 if (!JSValueIsUndefined(context
, value
)) 
1282     if (CYBridgeHash(pool
, CYPoolUTF8String(pool
, context
, property
), code
, flags
)) { 
1283         CYUTF8String parsed
; 
1286             parsed 
= CYPoolCode(pool
, code
); 
1287         } catch (const CYException 
&error
) { 
1288             CYThrow("%s", pool
.strcat("error caching ", CYPoolCString(pool
, context
, property
), ": ", error
.PoolCString(pool
), NULL
)); 
1291         JSValueRef 
result(_jsccall(JSEvaluateScript
, context
, CYJSString(parsed
), NULL
, NULL
, 0)); 
1294             JSObjectRef 
cache(CYGetCachedObject(context
, CYJSString("cache"))); 
1295             CYSetProperty(context
, cache
, property
, result
); 
1304 static JSValueRef 
All_complete_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1305     _assert(count 
== 1); 
1307     CYUTF8String 
prefix(CYPoolUTF8String(pool
, context
, CYJSString(context
, arguments
[0]))); 
1309     JSObjectRef 
array(NULL
); 
1312     CYArrayBuilder
<1024> values(context
, array
); 
1314     sqlite3_stmt 
*statement
; 
1316     if (prefix
.size 
== 0) 
1317         _sqlcall(sqlite3_prepare(database_
, 
1319                 "\"cache\".\"name\" " 
1322                 " \"cache\".\"system\" & " CY_SYSTEM 
" == " CY_SYSTEM
 
1323         , -1, &statement
, NULL
)); 
1325         _sqlcall(sqlite3_prepare(database_
, 
1327                 "\"cache\".\"name\" " 
1330                 " \"cache\".\"name\" >= ? and \"cache\".\"name\" < ? and " 
1331                 " \"cache\".\"system\" & " CY_SYSTEM 
" == " CY_SYSTEM
 
1332         , -1, &statement
, NULL
)); 
1334         _sqlcall(sqlite3_bind_text(statement
, 1, prefix
.data
, prefix
.size
, SQLITE_STATIC
)); 
1336         char *after(pool
.strndup(prefix
.data
, prefix
.size
)); 
1337         ++after
[prefix
.size 
- 1]; 
1338         _sqlcall(sqlite3_bind_text(statement
, 2, after
, prefix
.size
, SQLITE_STATIC
)); 
1341     while (_sqlcall(sqlite3_step(statement
)) != SQLITE_DONE
) 
1342         values(CYCastJSValue(context
, CYJSString(sqlite3_column_string(statement
, 0)))); 
1344     _sqlcall(sqlite3_finalize(statement
)); 
1350 static void All_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
1351     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1352     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
1353     JSObjectRef 
alls(CYCastJSObject(context
, CYGetProperty(context
, cycript
, CYJSString("alls")))); 
1355     for (size_t i(0), count(CYArrayLength(context
, alls
)); i 
!= count
; ++i
) 
1356         if (JSObjectRef space 
= CYCastJSObject(context
, CYArrayGet(context
, alls
, count 
- i 
- 1))) { 
1357             JSPropertyNameArrayRef 
subset(JSObjectCopyPropertyNames(context
, space
)); 
1358             for (size_t index(0), count(JSPropertyNameArrayGetCount(subset
)); index 
!= count
; ++index
) 
1359                 JSPropertyNameAccumulatorAddName(names
, JSPropertyNameArrayGetNameAtIndex(subset
, index
)); 
1360             JSPropertyNameArrayRelease(subset
); 
1364 static JSObjectRef 
CArray_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1368 static JSObjectRef 
CString_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1372 static JSObjectRef 
Pointer_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1376 static JSObjectRef 
Type_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1380     } else if (count 
== 1) { 
1381         const char *encoding(CYPoolCString(pool
, context
, arguments
[0])); 
1382         sig::Signature signature
; 
1383         sig::Parse(pool
, &signature
, encoding
, &Structor_
); 
1384         return CYMakeType(context
, *signature
.elements
[0].type
); 
1385     } else if (count 
== 2) { 
1386         JSObjectRef 
types(CYCastJSObject(context
, arguments
[0])); 
1387         size_t count(CYArrayLength(context
, types
)); 
1389         JSObjectRef 
names(CYCastJSObject(context
, arguments
[1])); 
1391         sig::Aggregate 
type(false); 
1392         type
.signature
.elements 
= new(pool
) sig::Element
[count
]; 
1393         type
.signature
.count 
= count
; 
1395         for (size_t i(0); i 
!= count
; ++i
) { 
1396             sig::Element 
&element(type
.signature
.elements
[i
]); 
1397             element
.offset 
= _not(size_t); 
1399             JSValueRef 
name(CYArrayGet(context
, names
, i
)); 
1400             if (JSValueIsUndefined(context
, name
)) 
1401                 element
.name 
= NULL
; 
1403                 element
.name 
= CYPoolCString(pool
, context
, name
); 
1405             JSObjectRef 
object(CYCastJSObject(context
, CYArrayGet(context
, types
, i
))); 
1406             _assert(JSValueIsObjectOfClass(context
, object
, Type_privateData::Class_
)); 
1407             Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1408             element
.type 
= internal
->type_
; 
1411         return CYMakeType(context
, type
); 
1413         throw CYJSError(context
, "incorrect number of arguments to Type constructor"); 
1417 static JSValueRef Type_callAsFunction_$
With(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], sig::Callable 
&type
, JSValueRef 
*exception
) { CYTry 
{ 
1418     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1422     type
.signature
.elements 
= new(pool
) sig::Element
[1 + count
]; 
1423     type
.signature
.count 
= 1 + count
; 
1425     type
.signature
.elements
[0].name 
= NULL
; 
1426     type
.signature
.elements
[0].type 
= internal
->type_
; 
1427     type
.signature
.elements
[0].offset 
= _not(size_t); 
1429     for (size_t i(0); i 
!= count
; ++i
) { 
1430         sig::Element 
&element(type
.signature
.elements
[i 
+ 1]); 
1431         element
.name 
= NULL
; 
1432         element
.offset 
= _not(size_t); 
1434         JSObjectRef 
object(CYCastJSObject(context
, arguments
[i
])); 
1435         _assert(JSValueIsObjectOfClass(context
, object
, Type_privateData::Class_
)); 
1436         Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1438         element
.type 
= internal
->type_
; 
1441     return CYMakeType(context
, type
); 
1444 static JSValueRef 
Type_callAsFunction_arrayOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1446         throw CYJSError(context
, "incorrect number of arguments to Type.arrayOf"); 
1447     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1450     size_t index(CYGetIndex(pool
, context
, CYJSString(context
, arguments
[0]))); 
1451     if (index 
== _not(size_t)) 
1452         throw CYJSError(context
, "invalid array size used with Type.arrayOf"); 
1454     sig::Array 
type(*internal
->type_
, index
); 
1455     return CYMakeType(context
, type
); 
1458 static JSValueRef 
Type_callAsFunction_blockWith(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1460     return Type_callAsFunction_$
With(context
, object
, _this
, count
, arguments
, type
, exception
); 
1463 static JSValueRef 
Type_callAsFunction_constant(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1465         throw CYJSError(context
, "incorrect number of arguments to Type.constant"); 
1466     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1469     sig::Type 
*type(internal
->type_
->Copy(pool
)); 
1470     type
->flags 
|= JOC_TYPE_CONST
; 
1471     return CYMakeType(context
, *type
); 
1474 static JSValueRef 
Type_callAsFunction_functionWith(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1476     return Type_callAsFunction_$
With(context
, object
, _this
, count
, arguments
, type
, exception
); 
1479 static JSValueRef 
Type_callAsFunction_pointerTo(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1481         throw CYJSError(context
, "incorrect number of arguments to Type.pointerTo"); 
1482     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1484     if (dynamic_cast<sig::Primitive
<char> *>(internal
->type_
) != NULL
) 
1485         return CYMakeType(context
, sig::String()); 
1487         return CYMakeType(context
, sig::Pointer(*internal
->type_
)); 
1490 static JSValueRef 
Type_callAsFunction_withName(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1492         throw CYJSError(context
, "incorrect number of arguments to Type.withName"); 
1493     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1496     return CYMakeType(context
, *internal
->type_
->Copy(pool
, CYPoolCString(pool
, context
, arguments
[0]))); 
1499 static JSValueRef 
Type_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1501         throw CYJSError(context
, "incorrect number of arguments to type cast function"); 
1502     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1504     if (sig::Function 
*function 
= dynamic_cast<sig::Function 
*>(internal
->type_
)) 
1505         return CYMakeFunctor(context
, arguments
[0], function
->signature
); 
1508     sig::Type 
*type(internal
->type_
); 
1509     ffi_type 
*ffi(internal
->GetFFI()); 
1510     void *value(pool
.malloc
<void>(ffi
->size
, ffi
->alignment
)); 
1511     type
->PoolFFI(&pool
, context
, ffi
, value
, arguments
[0]); 
1512     return type
->FromFFI(context
, ffi
, value
); 
1515 static JSObjectRef 
Type_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1517         throw CYJSError(context
, "incorrect number of arguments to Type allocator"); 
1518     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1520     JSObjectRef 
pointer(CYMakePointer(context
, NULL
, *internal
->type_
, NULL
, NULL
)); 
1521     Pointer 
*value(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(pointer
))); 
1522     ffi_type 
*ffi(internal
->GetFFI()); 
1523     value
->value_ 
= value
->pool_
->malloc
<void>(ffi
->size
, ffi
->alignment
); 
1524     memset(value
->value_
, 0, ffi
->size
); 
1528 static JSObjectRef 
Functor_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1530         throw CYJSError(context
, "incorrect number of arguments to Functor constructor"); 
1532     const char *encoding(CYPoolCString(pool
, context
, arguments
[1])); 
1533     sig::Signature signature
; 
1534     sig::Parse(pool
, &signature
, encoding
, &Structor_
); 
1535     return CYMakeFunctor(context
, arguments
[0], signature
); 
1538 static JSValueRef 
CArray_callAsFunction_toPointer(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1539     CArray 
*internal(reinterpret_cast<CArray 
*>(JSObjectGetPrivate(_this
))); 
1540     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
1541     return CYMakePointer(context
, internal
->value_
, *internal
->type_
->type_
, NULL
, owner
); 
1544 static JSValueRef 
CString_callAsFunction_toPointer(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1545     CString 
*internal(reinterpret_cast<CString 
*>(JSObjectGetPrivate(_this
))); 
1546     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
1547     return CYMakePointer(context
, internal
->value_
, sig::Primitive
<char>(), NULL
, owner
); 
1550 static JSValueRef Functor_callAsFunction_$
cya(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1552     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(_this
))); 
1555     sig::Copy(pool
, type
.signature
, internal
->signature_
); 
1557     return CYMakePointer(context
, internal
->value_
, type
, NULL
, NULL
); 
1560 static JSValueRef 
Pointer_callAsFunction_toPointer(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1564 static JSValueRef 
CYValue_callAsFunction_valueOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1565     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1566     return CYCastJSValue(context
, reinterpret_cast<uintptr_t>(internal
->value_
)); 
1569 static JSValueRef 
CYValue_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1570     return CYValue_callAsFunction_valueOf(context
, object
, _this
, count
, arguments
, exception
); 
1573 static JSValueRef 
CYValue_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1574     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1575     std::ostringstream str
; 
1577     if (internal
->value_ 
== NULL
) 
1579     else if (dladdr(internal
->value_
, &info
) == 0) 
1580         str 
<< internal
->value_
; 
1582         str 
<< info
.dli_sname
; 
1583         off_t 
offset(static_cast<char *>(internal
->value_
) - static_cast<char *>(info
.dli_saddr
)); 
1585             str 
<< "+0x" << std::hex 
<< offset
; 
1587     std::string 
value(str
.str()); 
1588     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
1591 static JSValueRef 
Pointer_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1592     std::set
<void *> *objects(CYCastObjects(context
, _this
, count
, arguments
)); 
1594     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(_this
))); 
1597         JSValueRef 
value(CYGetProperty(context
, _this
, cyi_s
)); 
1598         if (!JSValueIsUndefined(context
, value
)) { 
1600             return CYCastJSValue(context
, pool
.strcat("&", CYPoolCCYON(pool
, context
, value
, objects
), NULL
)); 
1602     } catch (const CYException 
&e
) { 
1603         // XXX: it might be interesting to include this error 
1607     std::ostringstream str
; 
1609     sig::Pointer 
type(*internal
->type_
->type_
); 
1612     CYOutput 
output(*str
.rdbuf(), options
); 
1613     (new(pool
) CYTypeExpression(CYDecodeType(pool
, &type
)))->Output(output
, CYNoFlags
); 
1615     str 
<< "(" << internal
->value_ 
<< ")"; 
1616     std::string 
value(str
.str()); 
1617     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
1620 static JSValueRef 
CString_getProperty_length(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1621     CString 
*internal(reinterpret_cast<CString 
*>(JSObjectGetPrivate(object
))); 
1622     char *string(static_cast<char *>(internal
->value_
)); 
1623     return CYCastJSValue(context
, strlen(string
)); 
1626 static JSValueRef 
CString_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1627     return CYMakeType(context
, sig::String()); 
1630 static JSValueRef 
CArray_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1631     CArray 
*internal(reinterpret_cast<CArray 
*>(JSObjectGetPrivate(object
))); 
1632     sig::Array 
type(*internal
->type_
->type_
, internal
->length_
); 
1633     return CYMakeType(context
, type
); 
1636 static JSValueRef 
Pointer_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1637     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
1638     sig::Pointer 
type(*internal
->type_
->type_
); 
1639     return CYMakeType(context
, type
); 
1642 static JSValueRef 
CString_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1643     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(_this
))); 
1644     const char *string(static_cast<const char *>(internal
->value_
)); 
1645     std::ostringstream str
; 
1650         CYStringify(str
, string
, strlen(string
), true); 
1652     std::string 
value(str
.str()); 
1653     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
1656 static JSValueRef 
CString_callAsFunction_toString(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1657     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(_this
))); 
1658     const char *string(static_cast<const char *>(internal
->value_
)); 
1659     return CYCastJSValue(context
, string
); 
1662 static JSValueRef 
Functor_getProperty_type(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1663     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(object
))); 
1664     return CYMakeType(context
, &internal
->signature_
); 
1667 static JSValueRef 
Type_getProperty_alignment(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1668     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1669     return CYCastJSValue(context
, internal
->GetFFI()->alignment
); 
1672 static JSValueRef 
Type_getProperty_name(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1673     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1674     return CYCastJSValue(context
, internal
->type_
->GetName()); 
1677 static JSValueRef 
Type_getProperty_size(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1678     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1679     return CYCastJSValue(context
, internal
->GetFFI()->size
); 
1682 static JSValueRef 
Type_callAsFunction_toString(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1683     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1685     const char *type(sig::Unparse(pool
, internal
->type_
)); 
1686     return CYCastJSValue(context
, CYJSString(type
)); 
1689 static JSValueRef 
Type_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1690     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1694     CYOutput 
output(out
, options
); 
1695     (new(pool
) CYTypeExpression(CYDecodeType(pool
, internal
->type_
)))->Output(output
, CYNoFlags
); 
1696     return CYCastJSValue(context
, CYJSString(out
.str().c_str())); 
1699 static JSValueRef 
Type_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1700     return Type_callAsFunction_toString(context
, object
, _this
, count
, arguments
, exception
); 
1703 static JSStaticFunction All_staticFunctions
[2] = { 
1704     {"cy$complete", &All_complete_callAsFunction
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1708 static JSStaticFunction CArray_staticFunctions
[4] = { 
1709     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1710     {"toPointer", &CArray_callAsFunction_toPointer
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1711     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1715 static JSStaticValue CArray_staticValues
[2] = { 
1716     {"type", &CArray_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1717     {NULL
, NULL
, NULL
, 0} 
1720 static JSStaticFunction CString_staticFunctions
[6] = { 
1721     {"toCYON", &CString_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1722     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1723     {"toPointer", &CString_callAsFunction_toPointer
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1724     {"toString", &CString_callAsFunction_toString
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1725     {"valueOf", &CString_callAsFunction_toString
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1729 static JSStaticValue CString_staticValues
[3] = { 
1730     {"length", &CString_getProperty_length
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1731     {"type", &CString_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1732     {NULL
, NULL
, NULL
, 0} 
1735 static JSStaticFunction Pointer_staticFunctions
[5] = { 
1736     {"toCYON", &Pointer_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1737     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1738     {"toPointer", &Pointer_callAsFunction_toPointer
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1739     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1743 static JSStaticValue Pointer_staticValues
[2] = { 
1744     {"type", &Pointer_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1745     {NULL
, NULL
, NULL
, 0} 
1748 static JSStaticFunction Struct_staticFunctions
[2] = { 
1749     {"$cya", &Struct_callAsFunction_$cya
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1753 static JSStaticValue Struct_staticValues
[2] = { 
1754     {"type", &Struct_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1755     {NULL
, NULL
, NULL
, 0} 
1758 static JSStaticFunction Functor_staticFunctions
[5] = { 
1759     {"$cya", &Functor_callAsFunction_$cya
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1760     {"toCYON", &CYValue_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1761     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1762     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1767     JSStaticFunction 
const * const Functor::StaticFunctions 
= Functor_staticFunctions
; 
1770 static JSStaticValue Functor_staticValues
[2] = { 
1771     {"type", &Functor_getProperty_type
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1772     {NULL
, NULL
, NULL
, 0} 
1776     JSStaticValue 
const * const Functor::StaticValues 
= Functor_staticValues
; 
1779 static JSStaticValue Type_staticValues
[4] = { 
1780     {"alignment", &Type_getProperty_alignment
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1781     {"name", &Type_getProperty_name
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1782     {"size", &Type_getProperty_size
, NULL
, kJSPropertyAttributeReadOnly 
| kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1783     {NULL
, NULL
, NULL
, 0} 
1786 static JSStaticFunction Type_staticFunctions
[10] = { 
1787     {"arrayOf", &Type_callAsFunction_arrayOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1788     {"blockWith", &Type_callAsFunction_blockWith
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1789     {"constant", &Type_callAsFunction_constant
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1790     {"functionWith", &Type_callAsFunction_functionWith
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1791     {"pointerTo", &Type_callAsFunction_pointerTo
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1792     {"withName", &Type_callAsFunction_withName
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1793     {"toCYON", &Type_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1794     {"toJSON", &Type_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1795     {"toString", &Type_callAsFunction_toString
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1799 _visible 
void CYSetArgs(int argc
, const char *argv
[]) { 
1800     JSContextRef 
context(CYGetJSContext()); 
1801     JSValueRef args
[argc
]; 
1802     for (int i(0); i 
!= argc
; ++i
) 
1803         args
[i
] = CYCastJSValue(context
, argv
[i
]); 
1805     JSObjectRef 
array(CYObjectMakeArray(context
, argc
, args
)); 
1806     JSObjectRef 
System(CYGetCachedObject(context
, CYJSString("System"))); 
1807     CYSetProperty(context
, System
, CYJSString("args"), array
); 
1810 JSObjectRef 
CYGetGlobalObject(JSContextRef context
) { 
1811     return JSContextGetGlobalObject(context
); 
1814 // XXX: this is neither exceptin safe nor even terribly sane 
1815 class ExecutionHandle 
{ 
1817     JSContextRef context_
; 
1818     std::vector
<void *> handles_
; 
1821     ExecutionHandle(JSContextRef context
) : 
1824         handles_
.resize(GetHooks().size()); 
1825         for (size_t i(0); i 
!= GetHooks().size(); ++i
) { 
1826             CYHook 
*hook(GetHooks()[i
]); 
1827             if (hook
->ExecuteStart 
!= NULL
) 
1828                 handles_
[i
] = (*hook
->ExecuteStart
)(context_
); 
1834     ~ExecutionHandle() { 
1835         for (size_t i(GetHooks().size()); i 
!= 0; --i
) { 
1836             CYHook 
*hook(GetHooks()[i
-1]); 
1837             if (hook
->ExecuteEnd 
!= NULL
) 
1838                 (*hook
->ExecuteEnd
)(context_
, handles_
[i
-1]); 
1843 static volatile bool cancel_
; 
1845 static bool CYShouldTerminate(JSContextRef context
, void *arg
) { 
1849 _visible 
const char *CYExecute(JSContextRef context
, CYPool 
&pool
, CYUTF8String code
) { 
1850     ExecutionHandle 
handle(context
); 
1853     if (&JSContextGroupSetExecutionTimeLimit 
!= NULL
) 
1854         JSContextGroupSetExecutionTimeLimit(JSContextGetGroup(context
), 0.5, &CYShouldTerminate
, NULL
); 
1857         JSValueRef 
result(_jsccall(JSEvaluateScript
, context
, CYJSString(code
), NULL
, NULL
, 0)); 
1858         if (JSValueIsUndefined(context
, result
)) 
1861         std::set
<void *> objects
; 
1862         const char *json(_jsccall(CYPoolCCYON
, pool
, context
, result
, objects
)); 
1863         CYSetProperty(context
, CYGetGlobalObject(context
), Result_
, result
); 
1866     } catch (const CYException 
&error
) { 
1867         return pool
.strcat("throw ", error
.PoolCString(pool
), NULL
); 
1871 _visible 
void CYCancel() { 
1875 static const char *CYPoolLibraryPath(CYPool 
&pool
); 
1877 static bool initialized_ 
= false; 
1879 void CYInitializeDynamic() { 
1881         initialized_ 
= true; 
1885     const char *db(pool
.strcat(CYPoolLibraryPath(pool
), "/libcycript.db", NULL
)); 
1886     _sqlcall(sqlite3_open_v2(db
, &database_
, SQLITE_OPEN_READONLY
, NULL
)); 
1888     JSObjectMakeArray$ 
= reinterpret_cast<JSObjectRef (*)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*)>(dlsym(RTLD_DEFAULT
, "JSObjectMakeArray")); 
1889     JSSynchronousGarbageCollectForDebugging$ 
= reinterpret_cast<void (*)(JSContextRef
)>(dlsym(RTLD_DEFAULT
, "JSSynchronousGarbageCollectForDebugging")); 
1891     JSClassDefinition definition
; 
1893     definition 
= kJSClassDefinitionEmpty
; 
1894     definition
.className 
= "All"; 
1895     definition
.staticFunctions 
= All_staticFunctions
; 
1896     definition
.hasProperty 
= &All_hasProperty
; 
1897     definition
.getProperty 
= &All_getProperty
; 
1898     definition
.getPropertyNames 
= &All_getPropertyNames
; 
1899     All_ 
= JSClassCreate(&definition
); 
1901     definition 
= kJSClassDefinitionEmpty
; 
1902     definition
.className 
= "Context"; 
1903     definition
.finalize 
= &CYFinalize
; 
1904     Context_ 
= JSClassCreate(&definition
); 
1906     definition 
= kJSClassDefinitionEmpty
; 
1907     definition
.className 
= "CArray"; 
1908     definition
.staticFunctions 
= CArray_staticFunctions
; 
1909     definition
.staticValues 
= CArray_staticValues
; 
1910     definition
.getProperty 
= &CArray_getProperty
; 
1911     definition
.setProperty 
= &CArray_setProperty
; 
1912     definition
.finalize 
= &CYFinalize
; 
1913     CArray_ 
= JSClassCreate(&definition
); 
1915     definition 
= kJSClassDefinitionEmpty
; 
1916     definition
.className 
= "CString"; 
1917     definition
.staticFunctions 
= CString_staticFunctions
; 
1918     definition
.staticValues 
= CString_staticValues
; 
1919     definition
.getProperty 
= &CString_getProperty
; 
1920     definition
.setProperty 
= &CString_setProperty
; 
1921     definition
.finalize 
= &CYFinalize
; 
1922     CString_ 
= JSClassCreate(&definition
); 
1924     definition 
= kJSClassDefinitionEmpty
; 
1925     definition
.className 
= "Functor"; 
1926     definition
.staticFunctions 
= cy::Functor::StaticFunctions
; 
1927     definition
.staticValues 
= Functor_staticValues
; 
1928     definition
.callAsFunction 
= &Functor_callAsFunction
; 
1929     definition
.finalize 
= &CYFinalize
; 
1930     Functor_ 
= JSClassCreate(&definition
); 
1932     definition 
= kJSClassDefinitionEmpty
; 
1933     definition
.className 
= "Pointer"; 
1934     definition
.staticFunctions 
= Pointer_staticFunctions
; 
1935     definition
.staticValues 
= Pointer_staticValues
; 
1936     definition
.callAsFunction 
= &Pointer_callAsFunction
; 
1937     definition
.getProperty 
= &Pointer_getProperty
; 
1938     definition
.setProperty 
= &Pointer_setProperty
; 
1939     definition
.finalize 
= &CYFinalize
; 
1940     Pointer_ 
= JSClassCreate(&definition
); 
1942     definition 
= kJSClassDefinitionEmpty
; 
1943     definition
.className 
= "Struct"; 
1944     definition
.staticFunctions 
= Struct_staticFunctions
; 
1945     definition
.staticValues 
= Struct_staticValues
; 
1946     definition
.getProperty 
= &Struct_getProperty
; 
1947     definition
.setProperty 
= &Struct_setProperty
; 
1948     definition
.getPropertyNames 
= &Struct_getPropertyNames
; 
1949     definition
.finalize 
= &CYFinalize
; 
1950     Struct_ 
= JSClassCreate(&definition
); 
1952     definition 
= kJSClassDefinitionEmpty
; 
1953     definition
.className 
= "Type"; 
1954     definition
.staticValues 
= Type_staticValues
; 
1955     definition
.staticFunctions 
= Type_staticFunctions
; 
1956     definition
.callAsFunction 
= &Type_callAsFunction
; 
1957     definition
.callAsConstructor 
= &Type_callAsConstructor
; 
1958     definition
.finalize 
= &CYFinalize
; 
1959     Type_privateData::Class_ 
= JSClassCreate(&definition
); 
1961     definition 
= kJSClassDefinitionEmpty
; 
1962     definition
.className 
= "Global"; 
1963     //definition.getProperty = &Global_getProperty; 
1964     Global_ 
= JSClassCreate(&definition
); 
1966     Array_s 
= JSStringCreateWithUTF8CString("Array"); 
1967     cy_s 
= JSStringCreateWithUTF8CString("$cy"); 
1968     cyi_s 
= JSStringCreateWithUTF8CString("$cyi"); 
1969     length_s 
= JSStringCreateWithUTF8CString("length"); 
1970     message_s 
= JSStringCreateWithUTF8CString("message"); 
1971     name_s 
= JSStringCreateWithUTF8CString("name"); 
1972     pop_s 
= JSStringCreateWithUTF8CString("pop"); 
1973     prototype_s 
= JSStringCreateWithUTF8CString("prototype"); 
1974     push_s 
= JSStringCreateWithUTF8CString("push"); 
1975     splice_s 
= JSStringCreateWithUTF8CString("splice"); 
1976     toCYON_s 
= JSStringCreateWithUTF8CString("toCYON"); 
1977     toJSON_s 
= JSStringCreateWithUTF8CString("toJSON"); 
1978     toPointer_s 
= JSStringCreateWithUTF8CString("toPointer"); 
1979     toString_s 
= JSStringCreateWithUTF8CString("toString"); 
1980     weak_s 
= JSStringCreateWithUTF8CString("weak"); 
1982     Result_ 
= JSStringCreateWithUTF8CString("_"); 
1984     for (CYHook 
*hook 
: GetHooks()) 
1985         if (hook
->Initialize 
!= NULL
) 
1986             (*hook
->Initialize
)(); 
1989 void CYThrow(JSContextRef context
, JSValueRef value
) { 
1991         throw CYJSError(context
, value
); 
1994 const char *CYJSError::PoolCString(CYPool 
&pool
) const { 
1995     std::set
<void *> objects
; 
1996     // XXX: this used to be CYPoolCString 
1997     return CYPoolCCYON(pool
, context_
, value_
, objects
); 
2000 JSValueRef 
CYJSError::CastJSValue(JSContextRef context
, const char *name
) const { 
2001     // XXX: what if the context is different? or the name? I dunno. ("epic" :/) 
2005 JSValueRef 
CYCastJSError(JSContextRef context
, const char *name
, const char *message
) { 
2006     JSObjectRef 
Error(CYGetCachedObject(context
, CYJSString(name
))); 
2007     JSValueRef arguments
[1] = {CYCastJSValue(context
, message
)}; 
2008     return _jsccall(JSObjectCallAsConstructor
, context
, Error
, 1, arguments
); 
2011 JSValueRef 
CYPoolError::CastJSValue(JSContextRef context
, const char *name
) const { 
2012     return CYCastJSError(context
, name
, message_
); 
2015 CYJSError::CYJSError(JSContextRef context
, const char *format
, ...) { 
2016     _assert(context 
!= NULL
); 
2021     va_start(args
, format
); 
2022     // XXX: there might be a beter way to think about this 
2023     const char *message(pool
.vsprintf(64, format
, args
)); 
2026     value_ 
= CYCastJSError(context
, "Error", message
); 
2029 JSGlobalContextRef 
CYGetJSContext(JSContextRef context
) { 
2030     return reinterpret_cast<Context 
*>(JSObjectGetPrivate(CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
))))->context_
; 
2033 static const char *CYPoolLibraryPath(CYPool 
&pool
) { 
2035     _assert(dladdr(reinterpret_cast<void *>(&CYPoolLibraryPath
), &addr
) != 0); 
2036     char *lib(pool
.strdup(addr
.dli_fname
)); 
2038     char *slash(strrchr(lib
, '/')); 
2039     _assert(slash 
!= NULL
); 
2042     slash 
= strrchr(lib
, '/'); 
2043     if (slash 
!= NULL 
&& strcmp(slash
, "/.libs") == 0) 
2049 static JSValueRef 
require_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
2050     _assert(count 
== 1); 
2053     const char *name(CYPoolCString(pool
, context
, arguments
[0])); 
2054     if (strchr(name
, '/') == NULL 
&& ( 
2056         dlopen(pool
.strcat("/System/Library/Frameworks/", name
, ".framework/", name
, NULL
), RTLD_LAZY 
| RTLD_GLOBAL
) != NULL 
|| 
2057         dlopen(pool
.strcat("/System/Library/PrivateFrameworks/", name
, ".framework/", name
, NULL
), RTLD_LAZY 
| RTLD_GLOBAL
) != NULL 
|| 
2060         return CYJSUndefined(context
); 
2062     JSObjectRef 
resolve(CYCastJSObject(context
, CYGetProperty(context
, object
, CYJSString("resolve")))); 
2063     CYJSString 
path(context
, CYCallAsFunction(context
, resolve
, NULL
, 1, arguments
)); 
2065     CYJSString 
property("exports"); 
2067     JSObjectRef 
modules(CYGetCachedObject(context
, CYJSString("modules"))); 
2068     JSValueRef 
cache(CYGetProperty(context
, modules
, path
)); 
2071     if (!JSValueIsUndefined(context
, cache
)) { 
2072         JSObjectRef 
module(CYCastJSObject(context
, cache
)); 
2073         result 
= CYGetProperty(context
, module, property
); 
2075         CYUTF8String 
code(CYPoolFileUTF8String(pool
, CYPoolCString(pool
, context
, path
))); 
2076         _assert(code
.data 
!= NULL
); 
2078         size_t length(strlen(name
)); 
2079         if (length 
>= 5 && strcmp(name 
+ length 
- 5, ".json") == 0) { 
2080             JSObjectRef 
JSON(CYGetCachedObject(context
, CYJSString("JSON"))); 
2081             JSObjectRef 
parse(CYCastJSObject(context
, CYGetProperty(context
, JSON
, CYJSString("parse")))); 
2082             JSValueRef arguments
[1] = { CYCastJSValue(context
, CYJSString(code
)) }; 
2083             result 
= CYCallAsFunction(context
, parse
, JSON
, 1, arguments
); 
2085             JSObjectRef 
module(JSObjectMake(context
, NULL
, NULL
)); 
2086             CYSetProperty(context
, modules
, path
, module); 
2088             JSObjectRef 
exports(JSObjectMake(context
, NULL
, NULL
)); 
2089             CYSetProperty(context
, module, property
, exports
); 
2091             std::stringstream wrap
; 
2092             wrap 
<< "(function (exports, require, module, __filename) { " << code 
<< "\n});"; 
2093             code 
= CYPoolCode(pool
, *wrap
.rdbuf()); 
2095             JSValueRef 
value(_jsccall(JSEvaluateScript
, context
, CYJSString(code
), NULL
, NULL
, 0)); 
2096             JSObjectRef 
function(CYCastJSObject(context
, value
)); 
2098             JSValueRef arguments
[4] = { exports
, object
, module, CYCastJSValue(context
, path
) }; 
2099             CYCallAsFunction(context
, function
, NULL
, 4, arguments
); 
2100             result 
= CYGetProperty(context
, module, property
); 
2107 static bool CYRunScript(JSGlobalContextRef context
, const char *path
) { 
2109     CYUTF8String 
code(CYPoolFileUTF8String(pool
, pool
.strcat(CYPoolLibraryPath(pool
), path
, NULL
))); 
2110     if (code
.data 
== NULL
) 
2113     code 
= CYPoolCode(pool
, code
); 
2114     _jsccall(JSEvaluateScript
, context
, CYJSString(code
), NULL
, NULL
, 0); 
2118 extern "C" void CYDestroyWeak(JSWeakObjectMapRef weak
, void *data
) { 
2121 extern "C" void CYSetupContext(JSGlobalContextRef context
) { 
2122     CYInitializeDynamic(); 
2124     JSObjectRef 
global(CYGetGlobalObject(context
)); 
2126     JSObjectRef 
cy(JSObjectMake(context
, Context_
, new Context(context
))); 
2127     CYSetProperty(context
, global
, cy_s
, cy
, kJSPropertyAttributeDontEnum
); 
2129 /* Cache Globals {{{ */ 
2130     JSObjectRef 
Array(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Array")))); 
2131     CYSetProperty(context
, cy
, CYJSString("Array"), Array
); 
2133     JSObjectRef 
Array_prototype(CYCastJSObject(context
, CYGetProperty(context
, Array
, prototype_s
))); 
2134     CYSetProperty(context
, cy
, CYJSString("Array_prototype"), Array_prototype
); 
2136     JSObjectRef 
Boolean(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Boolean")))); 
2137     CYSetProperty(context
, cy
, CYJSString("Boolean"), Boolean
); 
2139     JSObjectRef 
Boolean_prototype(CYCastJSObject(context
, CYGetProperty(context
, Boolean
, prototype_s
))); 
2140     CYSetProperty(context
, cy
, CYJSString("Boolean_prototype"), Boolean_prototype
); 
2142     JSObjectRef 
Error(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Error")))); 
2143     CYSetProperty(context
, cy
, CYJSString("Error"), Error
); 
2145     JSObjectRef 
Function(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Function")))); 
2146     CYSetProperty(context
, cy
, CYJSString("Function"), Function
); 
2148     JSObjectRef 
Function_prototype(CYCastJSObject(context
, CYGetProperty(context
, Function
, prototype_s
))); 
2149     CYSetProperty(context
, cy
, CYJSString("Function_prototype"), Function_prototype
); 
2151     JSObjectRef 
JSON(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("JSON")))); 
2152     CYSetProperty(context
, cy
, CYJSString("JSON"), JSON
); 
2154     JSObjectRef 
Number(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Number")))); 
2155     CYSetProperty(context
, cy
, CYJSString("Number"), Number
); 
2157     JSObjectRef 
Number_prototype(CYCastJSObject(context
, CYGetProperty(context
, Number
, prototype_s
))); 
2158     CYSetProperty(context
, cy
, CYJSString("Number_prototype"), Number_prototype
); 
2160     JSObjectRef 
Object(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Object")))); 
2161     CYSetProperty(context
, cy
, CYJSString("Object"), Object
); 
2163     JSObjectRef 
Object_prototype(CYCastJSObject(context
, CYGetProperty(context
, Object
, prototype_s
))); 
2164     CYSetProperty(context
, cy
, CYJSString("Object_prototype"), Object_prototype
); 
2166     JSObjectRef 
String(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("String")))); 
2167     CYSetProperty(context
, cy
, CYJSString("String"), String
); 
2169     JSObjectRef 
String_prototype(CYCastJSObject(context
, CYGetProperty(context
, String
, prototype_s
))); 
2170     CYSetProperty(context
, cy
, CYJSString("String_prototype"), String_prototype
); 
2172     JSObjectRef 
SyntaxError(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("SyntaxError")))); 
2173     CYSetProperty(context
, cy
, CYJSString("SyntaxError"), SyntaxError
); 
2176     CYSetProperty(context
, Array_prototype
, toCYON_s
, &Array_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
2177     CYSetProperty(context
, String_prototype
, toCYON_s
, &String_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
2179     JSObjectRef 
cycript(JSObjectMake(context
, NULL
, NULL
)); 
2180     CYSetProperty(context
, global
, CYJSString("Cycript"), cycript
); 
2181     CYSetProperty(context
, cycript
, CYJSString("compile"), &Cycript_compile_callAsFunction
); 
2182     CYSetProperty(context
, cycript
, CYJSString("gc"), &Cycript_gc_callAsFunction
); 
2184     JSObjectRef 
CArray(JSObjectMakeConstructor(context
, CArray_
, &CArray_new
)); 
2185     CYSetPrototype(context
, CYCastJSObject(context
, CYGetProperty(context
, CArray
, prototype_s
)), Array_prototype
); 
2186     CYSetProperty(context
, cycript
, CYJSString("CArray"), CArray
); 
2188     JSObjectRef 
CString(JSObjectMakeConstructor(context
, CString_
, &CString_new
)); 
2189     CYSetPrototype(context
, CYCastJSObject(context
, CYGetProperty(context
, CString
, prototype_s
)), String_prototype
); 
2190     CYSetProperty(context
, cycript
, CYJSString("CString"), CString
); 
2192     JSObjectRef 
Functor(JSObjectMakeConstructor(context
, Functor_
, &Functor_new
)); 
2193     CYSetPrototype(context
, CYCastJSObject(context
, CYGetProperty(context
, Functor
, prototype_s
)), Function_prototype
); 
2194     CYSetProperty(context
, cycript
, CYJSString("Functor"), Functor
); 
2196     CYSetProperty(context
, cycript
, CYJSString("Pointer"), JSObjectMakeConstructor(context
, Pointer_
, &Pointer_new
)); 
2197     CYSetProperty(context
, cycript
, CYJSString("Type"), JSObjectMakeConstructor(context
, Type_privateData::Class_
, &Type_new
)); 
2199     JSObjectRef 
modules(JSObjectMake(context
, NULL
, NULL
)); 
2200     CYSetProperty(context
, cy
, CYJSString("modules"), modules
); 
2202     JSObjectRef 
all(JSObjectMake(context
, All_
, NULL
)); 
2203     CYSetProperty(context
, cycript
, CYJSString("all"), all
); 
2205     JSObjectRef 
cache(JSObjectMake(context
, NULL
, NULL
)); 
2206     CYSetProperty(context
, cy
, CYJSString("cache"), cache
); 
2207     CYSetPrototype(context
, cache
, all
); 
2209     JSObjectRef 
alls(_jsccall(JSObjectCallAsConstructor
, context
, Array
, 0, NULL
)); 
2210     CYSetProperty(context
, cycript
, CYJSString("alls"), alls
); 
2213         JSObjectRef 
last(NULL
), curr(global
); 
2215         goto next
; for (JSValueRef next
;;) { 
2216             if (JSValueIsNull(context
, next
)) 
2219             curr 
= CYCastJSObject(context
, next
); 
2221             next 
= JSObjectGetPrototype(context
, curr
); 
2224         CYSetPrototype(context
, last
, cache
); 
2227     JSObjectRef 
System(JSObjectMake(context
, NULL
, NULL
)); 
2228     CYSetProperty(context
, cy
, CYJSString("System"), System
); 
2230     CYSetProperty(context
, global
, CYJSString("require"), &require_callAsFunction
, kJSPropertyAttributeDontEnum
); 
2232     CYSetProperty(context
, global
, CYJSString("system"), System
); 
2233     CYSetProperty(context
, System
, CYJSString("args"), CYJSNull(context
)); 
2234     CYSetProperty(context
, System
, CYJSString("print"), &System_print
); 
2236     CYSetProperty(context
, global
, CYJSString("global"), global
); 
2239     if (&JSWeakObjectMapCreate 
!= NULL
) { 
2240         JSWeakObjectMapRef 
weak(JSWeakObjectMapCreate(context
, NULL
, &CYDestroyWeak
)); 
2241         CYSetProperty(context
, cy
, weak_s
, CYCastJSValue(context
, reinterpret_cast<uintptr_t>(weak
))); 
2245     CYSetProperty(context
, cache
, CYJSString("dlerror"), CYMakeFunctor(context
, "dlerror", "*"), kJSPropertyAttributeDontEnum
); 
2246     CYSetProperty(context
, cache
, CYJSString("RTLD_DEFAULT"), CYCastJSValue(context
, reinterpret_cast<intptr_t>(RTLD_DEFAULT
)), kJSPropertyAttributeDontEnum
); 
2247     CYSetProperty(context
, cache
, CYJSString("dlsym"), CYMakeFunctor(context
, "dlsym", "^v^v*"), kJSPropertyAttributeDontEnum
); 
2249     CYSetProperty(context
, cache
, CYJSString("NULL"), CYJSNull(context
), kJSPropertyAttributeDontEnum
); 
2251     CYSetProperty(context
, cache
, CYJSString("bool"), CYMakeType(context
, sig::Primitive
<bool>()), kJSPropertyAttributeDontEnum
); 
2252     CYSetProperty(context
, cache
, CYJSString("char"), CYMakeType(context
, sig::Primitive
<char>()), kJSPropertyAttributeDontEnum
); 
2253     CYSetProperty(context
, cache
, CYJSString("schar"), CYMakeType(context
, sig::Primitive
<signed char>()), kJSPropertyAttributeDontEnum
); 
2254     CYSetProperty(context
, cache
, CYJSString("uchar"), CYMakeType(context
, sig::Primitive
<unsigned char>()), kJSPropertyAttributeDontEnum
); 
2256     CYSetProperty(context
, cache
, CYJSString("short"), CYMakeType(context
, sig::Primitive
<short>()), kJSPropertyAttributeDontEnum
); 
2257     CYSetProperty(context
, cache
, CYJSString("int"), CYMakeType(context
, sig::Primitive
<int>()), kJSPropertyAttributeDontEnum
); 
2258     CYSetProperty(context
, cache
, CYJSString("long"), CYMakeType(context
, sig::Primitive
<long>()), kJSPropertyAttributeDontEnum
); 
2259     CYSetProperty(context
, cache
, CYJSString("longlong"), CYMakeType(context
, sig::Primitive
<long long>()), kJSPropertyAttributeDontEnum
); 
2261     CYSetProperty(context
, cache
, CYJSString("ushort"), CYMakeType(context
, sig::Primitive
<unsigned short>()), kJSPropertyAttributeDontEnum
); 
2262     CYSetProperty(context
, cache
, CYJSString("uint"), CYMakeType(context
, sig::Primitive
<unsigned int>()), kJSPropertyAttributeDontEnum
); 
2263     CYSetProperty(context
, cache
, CYJSString("ulong"), CYMakeType(context
, sig::Primitive
<unsigned long>()), kJSPropertyAttributeDontEnum
); 
2264     CYSetProperty(context
, cache
, CYJSString("ulonglong"), CYMakeType(context
, sig::Primitive
<unsigned long long>()), kJSPropertyAttributeDontEnum
); 
2266     CYSetProperty(context
, cache
, CYJSString("float"), CYMakeType(context
, sig::Primitive
<float>()), kJSPropertyAttributeDontEnum
); 
2267     CYSetProperty(context
, cache
, CYJSString("double"), CYMakeType(context
, sig::Primitive
<double>()), kJSPropertyAttributeDontEnum
); 
2269     for (CYHook 
*hook 
: GetHooks()) 
2270         if (hook
->SetupContext 
!= NULL
) 
2271             (*hook
->SetupContext
)(context
); 
2273     CYArrayPush(context
, alls
, cycript
); 
2275     CYRunScript(context
, "/libcycript.cy"); 
2278 static JSGlobalContextRef context_
; 
2280 _visible JSGlobalContextRef 
CYGetJSContext() { 
2281     CYInitializeDynamic(); 
2283     if (context_ 
== NULL
) { 
2284         context_ 
= JSGlobalContextCreate(Global_
); 
2285         CYSetupContext(context_
); 
2291 _visible 
void CYDestroyContext() { 
2292     if (context_ 
== NULL
) 
2294     JSGlobalContextRelease(context_
);