1 /* Cycript - Inlining/Optimizing JavaScript Compiler 
   2  * Copyright (C) 2009  Jay Freeman (saurik) 
   5 /* Modified BSD License {{{ */ 
   7  *        Redistribution and use in source and binary 
   8  * forms, with or without modification, are permitted 
   9  * provided that the following conditions are met: 
  11  * 1. Redistributions of source code must retain the 
  12  *    above copyright notice, this list of conditions 
  13  *    and the following disclaimer. 
  14  * 2. Redistributions in binary form must reproduce the 
  15  *    above copyright notice, this list of conditions 
  16  *    and the following disclaimer in the documentation 
  17  *    and/or other materials provided with the 
  19  * 3. The name of the author may not be used to endorse 
  20  *    or promote products derived from this software 
  21  *    without specific prior written permission. 
  23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 
  24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  25  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 
  28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
  34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  40 #include "Internal.hpp" 
  45 #include "cycript.hpp" 
  47 #include "sig/parse.hpp" 
  48 #include "sig/ffi_type.hpp" 
  50 #include "Pooling.hpp" 
  51 #include "Execute.hpp" 
  56 #include <ext/stdio_filebuf.h> 
  64 #include "Cycript.tab.hh" 
  67 #include "JavaScript.hpp" 
  70 struct CYHooks 
*hooks_
; 
  72 /* JavaScript Properties {{{ */ 
  73 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, size_t index
) { 
  74     JSValueRef 
exception(NULL
); 
  75     JSValueRef 
value(JSObjectGetPropertyAtIndex(context
, object
, index
, &exception
)); 
  76     CYThrow(context
, exception
); 
  80 JSValueRef 
CYGetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
) { 
  81     JSValueRef 
exception(NULL
); 
  82     JSValueRef 
value(JSObjectGetProperty(context
, object
, name
, &exception
)); 
  83     CYThrow(context
, exception
); 
  87 void CYSetProperty(JSContextRef context
, JSObjectRef object
, size_t index
, JSValueRef value
) { 
  88     JSValueRef 
exception(NULL
); 
  89     JSObjectSetPropertyAtIndex(context
, object
, index
, value
, &exception
); 
  90     CYThrow(context
, exception
); 
  93 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef value
, JSPropertyAttributes attributes
) { 
  94     JSValueRef 
exception(NULL
); 
  95     JSObjectSetProperty(context
, object
, name
, value
, attributes
, &exception
); 
  96     CYThrow(context
, exception
); 
  99 void CYSetProperty(JSContextRef context
, JSObjectRef object
, JSStringRef name
, JSValueRef (*callback
)(JSContextRef
, JSObjectRef
, JSObjectRef
, size_t, const JSValueRef
[], JSValueRef 
*), JSPropertyAttributes attributes
) { 
 100     CYSetProperty(context
, object
, name
, JSObjectMakeFunctionWithCallback(context
, name
, callback
), attributes
); 
 103 /* JavaScript Strings {{{ */ 
 104 JSStringRef 
CYCopyJSString(const char *value
) { 
 105     return value 
== NULL 
? NULL 
: JSStringCreateWithUTF8CString(value
); 
 108 JSStringRef 
CYCopyJSString(JSStringRef value
) { 
 109     return value 
== NULL 
? NULL 
: JSStringRetain(value
); 
 112 JSStringRef 
CYCopyJSString(CYUTF8String value
) { 
 113     // XXX: this is very wrong; it needs to convert to UTF16 and then create from there 
 114     return CYCopyJSString(value
.data
); 
 117 JSStringRef 
CYCopyJSString(JSContextRef context
, JSValueRef value
) { 
 118     if (JSValueIsNull(context
, value
)) 
 120     JSValueRef 
exception(NULL
); 
 121     JSStringRef 
string(JSValueToStringCopy(context
, value
, &exception
)); 
 122     CYThrow(context
, exception
); 
 126 static CYUTF16String 
CYCastUTF16String(JSStringRef value
) { 
 127     return CYUTF16String(JSStringGetCharactersPtr(value
), JSStringGetLength(value
)); 
 130 CYUTF8String 
CYPoolUTF8String(apr_pool_t 
*pool
, JSContextRef context
, JSStringRef value
) { 
 131     return CYPoolUTF8String(pool
, CYCastUTF16String(value
)); 
 134 const char *CYPoolCString(apr_pool_t 
*pool
, JSContextRef context
, JSStringRef value
) { 
 135     CYUTF8String 
utf8(CYPoolUTF8String(pool
, context
, value
)); 
 136     _assert(memchr(utf8
.data
, '\0', utf8
.size
) == NULL
); 
 140 const char *CYPoolCString(apr_pool_t 
*pool
, JSContextRef context
, JSValueRef value
) { 
 141     return JSValueIsNull(context
, value
) ? NULL 
: CYPoolCString(pool
, context
, CYJSString(context
, value
)); 
 144 /* Index Offsets {{{ */ 
 145 size_t CYGetIndex(apr_pool_t 
*pool
, JSContextRef context
, JSStringRef value
) { 
 146     return CYGetIndex(CYPoolUTF8String(pool
, context
, value
)); 
 150 static JSClassRef All_
; 
 151 static JSClassRef Context_
; 
 152 static JSClassRef Functor_
; 
 153 static JSClassRef Global_
; 
 154 static JSClassRef Pointer_
; 
 155 static JSClassRef Struct_
; 
 159 JSStringRef length_s
; 
 160 JSStringRef message_s
; 
 163 JSStringRef prototype_s
; 
 165 JSStringRef splice_s
; 
 166 JSStringRef toCYON_s
; 
 167 JSStringRef toJSON_s
; 
 168 JSStringRef toPointer_s
; 
 170 static JSStringRef Result_
; 
 172 void CYFinalize(JSObjectRef object
) { 
 173     CYData 
*internal(reinterpret_cast<CYData 
*>(JSObjectGetPrivate(object
))); 
 174     if (--internal
->count_ 
== 0) 
 178 void Structor_(apr_pool_t 
*pool
, sig::Type 
*&type
) { 
 180         type
->primitive 
== sig::pointer_P 
&& 
 181         type
->data
.data
.type 
!= NULL 
&& 
 182         type
->data
.data
.type
->primitive 
== sig::struct_P 
&& 
 183         type
->data
.data
.type
->name 
!= NULL 
&& 
 184         strcmp(type
->data
.data
.type
->name
, "_objc_class") == 0 
 186         type
->primitive 
= sig::typename_P
; 
 187         type
->data
.data
.type 
= NULL
; 
 191     if (type
->primitive 
!= sig::struct_P 
|| type
->name 
== NULL
) 
 194     size_t length(strlen(type
->name
)); 
 195     char keyed
[length 
+ 2]; 
 196     memcpy(keyed 
+ 1, type
->name
, length 
+ 1); 
 198     static const char *modes 
= "34"; 
 199     for (size_t i(0); i 
!= 2; ++i
) { 
 203         if (CYBridgeEntry 
*entry 
= CYBridgeHash(keyed
, length 
+ 1)) 
 206                     sig::Parse(pool
, &type
->data
.signature
, entry
->value_
, &Structor_
); 
 210                     sig::Signature signature
; 
 211                     sig::Parse(pool
, &signature
, entry
->value_
, &Structor_
); 
 212                     type 
= signature
.elements
[0].type
; 
 218 JSClassRef 
Type_privateData::Class_
; 
 223     JSGlobalContextRef context_
; 
 225     Context(JSGlobalContextRef context
) : 
 234     Type_privateData 
*type_
; 
 237     Pointer(void *value
, JSContextRef context
, JSObjectRef owner
, size_t length
, sig::Type 
*type
) : 
 238         CYOwned(value
, context
, owner
), 
 239         type_(new(pool_
) Type_privateData(type
)), 
 245 struct Struct_privateData 
: 
 248     Type_privateData 
*type_
; 
 250     Struct_privateData(JSContextRef context
, JSObjectRef owner
) : 
 251         CYOwned(NULL
, context
, owner
) 
 256 typedef std::map
<const char *, Type_privateData 
*, CYCStringLess
> TypeMap
; 
 257 static TypeMap Types_
; 
 259 JSObjectRef 
CYMakeStruct(JSContextRef context
, void *data
, sig::Type 
*type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 260     Struct_privateData 
*internal(new Struct_privateData(context
, owner
)); 
 261     apr_pool_t 
*pool(internal
->pool_
); 
 262     Type_privateData 
*typical(new(pool
) Type_privateData(type
, ffi
)); 
 263     internal
->type_ 
= typical
; 
 266         internal
->value_ 
= data
; 
 268         size_t size(typical
->GetFFI()->size
); 
 269         void *copy(apr_palloc(internal
->pool_
, size
)); 
 270         memcpy(copy
, data
, size
); 
 271         internal
->value_ 
= copy
; 
 274     return JSObjectMake(context
, Struct_
, internal
); 
 277 JSValueRef 
CYCastJSValue(JSContextRef context
, bool value
) { 
 278     return JSValueMakeBoolean(context
, value
); 
 281 JSValueRef 
CYCastJSValue(JSContextRef context
, double value
) { 
 282     return JSValueMakeNumber(context
, value
); 
 285 #define CYCastJSValue_(Type_) \ 
 286     JSValueRef CYCastJSValue(JSContextRef context, Type_ value) { \ 
 287         return JSValueMakeNumber(context, static_cast<double>(value)); \ 
 291 CYCastJSValue_(unsigned int) 
 292 CYCastJSValue_(long int) 
 293 CYCastJSValue_(long unsigned int) 
 294 CYCastJSValue_(long long int) 
 295 CYCastJSValue_(long long unsigned int) 
 297 JSValueRef 
CYJSUndefined(JSContextRef context
) { 
 298     return JSValueMakeUndefined(context
); 
 301 double CYCastDouble(JSContextRef context
, JSValueRef value
) { 
 302     JSValueRef 
exception(NULL
); 
 303     double number(JSValueToNumber(context
, value
, &exception
)); 
 304     CYThrow(context
, exception
); 
 308 bool CYCastBool(JSContextRef context
, JSValueRef value
) { 
 309     return JSValueToBoolean(context
, value
); 
 312 JSValueRef 
CYJSNull(JSContextRef context
) { 
 313     return JSValueMakeNull(context
); 
 316 JSValueRef 
CYCastJSValue(JSContextRef context
, JSStringRef value
) { 
 317     return value 
== NULL 
? CYJSNull(context
) : JSValueMakeString(context
, value
); 
 320 JSValueRef 
CYCastJSValue(JSContextRef context
, const char *value
) { 
 321     return CYCastJSValue(context
, CYJSString(value
)); 
 324 JSObjectRef 
CYCastJSObject(JSContextRef context
, JSValueRef value
) { 
 325     JSValueRef 
exception(NULL
); 
 326     JSObjectRef 
object(JSValueToObject(context
, value
, &exception
)); 
 327     CYThrow(context
, exception
); 
 331 JSValueRef 
CYCallAsFunction(JSContextRef context
, JSObjectRef function
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[]) { 
 332     JSValueRef 
exception(NULL
); 
 333     JSValueRef 
value(JSObjectCallAsFunction(context
, function
, _this
, count
, arguments
, &exception
)); 
 334     CYThrow(context
, exception
); 
 338 bool CYIsCallable(JSContextRef context
, JSValueRef value
) { 
 339     return value 
!= NULL 
&& JSValueIsObject(context
, value
) && JSObjectIsFunction(context
, (JSObjectRef
) value
); 
 342 static JSValueRef 
System_print(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 347         printf("%s\n", CYPoolCString(pool
, context
, arguments
[0])); 
 350     return CYJSUndefined(context
); 
 353 static size_t Nonce_(0); 
 355 static JSValueRef $
cyq(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 357     const char *name(apr_psprintf(pool
, "%s%"APR_SIZE_T_FMT
"", CYPoolCString(pool
, context
, arguments
[0]), Nonce_
++)); 
 358     return CYCastJSValue(context
, name
); 
 361 static JSValueRef 
Cycript_gc_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 362     JSGarbageCollect(context
); 
 363     return CYJSUndefined(context
); 
 366 const char *CYPoolCCYON(apr_pool_t 
*pool
, JSContextRef context
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 367     switch (JSType type 
= JSValueGetType(context
, value
)) { 
 368         case kJSTypeUndefined
: 
 373             return CYCastBool(context
, value
) ? "true" : "false"; 
 375         case kJSTypeNumber
: { 
 376             std::ostringstream str
; 
 377             CYNumerify(str
, CYCastDouble(context
, value
)); 
 378             std::string 
value(str
.str()); 
 379             return apr_pstrmemdup(pool
, value
.c_str(), value
.size()); 
 382         case kJSTypeString
: { 
 383             std::ostringstream str
; 
 384             CYUTF8String 
string(CYPoolUTF8String(pool
, context
, CYJSString(context
, value
))); 
 385             CYStringify(str
, string
.data
, string
.size
); 
 386             std::string 
value(str
.str()); 
 387             return apr_pstrmemdup(pool
, value
.c_str(), value
.size()); 
 391             return CYPoolCCYON(pool
, context
, (JSObjectRef
) value
); 
 393             throw CYJSError(context
, "JSValueGetType() == 0x%x", type
); 
 397 const char *CYPoolCCYON(apr_pool_t 
*pool
, JSContextRef context
, JSValueRef value
) { 
 398     JSValueRef 
exception(NULL
); 
 399     const char *cyon(CYPoolCCYON(pool
, context
, value
, &exception
)); 
 400     CYThrow(context
, exception
); 
 404 const char *CYPoolCCYON(apr_pool_t 
*pool
, JSContextRef context
, JSObjectRef object
) { 
 405     JSValueRef 
toCYON(CYGetProperty(context
, object
, toCYON_s
)); 
 406     if (CYIsCallable(context
, toCYON
)) { 
 407         JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toCYON
, object
, 0, NULL
)); 
 408         _assert(value 
!= NULL
); 
 409         return CYPoolCString(pool
, context
, value
); 
 412     JSValueRef 
toJSON(CYGetProperty(context
, object
, toJSON_s
)); 
 413     if (CYIsCallable(context
, toJSON
)) { 
 414         JSValueRef arguments
[1] = {CYCastJSValue(context
, CYJSString(""))}; 
 415         JSValueRef 
exception(NULL
); 
 416         const char *cyon(CYPoolCCYON(pool
, context
, CYCallAsFunction(context
, (JSObjectRef
) toJSON
, object
, 1, arguments
), &exception
)); 
 417         CYThrow(context
, exception
); 
 421     std::ostringstream str
; 
 425     // XXX: this is, sadly, going to leak 
 426     JSPropertyNameArrayRef 
names(JSObjectCopyPropertyNames(context
, object
)); 
 430     for (size_t index(0), count(JSPropertyNameArrayGetCount(names
)); index 
!= count
; ++index
) { 
 431         JSStringRef 
name(JSPropertyNameArrayGetNameAtIndex(names
, index
)); 
 432         JSValueRef 
value(CYGetProperty(context
, object
, name
)); 
 439         CYUTF8String 
string(CYPoolUTF8String(pool
, context
, name
)); 
 443             CYStringify(str
, string
.data
, string
.size
); 
 445         str 
<< ':' << CYPoolCCYON(pool
, context
, value
); 
 450     JSPropertyNameArrayRelease(names
); 
 452     std::string 
string(str
.str()); 
 453     return apr_pstrmemdup(pool
, string
.c_str(), string
.size()); 
 456 static JSValueRef 
Array_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
 458     std::ostringstream str
; 
 462     JSValueRef 
length(CYGetProperty(context
, _this
, length_s
)); 
 465     for (size_t index(0), count(CYCastDouble(context
, length
)); index 
!= count
; ++index
) { 
 466         JSValueRef 
value(CYGetProperty(context
, _this
, index
)); 
 473         if (!JSValueIsUndefined(context
, value
)) 
 474             str 
<< CYPoolCCYON(pool
, context
, value
); 
 483     std::string 
value(str
.str()); 
 484     return CYCastJSValue(context
, CYJSString(CYUTF8String(value
.c_str(), value
.size()))); 
 487 JSObjectRef 
CYMakePointer(JSContextRef context
, void *pointer
, size_t length
, sig::Type 
*type
, ffi_type 
*ffi
, JSObjectRef owner
) { 
 488     Pointer 
*internal(new Pointer(pointer
, context
, owner
, length
, type
)); 
 489     return JSObjectMake(context
, Pointer_
, internal
); 
 492 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, void (*function
)(), const char *type
, void **cache 
= NULL
) { 
 493     cy::Functor 
*internal
; 
 495     if (cache 
!= NULL 
&& *cache 
!= NULL
) { 
 496         internal 
= reinterpret_cast<cy::Functor 
*>(*cache
); 
 499         internal 
= new cy::Functor(type
, function
); 
 507     return JSObjectMake(context
, Functor_
, internal
); 
 510 static bool CYGetOffset(apr_pool_t 
*pool
, JSContextRef context
, JSStringRef value
, ssize_t 
&index
) { 
 511     return CYGetOffset(CYPoolCString(pool
, context
, value
), index
); 
 514 void *CYCastPointer_(JSContextRef context
, JSValueRef value
) { 
 515     switch (JSValueGetType(context
, value
)) { 
 518         case kJSTypeObject
: { 
 519             JSObjectRef 
object((JSObjectRef
) value
); 
 520             if (JSValueIsObjectOfClass(context
, value
, Pointer_
)) { 
 521                 Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 522                 return internal
->value_
; 
 524             JSValueRef 
toPointer(CYGetProperty(context
, object
, toPointer_s
)); 
 525             if (CYIsCallable(context
, toPointer
)) { 
 526                 JSValueRef 
value(CYCallAsFunction(context
, (JSObjectRef
) toPointer
, object
, 0, NULL
)); 
 527                 _assert(value 
!= NULL
); 
 528                 return CYCastPointer_(context
, value
); 
 531             double number(CYCastDouble(context
, value
)); 
 532             if (std::isnan(number
)) 
 533                 throw CYJSError(context
, "cannot convert value to pointer"); 
 534             return reinterpret_cast<void *>(static_cast<uintptr_t>(static_cast<long long>(number
))); 
 538 void CYPoolFFI(apr_pool_t 
*pool
, JSContextRef context
, sig::Type 
*type
, ffi_type 
*ffi
, void *data
, JSValueRef value
) { 
 539     switch (type
->primitive
) { 
 541             *reinterpret_cast<bool *>(data
) = JSValueToBoolean(context
, value
); 
 544 #define CYPoolFFI_(primitive, native) \ 
 545         case sig::primitive ## _P: \ 
 546             *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \ 
 549         CYPoolFFI_(uchar
, unsigned char) 
 550         CYPoolFFI_(char, char) 
 551         CYPoolFFI_(ushort
, unsigned short) 
 552         CYPoolFFI_(short, short) 
 553         CYPoolFFI_(ulong
, unsigned long) 
 554         CYPoolFFI_(long, long) 
 555         CYPoolFFI_(uint
, unsigned int) 
 557         CYPoolFFI_(ulonglong
, unsigned long long) 
 558         CYPoolFFI_(longlong
, long long) 
 559         CYPoolFFI_(float, float) 
 560         CYPoolFFI_(double, double) 
 563             uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 564             JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 565             for (size_t index(0); index 
!= type
->data
.data
.size
; ++index
) { 
 566                 ffi_type 
*field(ffi
->elements
[index
]); 
 569                 if (aggregate 
== NULL
) 
 572                     rhs 
= CYGetProperty(context
, aggregate
, index
); 
 573                     if (JSValueIsUndefined(context
, rhs
)) 
 574                         throw CYJSError(context
, "unable to extract array value"); 
 577                 CYPoolFFI(pool
, context
, type
->data
.data
.type
, field
, base
, rhs
); 
 584             *reinterpret_cast<void **>(data
) = CYCastPointer
<void *>(context
, value
); 
 588             *reinterpret_cast<const char **>(data
) = CYPoolCString(pool
, context
, value
); 
 591         case sig::struct_P
: { 
 592             uint8_t *base(reinterpret_cast<uint8_t *>(data
)); 
 593             JSObjectRef 
aggregate(JSValueIsObject(context
, value
) ? (JSObjectRef
) value 
: NULL
); 
 594             for (size_t index(0); index 
!= type
->data
.signature
.count
; ++index
) { 
 595                 sig::Element 
*element(&type
->data
.signature
.elements
[index
]); 
 596                 ffi_type 
*field(ffi
->elements
[index
]); 
 599                 if (aggregate 
== NULL
) 
 602                     rhs 
= CYGetProperty(context
, aggregate
, index
); 
 603                     if (JSValueIsUndefined(context
, rhs
)) { 
 604                         if (element
->name 
!= NULL
) 
 605                             rhs 
= CYGetProperty(context
, aggregate
, CYJSString(element
->name
)); 
 608                         if (JSValueIsUndefined(context
, rhs
)) undefined
: 
 609                             throw CYJSError(context
, "unable to extract structure value"); 
 613                 CYPoolFFI(pool
, context
, element
->type
, field
, base
, rhs
); 
 623             if (hooks_ 
!= NULL 
&& hooks_
->PoolFFI 
!= NULL
) 
 624                 if ((*hooks_
->PoolFFI
)(pool
, context
, type
, ffi
, data
, value
)) 
 627             CYThrow("unimplemented signature code: '%c''\n", type
->primitive
); 
 631 JSValueRef 
CYFromFFI(JSContextRef context
, sig::Type 
*type
, ffi_type 
*ffi
, void *data
, bool initialize
, JSObjectRef owner
) { 
 632     switch (type
->primitive
) { 
 634             return CYCastJSValue(context
, *reinterpret_cast<bool *>(data
)); 
 636 #define CYFromFFI_(primitive, native) \ 
 637         case sig::primitive ## _P: \ 
 638             return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \ 
 640         CYFromFFI_(uchar, unsigned char) 
 641         CYFromFFI_(char, char) 
 642         CYFromFFI_(ushort
, unsigned short) 
 643         CYFromFFI_(short, short) 
 644         CYFromFFI_(ulong
, unsigned long) 
 645         CYFromFFI_(long, long) 
 646         CYFromFFI_(uint
, unsigned int) 
 648         CYFromFFI_(ulonglong
, unsigned long long) 
 649         CYFromFFI_(longlong
, long long) 
 650         CYFromFFI_(float, float) 
 651         CYFromFFI_(double, double) 
 654             if (void *pointer 
= data
) 
 655                 return CYMakePointer(context
, pointer
, type
->data
.data
.size
, type
->data
.data
.type
, NULL
, owner
); 
 659             if (void *pointer 
= *reinterpret_cast<void **>(data
)) 
 660                 return CYMakePointer(context
, pointer
, _not(size_t), type
->data
.data
.type
, NULL
, owner
); 
 664             if (char *utf8 
= *reinterpret_cast<char **>(data
)) 
 665                 return CYCastJSValue(context
, utf8
); 
 669             return CYMakeStruct(context
, data
, type
, ffi
, owner
); 
 671             return CYJSUndefined(context
); 
 674             return CYJSNull(context
); 
 676             if (hooks_ 
!= NULL 
&& hooks_
->FromFFI 
!= NULL
) 
 677                 if (JSValueRef value 
= (*hooks_
->FromFFI
)(context
, type
, ffi
, data
, initialize
, owner
)) 
 680             CYThrow("unimplemented signature code: '%c''\n", type
->primitive
); 
 684 static void FunctionClosure_(ffi_cif 
*cif
, void *result
, void **arguments
, void *arg
) { 
 685     Closure_privateData 
*internal(reinterpret_cast<Closure_privateData 
*>(arg
)); 
 687     JSContextRef 
context(internal
->context_
); 
 689     size_t count(internal
->cif_
.nargs
); 
 690     JSValueRef values
[count
]; 
 692     for (size_t index(0); index 
!= count
; ++index
) 
 693         values
[index
] = CYFromFFI(context
, internal
->signature_
.elements
[1 + index
].type
, internal
->cif_
.arg_types
[index
], arguments
[index
]); 
 695     JSValueRef 
value(CYCallAsFunction(context
, internal
->function_
, NULL
, count
, values
)); 
 696     CYPoolFFI(NULL
, context
, internal
->signature_
.elements
[0].type
, internal
->cif_
.rtype
, result
, value
); 
 699 Closure_privateData 
*CYMakeFunctor_(JSContextRef context
, JSObjectRef function
, const char *type
, void (*callback
)(ffi_cif 
*, void *, void **, void *)) { 
 700     // XXX: in case of exceptions this will leak 
 701     // XXX: in point of fact, this may /need/ to leak :( 
 702     Closure_privateData 
*internal(new Closure_privateData(context
, function
, type
)); 
 704     ffi_closure 
*closure((ffi_closure 
*) _syscall(mmap( 
 705         NULL
, sizeof(ffi_closure
), 
 706         PROT_READ 
| PROT_WRITE
, MAP_ANON 
| MAP_PRIVATE
, 
 710     ffi_status 
status(ffi_prep_closure(closure
, &internal
->cif_
, callback
, internal
)); 
 711     _assert(status 
== FFI_OK
); 
 713     _syscall(mprotect(closure
, sizeof(*closure
), PROT_READ 
| PROT_EXEC
)); 
 715     internal
->value_ 
= closure
; 
 720 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSObjectRef function
, const char *type
) { 
 721     Closure_privateData 
*internal(CYMakeFunctor_(context
, function
, type
, &FunctionClosure_
)); 
 722     JSObjectRef 
object(JSObjectMake(context
, Functor_
, internal
)); 
 723     // XXX: see above notes about needing to leak 
 724     JSValueProtect(CYGetJSContext(context
), object
); 
 728 JSObjectRef 
CYGetCachedObject(JSContextRef context
, JSStringRef name
) { 
 729     return CYCastJSObject(context
, CYGetProperty(context
, CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
)), name
)); 
 732 static JSObjectRef 
CYMakeFunctor(JSContextRef context
, JSValueRef value
, const char *type
) { 
 733     JSObjectRef 
Function(CYGetCachedObject(context
, CYJSString("Function"))); 
 735     JSValueRef 
exception(NULL
); 
 736     bool function(JSValueIsInstanceOfConstructor(context
, value
, Function
, &exception
)); 
 737     CYThrow(context
, exception
); 
 740         JSObjectRef 
function(CYCastJSObject(context
, value
)); 
 741         return CYMakeFunctor(context
, function
, type
); 
 743         void (*function
)()(CYCastPointer
<void (*)()>(context
, value
)); 
 744         return CYMakeFunctor(context
, function
, type
); 
 748 static bool Index_(apr_pool_t 
*pool
, JSContextRef context
, Struct_privateData 
*internal
, JSStringRef property
, ssize_t 
&index
, uint8_t *&base
) { 
 749     Type_privateData 
*typical(internal
->type_
); 
 750     sig::Type 
*type(typical
->type_
); 
 754     const char *name(CYPoolCString(pool
, context
, property
)); 
 755     size_t length(strlen(name
)); 
 756     double number(CYCastDouble(name
, length
)); 
 758     size_t count(type
->data
.signature
.count
); 
 760     if (std::isnan(number
)) { 
 761         if (property 
== NULL
) 
 764         sig::Element 
*elements(type
->data
.signature
.elements
); 
 766         for (size_t local(0); local 
!= count
; ++local
) { 
 767             sig::Element 
*element(&elements
[local
]); 
 768             if (element
->name 
!= NULL 
&& strcmp(name
, element
->name
) == 0) { 
 776         index 
= static_cast<ssize_t
>(number
); 
 777         if (index 
!= number 
|| index 
< 0 || static_cast<size_t>(index
) >= count
) 
 782     ffi_type 
**elements(typical
->GetFFI()->elements
); 
 784     base 
= reinterpret_cast<uint8_t *>(internal
->value_
); 
 785     for (ssize_t 
local(0); local 
!= index
; ++local
) 
 786         base 
+= elements
[local
]->size
; 
 791 static JSValueRef 
Pointer_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 793     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 795     if (JSStringIsEqual(property
, length_s
)) 
 796         return internal
->length_ 
== _not(size_t) ? CYJSUndefined(context
) : CYCastJSValue(context
, internal
->length_
); 
 798     Type_privateData 
*typical(internal
->type_
); 
 800     if (typical
->type_ 
== NULL
) 
 804     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
 806     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
 809     ffi_type 
*ffi(typical
->GetFFI()); 
 811     uint8_t *base(reinterpret_cast<uint8_t *>(internal
->value_
)); 
 812     base 
+= ffi
->size 
* offset
; 
 814     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
 815     return CYFromFFI(context
, typical
->type_
, ffi
, base
, false, owner
); 
 818 static bool Pointer_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 820     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(object
))); 
 821     Type_privateData 
*typical(internal
->type_
); 
 823     if (typical
->type_ 
== NULL
) 
 827     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) 
 829     else if (!CYGetOffset(pool
, context
, property
, offset
)) 
 832     ffi_type 
*ffi(typical
->GetFFI()); 
 834     uint8_t *base(reinterpret_cast<uint8_t *>(internal
->value_
)); 
 835     base 
+= ffi
->size 
* offset
; 
 837     CYPoolFFI(NULL
, context
, typical
->type_
, ffi
, base
, value
); 
 841 static JSValueRef Struct_callAsFunction_$
cya(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 842     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(_this
))); 
 843     Type_privateData 
*typical(internal
->type_
); 
 844     return CYMakePointer(context
, internal
->value_
, _not(size_t), typical
->type_
, typical
->ffi_
, _this
); 
 847 static JSValueRef 
Struct_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 849     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 850     Type_privateData 
*typical(internal
->type_
); 
 855     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
 858     JSObjectRef 
owner(internal
->GetOwner() ?: object
); 
 860     return CYFromFFI(context
, typical
->type_
->data
.signature
.elements
[index
].type
, typical
->GetFFI()->elements
[index
], base
, false, owner
); 
 863 static bool Struct_setProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef value
, JSValueRef 
*exception
) { CYTry 
{ 
 865     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 866     Type_privateData 
*typical(internal
->type_
); 
 871     if (!Index_(pool
, context
, internal
, property
, index
, base
)) 
 874     CYPoolFFI(NULL
, context
, typical
->type_
->data
.signature
.elements
[index
].type
, typical
->GetFFI()->elements
[index
], base
, value
); 
 878 static void Struct_getPropertyNames(JSContextRef context
, JSObjectRef object
, JSPropertyNameAccumulatorRef names
) { 
 879     Struct_privateData 
*internal(reinterpret_cast<Struct_privateData 
*>(JSObjectGetPrivate(object
))); 
 880     Type_privateData 
*typical(internal
->type_
); 
 881     sig::Type 
*type(typical
->type_
); 
 886     size_t count(type
->data
.signature
.count
); 
 887     sig::Element 
*elements(type
->data
.signature
.elements
); 
 891     for (size_t index(0); index 
!= count
; ++index
) { 
 893         name 
= elements
[index
].name
; 
 896             sprintf(number
, "%zu", index
); 
 900         JSPropertyNameAccumulatorAddName(names
, CYJSString(name
)); 
 904 JSValueRef 
CYCallFunction(apr_pool_t 
*pool
, JSContextRef context
, size_t setups
, void *setup
[], size_t count
, const JSValueRef arguments
[], bool initialize
, JSValueRef 
*exception
, sig::Signature 
*signature
, ffi_cif 
*cif
, void (*function
)()) { CYTry 
{ 
 905     if (setups 
+ count 
!= signature
->count 
- 1) 
 906         throw CYJSError(context
, "incorrect number of arguments to ffi function"); 
 908     size_t size(setups 
+ count
); 
 910     memcpy(values
, setup
, sizeof(void *) * setups
); 
 912     for (size_t index(setups
); index 
!= size
; ++index
) { 
 913         sig::Element 
*element(&signature
->elements
[index 
+ 1]); 
 914         ffi_type 
*ffi(cif
->arg_types
[index
]); 
 916         values
[index
] = new(pool
) uint8_t[ffi
->size
]; 
 917         CYPoolFFI(pool
, context
, element
->type
, ffi
, values
[index
], arguments
[index 
- setups
]); 
 920     uint8_t value
[cif
->rtype
->size
]; 
 922     if (hooks_ 
!= NULL 
&& hooks_
->CallFunction 
!= NULL
) 
 923         (*hooks_
->CallFunction
)(context
, cif
, function
, value
, values
); 
 925         ffi_call(cif
, function
, value
, values
); 
 927     return CYFromFFI(context
, signature
->elements
[0].type
, cif
->rtype
, value
, initialize
); 
 930 static JSValueRef 
Functor_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
 932     cy::Functor 
*internal(reinterpret_cast<cy::Functor 
*>(JSObjectGetPrivate(object
))); 
 933     return CYCallFunction(pool
, context
, 0, NULL
, count
, arguments
, false, exception
, &internal
->signature_
, &internal
->cif_
, internal
->GetValue()); 
 936 static JSObjectRef 
CYMakeType(JSContextRef context
, const char *type
) { 
 937     Type_privateData 
*internal(new Type_privateData(type
)); 
 938     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
 941 static JSObjectRef 
CYMakeType(JSContextRef context
, sig::Type 
*type
) { 
 942     Type_privateData 
*internal(new Type_privateData(type
)); 
 943     return JSObjectMake(context
, Type_privateData::Class_
, internal
); 
 946 static void *CYCastSymbol(const char *name
) { 
 947     return dlsym(RTLD_DEFAULT
, name
); 
 950 static JSValueRef 
All_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
 951     JSObjectRef 
global(CYGetGlobalObject(context
)); 
 952     JSObjectRef 
cycript(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Cycript")))); 
 953     if (JSValueRef value 
= CYGetProperty(context
, cycript
, property
)) 
 954         if (!JSValueIsUndefined(context
, value
)) 
 958     CYUTF8String 
name(CYPoolUTF8String(pool
, context
, property
)); 
 960     if (hooks_ 
!= NULL 
&& hooks_
->RuntimeProperty 
!= NULL
) 
 961         if (JSValueRef value 
= (*hooks_
->RuntimeProperty
)(context
, name
)) 
 964     size_t length(name
.size
); 
 965     char keyed
[length 
+ 2]; 
 966     memcpy(keyed 
+ 1, name
.data
, length 
+ 1); 
 968     static const char *modes 
= "0124"; 
 969     for (size_t i(0); i 
!= 4; ++i
) { 
 973         if (CYBridgeEntry 
*entry 
= CYBridgeHash(keyed
, length 
+ 1)) 
 976                     return JSEvaluateScript(CYGetJSContext(context
), CYJSString(entry
->value_
), NULL
, NULL
, 0, NULL
); 
 979                     if (void (*symbol
)() = reinterpret_cast<void (*)()>(CYCastSymbol(name
.data
))) 
 980                         return CYMakeFunctor(context
, symbol
, entry
->value_
, &entry
->cache_
); 
 984                     if (void *symbol 
= CYCastSymbol(name
.data
)) { 
 985                         // XXX: this is horrendously inefficient 
 986                         sig::Signature signature
; 
 987                         sig::Parse(pool
, &signature
, entry
->value_
, &Structor_
); 
 989                         sig::sig_ffi_cif(pool
, &sig::ObjectiveC
, &signature
, &cif
); 
 990                         return CYFromFFI(context
, signature
.elements
[0].type
, cif
.rtype
, symbol
); 
 993                 // XXX: implement case 3 
 995                     return CYMakeType(context
, entry
->value_
); 
1002 static JSObjectRef 
Pointer_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1004         throw CYJSError(context
, "incorrect number of arguments to Functor constructor"); 
1008     void *value(CYCastPointer
<void *>(context
, arguments
[0])); 
1009     const char *type(CYPoolCString(pool
, context
, arguments
[1])); 
1011     sig::Signature signature
; 
1012     sig::Parse(pool
, &signature
, type
, &Structor_
); 
1014     return CYMakePointer(context
, value
, _not(size_t), signature
.elements
[0].type
, NULL
, NULL
); 
1017 static JSObjectRef 
Type_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1019         throw CYJSError(context
, "incorrect number of arguments to Type constructor"); 
1021     const char *type(CYPoolCString(pool
, context
, arguments
[0])); 
1022     return CYMakeType(context
, type
); 
1025 static JSValueRef 
Type_getProperty(JSContextRef context
, JSObjectRef object
, JSStringRef property
, JSValueRef 
*exception
) { CYTry 
{ 
1026     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1030     if (JSStringIsEqualToUTF8CString(property
, "$cyi")) { 
1031         type
.primitive 
= sig::pointer_P
; 
1032         type
.data
.data
.size 
= 0; 
1035         size_t index(CYGetIndex(pool
, context
, property
)); 
1036         if (index 
== _not(size_t)) 
1038         type
.primitive 
= sig::array_P
; 
1039         type
.data
.data
.size 
= index
; 
1045     type
.data
.data
.type 
= internal
->type_
; 
1047     return CYMakeType(context
, &type
); 
1050 static JSValueRef 
Type_callAsFunction(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1051     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1054         throw CYJSError(context
, "incorrect number of arguments to type cast function"); 
1055     sig::Type 
*type(internal
->type_
); 
1056     ffi_type 
*ffi(internal
->GetFFI()); 
1058     uint8_t value
[ffi
->size
]; 
1060     CYPoolFFI(pool
, context
, type
, ffi
, value
, arguments
[0]); 
1061     return CYFromFFI(context
, type
, ffi
, value
); 
1064 static JSObjectRef 
Type_callAsConstructor(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1066         throw CYJSError(context
, "incorrect number of arguments to type cast function"); 
1067     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(object
))); 
1069     sig::Type 
*type(internal
->type_
); 
1072     if (type
->primitive 
!= sig::array_P
) 
1073         length 
= _not(size_t); 
1075         length 
= type
->data
.data
.size
; 
1076         type 
= type
->data
.data
.type
; 
1079     void *value(malloc(internal
->GetFFI()->size
)); 
1080     return CYMakePointer(context
, value
, length
, type
, NULL
, NULL
); 
1083 static JSObjectRef 
Functor_new(JSContextRef context
, JSObjectRef object
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1085         throw CYJSError(context
, "incorrect number of arguments to Functor constructor"); 
1087     const char *type(CYPoolCString(pool
, context
, arguments
[1])); 
1088     return CYMakeFunctor(context
, arguments
[0], type
); 
1091 static JSValueRef 
CYValue_callAsFunction_valueOf(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1092     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1093     return CYCastJSValue(context
, reinterpret_cast<uintptr_t>(internal
->value_
)); 
1096 static JSValueRef 
CYValue_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1097     return CYValue_callAsFunction_valueOf(context
, object
, _this
, count
, arguments
, exception
); 
1100 static JSValueRef 
CYValue_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1101     CYValue 
*internal(reinterpret_cast<CYValue 
*>(JSObjectGetPrivate(_this
))); 
1103     sprintf(string
, "%p", internal
->value_
); 
1104     return CYCastJSValue(context
, string
); 
1107 static JSValueRef 
Pointer_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1108     Pointer 
*internal(reinterpret_cast<Pointer 
*>(JSObjectGetPrivate(_this
))); 
1109     if (internal
->length_ 
!= _not(size_t)) { 
1110         JSObjectRef 
Array(CYGetCachedObject(context
, Array_s
)); 
1111         JSObjectRef 
toCYON(CYCastJSObject(context
, CYGetProperty(context
, Array
, toCYON_s
))); 
1112         return CYCallAsFunction(context
, toCYON
, _this
, count
, arguments
); 
1115         sprintf(string
, "%p", internal
->value_
); 
1116         return CYCastJSValue(context
, string
); 
1120 static JSValueRef 
Type_callAsFunction_toString(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1121     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1123     const char *type(sig::Unparse(pool
, internal
->type_
)); 
1124     return CYCastJSValue(context
, CYJSString(type
)); 
1127 static JSValueRef 
Type_callAsFunction_toCYON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { CYTry 
{ 
1128     Type_privateData 
*internal(reinterpret_cast<Type_privateData 
*>(JSObjectGetPrivate(_this
))); 
1130     const char *type(sig::Unparse(pool
, internal
->type_
)); 
1131     size_t size(strlen(type
)); 
1132     char *cyon(new(pool
) char[12 + size 
+ 1]); 
1133     memcpy(cyon
, "new Type(\"", 10); 
1134     cyon
[12 + size
] = '\0'; 
1135     cyon
[12 + size 
- 2] = '"'; 
1136     cyon
[12 + size 
- 1] = ')'; 
1137     memcpy(cyon 
+ 10, type
, size
); 
1138     return CYCastJSValue(context
, CYJSString(cyon
)); 
1141 static JSValueRef 
Type_callAsFunction_toJSON(JSContextRef context
, JSObjectRef object
, JSObjectRef _this
, size_t count
, const JSValueRef arguments
[], JSValueRef 
*exception
) { 
1142     return Type_callAsFunction_toString(context
, object
, _this
, count
, arguments
, exception
); 
1145 static JSStaticFunction Pointer_staticFunctions
[4] = { 
1146     {"toCYON", &Pointer_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1147     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1148     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1152 static JSStaticFunction Struct_staticFunctions
[2] = { 
1153     {"$cya", &Struct_callAsFunction_$cya
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1157 static JSStaticFunction Functor_staticFunctions
[4] = { 
1158     {"toCYON", &CYValue_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1159     {"toJSON", &CYValue_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1160     {"valueOf", &CYValue_callAsFunction_valueOf
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1165     JSStaticFunction 
const * const Functor::StaticFunctions 
= Functor_staticFunctions
; 
1168 static JSStaticFunction Type_staticFunctions
[4] = { 
1169     {"toCYON", &Type_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1170     {"toJSON", &Type_callAsFunction_toJSON
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1171     {"toString", &Type_callAsFunction_toString
, kJSPropertyAttributeDontEnum 
| kJSPropertyAttributeDontDelete
}, 
1175 static JSObjectRef (*JSObjectMakeArray$
)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*); 
1177 void CYSetArgs(int argc
, const char *argv
[]) { 
1178     JSContextRef 
context(CYGetJSContext()); 
1179     JSValueRef args
[argc
]; 
1180     for (int i(0); i 
!= argc
; ++i
) 
1181         args
[i
] = CYCastJSValue(context
, argv
[i
]); 
1184     if (JSObjectMakeArray$ 
!= NULL
) { 
1185         JSValueRef 
exception(NULL
); 
1186         array 
= (*JSObjectMakeArray$
)(context
, argc
, args
, &exception
); 
1187         CYThrow(context
, exception
); 
1189         JSObjectRef 
Array(CYGetCachedObject(context
, CYJSString("Array"))); 
1190         JSValueRef 
value(CYCallAsFunction(context
, Array
, NULL
, argc
, args
)); 
1191         array 
= CYCastJSObject(context
, value
); 
1194     JSObjectRef 
System(CYGetCachedObject(context
, CYJSString("System"))); 
1195     CYSetProperty(context
, System
, CYJSString("args"), array
); 
1198 JSObjectRef 
CYGetGlobalObject(JSContextRef context
) { 
1199     return JSContextGetGlobalObject(context
); 
1202 const char *CYExecute(apr_pool_t 
*pool
, const char *code
) { 
1203     JSContextRef 
context(CYGetJSContext()); 
1204     JSValueRef 
exception(NULL
), result
; 
1207     if (hooks_ 
!= NULL 
&& hooks_
->ExecuteStart 
!= NULL
) 
1208         handle 
= (*hooks_
->ExecuteStart
)(context
); 
1215         result 
= JSEvaluateScript(context
, CYJSString(code
), NULL
, NULL
, 0, &exception
); 
1216     } catch (const char *error
) { 
1220     if (exception 
!= NULL
) { error
: 
1225     if (JSValueIsUndefined(context
, result
)) 
1229         json 
= CYPoolCCYON(pool
, context
, result
, &exception
); 
1230     } catch (const char *error
) { 
1234     if (exception 
!= NULL
) 
1237     CYSetProperty(context
, CYGetGlobalObject(context
), Result_
, result
); 
1239     if (hooks_ 
!= NULL 
&& hooks_
->ExecuteEnd 
!= NULL
) 
1240         (*hooks_
->ExecuteEnd
)(context
, handle
); 
1244 extern "C" void CydgetSetupContext(JSGlobalContextRef context
) { 
1245     CYSetupContext(context
); 
1248 static bool initialized_ 
= false; 
1250 void CYInitializeDynamic() { 
1252         initialized_ 
= true; 
1255     CYInitializeStatic(); 
1257     JSObjectMakeArray$ 
= reinterpret_cast<JSObjectRef (*)(JSContextRef
, size_t, const JSValueRef
[], JSValueRef 
*)>(dlsym(RTLD_DEFAULT
, "JSObjectMakeArray")); 
1259     JSClassDefinition definition
; 
1261     definition 
= kJSClassDefinitionEmpty
; 
1262     definition
.className 
= "All"; 
1263     definition
.getProperty 
= &All_getProperty
; 
1264     All_ 
= JSClassCreate(&definition
); 
1266     definition 
= kJSClassDefinitionEmpty
; 
1267     definition
.className 
= "Context"; 
1268     definition
.finalize 
= &CYFinalize
; 
1269     Context_ 
= JSClassCreate(&definition
); 
1271     definition 
= kJSClassDefinitionEmpty
; 
1272     definition
.className 
= "Functor"; 
1273     definition
.staticFunctions 
= cy::Functor::StaticFunctions
; 
1274     definition
.callAsFunction 
= &Functor_callAsFunction
; 
1275     definition
.finalize 
= &CYFinalize
; 
1276     Functor_ 
= JSClassCreate(&definition
); 
1278     definition 
= kJSClassDefinitionEmpty
; 
1279     definition
.className 
= "Pointer"; 
1280     definition
.staticFunctions 
= Pointer_staticFunctions
; 
1281     definition
.getProperty 
= &Pointer_getProperty
; 
1282     definition
.setProperty 
= &Pointer_setProperty
; 
1283     definition
.finalize 
= &CYFinalize
; 
1284     Pointer_ 
= JSClassCreate(&definition
); 
1286     definition 
= kJSClassDefinitionEmpty
; 
1287     definition
.className 
= "Struct"; 
1288     definition
.staticFunctions 
= Struct_staticFunctions
; 
1289     definition
.getProperty 
= &Struct_getProperty
; 
1290     definition
.setProperty 
= &Struct_setProperty
; 
1291     definition
.getPropertyNames 
= &Struct_getPropertyNames
; 
1292     definition
.finalize 
= &CYFinalize
; 
1293     Struct_ 
= JSClassCreate(&definition
); 
1295     definition 
= kJSClassDefinitionEmpty
; 
1296     definition
.className 
= "Type"; 
1297     definition
.staticFunctions 
= Type_staticFunctions
; 
1298     definition
.getProperty 
= &Type_getProperty
; 
1299     definition
.callAsFunction 
= &Type_callAsFunction
; 
1300     definition
.callAsConstructor 
= &Type_callAsConstructor
; 
1301     definition
.finalize 
= &CYFinalize
; 
1302     Type_privateData::Class_ 
= JSClassCreate(&definition
); 
1304     definition 
= kJSClassDefinitionEmpty
; 
1305     definition
.className 
= "Global"; 
1306     //definition.getProperty = &Global_getProperty; 
1307     Global_ 
= JSClassCreate(&definition
); 
1309     Array_s 
= JSStringCreateWithUTF8CString("Array"); 
1310     cy_s 
= JSStringCreateWithUTF8CString("$cy"); 
1311     length_s 
= JSStringCreateWithUTF8CString("length"); 
1312     message_s 
= JSStringCreateWithUTF8CString("message"); 
1313     name_s 
= JSStringCreateWithUTF8CString("name"); 
1314     pop_s 
= JSStringCreateWithUTF8CString("pop"); 
1315     prototype_s 
= JSStringCreateWithUTF8CString("prototype"); 
1316     push_s 
= JSStringCreateWithUTF8CString("push"); 
1317     splice_s 
= JSStringCreateWithUTF8CString("splice"); 
1318     toCYON_s 
= JSStringCreateWithUTF8CString("toCYON"); 
1319     toJSON_s 
= JSStringCreateWithUTF8CString("toJSON"); 
1320     toPointer_s 
= JSStringCreateWithUTF8CString("toPointer"); 
1322     Result_ 
= JSStringCreateWithUTF8CString("_"); 
1324     if (hooks_ 
!= NULL 
&& hooks_
->Initialize 
!= NULL
) 
1325         (*hooks_
->Initialize
)(); 
1328 void CYThrow(JSContextRef context
, JSValueRef value
) { 
1330         throw CYJSError(context
, value
); 
1333 const char *CYJSError::PoolCString(apr_pool_t 
*pool
) const { 
1334     // XXX: this used to be CYPoolCString 
1335     return CYPoolCCYON(pool
, context_
, value_
); 
1338 JSValueRef 
CYJSError::CastJSValue(JSContextRef context
) const { 
1339     // XXX: what if the context is different? 
1343 JSValueRef 
CYCastJSError(JSContextRef context
, const char *message
) { 
1344     JSObjectRef 
Error(CYGetCachedObject(context
, CYJSString("Error"))); 
1346     JSValueRef arguments
[1] = {CYCastJSValue(context
, message
)}; 
1348     JSValueRef 
exception(NULL
); 
1349     JSValueRef 
value(JSObjectCallAsConstructor(context
, Error
, 1, arguments
, &exception
)); 
1350     CYThrow(context
, exception
); 
1355 JSValueRef 
CYPoolError::CastJSValue(JSContextRef context
) const { 
1356     return CYCastJSError(context
, message_
); 
1359 CYJSError::CYJSError(JSContextRef context
, const char *format
, ...) { 
1360     _assert(context 
!= NULL
); 
1365     va_start(args
, format
); 
1366     const char *message(apr_pvsprintf(pool
, format
, args
)); 
1369     value_ 
= CYCastJSError(context
, message
); 
1372 JSGlobalContextRef 
CYGetJSContext(JSContextRef context
) { 
1373     return reinterpret_cast<Context 
*>(JSObjectGetPrivate(CYCastJSObject(context
, CYGetProperty(context
, CYGetGlobalObject(context
), cy_s
))))->context_
; 
1376 extern "C" void CYSetupContext(JSGlobalContextRef context
) { 
1377     CYInitializeDynamic(); 
1379     JSObjectRef 
global(CYGetGlobalObject(context
)); 
1381     JSObjectRef 
cy(JSObjectMake(context
, Context_
, new Context(context
))); 
1382     CYSetProperty(context
, global
, cy_s
, cy
, kJSPropertyAttributeDontEnum
); 
1384 /* Cache Globals {{{ */ 
1385     JSObjectRef 
Array(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Array")))); 
1386     CYSetProperty(context
, cy
, CYJSString("Array"), Array
); 
1388     JSObjectRef 
Array_prototype(CYCastJSObject(context
, CYGetProperty(context
, Array
, prototype_s
))); 
1389     CYSetProperty(context
, cy
, CYJSString("Array_prototype"), Array_prototype
); 
1391     JSObjectRef 
Error(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Error")))); 
1392     CYSetProperty(context
, cy
, CYJSString("Error"), Error
); 
1394     JSObjectRef 
Function(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Function")))); 
1395     CYSetProperty(context
, cy
, CYJSString("Function"), Function
); 
1397     JSObjectRef 
Function_prototype(CYCastJSObject(context
, CYGetProperty(context
, Function
, prototype_s
))); 
1398     CYSetProperty(context
, cy
, CYJSString("Function_prototype"), Function_prototype
); 
1400     JSObjectRef 
Object(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("Object")))); 
1401     CYSetProperty(context
, cy
, CYJSString("Object"), Object
); 
1403     JSObjectRef 
Object_prototype(CYCastJSObject(context
, CYGetProperty(context
, Object
, prototype_s
))); 
1404     CYSetProperty(context
, cy
, CYJSString("Object_prototype"), Object_prototype
); 
1406     JSObjectRef 
String(CYCastJSObject(context
, CYGetProperty(context
, global
, CYJSString("String")))); 
1407     CYSetProperty(context
, cy
, CYJSString("String"), String
); 
1410     CYSetProperty(context
, Array_prototype
, toCYON_s
, &Array_callAsFunction_toCYON
, kJSPropertyAttributeDontEnum
); 
1412     JSObjectRef 
cycript(JSObjectMake(context
, NULL
, NULL
)); 
1413     CYSetProperty(context
, global
, CYJSString("Cycript"), cycript
); 
1414     CYSetProperty(context
, cycript
, CYJSString("gc"), &Cycript_gc_callAsFunction
); 
1416     JSObjectRef 
Functor(JSObjectMakeConstructor(context
, Functor_
, &Functor_new
)); 
1417     JSObjectSetPrototype(context
, CYCastJSObject(context
, CYGetProperty(context
, Functor
, prototype_s
)), Function_prototype
); 
1418     CYSetProperty(context
, cycript
, CYJSString("Functor"), Functor
); 
1420     CYSetProperty(context
, cycript
, CYJSString("Pointer"), JSObjectMakeConstructor(context
, Pointer_
, &Pointer_new
)); 
1421     CYSetProperty(context
, cycript
, CYJSString("Type"), JSObjectMakeConstructor(context
, Type_privateData::Class_
, &Type_new
)); 
1423     JSObjectRef 
all(JSObjectMake(context
, All_
, NULL
)); 
1424     CYSetProperty(context
, cycript
, CYJSString("all"), all
); 
1427         JSObjectRef 
last(NULL
), curr(global
); 
1429         goto next
; for (JSValueRef next
;;) { 
1430             if (JSValueIsNull(context
, next
)) 
1433             curr 
= CYCastJSObject(context
, next
); 
1435             next 
= JSObjectGetPrototype(context
, curr
); 
1438         JSObjectSetPrototype(context
, last
, all
); 
1441     CYSetProperty(context
, global
, CYJSString("$cyq"), &$cyq
, kJSPropertyAttributeDontEnum
); 
1443     JSObjectRef 
System(JSObjectMake(context
, NULL
, NULL
)); 
1444     CYSetProperty(context
, cy
, CYJSString("System"), System
); 
1446     CYSetProperty(context
, global
, CYJSString("system"), System
); 
1447     CYSetProperty(context
, System
, CYJSString("args"), CYJSNull(context
)); 
1448     //CYSetProperty(context, System, CYJSString("global"), global); 
1449     CYSetProperty(context
, System
, CYJSString("print"), &System_print
); 
1451     if (hooks_ 
!= NULL 
&& hooks_
->SetupContext 
!= NULL
) 
1452         (*hooks_
->SetupContext
)(context
); 
1455 JSGlobalContextRef 
CYGetJSContext() { 
1456     CYInitializeDynamic(); 
1458     static JSGlobalContextRef context_
; 
1460     if (context_ 
== NULL
) { 
1461         context_ 
= JSGlobalContextCreate(Global_
); 
1462         CYSetupContext(context_
);