// 25.4.3.1 Promise ( executor ) static ejsval _ejs_Promise_impl (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval executor = _ejs_undefined; if (argc > 0) executor = args[0]; // 1. Let promise be the this value. ejsval promise = _this; // 2. If Type(promise) is not Object, then throw a TypeError exception. if (!EJSVAL_IS_OBJECT(promise)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "`this' is not an object"); // 3. If promise does not have a [[PromiseState]] internal slot, then throw a TypeError exception. if (!EJSVAL_IS_PROMISE(promise)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "`this' is not an promise"); EJSPromise* _promise = EJSVAL_TO_PROMISE(promise); // 4. If promise's [[PromiseState]] internal slot is not undefined, then throw a TypeError exception. if (_promise->state != PROMISE_STATE_UNINITIALIZED) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Promise constructor called on previously created object"); // 5. If IsCallable(executor) is false, then throw a TypeError exception. if (!EJSVAL_IS_CALLABLE(executor)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "executor is not callable"); // 6. Return InitializePromise(promise, executor). // 1. Assert: promise has a [[PromiseState]] internal slot and it’s value is undefined. // 2. Assert: IsCallable(executor) is true. // 3. Set promise's [[PromiseState]] internal slot to "pending". _promise->state = PROMISE_STATE_PENDING; // 4. Set promise's [[PromiseFulfillReactions]] internal slot to a new empty List. _promise->fulfillReactions = NULL; // 5. Set promise's [[PromiseRejectReactions]] internal slot to a new empty List. _promise->rejectReactions = NULL; // 6. Let resolvingFunctions be CreateResolvingFunctions(promise). ejsval resolvingFunctions_resolve; ejsval resolvingFunctions_reject; CreateResolvingFunctions(promise, &resolvingFunctions_resolve, &resolvingFunctions_reject); // 7. Let completion be the result of calling the [[Call]] internal method of executor with undefined as thisArgument and (resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]) a argumentsList. ejsval completion; ejsval executor_args[] = { resolvingFunctions_resolve, resolvingFunctions_reject }; EJSBool success = _ejs_invoke_closure_catch(&completion, executor, _ejs_undefined, 2, executor_args); // 8. If completion is an abrupt completion, then if (!success) { // a. Let status be the result of calling the [[Call]] internal method of resolvingFunctions.[[Reject]] with undefined as thisArgument and (completion.[[value]]) as argumentsList. // b. ReturnIfAbrupt(status). _ejs_invoke_closure(resolvingFunctions_reject, _ejs_undefined, 1, &completion); } // 9. Return promise. return promise; }
// 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)); }
// ECMA262 25.4.1.6.1 CreatePromiseCapabilityRecord( promise, constructor ) static ejsval CreatePromiseCapabilityRecord (ejsval promise, ejsval constructor) { // 1. Assert: promise is an uninitialized object created as if by invoking @@create on constructor. // 2. Assert: IsConstructor(constructor) is true. // 3. Let promiseCapability be a new PromiseCapability { [[Promise]]: promise, [[Resolve]]: undefined, [[Reject]]: undefined }. ejsval promiseCapability = EJS_CAPABILITY_NEW(); EJS_CAPABILITY_SET_PROMISE(promiseCapability, promise); EJS_CAPABILITY_SET_RESOLVE(promiseCapability, _ejs_undefined); EJS_CAPABILITY_SET_REJECT(promiseCapability, _ejs_undefined); // 4. Let executor be a new built-in function object as defined in GetCapabilitiesExecutor Functions (25.4.1.5.1). ejsval executor = _ejs_function_new_anon (promiseCapability, capabilitiesExecutor); // 5. Set the [[Capability]] internal slot of executor to promiseCapability. // 6. Let constructorResult be the result of calling the [[Call]] internal method of constructor, passing promise and (executor) as the arguments. // 7. ReturnIfAbrupt(constructorResult). ejsval constructorResult = _ejs_invoke_closure (constructor, promise, 1, &executor); // 8. If IsCallable(promiseCapability.[[Resolve]]) is false, then throw a TypeError exception. if (!EJSVAL_IS_CALLABLE(EJS_CAPABILITY_GET_RESOLVE(promiseCapability))) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, ""); // XXX // 9. If IsCallable(promiseCapability.[[Reject]]) is false, then throw a TypeError exception. if (!EJSVAL_IS_CALLABLE(EJS_CAPABILITY_GET_REJECT(promiseCapability))) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, ""); // XXX // 10. If Type(constructorResult) is Object and SameValue(promise, constructorResult) is false, then throw a TypeError exception. if (EJSVAL_IS_OBJECT(constructorResult) && !SameValue(promise, constructorResult)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "1"); // XXX // 11. Return promiseCapability. return promiseCapability; }
// ECMA262 25.4.4.5 Promise.resolve ( x ) static ejsval _ejs_Promise_resolve (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval x = _ejs_undefined; if (argc > 0) x = args[0]; // 1. Let C be the this value. ejsval C = _this; // 2. If IsPromise(x) is true, if (EJSVAL_IS_PROMISE(x)) { EJSPromise* _x = EJSVAL_TO_PROMISE(x); // a. Let constructor be the value of x's [[PromiseConstructor]] internal slot. // b. If SameValue(constructor, C) is true, return x. if (SameValue(_x->constructor, C)) return x; } // 3. Let promiseCapability be NewPromiseCapability(C). // 4. ReturnIfAbrupt(promiseCapability). ejsval promiseCapability = NewPromiseCapability(C); // 5. Let resolveResult be the result of calling the [[Call]] internal method of promiseCapability.[[Resolve]] with undefined as thisArgument and (x) as argumentsList. // 6. ReturnIfAbrupt(resolveResult). _ejs_invoke_closure(EJS_CAPABILITY_GET_RESOLVE(promiseCapability), _ejs_undefined, 1, &x); // 7. Return promiseCapability.[[Promise]]. return EJS_CAPABILITY_GET_PROMISE(promiseCapability); }
// 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(); }
static void _ejs_generator_start(EJSGenerator* gen) { _ejs_gc_push_generator(gen); _ejs_invoke_closure(gen->body, _ejs_undefined, 0, NULL); _ejs_gc_pop_generator(); gen->yielded_value = _ejs_create_iter_result(_ejs_undefined, _ejs_true); }
static ejsval bound_wrapper (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval target = EJS_BOUNDFUNC_ENV_GET_TARGET(env); ejsval thisArg = EJS_BOUNDFUNC_ENV_GET_THIS(env); uint32_t bound_argc = ToUint32(EJS_BOUNDFUNC_ENV_GET_ARGC(env)); if (bound_argc == 0) { return _ejs_invoke_closure(target, thisArg, argc, args); } else if (argc == 0) { return _ejs_invoke_closure(target, thisArg, bound_argc, _ejs_closureenv_get_slot_ref(env, EJS_BOUNDFUNC_FIRST_ARG_SLOT)); } else { uint32_t call_argc = argc + bound_argc; ejsval* call_args = alloca(sizeof(ejsval) * call_argc); memcpy (call_args, _ejs_closureenv_get_slot_ref(env, EJS_BOUNDFUNC_FIRST_ARG_SLOT), sizeof(ejsval) * bound_argc); memcpy (call_args + bound_argc, args, sizeof(ejsval) * argc); return _ejs_invoke_closure(target, thisArg, call_argc, call_args); } }
// ES6: 23.2.3.6 Set.prototype.forEach ( callbackfn , thisArg = undefined ) ejsval _ejs_Set_prototype_forEach (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval callbackfn = _ejs_undefined; ejsval thisArg = _ejs_undefined; if (argc > 0) callbackfn = args[0]; if (argc > 1) thisArg = args[1]; // 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, "Set.prototype.forEach called with non-object this."); // 3. If S does not have a [[SetData]] internal slot throw a TypeError exception. if (!EJSVAL_IS_SET(S)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Set.prototype.forEach called with non-Set this."); // 4. If S’s [[SetData]] internal slot is undefined, then throw a TypeError exception. // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. if (!EJSVAL_IS_CALLABLE(callbackfn)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Set.prototype.forEach callbackfn isn't a function."); // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. ejsval T = thisArg; EJSSet* set = EJSVAL_TO_SET(S); // 7. Let entries be the List that is the value of S’s [[SetData]] internal slot. EJSSetValueEntry* entries = set->head_insert; // 8. Repeat for each e that is an element of entries, in original insertion order for (EJSSetValueEntry *e = entries; e; e = e->next_insert) { // a. If e is not empty, then if (EJSVAL_IS_NO_ITER_VALUE_MAGIC(e->value)) continue; // i. Let funcResult be the result of calling the [[Call]] internal method of callbackfn with T as thisArgument and a List containing e, e, and S as argumentsList. // ii. ReturnIfAbrupt(funcResult). ejsval callback_args[3]; callback_args[0] = e->value; callback_args[1] = e->value; callback_args[2] = S; _ejs_invoke_closure (callbackfn, T, 3, callback_args); } // 9. Return undefined. return _ejs_undefined; }
// ECMA262 25.4.5.1 Promise.prototype.catch ( onRejected ) static ejsval _ejs_Promise_prototype_catch (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval onRejected = _ejs_undefined; if (argc > 0) onRejected = args[0]; // 1. Let promise be the this value. ejsval promise = _this; // 2. Return Invoke(promise, "then", (undefined, onRejected)). ejsval thenargs[] = { _ejs_undefined, onRejected }; return _ejs_invoke_closure(Get(promise, _ejs_atom_then), promise, 2, thenargs); }
ejsval ToObject(ejsval exp) { if (EJSVAL_IS_BOOLEAN(exp)) { ejsval new_boolean = _ejs_object_new (_ejs_Boolean_proto, &_ejs_Boolean_specops); _ejs_invoke_closure (_ejs_Boolean, new_boolean, 1, &exp); return new_boolean; } else if (EJSVAL_IS_NUMBER(exp)) { ejsval new_number = _ejs_object_new (_ejs_Number_proto, &_ejs_Number_specops); _ejs_invoke_closure (_ejs_Number, new_number, 1, &exp); return new_number; } else if (EJSVAL_IS_STRING(exp)) { ejsval new_str = _ejs_object_new (_ejs_String_prototype, &_ejs_String_specops); _ejs_invoke_closure (_ejs_String, new_str, 1, &exp); return new_str; } else if (EJSVAL_IS_UNDEFINED(exp)) return exp; // XXX else if (EJSVAL_IS_OBJECT(exp)) return exp; else EJS_NOT_IMPLEMENTED(); }
// ECMA262 25.4.1.6 NewPromiseCapability ( C ) static ejsval NewPromiseCapability(ejsval C) { // 1. If IsConstructor(C) is false, throw a TypeError exception. // 2. Assert: C is a constructor function that supports the parameter conventions of the Promise constructor (see 25.4.3.1). // 3. Let promise be CreateFromConstructor(C). ejsval creator = Get(C, _ejs_Symbol_create); // 4. ReturnIfAbrupt(promise). ejsval promise = _ejs_invoke_closure (creator, _ejs_undefined, 0, NULL); // 5. If Type(promise) is not Object, then throw a TypeError exception. if (!EJSVAL_IS_OBJECT(promise)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "promise constructor returned non-object"); // 6. Return CreatePromiseCapabilityRecord(promise, C). return CreatePromiseCapabilityRecord(promise, C); }
// ES6 Draft rev32 Feb 2, 2015 // 9.2.3 // [[Construct]] ( argumentsList, newTarget) ejsval _ejs_construct_closure (ejsval _closure, ejsval newTarget, uint32_t argc, ejsval* args) { // 1. Assert: F is an ECMAScript function object. EJSFunction* F = (EJSFunction*)EJSVAL_TO_OBJECT(_closure); // 2. Assert: Type(newTarget) is Object. // 3. Let callerContext be the running execution context. // 4. Let kind be F’s [[ConstructorKind]] internal slot. EJSConstructorKind kind = F->constructor_kind; ejsval thisArgument = _ejs_undefined; // 5. If kind is "base", then if (kind == CONSTRUCTOR_KIND_BASE) { // a. Let thisArgument be OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%"). // b. ReturnIfAbrupt(thisArgument). } // 6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget). // 7. ReturnIfAbrupt(calleeContext). // 8. Assert: calleeContext is now the active execution context. // 9. If kind is "base", then if (kind == CONSTRUCTOR_KIND_BASE) { // a. Let status be OrdinaryCallBindThis(F, calleeContext, thisArgument). // b. If status is an abrupt completion, then // i. Remove calleeContext from the execution context stack and restore callerContext as the running execution context. // ii. Return status. } // 10. Let constructorEnv be the LexicalEnvironment of calleeContext. // 11. Let envRec be constructorEnv’s environment record. // 12. Let result be OrdinaryCallEvaluateBody(F, calleeContext, argumentsList). ejsval result = _ejs_invoke_closure(_closure, thisArgument, argc, args); // 13. Remove calleeContext from the execution context stack and restore callerContext as the running execution context. // 14. If result.[[type]] is return, then // a. If Type(result.[[value]]) is Object, return NormalCompletion(result.[[value]]). if (EJSVAL_IS_OBJECT(result)) return result; // b. If kind is "base", return NormalCompletion(thisArgument). if (kind == CONSTRUCTOR_KIND_BASE) return thisArgument; // c. Throw a TypeError exception. _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "9.2.3/14.c"); // 15. ReturnIfAbrupt(result). // 16. Return the result of calling the GetThisBinding concrete method of envRec’s with no arguments EJS_NOT_IMPLEMENTED(); }
// ECMA262 25.4.4.4 Promise.reject ( r ) static ejsval _ejs_Promise_reject (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval r = _ejs_undefined; if (argc > 0) r = args[0]; // 1. Let C be the this value. ejsval C = _this; // 2. Let promiseCapability be NewPromiseCapability(C). // 3. ReturnIfAbrupt(promiseCapability). ejsval promiseCapability = NewPromiseCapability(C); // 4. Let rejectResult be the result of calling the [[Call]] internal method of promiseCapability.[[Reject]] with undefined as thisArgument and (r) as argumentsList. // 5. ReturnIfAbrupt(rejectResult). _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &r); // 6. Return promiseCapability.[[Promise]]. return EJS_CAPABILITY_GET_PROMISE(promiseCapability); }
ejsval _ejs_regexp_replace(ejsval str, ejsval search_re, ejsval replace) { EJSRegExp* re = (EJSRegExp*)EJSVAL_TO_OBJECT(search_re); pcre16_extra extra; memset (&extra, 0, sizeof(extra)); pcre16* code = (pcre16*)re->compiled_pattern; int capture_count; pcre16_fullinfo (code, NULL, PCRE_INFO_CAPTURECOUNT, &capture_count); int ovec_count = 3 * (1 + capture_count); int* ovec = malloc(sizeof(int) * ovec_count); int cur_off = 0; do { EJSPrimString *flat_str = _ejs_string_flatten (str); jschar *chars_str = flat_str->data.flat; int rv = pcre16_exec(code, &extra, chars_str, flat_str->length, cur_off, PCRE_NO_UTF16_CHECK, ovec, ovec_count); if (rv < 0) break; ejsval replaceval; if (EJSVAL_IS_FUNCTION(replace)) { ejsval substr_match = _ejs_string_new_substring (str, ovec[0], ovec[1] - ovec[0]); ejsval capture = _ejs_string_new_substring (str, ovec[2], ovec[3] - ovec[2]); _ejs_log ("substring match is %s\n", ucs2_to_utf8(_ejs_string_flatten(substr_match)->data.flat)); _ejs_log ("capture is %s\n", ucs2_to_utf8(_ejs_string_flatten(capture)->data.flat)); int argc = 3; ejsval args[3]; args[0] = substr_match; args[1] = capture; args[2] = _ejs_undefined; replaceval = ToString(_ejs_invoke_closure (replace, _ejs_undefined, argc, args)); } else { replaceval = ToString(replace); } if (ovec[0] == 0) { // we matched from the beginning of the string, so nothing from there to prepend str = _ejs_string_concat (replaceval, _ejs_string_new_substring (str, ovec[1], flat_str->length - ovec[1])); } else { str = _ejs_string_concatv (_ejs_string_new_substring (str, 0, ovec[0]), replaceval, _ejs_string_new_substring (str, ovec[1], flat_str->length - ovec[1]), _ejs_null); } cur_off = ovec[1]; // if the RegExp object was created without a 'g' flag, only replace the first match if (!re->global) break; } while (EJS_TRUE); free (ovec); return str; }
// ES6: 23.2.1.1 Set ( [ iterable ] ) static ejsval _ejs_Set_impl (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { // 1. Let set be the this value. ejsval set = _this; if (EJSVAL_IS_UNDEFINED(set)) { EJSObject* obj = (EJSObject*)_ejs_gc_new(EJSSet); _ejs_init_object (obj, _ejs_Set_prototype, &_ejs_Set_specops); set = OBJECT_TO_EJSVAL(obj); } // 2. If Type(set) is not Object then, throw a TypeError exception. if (!EJSVAL_IS_OBJECT(set)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Set constructor called with non-object this."); // 3. If set does not have a [[SetData]] internal slot, then throw a TypeError exception. if (!EJSVAL_IS_SET(set)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Set constructor called with non-Set this."); EJSSet* _set = EJSVAL_TO_SET(set); // 4. If set’s [[SetData]] internal slot is not undefined, then throw a TypeError exception. if (_set->head_insert) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Set constructor called with an already initialized Set"); // 5. If iterable is not present, let iterable be undefined. ejsval iterable = _ejs_undefined; if (argc > 0) iterable = args[0]; ejsval iter = _ejs_undefined; ejsval adder = _ejs_undefined; // 6. If iterable is either undefined or null, then let iter be undefined. // 7. Else, if (!EJSVAL_IS_UNDEFINED(iterable) && !EJSVAL_IS_NULL(iterable)) { // a. Let iter be the result of GetIterator(iterable). // b. ReturnIfAbrupt(iter). iter = GetIterator (iterable, _ejs_undefined); // c. Let adder be the result of Get(set, "add"). // d. ReturnIfAbrupt(adder). adder = Get (set, _ejs_atom_add); // e. If IsCallable(adder) is false, throw a TypeError Exception. if (!EJSVAL_IS_CALLABLE(adder)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Set.prototype.add is not a function"); } // 8. If the value of sets’s [[SetData]] internal slot is not undefined, then throw a TypeError exception. // 9. Assert: set has not been reentrantly initialized. // 10. Set set’s [[SetData]] internal slot to a new empty List. // 11. If iter is undefined, then return set. if (EJSVAL_IS_UNDEFINED(iter)) return set; // 12. Repeat for (;;) { // a. Let next be the result of IteratorStep(iter). // b. ReturnIfAbrupt(next). ejsval next = IteratorStep (iter); // c. If next is false, then return set. if (!EJSVAL_TO_BOOLEAN(next)) return set; // d. Let nextValue be IteratorValue(next). // e. ReturnIfAbrupt(nextValue). ejsval nextValue = IteratorValue (next); // f. Let status be the result of calling the [[Call]] internal method of adder with set as thisArgument // and a List whose sole element is nextValue as argumentsList. // g. ReturnIfAbrupt(status). _ejs_invoke_closure (adder, set, 1, &nextValue); } return set; }
// ECMA262 15.3.4.3 static ejsval _ejs_Function_prototype_apply (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval func = _this; /* 1. If IsCallable(func) is false, then throw a TypeError exception. */ if (!EJSVAL_IS_CALLABLE(_this)) { printf ("throw TypeError, func is not callable\n"); EJS_NOT_IMPLEMENTED(); } ejsval thisArg = _ejs_undefined; ejsval argArray = _ejs_undefined; if (argc > 0) thisArg = args[0]; if (argc > 1) argArray = args[1]; /* 2. If argArray is null or undefined, then */ if (EJSVAL_IS_UNDEFINED(argArray) || EJSVAL_IS_NULL(argArray)) { /* a. Return the result of calling the [[Call]] internal method of func, providing thisArg as the this value */ /* and an empty list of arguments. */ return _ejs_invoke_closure (func, thisArg, 0, NULL); } /* 3. If Type(argArray) is not Object, then throw a TypeError exception. */ if (!EJSVAL_IS_OBJECT(argArray)) { printf ("throw TypeError, argArray is not an object\n"); EJS_NOT_IMPLEMENTED(); } EJSObject* argArray_ = EJSVAL_TO_OBJECT(argArray); /* 4. Let len be the result of calling the [[Get]] internal method of argArray with argument "length". */ ejsval len = OP(argArray_,Get) (argArray, _ejs_atom_length, argArray); /* 5. Let n be ToUint32(len). */ uint32_t n = (uint32_t)EJSVAL_TO_NUMBER(len); ejsval* argList; EJSBool argList_allocated = EJS_FALSE; if (EJSVAL_IS_DENSE_ARRAY(argArray)) { argList = EJSDENSEARRAY_ELEMENTS(argArray_); } else { /* 6. Let argList be an empty List. */ argList = (ejsval*)malloc(sizeof(ejsval) * n); argList_allocated = EJS_TRUE; /* 7. Let index be 0. */ int index = 0; /* 8. Repeat while index < n */ while (index < n) { /* a. Let indexName be ToString(index). */ ejsval indexName = NUMBER_TO_EJSVAL(index); /* b. Let nextArg be the result of calling the [[Get]] internal method of argArray with indexName as the */ /* argument. */ ejsval nextArg = OP(argArray_,Get)(argArray, indexName, argArray); /* c. Append nextArg as the last element of argList. */ argList[index] = nextArg; /* d. Set index to index + 1. */ ++index; } } /* 9. Return the result of calling the [[Call]] internal method of func, providing thisArg as the this value and */ /* argList as the list of arguments. */ ejsval rv = EJSVAL_TO_FUNC(func) (EJSVAL_TO_ENV(func), thisArg, n, argList); if (argList_allocated) free (argList); return rv; }
// ECMA262 25.4.4.3 Promise.race ( iterable ) static ejsval _ejs_Promise_race (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { EJSBool success; ejsval iterable = _ejs_undefined; if (argc > 0) iterable = args[0]; // 1. Let C be the this value. ejsval C = _this; // 2. Let promiseCapability be NewPromiseCapability(C). // 3. ReturnIfAbrupt(promiseCapability). ejsval promiseCapability = NewPromiseCapability(C); // 4. Let iterator be GetIterator(iterable). ejsval iterator; success = GetIteratorP(&iterator, iterable); // 5. IfAbruptRejectPromise(iterator, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &iterator); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // 6. Repeat while (EJS_TRUE) { ejsval next; // a. Let next be IteratorStep(iterator). EJSBool success = IteratorStepP(&next, iterator); // b. IfAbruptRejectPromise(next, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &next); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // c. If next is false, return promiseCapability.[[Promise]]. if (EJSVAL_IS_BOOLEAN(next) && !EJSVAL_TO_BOOLEAN(next)) return EJS_CAPABILITY_GET_PROMISE(promiseCapability); // d. Let nextValue be IteratorValue(next). ejsval nextValue; success = IteratorValueP(&nextValue, next); // e. IfAbruptRejectPromise(nextValue, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &nextValue); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // f. Let nextPromise be Invoke(C, "resolve", (nextValue)). ejsval nextPromise; success = _ejs_invoke_closure_catch(&nextPromise, C, _ejs_atom_resolve, 1, &nextValue); // g. IfAbruptRejectPromise(nextPromise, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &nextPromise); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // h. Let result be Invoke(nextPromise, "then", (promiseCapability.[[Resolve]], promiseCapability.[[Reject]])). ejsval result; ejsval args[] = { EJS_CAPABILITY_GET_RESOLVE(promiseCapability), EJS_CAPABILITY_GET_REJECT(promiseCapability) }; success = _ejs_invoke_closure_catch(&result, nextPromise, _ejs_atom_then, 2, args); // i. IfAbruptRejectPromise(result, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &result); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } } }
// ECMA262 25.4.4.1 Promise.all ( iterable ) static ejsval _ejs_Promise_all (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { EJSBool success; ejsval iterable = _ejs_undefined; if (argc > 0) iterable = args[0]; // 1. Let C be the this value. ejsval C = _this; // 2. Let promiseCapability be NewPromiseCapability(C). // 3. ReturnIfAbrupt(promiseCapability). ejsval promiseCapability = NewPromiseCapability(C); // 4. Let iterator be GetIterator(iterable). ejsval iterator; success = GetIteratorP(&iterator, iterable); // 5. IfAbruptRejectPromise(iterator, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &iterator); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // 6. Let values be ArrayCreate(0). ejsval values = _ejs_array_new(0, EJS_FALSE); // 7. Let remainingElementsCount be a new Record { [[value]]: 1 }. int remainingElementsCount = 1; // 8. Let index be 0. int index = 0; // 9. Repeat while (EJS_TRUE) { // a. Let next be IteratorStep(iterator). ejsval next; success = IteratorStepP(&next, iterator); // b. IfAbruptRejectPromise(next, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &next); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // c. If next is false, if (EJSVAL_IS_BOOLEAN(next) && !EJSVAL_TO_BOOLEAN(next)) { // i. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] - 1. remainingElementsCount --; // ii. If remainingElementsCount.[[value]] is 0, if (remainingElementsCount == 0) { // 1. Let resolveResult be the result of calling the [[Call]] internal method of promiseCapability.[[Resolve]] with undefined as thisArgument and (values) as argumentsList. ejsval resolveResult; success = _ejs_invoke_closure_catch(&resolveResult, EJS_CAPABILITY_GET_RESOLVE(promiseCapability), _ejs_undefined, 1, &values); // 2. ReturnIfAbrupt(resolveResult). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &resolveResult); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } } // iii. Return promiseCapability.[[Promise]]. return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // d. Let nextValue be IteratorValue(next). ejsval nextValue; success = IteratorValueP(&nextValue, next); // e. IfAbruptRejectPromise(nextValue, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &nextValue); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // f. Let nextPromise be Invoke(C, "resolve", (nextValue)). ejsval nextPromise; success = _ejs_invoke_closure_catch (&nextPromise, Get(C, _ejs_atom_resolve), C, 1, &nextValue); // g. IfAbruptRejectPromise(nextPromise, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &nextPromise); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // h. Let resolveElement be a new built-in function object as defined in Promise.all Resolve Element Functions. ejsval resolvingElement_env = _ejs_closureenv_new(6); ejsval resolveElement = _ejs_function_new_anon(resolvingElement_env, resolve_element); // i. Set the [[AlreadyCalled]] internal slot of resolveElement to false. EJS_RESOLVEELEMENT_SET_ALREADY_CALLED(resolvingElement_env, _ejs_false); // j. Set the [[Index]] internal slot of resolveElement to index. EJS_RESOLVEELEMENT_SET_INDEX(resolvingElement_env, NUMBER_TO_EJSVAL(index)); // k. Set the [[Values]] internal slot of resolveElement to values. EJS_RESOLVEELEMENT_SET_VALUES(resolvingElement_env, values); // l. Set the [[Capabilities]] internal slot of resolveElement to promiseCapability. EJS_RESOLVEELEMENT_SET_CAPABILITIES(resolvingElement_env, promiseCapability); // m. Set the [[RemainingElements]] internal slot of resolveElement to remainingElementsCount. EJS_RESOLVEELEMENT_SET_REMAINING_ELEMENTS(resolvingElement_env, NUMBER_TO_EJSVAL(remainingElementsCount)); // n. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] + 1. remainingElementsCount++; // o. Let result be Invoke(nextPromise, "then", (resolveElement, promiseCapability.[[Reject]])). ejsval thenargs[] = { resolveElement, EJS_CAPABILITY_GET_REJECT(promiseCapability) }; ejsval result; success = _ejs_invoke_closure_catch (&result, Get(nextPromise, _ejs_atom_then), nextPromise, 2, thenargs); // p. IfAbruptRejectPromise(result, promiseCapability). if (!success) { _ejs_invoke_closure(EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &result); return EJS_CAPABILITY_GET_PROMISE(promiseCapability); } // q. Set index to index + 1. index ++; } }
void allinone_for_load_just_ensure_these_functions_and_variables_are_included_please_do_not_call() { JSValueHash(_ejs_nan); JSValueHash(jsPositiveInfinity); JSValueHash(jsNegativeInfinity); JSValueHash(jsMax); JSValueHash(jsMin); JSValueHash(_ejs_null); JSValueHash(_ejs_undefined); JSValueHash(_ejs_true); JSValueHash(_ejs_false); JSValueHash(_ejs_one); JSValueHash(_ejs_zero); JSValueHash(_ejs_global); JSValueHash(_ejs_console); JSValueHash(_ejs_Object); JSValueHash(_ejs_Boolean); JSValueHash(_ejs_Number); JSValueHash(_ejs_String); JSValueHash(_ejs_Array); JSValueHash(_ejs_Function); JSValueHash(_ejs_Process); JSValueHash(_ejs_Symbol_create); JSValueHash(_ejs_Math); JSValueHash(_ejs_JSON); jsextern_print_tick(); jsextern_os_msleep(0); jsextern_os_swap(NULL, 0, 0); jsextern_pcre_compile(NULL); jsextern_pcre_study(NULL); jsextern_pcre_bracketcount(NULL); jsextern_pcre_exec(NULL, NULL, NULL, 0, 0, NULL, 0); jsextern_pcre_free(NULL); jsextern_thread_create((void *(*)(void *))NULL, NULL); jsextern_thread_destroy(0); jsextern_mutex_create(); jsextern_mutex_destroy(0); jsextern_mutex_lock(0); jsextern_mutex_unlock(0); jsextern_signal_create(); jsextern_signal_destroy(0); jsextern_signal_wait(0); jsextern_signal_send(0); JSValueHash(_ejs_undefined); _ejs_eval(_ejs_undefined, _ejs_undefined, 0, NULL); //Object _ejs_object_getprop_utf8(_ejs_undefined, NULL); _ejs_object_setprop_utf8(_ejs_global, NULL, _ejs_undefined); _ejs_object_define_value_property(_ejs_undefined, _ejs_undefined, _ejs_undefined, 0); _ejs_object_define_getter_property(_ejs_undefined, _ejs_undefined, _ejs_undefined, 0); _ejs_object_define_setter_property(_ejs_undefined, _ejs_undefined, _ejs_undefined, 0); _ejs_Object_create(_ejs_undefined, _ejs_undefined, 0, NULL); _ejs_Object_getOwnPropertyNames(_ejs_undefined, _ejs_undefined, 0, NULL); //vtable _ejs_specop_get(_ejs_undefined, _ejs_undefined, _ejs_undefined); _ejs_specop_set(_ejs_undefined, _ejs_undefined, _ejs_undefined, _ejs_undefined); //option ToEJSBool(_ejs_undefined); ToDouble(_ejs_undefined); ToUint32(_ejs_undefined); _ejs_op_typeof(_ejs_undefined); _ejs_op_instanceof(_ejs_undefined, _ejs_undefined); _ejs_op_typeof_is_array(_ejs_undefined); _ejs_op_plusplus(_ejs_undefined, EJS_FALSE); _ejs_op_minusminus(_ejs_undefined, EJS_FALSE); _ejs_op_bitwise_xor(_ejs_undefined, _ejs_undefined); _ejs_op_bitwise_and(_ejs_undefined, _ejs_undefined); _ejs_op_bitwise_or(_ejs_undefined, _ejs_undefined); _ejs_op_rsh(_ejs_undefined, _ejs_undefined); _ejs_op_ursh(_ejs_undefined, _ejs_undefined); _ejs_op_lsh(_ejs_undefined, _ejs_undefined); _ejs_op_ulsh(_ejs_undefined, _ejs_undefined); _ejs_op_mod(_ejs_undefined, _ejs_undefined); _ejs_op_add(_ejs_undefined, _ejs_undefined); _ejs_op_sub(_ejs_undefined, _ejs_undefined); _ejs_op_mult(_ejs_undefined, _ejs_undefined); _ejs_op_div(_ejs_undefined, _ejs_undefined); _ejs_op_lt(_ejs_undefined, _ejs_undefined); _ejs_op_le(_ejs_undefined, _ejs_undefined); _ejs_op_gt(_ejs_undefined, _ejs_undefined); _ejs_op_ge(_ejs_undefined, _ejs_undefined); _ejs_op_strict_eq(_ejs_undefined, _ejs_undefined); _ejs_op_strict_neq(_ejs_undefined, _ejs_undefined); _ejs_op_eq(_ejs_undefined, _ejs_undefined); _ejs_op_neq(_ejs_undefined, _ejs_undefined); //arguments _ejs_arguments_new(0, NULL); //Array _ejs_array_new(jsValue32Size, false); //String _ejs_string_new_utf8_len(NULL, 0); //Function _ejs_function_new_utf8(_ejs_undefined, NULL, (EJSClosureFunc)NULL); _ejs_invoke_closure(_ejs_undefined, _ejs_undefined, 0, NULL); //RegExp _ejs_regexp_new_utf8(NULL, NULL); }