X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/1eeb7e57bf949a0198dddb0eb734c36eed82f59b..51b6165e0dd24e4d40ff80e504922f705ddd7b62:/Execute.cpp diff --git a/Execute.cpp b/Execute.cpp index e118146..a71d29f 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -22,6 +22,9 @@ #include "Internal.hpp" #include +#include +#include +#include #include "cycript.hpp" @@ -32,6 +35,7 @@ #include "Execute.hpp" #include +#include #include #include @@ -42,6 +46,7 @@ #include "Parser.hpp" +#include "Decode.hpp" #include "Error.hpp" #include "JavaScript.hpp" #include "String.hpp" @@ -122,6 +127,7 @@ static JSClassRef Struct_; JSStringRef Array_s; JSStringRef cy_s; +JSStringRef cyi_s; JSStringRef length_s; JSStringRef message_s; JSStringRef name_s; @@ -336,8 +342,13 @@ static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _th return CYCastJSValue(context, name); } CYCatch(NULL) } -static JSValueRef Cycript_gc_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + +void CYGarbageCollect(JSContextRef context) { JSGarbageCollect(context); +} + +static JSValueRef Cycript_gc_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + CYGarbageCollect(context); return CYJSUndefined(context); } CYCatch(NULL) } @@ -491,11 +502,11 @@ JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, si return JSObjectMake(context, Pointer_, internal); } -static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) { - return JSObjectMake(context, Functor_, new cy::Functor(type, function)); +static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const sig::Signature &signature) { + return JSObjectMake(context, Functor_, new cy::Functor(signature, function)); } -static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const char *type, void **cache) { +static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const char *encoding, void **cache) { cy::Functor *internal; if (*cache != NULL) internal = reinterpret_cast(*cache); @@ -504,7 +515,7 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const if (function == NULL) return NULL; - internal = new cy::Functor(type, function); + internal = new cy::Functor(encoding, function); *cache = internal; } @@ -710,12 +721,12 @@ static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void CYExecuteClosure(cif, result, arguments, arg, &FunctionAdapter_); } -Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) { +Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const sig::Signature &signature, 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(context, function, type)); + Closure_privateData *internal(new Closure_privateData(context, function, signature)); -#if defined(__APPLE__) && defined(__arm__) +#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) void *executable; ffi_closure *writable(reinterpret_cast(ffi_closure_alloc(sizeof(ffi_closure), &executable))); @@ -741,8 +752,8 @@ Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, return internal; } -static JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char *type) { - Closure_privateData *internal(CYMakeFunctor_(context, function, type, &FunctionClosure_)); +static JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const sig::Signature &signature) { + Closure_privateData *internal(CYMakeFunctor_(context, function, signature, &FunctionClosure_)); JSObjectRef object(JSObjectMake(context, Functor_, internal)); // XXX: see above notes about needing to leak JSValueProtect(CYGetJSContext(context), object); @@ -753,16 +764,16 @@ 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) { +static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const sig::Signature &signature) { JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function"))); bool function(_jsccall(JSValueIsInstanceOfConstructor, context, value, Function)); if (function) { JSObjectRef function(CYCastJSObject(context, value)); - return CYMakeFunctor(context, function, type); + return CYMakeFunctor(context, function, signature); } else { void (*function)()(CYCastPointer(context, value)); - return CYMakeFunctor(context, function, type); + return CYMakeFunctor(context, function, signature); } } @@ -817,9 +828,9 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, return internal->length_ == _not(size_t) ? CYJSUndefined(context) : CYCastJSValue(context, internal->length_); Type_privateData *typical(internal->type_); - if (typical->type_ == NULL) return NULL; + sig::Type &type(*typical->type_); ssize_t offset; if (JSStringIsEqualToUTF8CString(property, "$cyi")) @@ -827,13 +838,16 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, else if (!CYGetOffset(pool, context, property, offset)) return NULL; + if (type.primitive == sig::function_P) + return CYMakeFunctor(context, reinterpret_cast(internal->value_), type.data.signature); + ffi_type *ffi(typical->GetFFI()); uint8_t *base(reinterpret_cast(internal->value_)); base += ffi->size * offset; JSObjectRef owner(internal->GetOwner() ?: object); - return CYFromFFI(context, typical->type_, ffi, base, false, owner); + return CYFromFFI(context, &type, ffi, base, false, owner); } CYCatch(NULL) } static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { @@ -954,8 +968,8 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec return CYCallFunction(pool, context, 0, NULL, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue()); } CYCatch(NULL) } -JSObjectRef CYMakeType(JSContextRef context, const char *type) { - Type_privateData *internal(new Type_privateData(type)); +JSObjectRef CYMakeType(JSContextRef context, const char *encoding) { + Type_privateData *internal(new Type_privateData(encoding)); return JSObjectMake(context, Type_privateData::Class_, internal); } @@ -964,6 +978,19 @@ JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) { return JSObjectMake(context, Type_privateData::Class_, internal); } +JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature) { + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + type.primitive = sig::function_P; + sig::Copy(pool, type.data.signature, *signature); + + return CYMakeType(context, &type); +} + 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")))); @@ -1051,6 +1078,38 @@ static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t cou return CYMakeType(context, type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_$With(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], sig::Primitive primitive, JSValueRef *exception) { CYTry { + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + type.primitive = primitive; + type.data.signature.elements = new(pool) sig::Element[1 + count]; + type.data.signature.count = 1 + count; + + type.data.signature.elements[0].name = NULL; + type.data.signature.elements[0].type = internal->type_; + type.data.signature.elements[0].offset = _not(size_t); + + for (size_t i(0); i != count; ++i) { + sig::Element &element(type.data.signature.elements[i + 1]); + element.name = NULL; + element.offset = _not(size_t); + + JSObjectRef object(CYCastJSObject(context, arguments[i])); + _assert(JSValueIsObjectOfClass(context, object, Type_privateData::Class_)); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + + element.type = internal->type_; + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 1) throw CYJSError(context, "incorrect number of arguments to Type.arrayOf"); @@ -1072,6 +1131,10 @@ static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef return CYMakeType(context, &type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_blockWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + return Type_callAsFunction_$With(context, object, _this, count, arguments, sig::block_P, exception); +} + static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 0) throw CYJSError(context, "incorrect number of arguments to Type.constant"); @@ -1082,6 +1145,10 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef return CYMakeType(context, &type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + return Type_callAsFunction_$With(context, object, _this, count, arguments, sig::function_P, exception); +} + static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 0) throw CYJSError(context, "incorrect number of arguments to Type.pointerTo"); @@ -1089,11 +1156,18 @@ static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRe sig::Type type; type.name = NULL; - type.flags = 0; - type.primitive = sig::pointer_P; - type.data.data.type = internal->type_; - type.data.data.size = 0; + if (internal->type_->primitive == sig::char_P) { + type.flags = internal->type_->flags; + type.primitive = sig::string_P; + type.data.data.type = NULL; + type.data.data.size = 0; + } else { + type.flags = 0; + type.primitive = sig::pointer_P; + type.data.data.type = internal->type_; + type.data.data.size = 0; + } return CYMakeType(context, &type); } CYCatch(NULL) } @@ -1116,6 +1190,9 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, throw CYJSError(context, "incorrect number of arguments to type cast function"); Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + if (internal->type_->primitive == sig::function_P) + return CYMakeFunctor(context, arguments[0], internal->type_->data.signature); + sig::Type *type(internal->type_); ffi_type *ffi(internal->GetFFI()); // XXX: alignment? @@ -1140,7 +1217,7 @@ static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef obje type = type->data.data.type; } - void *value(malloc(internal->GetFFI()->size)); + void *value(calloc(1, internal->GetFFI()->size)); return CYMakePointer(context, value, length, type, NULL, NULL); } CYCatch(NULL) } @@ -1148,8 +1225,10 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t if (count != 2) throw CYJSError(context, "incorrect number of arguments to Functor constructor"); CYPool pool; - const char *type(CYPoolCString(pool, context, arguments[1])); - return CYMakeFunctor(context, arguments[0], type); + const char *encoding(CYPoolCString(pool, context, arguments[1])); + sig::Signature signature; + sig::Parse(pool, &signature, encoding, &Structor_); + return CYMakeFunctor(context, arguments[0], signature); } CYCatch(NULL) } static JSValueRef CYValue_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1174,17 +1253,29 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype"))); JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s))); return CYCallAsFunction(context, toCYON, _this, count, arguments); - } else { + } else if (internal->type_->type_ == NULL) pointer: { char string[32]; sprintf(string, "%p", internal->value_); return CYCastJSValue(context, string); + } try { + JSValueRef value(CYGetProperty(context, _this, cyi_s)); + if (JSValueIsUndefined(context, value)) + goto pointer; + CYPool pool; + return CYCastJSValue(context, pool.strcat("&", CYPoolCCYON(pool, context, value), NULL)); + } catch (const CYException &e) { + goto pointer; } } CYCatch(NULL) } +static JSValueRef Pointer_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); + return CYMakeType(context, internal->type_->type_); +} CYCatch(NULL) } + static JSValueRef Functor_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - CYPool pool; - return CYCastJSValue(context, Unparse(pool, &internal->signature_)); + return CYMakeType(context, &internal->signature_); } CYCatch(NULL) } static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1211,12 +1302,12 @@ static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - CYPool pool; - const char *type(sig::Unparse(pool, internal->type_)); - std::ostringstream str; - CYStringify(str, type, strlen(type)); - char *cyon(pool.strcat("new Type(", str.str().c_str(), ")", NULL)); - return CYCastJSValue(context, CYJSString(cyon)); + CYLocalPool pool; + std::ostringstream out; + CYOptions options; + CYOutput output(out, options); + (new(pool) CYEncodedType(Decode(pool, internal->type_)))->Output(output, CYNoFlags); + return CYCastJSValue(context, CYJSString(out.str().c_str())); } CYCatch(NULL) } static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @@ -1230,6 +1321,11 @@ static JSStaticFunction Pointer_staticFunctions[4] = { {NULL, NULL, 0} }; +static JSStaticValue Pointer_staticValues[2] = { + {"type", &Pointer_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, NULL, 0} +}; + static JSStaticFunction Struct_staticFunctions[2] = { {"$cya", &Struct_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} @@ -1258,9 +1354,11 @@ static JSStaticValue Type_staticValues[4] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Type_staticFunctions[8] = { +static JSStaticFunction Type_staticFunctions[10] = { {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"blockWith", &Type_callAsFunction_blockWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"functionWith", &Type_callAsFunction_functionWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -1294,8 +1392,7 @@ JSObjectRef CYGetGlobalObject(JSContextRef context) { return JSContextGetGlobalObject(context); } -const char *CYExecute(CYPool &pool, CYUTF8String code) { - JSContextRef context(CYGetJSContext()); +const char *CYExecute(JSContextRef context, CYPool &pool, CYUTF8String code) { JSValueRef exception(NULL); void *handle; @@ -1340,10 +1437,6 @@ const char *CYExecute(CYPool &pool, CYUTF8String code) { } } -extern "C" void CydgetSetupContext(JSGlobalContextRef context) { - CYSetupContext(context); -} - static bool initialized_ = false; void CYInitializeDynamic() { @@ -1377,6 +1470,7 @@ void CYInitializeDynamic() { definition = kJSClassDefinitionEmpty; definition.className = "Pointer"; definition.staticFunctions = Pointer_staticFunctions; + definition.staticValues = Pointer_staticValues; definition.getProperty = &Pointer_getProperty; definition.setProperty = &Pointer_setProperty; definition.finalize = &CYFinalize; @@ -1407,6 +1501,7 @@ void CYInitializeDynamic() { Array_s = JSStringCreateWithUTF8CString("Array"); cy_s = JSStringCreateWithUTF8CString("$cy"); + cyi_s = JSStringCreateWithUTF8CString("$cyi"); length_s = JSStringCreateWithUTF8CString("length"); message_s = JSStringCreateWithUTF8CString("message"); name_s = JSStringCreateWithUTF8CString("name"); @@ -1468,6 +1563,113 @@ JSGlobalContextRef CYGetJSContext(JSContextRef context) { return reinterpret_cast(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_; } +extern "C" bool CydgetMemoryParse(const uint16_t **data, size_t *size); + +void *CYMapFile(const char *path, size_t *psize) { + int fd; + _syscall(fd = open(path, O_RDONLY)); + + struct stat stat; + _syscall(fstat(fd, &stat)); + size_t size(stat.st_size); + + *psize = size; + + void *base; + _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); + + _syscall(close(fd)); + return base; +} + +static void CYRunSetups(JSContextRef context) { + std::string folder("/etc/cycript/setup.d"); + DIR *setups(opendir(folder.c_str())); + if (setups == NULL) + return; + + for (;;) { + dirent setup; + dirent *result; + _syscall(readdir_r(setups, &setup, &result)); + + if (result == NULL) + break; + _assert(result == &setup); + + const char *name(setup.d_name); + size_t length(strlen(name)); + if (length < 4) + continue; + + if (name[0] == '.') + continue; + if (memcmp(name + length - 3, ".cy", 3) != 0) + continue; + + std::string script(folder + "/" + name); + CYUTF8String utf8; + utf8.data = reinterpret_cast(CYMapFile(script.c_str(), &utf8.size)); + + CYPool pool; + CYUTF16String utf16(CYPoolUTF16String(pool, utf8)); + munmap(const_cast(utf8.data), utf8.size); + + // XXX: this should not be used + CydgetMemoryParse(&utf16.data, &utf16.size); + + CYExecute(context, pool, CYPoolUTF8String(pool, utf16)); + free(const_cast(utf16.data)); + } + + _syscall(closedir(setups)); +} + +static JSValueRef require(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + _assert(count == 1); + CYPool pool; + + Dl_info addr; + _assert(dladdr(reinterpret_cast(&require), &addr) != 0); + char *lib(pool.strdup(addr.dli_fname)); + + char *slash(strrchr(lib, '/')); + _assert(slash != NULL); + *slash = '\0'; + + CYJSString property("exports"); + JSObjectRef module; + + const char *path(pool.strcat(lib, "/cycript/", CYPoolCString(pool, context, arguments[0]), ".cy", NULL)); + CYJSString key(path); + JSObjectRef modules(CYGetCachedObject(context, CYJSString("modules"))); + JSValueRef cache(CYGetProperty(context, modules, key)); + + if (!JSValueIsUndefined(context, cache)) + module = CYCastJSObject(context, cache); + else { + CYUTF8String code; + code.data = reinterpret_cast(CYMapFile(path, &code.size)); + + std::stringstream wrap; + wrap << "(function (exports, require, module) { " << code << "\n});"; + code = CYPoolCode(pool, wrap.str().c_str()); + + JSValueRef value(_jsccall(JSEvaluateScript, context, CYJSString(code), NULL, NULL, 0)); + JSObjectRef function(CYCastJSObject(context, value)); + + module = JSObjectMake(context, NULL, NULL); + JSObjectRef exports(JSObjectMake(context, NULL, NULL)); + CYSetProperty(context, module, property, exports); + + JSValueRef arguments[3] = { exports, JSObjectMakeFunctionWithCallback(context, CYJSString("require"), &require), module }; + CYCallAsFunction(context, function, NULL, 3, arguments); + CYSetProperty(context, modules, key, module); + } + + return CYGetProperty(context, module, property); +} CYCatch(NULL) } + extern "C" void CYSetupContext(JSGlobalContextRef context) { CYInitializeDynamic(); @@ -1519,6 +1721,9 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); CYSetProperty(context, cycript, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); + JSObjectRef modules(JSObjectMake(context, NULL, NULL)); + CYSetProperty(context, cy, CYJSString("modules"), modules); + JSObjectRef all(JSObjectMake(context, All_, NULL)); CYSetProperty(context, cycript, CYJSString("all"), all); @@ -1545,6 +1750,8 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { JSObjectRef System(JSObjectMake(context, NULL, NULL)); CYSetProperty(context, cy, CYJSString("System"), System); + CYSetProperty(context, all, CYJSString("require"), &require, kJSPropertyAttributeDontEnum); + CYSetProperty(context, global, CYJSString("system"), System); CYSetProperty(context, System, CYJSString("args"), CYJSNull(context)); //CYSetProperty(context, System, CYJSString("global"), global); @@ -1557,13 +1764,15 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { (*hooks_->SetupContext)(context); CYArrayPush(context, alls, cycript); + + CYRunSetups(context); } +static JSGlobalContextRef context_; + JSGlobalContextRef CYGetJSContext() { CYInitializeDynamic(); - static JSGlobalContextRef context_; - if (context_ == NULL) { context_ = JSGlobalContextCreate(Global_); CYSetupContext(context_); @@ -1571,3 +1780,10 @@ JSGlobalContextRef CYGetJSContext() { return context_; } + +void CYDestroyContext() { + if (context_ == NULL) + return; + JSGlobalContextRelease(context_); + context_ = NULL; +}