X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/00b9328fc47038f081ad49fff7c14cc6a7d212b3..34fc459cda2c8212ceed2bdc23e0fb51831486f5:/Library.cpp diff --git a/Library.cpp b/Library.cpp index ca7b1af..5517565 100644 --- a/Library.cpp +++ b/Library.cpp @@ -113,7 +113,7 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, J CYThrow(context, exception); } -void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes = kJSPropertyAttributeNone) { +void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes) { CYSetProperty(context, object, name, JSObjectMakeFunctionWithCallback(context, name, callback), attributes); } /* }}} */ @@ -127,7 +127,7 @@ JSStringRef CYCopyJSString(JSStringRef value) { } JSStringRef CYCopyJSString(CYUTF8String value) { - // XXX: this is very wrong + // XXX: this is very wrong; it needs to convert to UTF16 and then create from there return CYCopyJSString(value.data); } @@ -260,7 +260,7 @@ void CYStringify(std::ostringstream &str, const char *data, size_t size) { break; default: - // this test is designed to be "awewsome", generating neither warnings nor incorrect results + // this test is designed to be "awesome", generating neither warnings nor incorrect results if (*value < 0x20 || *value >= 0x7f) str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(uint8_t(*value)); else simple: @@ -300,24 +300,15 @@ bool CYIsKey(CYUTF8String value) { } /* }}} */ -static JSGlobalContextRef Context_; -static JSObjectRef System_; - +static JSClassRef All_; +static JSClassRef Context_; static JSClassRef Functor_; static JSClassRef Global_; static JSClassRef Pointer_; -static JSClassRef Runtime_; static JSClassRef Struct_; -JSObjectRef Array_; -JSObjectRef Error_; -JSObjectRef Function_; -JSObjectRef String_; - -JSObjectRef Array_prototype_; -JSObjectRef Function_prototype_; -JSObjectRef Object_prototype_; - +JSStringRef Array_s; +JSStringRef cy_s; JSStringRef length_s; JSStringRef message_s; JSStringRef name_s; @@ -407,6 +398,17 @@ void Structor_(apr_pool_t *pool, sig::Type *&type) { JSClassRef Type_privateData::Class_; +struct Context : + CYData +{ + JSGlobalContextRef context_; + + Context(JSGlobalContextRef context) : + context_(context) + { + } +}; + struct Pointer : CYOwned { @@ -519,7 +521,7 @@ JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) { return object; } -JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, JSValueRef arguments[]) { +JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]) { JSValueRef exception(NULL); JSValueRef value(JSObjectCallAsFunction(context, function, _this, count, arguments, &exception)); CYThrow(context, exception); @@ -596,6 +598,7 @@ const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef obje JSValueRef toCYON(CYGetProperty(context, object, toCYON_s)); if (CYIsCallable(context, toCYON)) { JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toCYON, object, 0, NULL)); + _assert(value != NULL); return CYPoolCString(pool, context, value); } @@ -889,12 +892,21 @@ Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, static JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) { Closure_privateData *internal(CYMakeFunctor_(context, function, type, &FunctionClosure_)); - return JSObjectMake(context, Functor_, internal); + JSObjectRef object(JSObjectMake(context, Functor_, internal)); + // XXX: see above notes about needing to leak + JSValueProtect(CYGetJSContext(context), object); + return object; +} + +JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) { + return CYCastJSObject(context, CYGetProperty(context, CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s)), name)); } static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const char *type) { + JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function"))); + JSValueRef exception(NULL); - bool function(JSValueIsInstanceOfConstructor(context, value, Function_, &exception)); + bool function(JSValueIsInstanceOfConstructor(context, value, Function, &exception)); CYThrow(context, exception); if (function) { @@ -1108,7 +1120,13 @@ static void *CYCastSymbol(const char *name) { return dlsym(RTLD_DEFAULT, name); } -static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { +static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + JSObjectRef global(CYGetGlobalObject(context)); + JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript")))); + if (JSValueRef value = CYGetProperty(context, cycript, property)) + if (!JSValueIsUndefined(context, value)) + return value; + CYPool pool; CYUTF8String name(CYPoolUTF8String(pool, context, property)); @@ -1280,10 +1298,11 @@ static JSValueRef CYValue_callAsFunction_toCYON(JSContextRef context, JSObjectRe 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 { + if (internal->length_ != _not(size_t)) { + JSObjectRef Array(CYGetCachedObject(context, Array_s)); + JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s))); + return CYCallAsFunction(context, toCYON, _this, count, arguments); + } else { char string[32]; sprintf(string, "%p", internal->value_); return CYCastJSValue(context, string); @@ -1359,11 +1378,13 @@ void CYSetArgs(int argc, const char *argv[]) { array = (*JSObjectMakeArray$)(context, argc, args, &exception); CYThrow(context, exception); } else { - JSValueRef value(CYCallAsFunction(context, Array_, NULL, argc, args)); + JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array"))); + JSValueRef value(CYCallAsFunction(context, Array, NULL, argc, args)); array = CYCastJSObject(context, value); } - CYSetProperty(context, System_, CYJSString("args"), array); + JSObjectRef System(CYGetCachedObject(context, CYJSString("System"))); + CYSetProperty(context, System, CYJSString("args"), array); } JSObjectRef CYGetGlobalObject(JSContextRef context) { @@ -1429,6 +1450,16 @@ void CYInitialize() { JSClassDefinition definition; + definition = kJSClassDefinitionEmpty; + definition.className = "All"; + definition.getProperty = &All_getProperty; + All_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Context"; + definition.finalize = &CYFinalize; + Context_ = JSClassCreate(&definition); + definition = kJSClassDefinitionEmpty; definition.className = "Functor"; definition.staticFunctions = cy::Functor::StaticFunctions; @@ -1462,15 +1493,12 @@ void CYInitialize() { 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); + Array_s = JSStringCreateWithUTF8CString("Array"); + cy_s = JSStringCreateWithUTF8CString("$cy"); length_s = JSStringCreateWithUTF8CString("length"); message_s = JSStringCreateWithUTF8CString("message"); name_s = JSStringCreateWithUTF8CString("name"); @@ -1498,7 +1526,8 @@ void CYThrow(JSContextRef context, JSValueRef value) { } const char *CYJSError::PoolCString(apr_pool_t *pool) const { - return CYPoolCString(pool, context_, value_); + // XXX: this used to be CYPoolCString + return CYPoolCCYON(pool, context_, value_); } JSValueRef CYJSError::CastJSValue(JSContextRef context) const { @@ -1508,10 +1537,10 @@ JSValueRef CYJSError::CastJSValue(JSContextRef context) const { void CYThrow(const char *format, ...) { va_list args; - va_start (args, format); + va_start(args, format); throw CYPoolError(format, args); // XXX: does this matter? :( - va_end (args); + va_end(args); } const char *CYPoolError::PoolCString(apr_pool_t *pool) const { @@ -1520,9 +1549,9 @@ const char *CYPoolError::PoolCString(apr_pool_t *pool) const { CYPoolError::CYPoolError(const char *format, ...) { va_list args; - va_start (args, format); + va_start(args, format); message_ = apr_pvsprintf(pool_, format, args); - va_end (args); + va_end(args); } CYPoolError::CYPoolError(const char *format, va_list args) { @@ -1530,10 +1559,12 @@ CYPoolError::CYPoolError(const char *format, va_list args) { } JSValueRef CYCastJSError(JSContextRef context, const char *message) { + JSObjectRef Error(CYGetCachedObject(context, CYJSString("Error"))); + JSValueRef arguments[1] = {CYCastJSValue(context, message)}; JSValueRef exception(NULL); - JSValueRef value(JSObjectCallAsConstructor(context, Error_, 1, arguments, &exception)); + JSValueRef value(JSObjectCallAsConstructor(context, Error, 1, arguments, &exception)); CYThrow(context, exception); return value; @@ -1549,66 +1580,76 @@ CYJSError::CYJSError(JSContextRef context, const char *format, ...) { CYPool pool; va_list args; - va_start (args, format); + va_start(args, format); const char *message(apr_pvsprintf(pool, format, args)); - va_end (args); + va_end(args); value_ = CYCastJSError(context, message); } JSGlobalContextRef CYGetJSContext(JSContextRef context) { - // XXX: do something better - return Context_; + return reinterpret_cast(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_; } -void CYSetupContext(JSGlobalContextRef context) { +extern "C" void CYSetupContext(JSGlobalContextRef context) { + CYInitialize(); + JSObjectRef global(CYGetGlobalObject(context)); - Array_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array"))); - JSValueProtect(context, Array_); - Array_prototype_ = CYCastJSObject(context, CYGetProperty(context, Array_, prototype_s)); - JSValueProtect(context, Array_prototype_); + JSObjectRef cy(JSObjectMake(context, Context_, new Context(context))); + CYSetProperty(context, global, cy_s, cy, kJSPropertyAttributeDontEnum); - Error_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error"))); - JSValueProtect(context, Error_); +/* Cache Globals {{{ */ + JSObjectRef Array(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Array")))); + CYSetProperty(context, cy, CYJSString("Array"), Array); - Function_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function"))); - JSValueProtect(context, Function_); - Function_prototype_ = (JSObjectRef) CYGetProperty(context, Function_, prototype_s); - JSValueProtect(context, Function_prototype_); + JSObjectRef Array_prototype(CYCastJSObject(context, CYGetProperty(context, Array, prototype_s))); + CYSetProperty(context, cy, CYJSString("Array_prototype"), Array_prototype); - JSObjectRef Object(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Object")))); - Object_prototype_ = CYCastJSObject(context, CYGetProperty(context, Object, prototype_s)); - JSValueProtect(context, Object_prototype_); + JSObjectRef Error(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error")))); + CYSetProperty(context, cy, CYJSString("Error"), Error); - String_ = CYCastJSObject(context, CYGetProperty(context, global, CYJSString("String"))); - JSValueProtect(context, String_); + JSObjectRef Function(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function")))); + CYSetProperty(context, cy, CYJSString("Function"), Function); - JSObjectSetPrototype(context, global, JSObjectMake(context, Runtime_, NULL)); + JSObjectRef Function_prototype(CYCastJSObject(context, CYGetProperty(context, Function, prototype_s))); + CYSetProperty(context, cy, CYJSString("Function_prototype"), Function_prototype); - CYSetProperty(context, Array_prototype_, toCYON_s, &Array_callAsFunction_toCYON, kJSPropertyAttributeDontEnum); + JSObjectRef Object(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Object")))); + CYSetProperty(context, cy, CYJSString("Object"), Object); - JSObjectRef Functor(JSObjectMakeConstructor(context, Functor_, &Functor_new)); + JSObjectRef Object_prototype(CYCastJSObject(context, CYGetProperty(context, Object, prototype_s))); + CYSetProperty(context, cy, CYJSString("Object_prototype"), Object_prototype); - JSObjectSetPrototype(context, (JSObjectRef) CYGetProperty(context, Functor, prototype_s), Function_prototype_); + JSObjectRef String(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("String")))); + CYSetProperty(context, cy, CYJSString("String"), String); +/* }}} */ - 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)); + CYSetProperty(context, Array_prototype, toCYON_s, &Array_callAsFunction_toCYON, kJSPropertyAttributeDontEnum); JSObjectRef cycript(JSObjectMake(context, NULL, NULL)); CYSetProperty(context, global, CYJSString("Cycript"), cycript); CYSetProperty(context, cycript, CYJSString("gc"), &Cycript_gc_callAsFunction); + JSObjectRef Functor(JSObjectMakeConstructor(context, Functor_, &Functor_new)); + JSObjectSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, Functor, prototype_s)), Function_prototype); + CYSetProperty(context, cycript, CYJSString("Functor"), Functor); + + CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); + CYSetProperty(context, cycript, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); + + JSObjectRef all(JSObjectMake(context, All_, NULL)); + CYSetProperty(context, cycript, CYJSString("all"), all); + CYSetProperty(context, global, CYJSString("$cyq"), &$cyq); - System_ = JSObjectMake(context, NULL, NULL); - JSValueProtect(context, System_); + JSObjectRef System(JSObjectMake(context, NULL, NULL)); + CYSetProperty(context, cy, CYJSString("System"), Function); - 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); + 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); @@ -1617,10 +1658,13 @@ void CYSetupContext(JSGlobalContextRef context) { JSGlobalContextRef CYGetJSContext() { CYInitialize(); - if (Context_ == NULL) { - Context_ = JSGlobalContextCreate(Global_); - CYSetupContext(Context_); + static JSGlobalContextRef context_; + + if (context_ == NULL) { + context_ = JSGlobalContextCreate(Global_); + CYSetupContext(context_); + JSObjectSetPrototype(context_, CYGetGlobalObject(context_), JSObjectMake(context_, All_, NULL)); } - return Context_; + return context_; }