static int comparison_oper(VAL left, VAL right) { double l, r; if(js_value_get_type(left) == JS_T_STRING && js_value_get_type(right) == JS_T_STRING) { return js_string_cmp(&js_value_get_pointer(left)->string, &js_value_get_pointer(right)->string); } else { l = js_value_get_double(js_to_number(left)); r = js_value_get_double(js_to_number(right)); if(l < r) { return -1; } else if(l > r) { return 1; } else { return 0; } } }
static VAL js_object_base_default_value(js_value_t* obj, js_type_t preferred_type) { VAL fn, ret, this = js_value_make_pointer(obj); if(!preferred_type) { preferred_type = JS_T_NUMBER; } if(preferred_type == JS_T_STRING) { fn = js_object_get(this, js_cstring("toString")); if(js_value_get_type(fn) == JS_T_FUNCTION) { ret = js_call(fn, this, 0, NULL); if(js_value_is_primitive(ret)) { return ret; } } fn = js_object_get(this, js_cstring("valueOf")); if(js_value_get_type(fn) == JS_T_FUNCTION) { ret = js_call(fn, this, 0, NULL); if(js_value_is_primitive(ret)) { return ret; } } // @TODO throw exception js_panic("could not convert object to string"); } else if(preferred_type == JS_T_NUMBER) { fn = js_object_get(this, js_cstring("valueOf")); if(js_value_get_type(fn) == JS_T_FUNCTION) { ret = js_call(fn, this, 0, NULL); if(js_value_is_primitive(ret)) { return ret; } } fn = js_object_get(this, js_cstring("toString")); if(js_value_get_type(fn) == JS_T_FUNCTION) { ret = js_call(fn, this, 0, NULL); if(js_value_is_primitive(ret)) { return ret; } } // @TODO throw exception js_panic("could not convert object to string"); } js_panic("could not convert object to string"); }
static VAL js_object_base_get(js_value_t* obj, js_string_t* prop) { js_property_descriptor_t* descr = NULL; js_value_t* this = obj; while(!st_lookup(obj->object.properties, (st_data_t)prop, (st_data_t*)&descr)) { /* if not in object, look in prototype */ if(js_value_is_primitive(obj->object.prototype)) { /* do not attempt if prototype is primitive */ return js_value_undefined(); } obj = js_value_get_pointer(obj->object.prototype); } if(!descr->is_accessor) { return descr->data.value; } else { if(js_value_get_type(descr->accessor.get) == JS_T_FUNCTION) { return js_call(descr->accessor.get, js_value_make_pointer(this), 0, NULL); } return js_value_undefined(); } }
static void js_object_base_put(js_value_t* obj, js_string_t* prop, VAL value) { js_property_descriptor_t* descr = NULL; if(st_lookup(obj->object.properties, (st_data_t)prop, (st_data_t*)&descr)) { if(!descr->is_accessor) { if(descr->data.writable) { descr->data.value = value; } } else { if(js_value_get_type(descr->accessor.set) == JS_T_FUNCTION) { js_call(descr->accessor.set, js_value_make_pointer(obj), 1, &value); } } return; } descr = js_alloc(sizeof(js_property_descriptor_t)); descr->is_accessor = false; descr->enumerable = true; descr->configurable = true; descr->data.value = value; descr->data.writable = true; st_insert(obj->object.properties, (st_data_t)prop, (st_data_t)descr); }