Exemple #1
0
// 25.4.2.2 PromiseResolveThenableTask ( promiseToResolve, thenable, then) 
static void
PromiseResolveThenableTask (ejsval promiseToResolve, ejsval thenable, ejsval then)
{
    // 1. Let resolvingFunctions be CreateResolvingFunctions(promiseToResolve).
    ejsval resolvingFunctions_resolve;
    ejsval resolvingFunctions_reject;
    CreateResolvingFunctions(promiseToResolve, &resolvingFunctions_resolve, &resolvingFunctions_reject);

    // 2. Let thenCallResult be the result of calling the [[Call]] internal method of then passing thenable as the thisArgument and (resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]) as argumentsList. 
    ejsval thenCallResult;
    ejsval args[] = { resolvingFunctions_resolve, resolvingFunctions_reject };
    EJSBool success = _ejs_invoke_closure_catch(&thenCallResult, then, thenable, 2, args);

    // 3. If thenCallResult is an abrupt completion, 
    if (!success) {
        //    a. Let status be the result of calling the [[Call]] internal method of resolvingFunctions.[[Reject]] passing undefined as the thisArgument and (thenCallResult.[[value]]) as argumentsList. 
        ejsval status;
        success = _ejs_invoke_closure_catch(&status, resolvingFunctions_reject, _ejs_undefined, 1, &thenCallResult);
        
        //    b. NextTask status. 
        EJS_NOT_IMPLEMENTED();
    }
    // 4. NextTask thenCallResult. 
    EJS_NOT_IMPLEMENTED();
}
Exemple #2
0
// 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;
}
Exemple #3
0
// 25.4.2.1 PromiseReactionTask ( reaction, argument ) 
static void
PromiseReactionTask (EJSPromiseReaction* reaction, ejsval argument)
{
    // 1. Assert: reaction is a PromiseReaction Record. 
    // 2. Let promiseCapability be reaction.[[Capabilities]]. 
    ejsval promiseCapability = reaction->capabilities;

    // 3. Let handler be reaction.[[Handler]]. 
    ejsval handler = reaction->handler;

    EJSBool success;
    ejsval handlerResult = _ejs_undefined;

    // 4. If handler is "Identity", then let handlerResult be NormalCompletion(argument). 
    if (SameValue(handler, _ejs_identity_function)) {
        success = EJS_TRUE;
        handlerResult = argument;
    }
    // 5. Else If handler is "Thrower", then let handlerResult be Completion{[[type]]: throw, [[value]]: argument, [[target]]: empty}. 
    if (SameValue(handler, _ejs_thrower_function)) {
        success = EJS_FALSE;
        handlerResult = argument;
    }
    // 6. Else, Let let handlerResult be the result of calling the [[Call]] internal method of handler passing undefined as thisArgument and (argument) as argumentsList. 
    else
        success = _ejs_invoke_closure_catch(&handlerResult, handler, _ejs_undefined, 1, &argument);

    ejsval status;

    // 7. If handlerResult is an abrupt completion, then 
    if (!success) {
        //    a. Let status be the result of calling the [[Call]] internal method of promiseCapability.[[Reject]] passing undefined as thisArgument and (handlerResult.[[value]]) as argumentsList. 
        success = _ejs_invoke_closure_catch(&status, EJS_CAPABILITY_GET_REJECT(promiseCapability), _ejs_undefined, 1, &handlerResult);

        //    b. NextTask status. 
        return;//EJS_NOT_IMPLEMENTED();
    }
    // 8. Let handlerResult be handlerResult.[[value]]. 
    // 9. Let status be the result of calling the [[Call]] internal method of promiseCapability.[[Resolve]] passing undefined as thisArgument and (handlerResult) as argumentsList. 
    success = _ejs_invoke_closure_catch(&status, EJS_CAPABILITY_GET_RESOLVE(promiseCapability), _ejs_undefined, 1, &handlerResult);
    
    // 10. NextTask status. 
}
Exemple #4
0
// 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);
        }
    }
}
Exemple #5
0
// 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 ++;
    }
}
Exemple #6
0
// ES2015, June 2015
// 23.4.1.1  WeakSet ( [ iterable ] )
static EJS_NATIVE_FUNC(_ejs_WeakSet_impl) {
    ejsval iterable = _ejs_undefined;
    if (argc > 0)
        iterable = args[0];

    // 1. If NewTarget is undefined, throw a TypeError exception.
    if (EJSVAL_IS_UNDEFINED(newTarget))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "WeakSet constructor must be called with new");

    // 2. Let set be OrdinaryCreateFromConstructor(NewTarget, "%WeakSetPrototype%", «[[WeakSetData]]»).
    // 3. ReturnIfAbrupt(set).
    // 4. Set set’s [[WeakSetData]] internal slot to a new empty List.
    ejsval set = OrdinaryCreateFromConstructor(newTarget, _ejs_WeakSet_prototype, &_ejs_WeakSet_specops);
    *_this = set;

    // 5. If iterable is not present, let iterable be undefined.
    // 6. If iterable is either undefined or null, let iter be undefined.
    ejsval iter;
    ejsval adder;
    if (EJSVAL_IS_NULL_OR_UNDEFINED(iterable)) {
        iter = _ejs_undefined;
    }
    // 7. Else,
    else {
        // a. Let adder be Get(set, "add").
        // b. ReturnIfAbrupt(adder).
        adder = Get (set, _ejs_atom_add);
        
        // c. If IsCallable(adder) is false, throw a TypeError exception.
        if (!IsCallable(adder))
            _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "WeakSet.prototype.add is not a function");

        // d. Let iter be GetIterator(iterable).
        // e. ReturnIfAbrupt(iter).
        iter = GetIterator(iterable, _ejs_undefined);
    }
    // 8. If iter is undefined, return set.
    if (EJSVAL_IS_UNDEFINED(iter))
        return set;

    // 9. Repeat
    for (;;) {
        // a. Let next be IteratorStep(iter).
        // b. ReturnIfAbrupt(next).
        ejsval next = IteratorStep (iter);

        // c. If next is false, 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 Call(adder, set, «nextValue »).
        // XXX _ejs_invoke_closure won't call proxy methods
        ejsval rv;

        EJSBool status = _ejs_invoke_closure_catch (&rv, adder, &set, 1, &nextValue, _ejs_undefined);

        // g. If status is an abrupt completion, return IteratorClose(iter, status).
        if (!status)
            return IteratorClose(iter, rv, EJS_TRUE);
    }
}