/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2014 Jay Freeman (saurik)
+ * Copyright (C) 2009-2015 Jay Freeman (saurik)
*/
/* GNU Affero General Public License, Version 3 {{{ */
#include "JavaScript.hpp"
#include "String.hpp"
-std::vector<CYHook *> hooks_;
+static std::vector<CYHook *> &GetHooks() {
+ static std::vector<CYHook *> hooks;
+ return hooks;
+}
CYRegisterHook::CYRegisterHook(CYHook *hook) {
- hooks_.push_back(hook);
+ GetHooks().push_back(hook);
}
/* JavaScript Properties {{{ */
void CYSetPrototype(JSContextRef context, JSObjectRef object, JSValueRef value) {
JSObjectSetPrototype(context, object, value);
- _assert(JSObjectGetPrototype(context, object) == value);
+ _assert(CYIsStrictEqual(context, JSObjectGetPrototype(context, object), value));
}
/* }}} */
/* JavaScript Strings {{{ */
JSStringRef toJSON_s;
JSStringRef toPointer_s;
JSStringRef toString_s;
+JSStringRef weak_s;
static JSStringRef Result_;
}
};
-typedef std::map<const char *, Type_privateData *, CYCStringLess> TypeMap;
-static TypeMap Types_;
-
JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
Struct_privateData *internal(new Struct_privateData(context, owner));
CYPool &pool(*internal->pool_);
}
static void *CYCastSymbol(const char *name) {
+ for (CYHook *hook : GetHooks())
+ if (hook->CastSymbol != NULL)
+ if (void *value = (*hook->CastSymbol)(name))
+ return value;
return dlsym(RTLD_DEFAULT, name);
}
return value != NULL && JSValueIsObject(context, value) && JSObjectIsFunction(context, (JSObjectRef) value);
}
+bool CYIsEqual(JSContextRef context, JSValueRef lhs, JSValueRef rhs) {
+ return _jsccall(JSValueIsEqual, context, lhs, rhs);
+}
+
+bool CYIsStrictEqual(JSContextRef context, JSValueRef lhs, JSValueRef rhs) {
+ return JSValueIsStrictEqual(context, lhs, rhs);
+}
+
size_t CYArrayLength(JSContextRef context, JSObjectRef array) {
return CYCastDouble(context, CYGetProperty(context, array, length_s));
}
}
void *CYCastPointer_(JSContextRef context, JSValueRef value) {
- switch (JSValueGetType(context, value)) {
+ if (value == NULL)
+ return NULL;
+ else switch (JSValueGetType(context, value)) {
case kJSTypeNull:
return NULL;
case kJSTypeObject: {
break;
default:
- for (CYHook *hook : hooks_)
+ for (CYHook *hook : GetHooks())
if (hook->PoolFFI != NULL)
if ((*hook->PoolFFI)(pool, context, type, ffi, data, value))
return;
null:
return CYJSNull(context);
default:
- for (CYHook *hook : hooks_)
+ for (CYHook *hook : GetHooks())
if (hook->FromFFI != NULL)
if (JSValueRef value = (*hook->FromFFI)(context, type, ffi, data, initialize, owner))
return value;
return object;
}
+JSValueRef CYGetCachedValue(JSContextRef context, JSStringRef name) {
+ return CYGetProperty(context, CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s)), name);
+}
+
JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) {
- return CYCastJSObject(context, CYGetProperty(context, CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s)), name));
+ return CYCastJSObject(context, CYGetCachedValue(context, name));
}
static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const sig::Signature &signature) {
uint8_t value[cif->rtype->size];
- for (CYHook *hook : hooks_)
+ for (CYHook *hook : GetHooks())
if (hook->CallFunction != NULL) {
// XXX: this only supports one hook, but it is a bad idea anyway
(*hook->CallFunction)(context, cif, function, value, values);
ExecutionHandle(JSContextRef context) :
context_(context)
{
- handles_.resize(hooks_.size());
- for (size_t i(0); i != hooks_.size(); ++i) {
- CYHook *hook(hooks_[i]);
+ handles_.resize(GetHooks().size());
+ for (size_t i(0); i != GetHooks().size(); ++i) {
+ CYHook *hook(GetHooks()[i]);
if (hook->ExecuteStart != NULL)
handles_[i] = (*hook->ExecuteStart)(context_);
else
}
~ExecutionHandle() {
- for (size_t i(hooks_.size()); i != 0; --i) {
- CYHook *hook(hooks_[i-1]);
+ for (size_t i(GetHooks().size()); i != 0; --i) {
+ CYHook *hook(GetHooks()[i-1]);
if (hook->ExecuteEnd != NULL)
(*hook->ExecuteEnd)(context_, handles_[i-1]);
}
toJSON_s = JSStringCreateWithUTF8CString("toJSON");
toPointer_s = JSStringCreateWithUTF8CString("toPointer");
toString_s = JSStringCreateWithUTF8CString("toString");
+ weak_s = JSStringCreateWithUTF8CString("weak");
Result_ = JSStringCreateWithUTF8CString("_");
- for (CYHook *hook : hooks_)
+ for (CYHook *hook : GetHooks())
if (hook->Initialize != NULL)
(*hook->Initialize)();
}
extern "C" bool CydgetMemoryParse(const uint16_t **data, size_t *size);
void *CYMapFile(const char *path, size_t *psize) {
- int fd(_syscall_(open(path, O_RDONLY), 1, {ENOENT}));
+ int fd(_syscall_(open(path, O_RDONLY), 1, ENOENT));
if (fd == -1)
return NULL;
//CYSetProperty(context, System, CYJSString("global"), global);
CYSetProperty(context, System, CYJSString("print"), &System_print);
+#ifdef __APPLE__
+ if (&JSWeakObjectMapCreate != NULL) {
+ JSWeakObjectMapRef weak(JSWeakObjectMapCreate(context, NULL, NULL));
+ CYSetProperty(context, cy, weak_s, CYCastJSValue(context, reinterpret_cast<uintptr_t>(weak)));
+ }
+#endif
+
if (CYBridgeEntry *entry = CYBridgeHash("1dlerror", 8))
entry->cache_ = new cy::Functor(entry->value_, reinterpret_cast<void (*)()>(&dlerror));
- for (CYHook *hook : hooks_)
+ for (CYHook *hook : GetHooks())
if (hook->SetupContext != NULL)
(*hook->SetupContext)(context);