X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/b5dd57dc1e068c730142fb1007ce6c43a6ef7090..00b9328fc47038f081ad49fff7c14cc6a7d212b3:/Library.cpp diff --git a/Library.cpp b/Library.cpp index cccd69b..ca7b1af 100644 --- a/Library.cpp +++ b/Library.cpp @@ -112,6 +112,10 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, J JSObjectSetProperty(context, object, name, value, attributes, &exception); CYThrow(context, exception); } + +void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes = kJSPropertyAttributeNone) { + CYSetProperty(context, object, name, JSObjectMakeFunctionWithCallback(context, name, callback), attributes); +} /* }}} */ /* JavaScript Strings {{{ */ JSStringRef CYCopyJSString(const char *value) { @@ -186,19 +190,25 @@ const char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef val /* Index Offsets {{{ */ size_t CYGetIndex(const CYUTF8String &value) { if (value.data[0] != '0') { - char *end; - size_t index(strtoul(value.data, &end, 10)); - if (value.data + value.size == end) - return index; - } else if (value.data[1] == '\0') + size_t index(0); + for (size_t i(0); i != value.size; ++i) { + if (!DigitRange_[value.data[i]]) + return _not(size_t); + index *= 10; + index += value.data[i] - '0'; + } + return index; + } else if (value.size == 1) return 0; - return _not(size_t); + else + return _not(size_t); } size_t CYGetIndex(apr_pool_t *pool, JSContextRef context, JSStringRef value) { return CYGetIndex(CYPoolUTF8String(pool, context, value)); } +// XXX: this isn't actually right bool CYGetOffset(const char *value, ssize_t &index) { if (value[0] != '0') { char *end; @@ -294,31 +304,31 @@ static JSGlobalContextRef Context_; static JSObjectRef System_; static JSClassRef Functor_; +static JSClassRef Global_; static JSClassRef Pointer_; static JSClassRef Runtime_; static JSClassRef Struct_; -static JSStringRef Result_; - JSObjectRef Array_; JSObjectRef Error_; JSObjectRef Function_; JSObjectRef String_; -JSStringRef length_; -JSStringRef message_; -JSStringRef name_; -JSStringRef prototype_; -JSStringRef toCYON_; -JSStringRef toJSON_; - -JSObjectRef Object_prototype_; +JSObjectRef Array_prototype_; JSObjectRef Function_prototype_; +JSObjectRef Object_prototype_; -JSObjectRef Array_prototype_; -JSObjectRef Array_pop_; -JSObjectRef Array_push_; -JSObjectRef Array_splice_; +JSStringRef length_s; +JSStringRef message_s; +JSStringRef name_s; +JSStringRef pop_s; +JSStringRef prototype_s; +JSStringRef push_s; +JSStringRef splice_s; +JSStringRef toCYON_s; +JSStringRef toJSON_s; + +static JSStringRef Result_; sqlite3 *Bridge_; @@ -334,8 +344,19 @@ struct CStringMapLess : } }; -void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *&type) { - if (name == NULL) +void Structor_(apr_pool_t *pool, sig::Type *&type) { + if ( + type->primitive == sig::pointer_P && + type->data.data.type != NULL && + type->data.data.type->primitive == sig::struct_P && + strcmp(type->data.data.type->name, "_objc_class") == 0 + ) { + type->primitive = sig::typename_P; + type->data.data.type = NULL; + return; + } + + if (type->primitive != sig::struct_P || type->name == NULL) return; sqlite3_stmt *statement; @@ -351,7 +372,7 @@ void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type " limit 1" , -1, &statement, NULL)); - _sqlcall(sqlite3_bind_text(statement, 1, name, -1, SQLITE_STATIC)); + _sqlcall(sqlite3_bind_text(statement, 1, type->name, -1, SQLITE_STATIC)); int mode; const char *value; @@ -390,10 +411,12 @@ struct Pointer : CYOwned { Type_privateData *type_; + size_t length_; - Pointer(void *value, JSContextRef context, JSObjectRef owner, sig::Type *type) : + Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, sig::Type *type) : CYOwned(value, context, owner), - type_(new(pool_) Type_privateData(type)) + type_(new(pool_) Type_privateData(type)), + length_(length) { } }; @@ -522,7 +545,7 @@ static size_t Nonce_(0); static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYPool pool; - const char *name(apr_psprintf(pool, "%s%zu", CYPoolCString(pool, context, arguments[0]), Nonce_++)); + const char *name(apr_psprintf(pool, "%s%"APR_SIZE_T_FMT"", CYPoolCString(pool, context, arguments[0]), Nonce_++)); return CYCastJSValue(context, name); } @@ -570,13 +593,13 @@ const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value } const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { - JSValueRef toCYON(CYGetProperty(context, object, toCYON_)); + JSValueRef toCYON(CYGetProperty(context, object, toCYON_s)); if (CYIsCallable(context, toCYON)) { JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toCYON, object, 0, NULL)); return CYPoolCString(pool, context, value); } - JSValueRef toJSON(CYGetProperty(context, object, toJSON_)); + JSValueRef toJSON(CYGetProperty(context, object, toJSON_s)); if (CYIsCallable(context, toJSON)) { JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(""))}; JSValueRef exception(NULL); @@ -626,7 +649,7 @@ static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef str << '['; - JSValueRef length(CYGetProperty(context, _this, length_)); + JSValueRef length(CYGetProperty(context, _this, length_s)); bool comma(false); for (size_t index(0), count(CYCastDouble(context, length)); index != count; ++index) { @@ -651,8 +674,8 @@ static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size()))); } CYCatch } -JSObjectRef CYMakePointer(JSContextRef context, void *pointer, sig::Type *type, ffi_type *ffi, JSObjectRef owner) { - Pointer *internal(new Pointer(pointer, context, owner, type)); +JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner) { + Pointer *internal(new Pointer(pointer, context, owner, length, type)); return JSObjectMake(context, Pointer_, internal); } @@ -706,6 +729,27 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type CYPoolFFI_(float, float) CYPoolFFI_(double, double) + case sig::array_P: { + uint8_t *base(reinterpret_cast(data)); + JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL); + for (size_t index(0); index != type->data.data.size; ++index) { + ffi_type *field(ffi->elements[index]); + + JSValueRef rhs; + if (aggregate == NULL) + rhs = value; + else { + rhs = CYGetProperty(context, aggregate, index); + if (JSValueIsUndefined(context, rhs)) + throw CYJSError(context, "unable to extract array value"); + } + + CYPoolFFI(pool, context, type->data.data.type, field, base, rhs); + // XXX: alignment? + base += field->size; + } + } break; + case sig::pointer_P: *reinterpret_cast(data) = CYCastPointer(context, value); break; @@ -750,8 +794,7 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type if ((*hooks_->PoolFFI)(pool, context, type, ffi, data, value)) return; - fprintf(stderr, "CYPoolFFI(%c)\n", type->primitive); - _assert(false); + CYThrow("unimplemented signature code: '%c''\n", type->primitive); } } @@ -777,9 +820,14 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void CYFromFFI_(float, float) CYFromFFI_(double, double) + case sig::array_P: + if (void *pointer = data) + return CYMakePointer(context, pointer, type->data.data.size, type->data.data.type, NULL, owner); + else goto null; + case sig::pointer_P: if (void *pointer = *reinterpret_cast(data)) - return CYMakePointer(context, pointer, type->data.data.type, ffi, owner); + return CYMakePointer(context, pointer, _not(size_t), type->data.data.type, NULL, owner); else goto null; case sig::string_P: @@ -799,8 +847,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void if (JSValueRef value = (*hooks_->FromFFI)(context, type, ffi, data, initialize, owner)) return value; - fprintf(stderr, "CYFromFFI(%c)\n", type->primitive); - _assert(false); + CYThrow("unimplemented signature code: '%c''\n", type->primitive); } } @@ -822,7 +869,7 @@ static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) { // XXX: in case of exceptions this will leak // XXX: in point of fact, this may /need/ to leak :( - Closure_privateData *internal(new Closure_privateData(CYGetJSContext(), function, type)); + Closure_privateData *internal(new Closure_privateData(context, function, type)); ffi_closure *closure((ffi_closure *) _syscall(mmap( NULL, sizeof(ffi_closure), @@ -902,52 +949,34 @@ static bool Index_(apr_pool_t *pool, JSContextRef context, Struct_privateData *i return true; } -static JSValueRef Pointer_getIndex(JSContextRef context, JSObjectRef object, size_t index, JSValueRef *exception) { CYTry { +static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYPool pool; Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); - Type_privateData *typical(internal->type_); - - ffi_type *ffi(typical->GetFFI()); - - uint8_t *base(reinterpret_cast(internal->value_)); - base += ffi->size * index; - JSObjectRef owner(internal->GetOwner() ?: object); - return CYFromFFI(context, typical->type_, ffi, base, false, owner); -} CYCatch } + if (JSStringIsEqual(property, length_s)) + return internal->length_ == _not(size_t) ? CYJSUndefined(context) : CYCastJSValue(context, internal->length_); -static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { - CYPool pool; - Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); Type_privateData *typical(internal->type_); if (typical->type_ == NULL) return NULL; ssize_t offset; - if (!CYGetOffset(pool, context, property, offset)) + if (JSStringIsEqualToUTF8CString(property, "$cyi")) + offset = 0; + else if (!CYGetOffset(pool, context, property, offset)) return NULL; - return Pointer_getIndex(context, object, offset, exception); -} - -static JSValueRef Pointer_getProperty_$cyi(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { - return Pointer_getIndex(context, object, 0, exception); -} - -static bool Pointer_setIndex(JSContextRef context, JSObjectRef object, size_t index, JSValueRef value, JSValueRef *exception) { CYTry { - Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); - Type_privateData *typical(internal->type_); - ffi_type *ffi(typical->GetFFI()); uint8_t *base(reinterpret_cast(internal->value_)); - base += ffi->size * index; + base += ffi->size * offset; - CYPoolFFI(NULL, context, typical->type_, ffi, base, value); - return true; + JSObjectRef owner(internal->GetOwner() ?: object); + return CYFromFFI(context, typical->type_, ffi, base, false, owner); } CYCatch } -static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { +static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { CYPool pool; Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); Type_privateData *typical(internal->type_); @@ -956,20 +985,24 @@ static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStri return NULL; ssize_t offset; - if (!CYGetOffset(pool, context, property, offset)) + if (JSStringIsEqualToUTF8CString(property, "$cyi")) + offset = 0; + else if (!CYGetOffset(pool, context, property, offset)) return NULL; - return Pointer_setIndex(context, object, offset, value, exception); -} + ffi_type *ffi(typical->GetFFI()); -static bool Pointer_setProperty_$cyi(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { - return Pointer_setIndex(context, object, 0, value, exception); -} + uint8_t *base(reinterpret_cast(internal->value_)); + base += ffi->size * offset; + + CYPoolFFI(NULL, context, typical->type_, ffi, base, value); + return true; +} CYCatch } static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { Struct_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); Type_privateData *typical(internal->type_); - return CYMakePointer(context, internal->value_, typical->type_, typical->ffi_, _this); + return CYMakePointer(context, internal->value_, _not(size_t), typical->type_, typical->ffi_, _this); } static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1021,7 +1054,7 @@ static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JS name = elements[index].name; if (name == NULL) { - sprintf(number, "%lu", index); + sprintf(number, "%zu", index); name = number; } @@ -1062,7 +1095,7 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec } static JSObjectRef CYMakeType(JSContextRef context, const char *type) { - Type_privateData *internal(new Type_privateData(NULL, type)); + Type_privateData *internal(new Type_privateData(type)); return JSObjectMake(context, Type_privateData::Class_, internal); } @@ -1117,18 +1150,22 @@ static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, return NULL; case 0: - return JSEvaluateScript(CYGetJSContext(), CYJSString(value), NULL, NULL, 0, NULL); - case 1: - return CYMakeFunctor(context, reinterpret_cast(CYCastSymbol(name.data)), value); + return JSEvaluateScript(CYGetJSContext(context), CYJSString(value), NULL, NULL, 0, NULL); - case 2: { - // XXX: this is horrendously inefficient - sig::Signature signature; - sig::Parse(pool, &signature, value, &Structor_); - ffi_cif cif; - sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); - return CYFromFFI(context, signature.elements[0].type, cif.rtype, CYCastSymbol(name.data)); - } + case 1: + if (void (*symbol)() = reinterpret_cast(CYCastSymbol(name.data))) + return CYMakeFunctor(context, symbol, value); + else return NULL; + + case 2: + if (void *symbol = CYCastSymbol(name.data)) { + // XXX: this is horrendously inefficient + sig::Signature signature; + sig::Parse(pool, &signature, value, &Structor_); + ffi_cif cif; + sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); + return CYFromFFI(context, signature.elements[0].type, cif.rtype, symbol); + } else return NULL; // XXX: implement case 3 case 4: @@ -1148,7 +1185,7 @@ static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t sig::Signature signature; sig::Parse(pool, &signature, type, &Structor_); - return CYMakePointer(context, value, signature.elements[0].type, NULL, NULL); + return CYMakePointer(context, value, _not(size_t), signature.elements[0].type, NULL, NULL); } CYCatch } static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1204,17 +1241,17 @@ static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef obje Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); sig::Type *type(internal->type_); - size_t size; + size_t length; if (type->primitive != sig::array_P) - size = 0; + length = _not(size_t); else { - size = type->data.data.size; + length = type->data.data.size; type = type->data.data.type; } void *value(malloc(internal->GetFFI()->size)); - return CYMakePointer(context, value, type, NULL, NULL); + return CYMakePointer(context, value, length, type, NULL, NULL); } CYCatch } static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1235,13 +1272,24 @@ static JSValueRef CYValue_callAsFunction_toJSON(JSContextRef context, JSObjectRe } static JSValueRef CYValue_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { -CYValue *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + CYValue *internal(reinterpret_cast(JSObjectGetPrivate(_this))); char string[32]; sprintf(string, "%p", internal->value_); - return CYCastJSValue(context, string); } CYCatch } +static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + Pointer *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + if (internal->length_ != _not(size_t)) + // XXX: maybe dynamically look up Array.toCYON? + return Array_callAsFunction_toCYON(context, object, _this, count, arguments, exception); + else { + char string[32]; + sprintf(string, "%p", internal->value_); + return CYCastJSValue(context, string); + } +} CYCatch } + static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); CYPool pool; @@ -1267,13 +1315,8 @@ static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef o return Type_callAsFunction_toString(context, object, _this, count, arguments, exception); } -static JSStaticValue Pointer_staticValues[2] = { - {"$cyi", &Pointer_getProperty_$cyi, &Pointer_setProperty_$cyi, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {NULL, NULL, NULL, 0} -}; - static JSStaticFunction Pointer_staticFunctions[4] = { - {"toCYON", &CYValue_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"toCYON", &Pointer_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} @@ -1302,7 +1345,7 @@ static JSStaticFunction Type_staticFunctions[4] = { {NULL, NULL, 0} }; -static JSObjectRef (*$JSObjectMakeArray)(JSContextRef, size_t, const JSValueRef[], JSValueRef *); +static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *); void CYSetArgs(int argc, const char *argv[]) { JSContextRef context(CYGetJSContext()); @@ -1311,9 +1354,9 @@ void CYSetArgs(int argc, const char *argv[]) { args[i] = CYCastJSValue(context, argv[i]); JSObjectRef array; - if ($JSObjectMakeArray != NULL) { + if (JSObjectMakeArray$ != NULL) { JSValueRef exception(NULL); - array = (*$JSObjectMakeArray)(context, argc, args, &exception); + array = (*JSObjectMakeArray$)(context, argc, args, &exception); CYThrow(context, exception); } else { JSValueRef value(CYCallAsFunction(context, Array_, NULL, argc, args)); @@ -1382,7 +1425,66 @@ void CYInitialize() { _aprcall(apr_pool_create(&Pool_, NULL)); _sqlcall(sqlite3_open("/usr/lib/libcycript.db", &Bridge_)); - $JSObjectMakeArray = reinterpret_cast(dlsym(RTLD_DEFAULT, "JSObjectMakeArray")); + JSObjectMakeArray$ = reinterpret_cast(dlsym(RTLD_DEFAULT, "JSObjectMakeArray")); + + JSClassDefinition definition; + + definition = kJSClassDefinitionEmpty; + definition.className = "Functor"; + definition.staticFunctions = cy::Functor::StaticFunctions; + definition.callAsFunction = &Functor_callAsFunction; + definition.finalize = &CYFinalize; + Functor_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Pointer"; + definition.staticFunctions = Pointer_staticFunctions; + definition.getProperty = &Pointer_getProperty; + definition.setProperty = &Pointer_setProperty; + definition.finalize = &CYFinalize; + Pointer_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Struct"; + definition.staticFunctions = Struct_staticFunctions; + definition.getProperty = &Struct_getProperty; + definition.setProperty = &Struct_setProperty; + definition.getPropertyNames = &Struct_getPropertyNames; + definition.finalize = &CYFinalize; + Struct_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Type"; + definition.staticFunctions = Type_staticFunctions; + definition.getProperty = &Type_getProperty; + definition.callAsFunction = &Type_callAsFunction; + definition.callAsConstructor = &Type_callAsConstructor; + definition.finalize = &CYFinalize; + Type_privateData::Class_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Runtime"; + definition.getProperty = &Runtime_getProperty; + Runtime_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + //definition.getProperty = &Global_getProperty; + Global_ = JSClassCreate(&definition); + + length_s = JSStringCreateWithUTF8CString("length"); + message_s = JSStringCreateWithUTF8CString("message"); + name_s = JSStringCreateWithUTF8CString("name"); + pop_s = JSStringCreateWithUTF8CString("pop"); + prototype_s = JSStringCreateWithUTF8CString("prototype"); + push_s = JSStringCreateWithUTF8CString("push"); + splice_s = JSStringCreateWithUTF8CString("splice"); + toCYON_s = JSStringCreateWithUTF8CString("toCYON"); + toJSON_s = JSStringCreateWithUTF8CString("toJSON"); + + Result_ = JSStringCreateWithUTF8CString("_"); + + if (hooks_ != NULL && hooks_->Initialize != NULL) + (*hooks_->Initialize)(); } apr_pool_t *CYGetGlobalPool() { @@ -1427,13 +1529,22 @@ CYPoolError::CYPoolError(const char *format, va_list args) { message_ = apr_pvsprintf(pool_, format, args); } +JSValueRef CYCastJSError(JSContextRef context, const char *message) { + JSValueRef arguments[1] = {CYCastJSValue(context, message)}; + + JSValueRef exception(NULL); + JSValueRef value(JSObjectCallAsConstructor(context, Error_, 1, arguments, &exception)); + CYThrow(context, exception); + + return value; +} + JSValueRef CYPoolError::CastJSValue(JSContextRef context) const { - return CYCastJSValue(context, message_); + return CYCastJSError(context, message_); } CYJSError::CYJSError(JSContextRef context, const char *format, ...) { - if (context == NULL) - context = CYGetJSContext(); + _assert(context != NULL); CYPool pool; @@ -1442,133 +1553,73 @@ CYJSError::CYJSError(JSContextRef context, const char *format, ...) { const char *message(apr_pvsprintf(pool, format, args)); va_end (args); - JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(message))}; + value_ = CYCastJSError(context, message); +} - JSValueRef exception(NULL); - value_ = JSObjectCallAsConstructor(context, Error_, 1, arguments, &exception); - CYThrow(context, exception); +JSGlobalContextRef CYGetJSContext(JSContextRef context) { + // XXX: do something better + return Context_; } -JSGlobalContextRef CYGetJSContext() { - CYInitialize(); +void CYSetupContext(JSGlobalContextRef context) { + JSObjectRef global(CYGetGlobalObject(context)); - if (Context_ == NULL) { - JSClassDefinition definition; - - definition = kJSClassDefinitionEmpty; - definition.className = "Functor"; - definition.staticFunctions = cy::Functor::StaticFunctions; - definition.callAsFunction = &Functor_callAsFunction; - definition.finalize = &CYFinalize; - Functor_ = JSClassCreate(&definition); - - definition = kJSClassDefinitionEmpty; - definition.className = "Pointer"; - definition.staticValues = Pointer_staticValues; - definition.staticFunctions = Pointer_staticFunctions; - definition.getProperty = &Pointer_getProperty; - definition.setProperty = &Pointer_setProperty; - definition.finalize = &CYFinalize; - Pointer_ = JSClassCreate(&definition); - - definition = kJSClassDefinitionEmpty; - definition.className = "Struct"; - definition.staticFunctions = Struct_staticFunctions; - definition.getProperty = &Struct_getProperty; - definition.setProperty = &Struct_setProperty; - definition.getPropertyNames = &Struct_getPropertyNames; - definition.finalize = &CYFinalize; - Struct_ = JSClassCreate(&definition); - - definition = kJSClassDefinitionEmpty; - definition.className = "Type"; - definition.staticFunctions = Type_staticFunctions; - definition.getProperty = &Type_getProperty; - definition.callAsFunction = &Type_callAsFunction; - definition.callAsConstructor = &Type_callAsConstructor; - definition.finalize = &CYFinalize; - Type_privateData::Class_ = JSClassCreate(&definition); - - definition = kJSClassDefinitionEmpty; - definition.className = "Runtime"; - definition.getProperty = &Runtime_getProperty; - Runtime_ = JSClassCreate(&definition); - - definition = kJSClassDefinitionEmpty; - //definition.getProperty = &Global_getProperty; - JSClassRef Global(JSClassCreate(&definition)); - - JSGlobalContextRef context(JSGlobalContextCreate(Global)); - Context_ = context; - JSObjectRef global(CYGetGlobalObject(context)); - - JSObjectSetPrototype(context, global, JSObjectMake(context, Runtime_, NULL)); - - Array_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array"))); - JSValueProtect(context, Array_); - - Error_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error"))); - JSValueProtect(context, Error_); - - Function_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function"))); - JSValueProtect(context, Function_); - - String_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("String"))); - JSValueProtect(context, String_); - - length_ = JSStringCreateWithUTF8CString("length"); - message_ = JSStringCreateWithUTF8CString("message"); - name_ = JSStringCreateWithUTF8CString("name"); - prototype_ = JSStringCreateWithUTF8CString("prototype"); - toCYON_ = JSStringCreateWithUTF8CString("toCYON"); - toJSON_ = JSStringCreateWithUTF8CString("toJSON"); - - JSObjectRef Object(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Object")))); - Object_prototype_ = CYCastJSObject(context, CYGetProperty(context, Object, prototype_)); - JSValueProtect(context, Object_prototype_); - - Array_prototype_ = CYCastJSObject(context, CYGetProperty(context, Array_, prototype_)); - Array_pop_ = CYCastJSObject(context, CYGetProperty(context, Array_prototype_, CYJSString("pop"))); - Array_push_ = CYCastJSObject(context, CYGetProperty(context, Array_prototype_, CYJSString("push"))); - Array_splice_ = CYCastJSObject(context, CYGetProperty(context, Array_prototype_, CYJSString("splice"))); - - CYSetProperty(context, Array_prototype_, toCYON_, JSObjectMakeFunctionWithCallback(context, toCYON_, &Array_callAsFunction_toCYON), kJSPropertyAttributeDontEnum); - - JSValueProtect(context, Array_prototype_); - JSValueProtect(context, Array_pop_); - JSValueProtect(context, Array_push_); - JSValueProtect(context, Array_splice_); - - JSObjectRef Functor(JSObjectMakeConstructor(context, Functor_, &Functor_new)); - - Function_prototype_ = (JSObjectRef) CYGetProperty(context, Function_, prototype_); - JSValueProtect(context, Function_prototype_); - - JSObjectSetPrototype(context, (JSObjectRef) CYGetProperty(context, Functor, prototype_), Function_prototype_); - - CYSetProperty(context, global, CYJSString("Functor"), Functor); - CYSetProperty(context, global, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); - CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); - - JSObjectRef cycript(JSObjectMake(context, NULL, NULL)); - CYSetProperty(context, global, CYJSString("Cycript"), cycript); - CYSetProperty(context, cycript, CYJSString("gc"), JSObjectMakeFunctionWithCallback(context, CYJSString("gc"), &Cycript_gc_callAsFunction)); - - CYSetProperty(context, global, CYJSString("$cyq"), JSObjectMakeFunctionWithCallback(context, CYJSString("$cyq"), &$cyq)); - - System_ = JSObjectMake(context, NULL, NULL); - JSValueProtect(context, System_); + Array_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array"))); + JSValueProtect(context, Array_); + Array_prototype_ = CYCastJSObject(context, CYGetProperty(context, Array_, prototype_s)); + JSValueProtect(context, Array_prototype_); + + Error_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error"))); + JSValueProtect(context, Error_); + + Function_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function"))); + JSValueProtect(context, Function_); + Function_prototype_ = (JSObjectRef) CYGetProperty(context, Function_, prototype_s); + JSValueProtect(context, Function_prototype_); - CYSetProperty(context, global, CYJSString("system"), System_); - CYSetProperty(context, System_, CYJSString("args"), CYJSNull(context)); - //CYSetProperty(context, System_, CYJSString("global"), global); + JSObjectRef Object(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Object")))); + Object_prototype_ = CYCastJSObject(context, CYGetProperty(context, Object, prototype_s)); + JSValueProtect(context, Object_prototype_); - CYSetProperty(context, System_, CYJSString("print"), JSObjectMakeFunctionWithCallback(context, CYJSString("print"), &System_print)); + String_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("String"))); + JSValueProtect(context, String_); - Result_ = JSStringCreateWithUTF8CString("_"); + JSObjectSetPrototype(context, global, JSObjectMake(context, Runtime_, NULL)); - if (hooks_ != NULL && hooks_->SetupContext != NULL) - (*hooks_->SetupContext)(context); + CYSetProperty(context, Array_prototype_, toCYON_s, &Array_callAsFunction_toCYON, kJSPropertyAttributeDontEnum); + + JSObjectRef Functor(JSObjectMakeConstructor(context, Functor_, &Functor_new)); + + JSObjectSetPrototype(context, (JSObjectRef) CYGetProperty(context, Functor, prototype_s), Function_prototype_); + + CYSetProperty(context, global, CYJSString("Functor"), Functor); + CYSetProperty(context, global, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); + CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); + + JSObjectRef cycript(JSObjectMake(context, NULL, NULL)); + CYSetProperty(context, global, CYJSString("Cycript"), cycript); + CYSetProperty(context, cycript, CYJSString("gc"), &Cycript_gc_callAsFunction); + + CYSetProperty(context, global, CYJSString("$cyq"), &$cyq); + + System_ = JSObjectMake(context, NULL, NULL); + JSValueProtect(context, System_); + + CYSetProperty(context, global, CYJSString("system"), System_); + CYSetProperty(context, System_, CYJSString("args"), CYJSNull(context)); + //CYSetProperty(context, System_, CYJSString("global"), global); + CYSetProperty(context, System_, CYJSString("print"), &System_print); + + if (hooks_ != NULL && hooks_->SetupContext != NULL) + (*hooks_->SetupContext)(context); +} + +JSGlobalContextRef CYGetJSContext() { + CYInitialize(); + + if (Context_ == NULL) { + Context_ = JSGlobalContextCreate(Global_); + CYSetupContext(Context_); } return Context_;