CYThrow(context, exception);
}
-void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value) {
+void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes = kJSPropertyAttributeNone) {
JSValueRef exception(NULL);
- JSObjectSetProperty(context, object, name, value, kJSPropertyAttributeNone, &exception);
+ JSObjectSetProperty(context, object, name, value, attributes, &exception);
CYThrow(context, exception);
}
/* }}} */
return value == NULL ? NULL : JSStringRetain(value);
}
+JSStringRef CYCopyJSString(CYUTF8String value) {
+ // XXX: this is very wrong
+ return CYCopyJSString(value.data);
+}
+
JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) {
if (JSValueIsNull(context, value))
return NULL;
/* }}} */
#endif
+/* 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')
+ return 0;
+ return _not(size_t);
+}
+
+size_t CYGetIndex(apr_pool_t *pool, JSStringRef value) {
+ return CYGetIndex(CYPoolUTF8String(pool, value));
+}
+
+bool CYGetOffset(const char *value, ssize_t &index) {
+ if (value[0] != '0') {
+ char *end;
+ index = strtol(value, &end, 10);
+ if (value + strlen(value) == end)
+ return true;
+ } else if (value[1] == '\0') {
+ index = 0;
+ return true;
+ }
+
+ return false;
+}
+
+#ifdef __OBJC__
+size_t CYGetIndex(NSString *value) {
+ return CYGetIndex(CYCastUTF8String(value));
+}
+
+bool CYGetOffset(apr_pool_t *pool, NSString *value, ssize_t &index) {
+ return CYGetOffset(CYPoolCString(pool, value), index);
+}
+#endif
+/* }}} */
+
/* JavaScript *ify {{{ */
void CYStringify(std::ostringstream &str, const char *data, size_t size) {
unsigned quot(0), apos(0);
}
/* }}} */
+bool CYIsKey(CYUTF8String value) {
+ const char *data(value.data);
+ size_t size(value.size);
+
+ if (size == 0)
+ return false;
+
+ if (DigitRange_[data[0]]) {
+ size_t index(CYGetIndex(value));
+ if (index == _not(size_t))
+ return false;
+ } else {
+ if (!WordStartRange_[data[0]])
+ return false;
+ for (size_t i(1); i != size; ++i)
+ if (!WordEndRange_[data[i]])
+ return false;
+ }
+
+ return true;
+}
+
static JSGlobalContextRef Context_;
static JSObjectRef System_;
return JSValueMakeUndefined(context);
}
-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')
- return 0;
- return _not(size_t);
-}
-
-size_t CYGetIndex(apr_pool_t *pool, JSStringRef value) {
- return CYGetIndex(CYPoolUTF8String(pool, value));
-}
-
-bool CYGetOffset(const char *value, ssize_t &index) {
- if (value[0] != '0') {
- char *end;
- index = strtol(value, &end, 10);
- if (value + strlen(value) == end)
- return true;
- } else if (value[1] == '\0') {
- index = 0;
- return true;
- }
-
- return false;
-}
-
-#ifdef __OBJC__
-size_t CYGetIndex(NSString *value) {
- return CYGetIndex(CYCastUTF8String(value));
-}
-
-bool CYGetOffset(apr_pool_t *pool, NSString *value, ssize_t &index) {
- return CYGetOffset(CYPoolCString(pool, value), index);
-}
-#endif
-
#ifdef __OBJC__
@interface NSMethodSignature (Cycript)
- (NSString *) _typeString;
#ifdef __APPLE__
for (id object in self) {
#else
- id object;
for (size_t index(0), count([self count]); index != count; ++index) {
- object = [self objectAtIndex:index];
+ id object([self objectAtIndex:index]);
#endif
if (comma)
[json appendString:@","];
}
- (NSString *) cy$toKey {
- const char *value([self UTF8String]);
- size_t size(strlen(value));
-
- if (size == 0)
- goto cyon;
-
- if (DigitRange_[value[0]]) {
- size_t index(CYGetIndex(self));
- if (index == _not(size_t))
- goto cyon;
- } else {
- if (!WordStartRange_[value[0]])
- goto cyon;
- for (size_t i(1); i != size; ++i)
- if (!WordEndRange_[value[i]])
- goto cyon;
- }
-
- return self;
-
- cyon:
+ if (CYIsKey(CYCastUTF8String(self)))
+ return self;
return [self cy$toCYON];
}
return value != NULL && JSValueIsObject(context, value) && JSObjectIsFunction(context, (JSObjectRef) value);
}
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object);
+
#ifdef __OBJC__
@implementation CYJSObject
}
- (NSString *) cy$toCYON {
- JSValueRef toCYON(CYGetProperty(context_, object_, toCYON_));
- if (!CYIsCallable(context_, toCYON)) super:
- return [super cy$toCYON];
- else if (JSValueRef value = CYCallAsFunction(context_, (JSObjectRef) toCYON, object_, 0, NULL))
- return CYCastNSString(NULL, CYJSString(context_, value));
- else goto super;
+ CYPool pool;
+ JSValueRef exception(NULL);
+ const char *cyon(CYPoolCCYON(pool, context_, object_));
+ CYThrow(context_, exception);
+ return cyon == NULL ? [super cy$toCYON] : [NSString stringWithUTF8String:cyon];
}
- (NSUInteger) count {
return apr_pstrmemdup(pool, value.c_str(), value.size());
} break;
- case kJSTypeObject: {
- JSObjectRef object((JSObjectRef) value);
- JSValueRef toCYON(CYGetProperty(context, object, toCYON_));
-
- if (CYIsCallable(context, toCYON)) {
- JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toCYON, object, 0, NULL));
- return CYPoolCString(pool, context, value);
- }
-
- return "\"[object /* XXX: implement something awesome */]\"";
- } break;
+ case kJSTypeObject: CYTry {
+ return CYPoolCCYON(pool, context, (JSObjectRef) value);
+ } CYCatch
default:
_throw(NSInternalInconsistencyException, "JSValueGetType() == 0x%x", type);
}
}
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value) {
+ JSValueRef exception(NULL);
+ const char *cyon(CYPoolCCYON(pool, context, value, &exception));
+ CYThrow(context, exception);
+ return cyon;
+}
+
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object) {
+ JSValueRef toCYON(CYGetProperty(context, object, toCYON_));
+ if (CYIsCallable(context, toCYON)) {
+ JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toCYON, object, 0, NULL));
+ return CYPoolCString(pool, context, value);
+ }
+
+ JSValueRef toJSON(CYGetProperty(context, object, toJSON_));
+ if (CYIsCallable(context, toJSON)) {
+ JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(""))};
+ JSValueRef exception(NULL);
+ const char *cyon(CYPoolCCYON(pool, context, CYCallAsFunction(context, (JSObjectRef) toJSON, object, 1, arguments), &exception));
+ CYThrow(context, exception);
+ return cyon;
+ }
+
+ std::ostringstream str;
+
+ str << '{';
+
+ // XXX: this is, sadly, going to leak
+ JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object));
+
+ bool comma(false);
+
+ for (size_t index(0), count(JSPropertyNameArrayGetCount(names)); index != count; ++index) {
+ JSStringRef name(JSPropertyNameArrayGetNameAtIndex(names, index));
+ JSValueRef value(CYGetProperty(context, object, name));
+
+ if (comma)
+ str << ',';
+ else
+ comma = true;
+
+ CYUTF8String string(CYPoolUTF8String(pool, name));
+ if (CYIsKey(string))
+ str << string.data;
+ else
+ CYStringify(str, string.data, string.size);
+
+ str << ':' << CYPoolCCYON(pool, context, value);
+ }
+
+ str << '}';
+
+ JSPropertyNameArrayRelease(names);
+
+ std::string string(str.str());
+ return apr_pstrmemdup(pool, string.c_str(), string.size());
+}
+
+static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+ CYPool pool;
+ std::ostringstream str;
+
+ str << '[';
+
+ // XXX: this is, sadly, going to leak
+ // XXX: shouldn't this be done with .length?!
+ JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, _this));
+
+ bool comma(false);
+
+ for (size_t index(0), count(JSPropertyNameArrayGetCount(names)); index != count; ++index) {
+ JSStringRef name(JSPropertyNameArrayGetNameAtIndex(names, index));
+ JSValueRef value(CYGetProperty(context, _this, name));
+
+ if (comma)
+ str << ',';
+ else
+ comma = true;
+
+ if (!JSValueIsUndefined(context, value))
+ str << CYPoolCCYON(pool, context, value);
+ else {
+ str << ',';
+ comma = false;
+ }
+ }
+
+ str << ']';
+
+ JSPropertyNameArrayRelease(names);
+
+ std::string value(str.str());
+ return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
+} CYCatch }
+
#ifdef __OBJC__
// XXX: use objc_getAssociatedObject and objc_setAssociatedObject on 10.6
struct CYInternal :
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_);