static void _ejs_arraybuffer_specop_put (ejsval obj, ejsval propertyName, ejsval val, ejsval receiver, EJSBool flag) { // check if propertyName is a uint32, or a string that we can convert to an uint32 int idx = -1; if (EJSVAL_IS_NUMBER(propertyName)) { double n = EJSVAL_TO_NUMBER(propertyName); if (floor(n) == n) { idx = (int)n; } } if (idx != -1) { if (idx >= EJS_DENSE_ARRAY_ALLOC(obj)) { int new_alloc = idx + 10; ejsval* new_elements = (ejsval*)malloc (sizeof(ejsval) * new_alloc); memmove (new_elements, EJS_DENSE_ARRAY_ELEMENTS(obj), EJS_DENSE_ARRAY_ALLOC(obj) * sizeof(ejsval)); free (EJS_DENSE_ARRAY_ELEMENTS(obj)); EJS_DENSE_ARRAY_ELEMENTS(obj) = new_elements; EJS_DENSE_ARRAY_ALLOC(obj) = new_alloc; } EJS_DENSE_ARRAY_ELEMENTS(obj)[idx] = val; EJS_ARRAY_LEN(obj) = idx + 1; if (EJS_ARRAY_LEN(obj) >= EJS_DENSE_ARRAY_ALLOC(obj)) abort(); return; } // if we fail there, we fall back to the object impl below _ejs_Object_specops.put (obj, propertyName, val, receiver, flag); }
// ECMA262: 26.1.1 Reflect.apply ( target, thisArgument, argumentsList ) static ejsval _ejs_Reflect_apply (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval target = _ejs_undefined; ejsval thisArgument = _ejs_undefined; ejsval argumentsList = _ejs_undefined; if (argc > 0) target = args[0]; if (argc > 1) thisArgument = args[1]; if (argc > 2) argumentsList = args[2]; // 1. Let obj be ToObject(target). // 2. ReturnIfAbrupt(obj). ejsval obj = ToObject(target); // 3. If IsCallable(obj) is false, then throw a TypeError exception. if (!EJSVAL_IS_CALLABLE(obj)) _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, "target is not callable"); // 4. Let args be CreateListFromArray (argumentsList). // 5. ReturnIfAbrupt(args). if (!EJSVAL_IS_ARRAY(argumentsList)) _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, "argumentsList is not an array"); // sparse arrays kinda suck here... if (!EJSVAL_IS_DENSE_ARRAY(argumentsList)) _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, "argumentsList is not a dense array"); // 6. Perform the PrepareForTailCall abstract operation. // 7. Return the result of calling the [[Call]] internal method of obj with arguments thisArgument and args. return _ejs_invoke_closure(obj, thisArgument, EJS_ARRAY_LEN(argumentsList), EJS_DENSE_ARRAY_ELEMENTS(argumentsList)); }
static ejsval _ejs_arraybuffer_specop_get (ejsval obj, ejsval propertyName, ejsval receiver) { // check if propertyName is an integer, or a string that we can convert to an int EJSBool is_index = EJS_FALSE; int idx = 0; if (EJSVAL_IS_NUMBER(propertyName)) { double n = EJSVAL_TO_NUMBER(propertyName); if (floor(n) == n) { idx = (int)n; is_index = EJS_TRUE; } } if (is_index) { if (idx < 0 || idx > EJS_ARRAY_LEN(obj)) { printf ("getprop(%d) on an array, returning undefined\n", idx); return _ejs_undefined; } return EJS_DENSE_ARRAY_ELEMENTS(obj)[idx]; } // we also handle the length getter here if (EJSVAL_IS_STRING(propertyName) && !ucs2_strcmp (_ejs_ucs2_byteLength, EJSVAL_TO_FLAT_STRING(propertyName))) { return NUMBER_TO_EJSVAL (EJS_ARRAY_BUFFER_BYTE_LEN(obj)); } // otherwise we fallback to the object implementation return _ejs_Object_specops.get (obj, propertyName, receiver); }
static EJSPropertyDesc* _ejs_arraybuffer_specop_get_own_property (ejsval obj, ejsval propertyName) { if (EJSVAL_IS_NUMBER(propertyName)) { double needle = EJSVAL_TO_NUMBER(propertyName); int needle_int; if (EJSDOUBLE_IS_INT32(needle, &needle_int)) { if (needle_int >= 0 && needle_int < EJS_ARRAY_LEN(obj)) return NULL; // XXX } } // XXX we need to handle the length property here (see EJSArray's get_own_property) return _ejs_Object_specops.get_own_property (obj, propertyName); }
static EJSBool _ejs_arraybuffer_specop_has_property (ejsval obj, ejsval propertyName) { // check if propertyName is a uint32, or a string that we can convert to an uint32 int idx = -1; if (EJSVAL_IS_NUMBER(propertyName)) { double n = EJSVAL_TO_NUMBER(propertyName); if (floor(n) == n) { idx = (int)n; return idx > 0 && idx < EJS_ARRAY_LEN(obj); } } // if we fail there, we fall back to the object impl below return _ejs_Object_specops.has_property (obj, propertyName); }
static EJSBool _ejs_arraybuffer_specop_delete (ejsval obj, ejsval propertyName, EJSBool flag) { // check if propertyName is a uint32, or a string that we can convert to an uint32 int idx = -1; if (EJSVAL_IS_NUMBER(propertyName)) { double n = EJSVAL_TO_NUMBER(propertyName); if (floor(n) == n) { idx = (int)n; } } if (idx == -1) return _ejs_Object_specops._delete (obj, propertyName, flag); // if it's outside the array bounds, do nothing if (idx < EJS_ARRAY_LEN(obj)) EJS_DENSE_ARRAY_ELEMENTS(obj)[idx] = _ejs_undefined; return EJS_TRUE; }
ejsval ToNumber(ejsval exp) { if (EJSVAL_IS_NUMBER(exp)) return exp; else if (EJSVAL_IS_BOOLEAN(exp)) return EJSVAL_TO_BOOLEAN(exp) ? _ejs_one : _ejs_zero; else if (EJSVAL_IS_STRING(exp)) { char* num_utf8 = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(exp)); char *endptr; double d = strtod(num_utf8, &endptr); if (*endptr != '\0') return _ejs_nan; ejsval rv = NUMBER_TO_EJSVAL(d); // XXX NaN free (num_utf8); return rv; } else if (EJSVAL_IS_UNDEFINED(exp)) return _ejs_nan; else if (EJSVAL_IS_OBJECT(exp)) { if (EJSVAL_IS_DATE(exp)) { return NUMBER_TO_EJSVAL(_ejs_date_get_time ((EJSDate*)EJSVAL_TO_OBJECT(exp))); } else if (EJSVAL_IS_ARRAY(exp)) { int len = EJS_ARRAY_LEN(exp); if (len == 0) return _ejs_zero; else if (len > 1) return _ejs_nan; else { // XXX we need to support sparse arrays here too EJS_ASSERT (EJSVAL_IS_DENSE_ARRAY(exp)); return ToNumber(EJS_DENSE_ARRAY_ELEMENTS(exp)[0]); } } else return _ejs_nan; } else EJS_NOT_IMPLEMENTED(); }
static ejsval JA(StringifyState *state, ejsval value) { ejsval final; /* 1. If stack contains value then throw a TypeError exception because the structure is cyclical. */ /* 2. Append value to stack. */ /* 3. Let stepback be indent. */ ejsval stepback = state->indent; /* 4. Let indent be the concatenation of indent and gap. */ state->indent = _ejs_string_concat (state->indent, state->gap); /* 5. Let partial be an empty List. */ ejsval partial = _ejs_array_new (0, EJS_FALSE); /* 6. Let len be the result of calling the [[Get]] internal method of value with argument "length". */ int len = EJS_ARRAY_LEN(value); /* 7. Let index be 0. */ int index = 0; /* 8. Repeat while index < len */ while (index < len) { /* a. Let strP be the result of calling the abstract operation Str with arguments ToString(index) and value. */ ejsval strP = Str (state, NUMBER_TO_EJSVAL(index), value); /* b. If strP is undefined */ if (EJSVAL_IS_UNDEFINED(strP)) { /* i. Append "null" to partial. */ _ejs_array_push_dense (partial, 1, &_ejs_atom_null); } /* c. Else */