// ECMA262 25.4.1.3 CreateResolvingFunctions ( promise ) static void CreateResolvingFunctions(ejsval promise, ejsval* out_resolve, ejsval* out_reject) { // 1. Let alreadyResolved be a new Record { [[value]]: false }. ejsval resolvingFunctions_env = _ejs_closureenv_new(2); *_ejs_closureenv_get_slot_ref(resolvingFunctions_env, 0) = _ejs_false; *_ejs_closureenv_get_slot_ref(resolvingFunctions_env, 1) = promise; // 2. Let resolve be a new built-in function object as defined in Promise Resolve Functions (25.4.1.4). // 3. Set the [[Promise]] internal slot of resolve to promise. // 4. Set the [[AlreadyResolved]] internal slot of resolve to alreadyResolved. *out_resolve = _ejs_function_new_anon(resolvingFunctions_env, resolve); // 5. Let reject be a new built-in function object as defined in Promise Reject Functions (25.4.1.3.1). // 6. Set the [[Promise]] internal slot of reject to promise. // 7. Set the [[AlreadyResolved]] internal slot of reject to alreadyResolved. *out_reject = _ejs_function_new_anon(resolvingFunctions_env, reject); // 8. Return a new Record { [[Resolve]]: resolve, [[Reject]]: reject }. }
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); } }
// ECMA262 25.4.1.4 Promise Resolve Functions static ejsval resolve(ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval resolution = _ejs_undefined; if (argc > 0) resolution = args[0]; // 1. Assert: F has a [[Promise]] internal slot whose value is an Object. // 2. Let promise be the value of F's [[Promise]] internal slot. ejsval promise = _ejs_closureenv_get_slot(env, 1); // 3. Let alreadyResolved by be the value of F's [[AlreadyResolved]] internal slot. ejsval alreadyResolved = _ejs_closureenv_get_slot(env, 0); // 4. If alreadyResolved. [[value]] is true, then return undefined. if (EJSVAL_TO_BOOLEAN(alreadyResolved)) { return _ejs_undefined; } // 5. Set alreadyResolved.[[value]] to true. *_ejs_closureenv_get_slot_ref(env, 0) = _ejs_true; // 6. If SameValue(resolution, promise) is true, then if (SameValue(resolution, promise)) { // a. Let selfResolutionError be a newly-created TypeError object. ejsval selfResolutionError = _ejs_nativeerror_new_utf8(EJS_TYPE_ERROR, ""); // XXX // b. Return RejectPromise(promise, selfResolutionError). return RejectPromise(promise, selfResolutionError); } // 7. If Type(resolution) is not Object, then if (!EJSVAL_IS_OBJECT(resolution)) { // a. Return FulfillPromise(promise, resolution). return FulfillPromise(promise, resolution); } // 8. Let then be Get(resolution, "then"). ejsval then = Get(resolution, _ejs_atom_then); // 9. If then is an abrupt completion, then // a. Return RejectPromise(promise, then.[[value]]). // XXX // 10. Let then be then.[[value]]. // 11. If IsCallable(then) is false, then if (!EJSVAL_IS_CALLABLE(then)) { // a. Return FulfillPromise(promise, resolution). return FulfillPromise(promise, resolution); } // 12. Perform EnqueueTask ("PromiseTasks", PromiseResolveThenableTask, (promise, resolution, then)) EnqueuePromiseResolveThenableTask (promise, resolution, then); // 13. Return undefined. return _ejs_undefined; }
// ECMA262 25.4.1.3.1 Promise Reject Functions static ejsval reject(ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval reason = _ejs_undefined; if (argc > 0) reason = args[0]; // 1. Assert: F has a [[Promise]] internal slot whose value is an Object. // 2. Let promise be the value of F's [[Promise]] internal slot. ejsval promise = _ejs_closureenv_get_slot(env, 1); // 3. Let alreadyResolved by be the value of F's [[AlreadyResolved]] internal slot. ejsval alreadyResolved = _ejs_closureenv_get_slot(env, 0); // 4. If alreadyResolved.[[value]] is true, then return undefined. if (EJSVAL_TO_BOOLEAN(alreadyResolved)) return _ejs_undefined; // 5. Set alreadyResolved.[[value]] to true. *_ejs_closureenv_get_slot_ref(env, 0) = _ejs_true; // 6. Return RejectPromise(promise, reason). return RejectPromise(promise, reason); }