From 3f7ac48bfc20d01bd13dee88034f6ec824b5e216 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sat, 19 Dec 2015 02:09:58 -0800 Subject: [PATCH] Port Error.toCYON() to JS and write Date.toCYON(). --- Execute.cpp | 77 ++++++++++++++++++++++++++++++++++----------------- apple.mk | 6 ++++ libcycript.cy | 21 ++++++++++++++ 3 files changed, 78 insertions(+), 26 deletions(-) create mode 100644 libcycript.cy diff --git a/Execute.cpp b/Execute.cpp index 9862755..8f36a45 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -538,21 +538,6 @@ static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size()))); } CYCatch(NULL) } -static JSValueRef Error_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - CYPool pool; - std::ostringstream str; - - str << "new " << CYPoolUTF8String(pool, context, CYJSString(context, CYGetProperty(context, _this, name_s))) << "("; - - CYUTF8String string(CYPoolUTF8String(pool, context, CYJSString(context, CYGetProperty(context, _this, message_s)))); - CYStringify(str, string.data, string.size); - - str << ")"; - - std::string value(str.str()); - return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size()))); -} CYCatch(NULL) } - static JSValueRef String_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CYPool pool; std::ostringstream str; @@ -1805,7 +1790,23 @@ JSGlobalContextRef CYGetJSContext(JSContextRef context) { return reinterpret_cast(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_; } -void *CYMapFile(const char *path, size_t *psize) { +struct CYFile { + void *data_; + size_t size_; + + CYFile(void *data, size_t size) : + data_(data), + size_(size) + { + } +}; + +static void CYFileExit(void *data) { + CYFile *file(reinterpret_cast(data)); + _syscall(munmap(file->data_, file->size_)); +} + +static void *CYPoolFile(CYPool &pool, const char *path, size_t *psize) { int fd(_syscall_(open(path, O_RDONLY), 1, ENOENT)); if (fd == -1) return NULL; @@ -1819,22 +1820,37 @@ void *CYMapFile(const char *path, size_t *psize) { void *base; _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); + CYFile *file(new (pool) CYFile(base, size)); + pool.atexit(&CYFileExit, file); + _syscall(close(fd)); return base; } -static JSValueRef require(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - _assert(count == 1); - CYPool pool; +static CYUTF8String CYPoolFileUTF8String(CYPool &pool, const char *path) { + CYUTF8String data; + data.data = reinterpret_cast(CYPoolFile(pool, path, &data.size)); + return data; +} +static const char *CYPoolLibraryPath(CYPool &pool) { Dl_info addr; - _assert(dladdr(reinterpret_cast(&require), &addr) != 0); + _assert(dladdr(reinterpret_cast(&CYPoolLibraryPath), &addr) != 0); char *lib(pool.strdup(addr.dli_fname)); char *slash(strrchr(lib, '/')); _assert(slash != NULL); *slash = '\0'; + return lib; +} + +static JSValueRef require(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + _assert(count == 1); + CYPool pool; + + const char *lib(CYPoolLibraryPath(pool)); + CYJSString property("exports"); JSObjectRef module; @@ -1848,8 +1864,7 @@ static JSValueRef require(JSContextRef context, JSObjectRef object, JSObjectRef if (!JSValueIsUndefined(context, cache)) module = CYCastJSObject(context, cache); else { - CYUTF8String code; - code.data = reinterpret_cast(CYMapFile(path, &code.size)); + CYUTF8String code(CYPoolFileUTF8String(pool, path)); if (code.data == NULL) { if (strchr(name, '/') == NULL && ( @@ -1883,6 +1898,18 @@ static JSValueRef require(JSContextRef context, JSObjectRef object, JSObjectRef return CYGetProperty(context, module, property); } CYCatch(NULL) } +static bool CYRunScript(JSGlobalContextRef context, const char *path) { + CYPool pool; + CYUTF8String code(CYPoolFileUTF8String(pool, path)); + if (code.data == NULL) + return false; + + CYStream stream(code.data, code.data + code.size); + code = CYPoolCode(pool, stream); + _jsccall(JSEvaluateScript, context, CYJSString(code), NULL, NULL, 0); + return true; +} + extern "C" void CYDestroyWeak(JSWeakObjectMapRef weak, void *data) { } @@ -1910,9 +1937,6 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { JSObjectRef Error(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Error")))); CYSetProperty(context, cy, CYJSString("Error"), Error); - JSObjectRef Error_prototype(CYCastJSObject(context, CYGetProperty(context, Error, prototype_s))); - CYSetProperty(context, cy, CYJSString("Error_prototype"), Error_prototype); - JSObjectRef Function(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Function")))); CYSetProperty(context, cy, CYJSString("Function"), Function); @@ -1942,7 +1966,6 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { /* }}} */ CYSetProperty(context, Array_prototype, toCYON_s, &Array_callAsFunction_toCYON, kJSPropertyAttributeDontEnum); - CYSetProperty(context, Error_prototype, toCYON_s, &Error_callAsFunction_toCYON, kJSPropertyAttributeDontEnum); CYSetProperty(context, String_prototype, toCYON_s, &String_callAsFunction_toCYON, kJSPropertyAttributeDontEnum); JSObjectRef cycript(JSObjectMake(context, NULL, NULL)); @@ -2001,6 +2024,8 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { if (CYBridgeEntry *entry = CYBridgeHash("1dlerror", 8)) entry->cache_ = new cy::Functor(entry->value_, reinterpret_cast(&dlerror)); + CYRunScript(context, "libcycript.cy"); + for (CYHook *hook : GetHooks()) if (hook->SetupContext != NULL) (*hook->SetupContext)(context); diff --git a/apple.mk b/apple.mk index ad0f022..bd0b69e 100644 --- a/apple.mk +++ b/apple.mk @@ -37,6 +37,7 @@ cycript += Cycript.lib/cycript0.9 cycript += Cycript.lib/libcycript.dylib cycript += Cycript.lib/libcycript-sys.dylib cycript += Cycript.lib/libcycript-sim.dylib +cycript += Cycript.lib/libcycript.cy framework := framework += Cycript @@ -69,6 +70,7 @@ $(deb): Cycript.lib/cycript Cycript.lib/libcycript.dylib $(lipo) -extract armv6 -output package/usr/bin/cycript Cycript.lib/cycript $(lipo) -extract armv6 -extract arm64 -output package/usr/lib/libcycript.dylib Cycript.lib/libcycript.dylib ln -s libcycript.dylib package/usr/lib/libcycript.0.dylib + cp -a libcycript.cy package/usr/lib/libcycript.cy ./dpkg-deb.sh -Zlzma -b package $@ deb: $(deb) @@ -190,6 +192,10 @@ Cycript.%/Cycript.framework/Headers/Cycript.h: Cycript.h @mkdir -p $(dir $@) cp -a $< $@ +Cycript.lib/libcycript.cy: + @mkdir -p $(dir $@) + ln -sf ../libcycript.cy $@ + Cycript.lib/cycript0.9: @mkdir -p $(dir $@) ln -s ../modules $@ diff --git a/libcycript.cy b/libcycript.cy new file mode 100644 index 0000000..e9a612f --- /dev/null +++ b/libcycript.cy @@ -0,0 +1,21 @@ +let $cy_set = function(object, properties) { + for (const name in properties) + Object.defineProperty(object, name, { + configurable: true, + enumerable: false, + writable: true, + value: properties[name], + }); +}; + +$cy_set(Date.prototype, { + toCYON: function() { + return `new ${this.constructor.name}(${this.toUTCString().toCYON()})`; + }, +}); + +$cy_set(Error.prototype, { + toCYON: function() { + return `new ${this.constructor.name}(${this.message.toCYON()})`; + }, +}); -- 2.45.2