// returns an EJSPrimString*. // maybe we could change it to return a char* to match ToDouble? that way string concat wouldn't create // temporary strings for non-PrimString objects only to throw them away after concatenation? ejsval ToString(ejsval exp) { if (EJSVAL_IS_MAGIC_IMPL(exp)) { // holes in dense arrays end up here return _ejs_atom_empty; } else if (EJSVAL_IS_NULL(exp)) return _ejs_atom_null; else if (EJSVAL_IS_UNDEFINED(exp)) return _ejs_atom_undefined; else if (EJSVAL_IS_BOOLEAN(exp)) return EJSVAL_TO_BOOLEAN(exp) ? _ejs_atom_true : _ejs_atom_false; else if (EJSVAL_IS_NUMBER(exp)) return NumberToString(EJSVAL_TO_NUMBER(exp)); else if (EJSVAL_IS_STRING(exp)) return exp; else if (EJSVAL_IS_OBJECT(exp)) { ejsval toString = _ejs_object_getprop (exp, _ejs_atom_toString); if (!EJSVAL_IS_FUNCTION(toString)) { return _ejs_Object_prototype_toString(_ejs_null, exp, 0, NULL); } // should we be checking if this returns a string? i'd assume so... return _ejs_invoke_closure (toString, exp, 0, NULL); } else EJS_NOT_IMPLEMENTED(); }
ejsval _ejs_typedarray_new_from_array (EJSTypedArrayType element_type, ejsval arrayObj) { EJSObject *arr = EJSVAL_TO_OBJECT(arrayObj); int arrlen = EJSARRAY_LEN(arr); ejsval typedarr = _ejs_typedarray_new (element_type, arrlen); int i; void* data = _ejs_typedarray_get_data (EJSVAL_TO_OBJECT(typedarr)); // this is woefully underoptimized... for (i = 0; i < arrlen; i ++) { ejsval item = _ejs_object_getprop (arrayObj, NUMBER_TO_EJSVAL(i)); switch (element_type) { case EJS_TYPEDARRAY_INT8: ((int8_t*)data)[i] = (int8_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT8: ((uint8_t*)data)[i] = (uint8_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT8CLAMPED: EJS_NOT_IMPLEMENTED(); case EJS_TYPEDARRAY_INT16: ((int16_t*)data)[i] = (int16_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT16: ((uint16_t*)data)[i] = (uint16_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_INT32: ((int32_t*)data)[i] = (int32_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT32: ((uint32_t*)data)[i] = (uint32_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_FLOAT32: ((float*)data)[i] = (float)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_FLOAT64: ((double*)data)[i] = (double)EJSVAL_TO_NUMBER(item); break; default: EJS_NOT_REACHED(); } } return typedarr; }
// 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); }
// ECMA262 15.3.4.5 static ejsval _ejs_Function_prototype_bind (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { /* 1. Let Target be the this value. */ ejsval Target = _this; /* 2. If IsCallable(Target) is false, throw a TypeError exception. */ if (!EJSVAL_IS_CALLABLE(Target)) { _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "object not a function"); } ejsval thisArg = _ejs_undefined; if (argc > 0) thisArg = args[0]; /* 3. Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order. */ int bound_argc = argc > 1 ? argc - 1 : 0; /* 4. Let F be a new native ECMAScript object . */ ejsval bound_env = EJS_BOUNDFUNC_ENV_NEW(bound_argc); EJS_BOUNDFUNC_ENV_SET_TARGET(bound_env, Target); EJS_BOUNDFUNC_ENV_SET_THIS(bound_env, thisArg); EJS_BOUNDFUNC_ENV_SET_ARGC(bound_env, NUMBER_TO_EJSVAL(bound_argc)); for (int i = 0; i < bound_argc; i ++) { EJS_BOUNDFUNC_ENV_SET_ARG(bound_env, i, args[i+1]); } ejsval target_name = _ejs_object_getprop (Target, _ejs_atom_name); ejsval bound_name; if (EJSVAL_IS_STRING(target_name)) bound_name = _ejs_string_concat(_ejs_atom_bound_space, target_name); else bound_name = _ejs_atom_bound_space; ejsval F = _ejs_function_new (bound_env, bound_name, bound_wrapper); EJSFunction *F_ = (EJSFunction*)EJSVAL_TO_OBJECT(F); F_->bound = EJS_TRUE; return F; }
// ES6: 23.4.3.3 // WeakSet.prototype.delete ( value ) static EJS_NATIVE_FUNC(_ejs_WeakSet_prototype_delete) { ejsval value = _ejs_undefined; if (argc > 0) value = args[0]; // 1. Let S be the this value. ejsval S = *_this; // 2. If Type(S) is not Object, then throw a TypeError exception. if (!EJSVAL_IS_OBJECT(S)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "delete called with non-object this."); // 3. If S does not have a [[WeakSetData]] internal slot throw a TypeError exception. if (!EJSVAL_IS_WEAKSET(S)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "delete called with non-WeakSet this."); // 4. If S’s [[WeakSetData]] internal slot is undefined, then throw a TypeError exception. // 5. If Type(value) is not Object, then return false. if (!EJSVAL_IS_OBJECT(value)) return _ejs_false; // 6. Let entries be the List that is the value of M’s [[WeakSetData]] internal slot. #if WEAK_COLLECTIONS_USE_INVERTED_REP ejsval iset = _ejs_object_getprop(value, _ejs_WeakSetData_symbol); if (EJSVAL_IS_NULL_OR_UNDEFINED(iset)) return _ejs_false; if (!EJSVAL_IS_SET(iset)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "[[WeakSetData]] internal error"); return _ejs_set_delete (iset, S); #else // 7. Repeat for each e that is an element of entries, // a. If e is not empty and SameValue(e, value) is true, then // i. Replace the element of entries whose value is e with an element whose value is empty. // ii. Return true. // 8. Return false. return _ejs_false; #endif }
// ES6: 23.4.3.1 // WeakSet.prototype.add ( value ) static EJS_NATIVE_FUNC(_ejs_WeakSet_prototype_add) { ejsval value = _ejs_undefined; if (argc > 0) value = args[0]; // 1. Let S be the this value. ejsval S = *_this; // 2. If Type(S) is not Object, then throw a TypeError exception. if (!EJSVAL_IS_OBJECT(S)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "add called with non-object this."); // 3. If S does not have a [[WeakSetData]] internal slot throw a TypeError exception. if (!EJSVAL_IS_WEAKSET(S)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "add called with non-WeakSet this."); // 4. If S’s [[WeakSetData]] internal slot is undefined, then throw a TypeError exception. // 6. If Type(value) is not Object, then throw a TypeError exception. if (!EJSVAL_IS_OBJECT(value)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "add called with non-Object value."); #if WEAK_COLLECTIONS_USE_INVERTED_REP ejsval iset = _ejs_object_getprop(value, _ejs_WeakSetData_symbol); if (EJSVAL_IS_NULL_OR_UNDEFINED(iset)) { iset = _ejs_set_new(); _ejs_object_setprop(value, _ejs_WeakSetData_symbol, iset); } if (!EJSVAL_IS_SET(iset)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "[[WeakSetData]] internal error"); _ejs_set_add (iset, S); return S; #else // 7. Let entries be the List that is the value of S’s [[WeakSetData]] internal slot. // a. If e is not empty and SameValue(e, value) is true, then // 1. Return S. // 8. Append value as the last element of entries. // 9. Return S. #endif }