static ejsval _ejs_Process_get_env (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval env_obj = _ejs_object_new(_ejs_null, &_ejs_Object_specops); char** p = environ; while (*p) { char *env_entry = strdup(*p); char *eq = strchr(env_entry, '='); if (!eq) { free (env_entry); p++; continue; } *eq = '\0'; ejsval k = _ejs_string_new_utf8(env_entry); ejsval v = _ejs_string_new_utf8(eq+1); _ejs_object_define_value_property (env_obj, k, v, EJS_PROP_ENUMERABLE | EJS_PROP_NOT_CONFIGURABLE | EJS_PROP_NOT_WRITABLE); free (env_entry); p++; } return env_obj; }
ejsval Function_prototype_get_name(ejsval env, ejsval _this, int argc, ejsval *args) { Function* fun = ((Function*)EJSVAL_TO_OBJECT(_this)); std::string fun_name = fun->llvm_fun->getName(); return _ejs_string_new_utf8(fun_name.c_str()); }
static EJS_NATIVE_FUNC(ArrayType_prototype_toString) { std::string str; llvm::raw_string_ostream str_ostream(str); ((ArrayType*)EJSVAL_TO_OBJECT(*_this))->type->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
ejsval _ejs_function_new_utf8 (ejsval env, const char *name, EJSClosureFunc func) { ejsval function_name = _ejs_string_new_utf8 (name); ejsval rv = _ejs_function_new (env, function_name, func); return rv; }
static EJS_NATIVE_FUNC(GlobalVariable_prototype_toString) { std::string str; llvm::raw_string_ostream str_ostream(str); ((GlobalVariable*)EJSVAL_TO_OBJECT(*_this))->llvm_global->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
static EJS_NATIVE_FUNC(_ejs_Process_cwd) { char cwd[MAXPATHLEN]; getcwd(cwd, MAXPATHLEN); return _ejs_string_new_utf8(cwd); }
void _ejs_process_init(ejsval global, uint32_t argc, char **argv) { _ejs_Process = _ejs_object_new (_ejs_null, &_ejs_Object_specops); _ejs_object_setprop (global, _ejs_atom_process, _ejs_Process); ejsval _argv = _ejs_array_new (argc, EJS_FALSE); _ejs_object_setprop (_ejs_Process, _ejs_atom_argv, _argv); for (int i = 0; i < argc; i ++) _ejs_object_setprop (_argv, NUMBER_TO_EJSVAL(i), _ejs_string_new_utf8(argv[i])); #define OBJ_PROP(x) EJS_INSTALL_ATOM_GETTER(_ejs_Process, x, _ejs_Process_get_##x) #define OBJ_METHOD(x) EJS_INSTALL_ATOM_FUNCTION(_ejs_Process, x, _ejs_Process_##x) OBJ_PROP(env); OBJ_METHOD(exit); OBJ_METHOD(chdir); OBJ_METHOD(cwd); #undef OBJ_PROP #undef OBJ_METHOD }
static ejsval _ejs_path_resolve (ejsval env, ejsval _this, uint32_t argc, ejsval* args) { // FIXME node's implementation is a lot more flexible. we just combine the paths with a / between them. ejsval from = args[0]; ejsval to = args[1]; return _ejs_string_concat (from, _ejs_string_concat (_ejs_string_new_utf8("/"), to)); }
static EJSBool json_value_to_ejsval(JSON_Value *v, ejsval *rv) { switch (json_value_get_type (v)) { case JSONNull: *rv = _ejs_null; return EJS_TRUE; case JSONString: *rv = _ejs_string_new_utf8 (json_value_get_string(v)); return EJS_TRUE; case JSONNumber: *rv = NUMBER_TO_EJSVAL(json_value_get_number(v)); return EJS_TRUE; case JSONObject: { JSON_Object *obj = json_value_get_object (v); *rv = _ejs_object_create (_ejs_null); int count = json_object_get_count (obj); for (int i = 0; i < count; i ++) { const char *propkey = json_object_get_name (obj, i); ejsval propval; if (!json_value_to_ejsval (json_object_get_value (obj, propkey), &propval)) return EJS_FALSE; _ejs_object_setprop_utf8 (*rv, propkey, propval); } return EJS_TRUE; } case JSONArray: { JSON_Array *arr = json_value_get_array (v); int count = json_array_get_count (arr); *rv = _ejs_array_new (count, EJS_FALSE); for (int i = 0; i < count; i ++) { ejsval propkey = _ejs_number_new (i); ejsval propval; if (!json_value_to_ejsval (json_array_get_value (arr, i), &propval)) return EJS_FALSE; _ejs_object_setprop (*rv, propkey, propval); } return EJS_TRUE; } case JSONBoolean: *rv = BOOLEAN_TO_EJSVAL(json_value_get_boolean(v)); return EJS_TRUE; case JSONError: EJS_NOT_IMPLEMENTED(); return EJS_FALSE; } }
ejsval AllocaInst_prototype_toString(ejsval env, ejsval *_this, uint32_t argc, ejsval *args, ejsval newTarget) { std::string str; llvm::raw_string_ostream str_ostream(str); ((AllocaInst*)EJSVAL_TO_OBJECT(*_this))->llvm_alloca->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
ejsval FunctionType_prototype_toString(ejsval env, ejsval _this, int argc, ejsval *args) { std::string str; llvm::raw_string_ostream str_ostream(str); ((FunctionType*)EJSVAL_TO_OBJECT(_this))->type->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
ejsval LoadInst_prototype_toString(ejsval env, ejsval _this, int argc, ejsval *args) { std::string str; llvm::raw_string_ostream str_ostream(str); ((LoadInst*)EJSVAL_TO_OBJECT(_this))->llvm_load->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
void _ejs_uri_init (ejsval global) { /* 18.2.6.1 URI Syntax and Semantics */ /* a 'funny' thing is that we are flatting the string whenever we are encoding it. It would be nice to have it * in that state always! */ char *uriUnescaped = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~*'()"; _ejs_uriUnescaped = _ejs_string_new_utf8 (uriUnescaped); }
ejsval GlobalVariable_prototype_toString(ejsval env, ejsval _this, int argc, ejsval *args) { std::string str; llvm::raw_string_ostream str_ostream(str); ((GlobalVariable*)EJSVAL_TO_OBJECT(_this))->llvm_global->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
ejsval Call_prototype_toString(ejsval env, ejsval _this, int argc, ejsval *args) { std::string str; llvm::raw_string_ostream str_ostream(str); ((Call*)EJSVAL_TO_OBJECT(_this))->llvm_call->print(str_ostream, NULL); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
static ejsval _ejs_Process_cwd (ejsval env, ejsval _this, uint32_t argc, ejsval* args) { char cwd[MAXPATHLEN]; getcwd(cwd, MAXPATHLEN); return _ejs_string_new_utf8(cwd); }
static ejsval _ejs_path_basename (ejsval env, ejsval _this, uint32_t argc, ejsval* args) { ejsval path = args[0]; // FIXME node's implementation allows a second arg to strip the extension, but the compiler doesn't use it. char *utf8_path = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(path)); ejsval rv = _ejs_string_new_utf8(basename (utf8_path)); free (utf8_path); return rv; }
// ECMA262: 19.4.3.2 Symbol.prototype.toString () static EJS_NATIVE_FUNC(_ejs_Symbol_prototype_toString) { // 1. Let s be the this value. ejsval s = *_this; EJSPrimSymbol* sym; // 2. If Type(s) is Symbol, then let sym be s. if (EJSVAL_IS_SYMBOL(s)) { sym = EJSVAL_TO_SYMBOL(s); } // 3. Else, else { // a. If s does not have a [[SymbolData]] internal slot, then throw a TypeError exception. if (!EJSVAL_IS_SYMBOL_OBJECT(s)) { _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Symbol.prototype.toString called with non-symbol this"); } // b. Let sym be the value of s’s [[SymbolData]] internal slot. sym = EJSVAL_TO_SYMBOL(EJSVAL_TO_SYMBOL_OBJECT(s)->primSymbol); } // 4. Let desc be the value of sym’s [[Description]] attribute. ejsval desc = sym->description; // 5. If desc is undefined, then let desc be the empty string. if (EJSVAL_IS_UNDEFINED(desc)) desc = _ejs_atom_empty; // 6. Assert: Type(desc) is String. // 7. Let result be the result of concatenating the strings "Symbol(", desc, and ")". ejsval result = _ejs_string_concatv (_ejs_atom_Symbol, _ejs_string_new_utf8("("), desc, _ejs_string_new_utf8(")"), _ejs_null); // 8. Return result. return result; }
ejsval NumberToString(double d) { int32_t i; if (EJSDOUBLE_IS_INT32(d, &i)) { if (i >=0 && i <= 200) return *builtin_numbers_atoms[i]; jschar int_buf[UINT32_CHAR_BUFFER_LENGTH+1]; jschar *cp = IntToUCS2(int_buf, i, 10); return _ejs_string_new_ucs2 (cp); } char num_buf[256]; snprintf (num_buf, sizeof(num_buf), EJS_NUMBER_FORMAT, d); return _ejs_string_new_utf8 (num_buf); }
ejsval _ejs_function_new_utf8_with_proto (ejsval env, const char* name, EJSClosureFunc func, ejsval prototype) { ejsval function_name = _ejs_string_new_utf8 (name); EJSFunction *rv = _ejs_gc_new(EJSFunction); _ejs_init_object ((EJSObject*)rv, _ejs_Function_prototype, &_ejs_Function_specops); rv->func = func; rv->env = env; ejsval fun = OBJECT_TO_EJSVAL(rv); _ejs_object_define_value_property (fun, _ejs_atom_name, function_name, EJS_PROP_NOT_ENUMERABLE | EJS_PROP_NOT_CONFIGURABLE | EJS_PROP_NOT_WRITABLE); _ejs_object_define_value_property (fun, _ejs_atom_prototype, prototype, EJS_PROP_NOT_ENUMERABLE | EJS_PROP_CONFIGURABLE | EJS_PROP_WRITABLE); return fun; }
static EJS_NATIVE_FUNC(_ejs_Error_prototype_toString) { ejsval O = *_this; if (!EJSVAL_IS_OBJECT(O)) { _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Error.prototype.toString called on non-object"); } EJSObject *_thisobj = EJSVAL_TO_OBJECT(O); ejsval name = OP(_thisobj,Get)(O, _ejs_atom_name, O); if (EJSVAL_IS_NULL_OR_UNDEFINED(name)) name = _ejs_atom_Error; ejsval message = OP(_thisobj,Get)(O, _ejs_atom_message, O); if (EJSVAL_IS_NULL_OR_UNDEFINED(message)) return name; ejsval sep = _ejs_string_new_utf8(": "); return _ejs_string_concatv (name, sep, message, _ejs_null); }
// ECMA262 15.3.4.2 static ejsval _ejs_Function_prototype_toString (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { char terrible_fixed_buffer[256]; if (!EJSVAL_IS_FUNCTION(_this)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Function.prototype.toString is not generic."); ejsval func_name = _ejs_object_getprop (_this, _ejs_atom_name); char *utf8_funcname = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(func_name)); snprintf (terrible_fixed_buffer, sizeof (terrible_fixed_buffer), "function %s() {}", utf8_funcname); free (utf8_funcname); return _ejs_string_new_utf8(terrible_fixed_buffer); }
static ejsval _ejs_Error_prototype_toString (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { if (!EJSVAL_IS_OBJECT(_this)) { _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Error.prototype.toString called on non-object"); } EJSObject *_thisobj = EJSVAL_TO_OBJECT(_this); ejsval name = OP(_thisobj,Get)(_this, _ejs_atom_name, _this); if (EJSVAL_IS_NULL_OR_UNDEFINED(name)) name = _ejs_atom_Error; ejsval message = OP(_thisobj,Get)(_this, _ejs_atom_message, _this); if (EJSVAL_IS_NULL_OR_UNDEFINED(message)) return name; ejsval sep = _ejs_string_new_utf8(": "); return _ejs_string_concatv (name, sep, message, _ejs_null); }
static ejsval _ejs_path_resolve (ejsval env, ejsval _this, uint32_t argc, ejsval* args) { char** paths_utf8 = (char**)calloc(argc + 1, sizeof(char*)); int num_paths = 0; char cwd[MAXPATHLEN]; getcwd(cwd, MAXPATHLEN); paths_utf8[num_paths++] = strdup(cwd); for (int i = 0; i < argc; i ++) { ejsval arg = args[i]; if (!EJSVAL_IS_STRING(arg)) { for (int j = 0; j < num_paths; j ++) free(paths_utf8[j]); free (paths_utf8); _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Arguments to path.resolve must be strings"); } paths_utf8[num_paths++] = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(arg)); } int start_path; for (start_path = num_paths-1; start_path >= 0; start_path --) { if (paths_utf8[start_path][0] == '/') break; } // at this point paths_utf8[start_path] is our "root" for // resolving. it is either the right-most absolute path in the // argument list, or $cwd if there wasn't an absolute path in the // args. char* resolved = resolvev(&paths_utf8[start_path], num_paths - start_path); ejsval rv = _ejs_string_new_utf8(resolved); free (resolved); for (int j = 0; j < num_paths; j ++) free(paths_utf8[j]); free (paths_utf8); return rv; }
static EJS_NATIVE_FUNC(_ejs_Process_get_env) { ejsval env_obj = _ejs_object_new(_ejs_null, &_ejs_Object_specops); char** p = environ; while (*p) { char *env_entry = *p; char *eq = strchr(env_entry, '='); if (!eq) { p++; continue; } ejsval k = _ejs_string_new_utf8_len(env_entry, eq - env_entry); ejsval v = _ejs_string_new_utf8(eq+1); _ejs_object_define_value_property (env_obj, k, v, EJS_PROP_ENUMERABLE | EJS_PROP_NOT_CONFIGURABLE | EJS_PROP_NOT_WRITABLE); p++; } return env_obj; }
void _ejs_regexp_init(ejsval global) { _ejs_RegExp = _ejs_function_new_without_proto (_ejs_null, _ejs_atom_RegExp, (EJSClosureFunc)_ejs_RegExp_impl); _ejs_object_setprop (global, _ejs_atom_RegExp, _ejs_RegExp); _ejs_gc_add_root (&_ejs_RegExp_prototype); _ejs_RegExp_prototype = _ejs_object_new(_ejs_null, &_ejs_RegExp_specops); EJSRegExp* re_proto = (EJSRegExp*)EJSVAL_TO_OBJECT(_ejs_RegExp_prototype); re_proto->pattern = _ejs_string_new_utf8("(?:)"); re_proto->flags = _ejs_atom_empty; _ejs_object_setprop (_ejs_RegExp, _ejs_atom_prototype, _ejs_RegExp_prototype); #define OBJ_METHOD(x) EJS_INSTALL_ATOM_FUNCTION(_ejs_RegExp, x, _ejs_RegExp_##x) #define PROTO_METHOD(x) EJS_INSTALL_ATOM_FUNCTION(_ejs_RegExp_prototype, x, _ejs_RegExp_prototype_##x) #define PROTO_METHOD_VAL(x) EJS_INSTALL_ATOM_FUNCTION_VAL(_ejs_RegExp_prototype, x, _ejs_RegExp_prototype_##x) #define PROTO_GETTER(x) EJS_INSTALL_ATOM_GETTER(_ejs_RegExp_prototype, x, _ejs_RegExp_prototype_get_##x) _ejs_gc_add_root (&_ejs_RegExp_prototype_exec_closure); _ejs_RegExp_prototype_exec_closure = PROTO_METHOD_VAL(exec); PROTO_METHOD(test); PROTO_METHOD(toString); PROTO_GETTER(global); PROTO_GETTER(ignoreCase); PROTO_GETTER(lastIndex); PROTO_GETTER(multiline); PROTO_GETTER(source); PROTO_GETTER(sticky); PROTO_GETTER(unicode); #undef OBJ_METHOD #undef PROTO_METHOD EJS_INSTALL_SYMBOL_FUNCTION_FLAGS (_ejs_RegExp, create, _ejs_RegExp_create, EJS_PROP_NOT_ENUMERABLE); }
static ejsval Encode (ejsval string, ejsval unescaped) { EJSPrimString *stringObj = EJSVAL_TO_STRING(string); jschar *unescapedStr = EJSVAL_TO_FLAT_STRING(unescaped); /* 1. Let strLen be the number of code units in string. */ int32_t strLen = stringObj->length; /* 2. Let R be the empty String. */ ejsval R = _ejs_atom_empty; /* 3. Let k be 0. */ int32_t k = 0; /* 4. Repeat. */ for (;;) { /* a. If k equals strLen, return R. */ if (k == strLen) return R; /* b. Let C be the code unit at index k within string. */ jschar C = _ejs_string_ucs2_at (stringObj, k); jschar C_arr [2] = { C, 0 }; /* c. If C is in unescapedSet, then */ jschar *p = ucs2_strstr (unescapedStr, C_arr); if (p) { /* i. Let S be a String containing only the code unit C. */ ejsval S = _ejs_string_new_substring (string, k, 1); /* ii. Let R be a new String value computed by concatenating the previous value of R and S. */ R = _ejs_string_concat (R, S); } /* d. Else C is not in unescapedSet, */ else { /* i. If the code unit value of C is not less than 0xDC00 and not greater than 0xDFFF, throw a URIError exception. */ if (C >= 0xDC00 && C <= 0xDFFF) _ejs_throw_nativeerror_utf8 (EJS_URI_ERROR, "URI malformed"); /* ii. If the code unit value of C is less than 0xD800 or greater than 0xDBFF, then Let V be the code unit value of C. */ jschar V; if (C < 0xD800 || C > 0xDBFF) V = C; /* iii. Else, */ else { /* 1. Increase k by 1. */ k++; /* 2. If k equals strLen, throw a URIError exception. */ if (k == strLen) _ejs_throw_nativeerror_utf8 (EJS_URI_ERROR, "URI malformed"); /* 3. Let kChar be the code unit value of the code unit at index k within string. */ jschar kChar = _ejs_string_ucs2_at (stringObj, k); /* 4. If kChar is less than 0xDC00 or greater than 0xDFFF, throw a URIError exception. */ if (kChar < 0xDC00 || kChar > 0xDFFF) _ejs_throw_nativeerror_utf8 (EJS_URI_ERROR, "URI malformed"); /* 5. Let V be (((the code unit value of C) – 0xD800) × 0x400 + (kChar – 0xDC00) + 0x10000). */ V = (C - 0xD800) * 0x400 + (kChar - 0xDC00) + 0x10000; } /* iv. Let Octets be the array of octets resulting by applying the UTF-8 transformation to V, and let L be the array size. */ char octets[4]; int32_t L = ucs2_to_utf8_char (V, octets); /* v. Let j be 0. */ int32_t j = 0; /* vi. Repeat, while j < L. */ while (j < L) { /* 1. Let jOctet be the value at index j within Octets. */ char jOctet = octets [j]; /* 2. Let S be a String containing three code units “%XY” where XY are two uppercase hexadecimal * digits encoding the value of jOctet. */ char buff[4]; sprintf(buff, "%%%X", jOctet); ejsval S = _ejs_string_new_utf8 (buff); /* 3. Let R be a new String value computed by concatenating the previous value of R and S. */ R = _ejs_string_concat (R, S); /* 4. Increase j by 1. */ j++; } } /* e. Increase k by 1. */ k++; } }
static ejsval _ejs_path_relative (ejsval env, ejsval _this, uint32_t argc, ejsval* args) { ejsval from = _ejs_undefined; ejsval to = _ejs_undefined; if (argc > 0) from = args[0]; if (argc > 1) to = args[1]; if (!EJSVAL_IS_STRING(from) || !EJSVAL_IS_STRING(to)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Arguments to path.relative must be strings"); char *from_utf8 = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(from)); char *to_utf8 = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(to)); if (from_utf8[0] != '/') from_utf8 = make_absolute(from_utf8); if (to_utf8[0] != '/') to_utf8 = make_absolute(to_utf8); char* p = to_utf8 + strlen(to_utf8) - 1; int up = 0; EJSBool seen_slash = EJS_FALSE; while (p != to_utf8) { if (*p == '/') { if (seen_slash) continue; // skip adjacent slashes seen_slash = EJS_TRUE; char* prefix = strndup(to_utf8, p - to_utf8); if (!strcmp(from_utf8, prefix)) { up = -1; free (prefix); goto done; } if (strstr(from_utf8, prefix) == from_utf8) { free (prefix); goto done; } free (prefix); up ++; } else { seen_slash = EJS_FALSE; } p--; } // we made it all the way to the end, fall through to building up our string done: { ejsval dotdotslash = _ejs_string_new_utf8("../"); ejsval rv = _ejs_string_new_utf8(p+1); while (up >= 0) { rv = _ejs_string_concat(dotdotslash, rv); up--; } free (from_utf8); free (to_utf8); return rv; } }
ejsval BasicBlock_prototype_get_name(ejsval env, ejsval _this, int argc, ejsval *args) { BasicBlock* bb = ((BasicBlock*)EJSVAL_TO_OBJECT(_this)); return _ejs_string_new_utf8(bb->llvm_bb->getName().data()); }
ejsval _ejs_nativeerror_new_utf8 (EJSNativeErrorType err_type, const char *message) { ejsval msg = _ejs_string_new_utf8 (message); return _ejs_nativeerror_new (err_type, msg); }