js_vm_t* js_vm_new() { js_vm_t* vm = js_alloc(sizeof(js_vm_t)); // this proto/constructor is fixed up later by js_lib_initialize vm->global_scope = js_scope_make_global(vm, js_value_make_object(js_value_undefined(), js_value_undefined())); js_object_put(vm->global_scope->global_object, js_cstring("global"), vm->global_scope->global_object); js_lib_initialize(vm); return vm; }
js_string_t* js_string_from_double(double number) { if(number != number) { return js_cstring("NaN"); } if(!isfinite(number)) { if(number > 0) { return js_cstring("Infinity"); } else { return js_cstring("-Infinity"); } } double whole = floor(number); double frac = fabs(number) - fabs(whole); char buff[1024]; char* ptr = buff; if(whole < 0) { *ptr++ = '-'; whole = -number; } if(whole == 0) { *ptr++ = '0'; } char minibuff[1024]; memset(minibuff, 0, 1024); uint32_t minibuff_i = 0; while(whole > 0) { minibuff[minibuff_i++] = '0' + (int)fmod(whole, 10.0); whole = floor(whole / 10.0); } while(minibuff_i > 0) { *ptr++ = minibuff[--minibuff_i]; } uint32_t frac_i; if(frac > 0) { *ptr++ = '.'; for(frac_i = 0; frac_i < 6; frac_i++) { frac = fmod(frac * 10.0, 10.0); *ptr++ = '0' + (int)floor(frac); } } *ptr++ = 0; return js_cstring(buff); }
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"); }
#include <stddef.h> #include "string.h" #include "lib.h" #include "exception.h" static VAL make_generic_error(js_string_t* name, VAL proto, VAL class, uint32_t argc, VAL* argv) { VAL obj = js_value_make_object(proto, class); js_object_put(obj, js_cstring("name"), js_value_wrap_string(name)); if(argc > 0) { js_object_put(obj, js_cstring("message"), js_to_string(argv[0])); } return obj; } static VAL Error_construct(js_vm_t* vm, void* state, VAL this, uint32_t argc, VAL* argv) { return make_generic_error(js_cstring("Error"), vm->lib.Error_prototype, vm->lib.Error, argc, argv); } static VAL RangeError_construct(js_vm_t* vm, void* state, VAL this, uint32_t argc, VAL* argv) { return make_generic_error(js_cstring("RangeError"), vm->lib.RangeError_prototype, vm->lib.RangeError, argc, argv); } static VAL ReferenceError_construct(js_vm_t* vm, void* state, VAL this, uint32_t argc, VAL* argv) { return make_generic_error(js_cstring("ReferenceError"), vm->lib.ReferenceError_prototype, vm->lib.ReferenceError, argc, argv); } static VAL TypeError_construct(js_vm_t* vm, void* state, VAL this, uint32_t argc, VAL* argv)