예제 #1
0
// 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;
}
예제 #2
0
// 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));
}
예제 #3
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;
}
예제 #4
0
파일: ejs-json.c 프로젝트: eberan/echo-js
/* 15.12.2 */
static ejsval
_ejs_JSON_parse (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    ejsval text = _ejs_undefined;
    ejsval reviver = _ejs_undefined;

    if (argc > 0) text = args[0];
    if (argc > 1) reviver = args[1];


    /* 1. Let JText be ToString(text). */
    ejsval jtext = ToString(text);

    /* 2. Parse JText using the grammars in 15.12.1. Throw a SyntaxError exception if JText did not conform to the 
       JSON grammar for the goal symbol JSONText.  */
    char *flattened_jtext =  ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(jtext));

    /* 3. Let unfiltered be the result of parsing and evaluating JText as if it was the source text of an ECMAScript 
       Program but using JSONString in place of StringLiteral. Note that since JText conforms to the JSON 
       grammar this result will be either a primitive value or an object that is defined by either an ArrayLiteral or 
       an ObjectLiteral. */
    JSON_Value* root_val = json_parse_string(flattened_jtext);

    free(flattened_jtext);

    if (root_val == NULL) {
        printf ("SyntaxError\n");
        EJS_NOT_IMPLEMENTED();
    }

    ejsval unfiltered;
    if (!json_value_to_ejsval(root_val, &unfiltered)) {
        json_value_free (root_val);
        /* unfiltered here is an exception */
        EJS_NOT_IMPLEMENTED();
    }

    json_value_free (root_val);

    /* 4. If IsCallable(reviver) is true, then */
    if (EJSVAL_IS_CALLABLE(reviver)) {
        printf ("no reviver support in JSON.parse yet\n");
        EJS_NOT_IMPLEMENTED();
        /*    a. Let root be a new object created as if by the expression new Object(), where Object is the
              standard built-in constructor with that name. */
        /*    b. Call the [[DefineOwnProperty]] internal method of root with the empty String, the 
              PropertyDescriptor {[[Value]]: unfiltered, [[Writable]]: true, [[Enumerable]]: true, 
              [[Configurable]]: true}, and false as arguments. */
        /*    c. Return the result of calling the abstract operation Walk, passing root and the empty String. The 
              abstract operation Walk is described below. */
    }
    /* 5. Else */
    else {
        /*    a. Return unfiltered. */
        return unfiltered;
    }
}
예제 #5
0
파일: ejs-set.c 프로젝트: jmars/echo-js
// 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;
}
예제 #6
0
// 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;
}
예제 #7
0
// 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;
}
예제 #8
0
// 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;
}
예제 #9
0
파일: ejs-function.c 프로젝트: eddid/jslang
// 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 F = _ejs_function_new_anon (bound_env, bound_wrapper);
    EJSFunction *F_ = (EJSFunction*)EJSVAL_TO_OBJECT(F);

    F_->bound = EJS_TRUE;

#if not_anymore
    /* 5. Set all the internal methods, except for [[Get]], of F as specified in 8.12. */
    /* 6. Set the [[Get]] internal property of F as specified in 15.3.5.4. */
    /* 7. Set the [[TargetFunction]] internal property of F to Target. */
    /* 8. Set the [[BoundThis]] internal property of F to the value of thisArg. */
    F_->bound_this = thisArg;

    /* 9. Set the [[BoundArgs]] internal property of F to A. */
    F_->bound_argc = bound_argc;
    F_->bound_args = bound_args;

    /* 10. Set the [[Class]] internal property of F to "Function". */
    /* 11. Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1. */
    /* 12. Set the [[Call]] internal property of F as described in 15.3.4.5.1. */
    /* 13. Set the [[Construct]] internal property of F as described in 15.3.4.5.2. */
    /* 14. Set the [[HasInstance]] internal property of F as described in 15.3.4.5.3. */
    /* 15. If the [[Class]] internal property of Target is "Function", then */
    /*     a. Let L be the length property of Target minus the length of A. */
    /*     b. Set the length own property of F to either 0 or L, whichever is larger.  */
    /* 16. Else set the length own property of F to 0. */
    /* 17. Set the attributes of the length own property of F to the values specified in 15.3.5.1. */
    /* 18. Set the [[Extensible]] internal property of F to true. */
    /* 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). */
    /* 20. Call the [[DefineOwnProperty]] internal method of F with arguments "caller", PropertyDescriptor  */
    /*     {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, and false. */
    /* 21. Call the [[DefineOwnProperty]] internal method of F with arguments "arguments", PropertyDescriptor */
    /*     {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, and false. */
    /* 22. Return F. */
#endif
    return F;
}
예제 #10
0
// ECMA262 25.4.5.3 Promise.prototype.then ( onFulfilled , onRejected ) 
static ejsval
_ejs_Promise_prototype_then (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    ejsval onFulfilled = _ejs_undefined;
    ejsval onRejected = _ejs_undefined;
    if (argc > 0) onFulfilled = args[0];
    if (argc > 1) onRejected  = args[1];

    // 1. Let promise be the this value. 
    ejsval promise = _this;

    // 2. If IsPromise(promise) is false, throw a TypeError exception. 
    if (!EJSVAL_IS_PROMISE(promise))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "this is not a promise");
        
    EJSPromise* _promise = EJSVAL_TO_PROMISE(promise);

    // 3. If IsCallable(onFulfilled) is undefined or nullfalse, then 
    if (!EJSVAL_IS_CALLABLE(onFulfilled)) {
        //    a. Let onFulfilled be "Identity" a new Identity Function (see 25.4.5.3.1).
        onFulfilled = _ejs_identity_function; // XXX does it really need to be a newly instantiated one? realm-specific?  we don't instantiate a new one
    }

    // 4. If IsCallable(onRejected) is undefined or nullfalse, then 
    if (!EJSVAL_IS_CALLABLE(onRejected)) {
        //    a. Let onRejected be "Thrower"a new Thrower Function (see 25.4.5.3.3). 
        onRejected = _ejs_thrower_function; // XXX does it really need to be a newly instantiated one?  realm-specific?  we don't instantiate a new one
    }
    // 5. If IsCallable(onFulfilled) is false or if IsCallable(onRejected) is false, then throw a TypeError exception. 
    if (!EJSVAL_IS_CALLABLE(onFulfilled) || !EJSVAL_IS_CALLABLE(onRejected)) {
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "1: shouldn't happen.  runtime error?");
    }

    // 6. Let C be Get(promise, "constructor"). 
    // 7. ReturnIfAbrupt(C). 
    ejsval C = Get(promise, _ejs_atom_constructor);

    // 8. Let promiseCapability be NewPromiseCapability(C). 
    // 9. ReturnIfAbrupt(promiseCapability). 
    ejsval promiseCapability = NewPromiseCapability(C);

    // 12. If the value of promise's [[PromiseState]] internal slot is "pending", 
    if (_promise->state == PROMISE_STATE_PENDING) {
        // 10. Let fulfillReaction be the PromiseReaction { [[Capabilities]]: promiseCapability, [[Handler]]: onFulfilled }.
        EJSPromiseReaction* fulfillReaction = _ejs_promise_reaction_new (promiseCapability, onFulfilled);
        // 11. Let rejectReaction  be the PromiseReaction { [[Capabilities]]: promiseCapability, [[Handler]]: onRejected  }.
        EJSPromiseReaction* rejectReaction  = _ejs_promise_reaction_new (promiseCapability, onRejected);

        //        a. Append fulfillReaction as the last element of the List that is the value of promise's [[PromiseFulfillReactions]] internal slot. 
        EJS_LIST_APPEND(EJSPromiseReaction, fulfillReaction, _promise->fulfillReactions);
        //        b. Append rejectReaction as the last element of the List that is the value of promise's [[PromiseRejectReactions]] internal slot. 
        EJS_LIST_APPEND(EJSPromiseReaction, rejectReaction, _promise->rejectReactions);
    }
    // 13. Else if the value of promise's [[PromiseState]] internal slot is "fulfilled", 
    else if (_promise->state == PROMISE_STATE_FULFILLED) {
        // 10. Let fulfillReaction be the PromiseReaction { [[Capabilities]]: promiseCapability, [[Handler]]: onFulfilled }.
        EJSPromiseReaction* fulfillReaction = _ejs_promise_reaction_new (promiseCapability, onFulfilled);

        //     a. Let value be the value of promise's [[PromiseResult]] internal slot. 
        ejsval value = _promise->result;
        //     b. Perform EnqueueTask("PromiseTasks", PromiseReactionTask, (fulfillReaction, value)). 
        EnqueuePromiseReactionTask (fulfillReaction, value);
    }
    // 14. Else if the value of promise's [[PromiseState]] internal slot is "rejected", 
    else if (_promise->state == PROMISE_STATE_REJECTED) {
        // 11. Let rejectReaction  be the PromiseReaction { [[Capabilities]]: promiseCapability, [[Handler]]: onRejected  }.
        EJSPromiseReaction* rejectReaction  = _ejs_promise_reaction_new (promiseCapability, onRejected);

        //     a. Let reason be the value of promise's [[PromiseResult]] internal slot. 
        ejsval reason = _promise->result;
        //     b. Perform EnqueueTask("PromiseTasks", PromiseReactionTask, (rejectReaction, reason)). 
        EnqueuePromiseReactionTask (rejectReaction, reason);
    }
    else {
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "2: shouldn't happen.  runtime error?");
    }
    // 15. Return promiseCapability.[[Promise]]. 
    return EJS_CAPABILITY_GET_PROMISE(promiseCapability);
}
예제 #11
0
파일: ejs-set.c 프로젝트: jmars/echo-js
// 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;
}
예제 #12
0
// 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");
    }

    if (argc == 0)
        return _this;

    ejsval thisArg = _ejs_undefined;
    if (argc >= 1)
        thisArg = args[0];

    EJSFunction *TargetFunc = (EJSFunction*)EJSVAL_TO_OBJECT(Target);

    /* 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 = 0;
    ejsval *bound_args = NULL;
    if (argc > 1) {
        bound_argc = argc-1;
        bound_args = malloc(sizeof(ejsval) * bound_argc);
        memcpy (bound_args, args, sizeof(ejsval) * bound_argc);
    }

    /* 4. Let F be a new native ECMAScript object . */

    ejsval F = _ejs_function_new (TargetFunc->env, _ejs_atom_empty, TargetFunc->func);
    EJSFunction *F_ = (EJSFunction*)EJSVAL_TO_OBJECT(F);

    F_->bound = EJS_TRUE;

    /* 5. Set all the internal methods, except for [[Get]], of F as specified in 8.12. */
    /* 6. Set the [[Get]] internal property of F as specified in 15.3.5.4. */
    /* 7. Set the [[TargetFunction]] internal property of F to Target. */
    /* 8. Set the [[BoundThis]] internal property of F to the value of thisArg. */
    F_->bound_this = thisArg;

    /* 9. Set the [[BoundArgs]] internal property of F to A. */
    F_->bound_argc = bound_argc;
    F_->bound_args = bound_args;

    /* 10. Set the [[Class]] internal property of F to "Function". */
    /* 11. Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1. */
    /* 12. Set the [[Call]] internal property of F as described in 15.3.4.5.1. */
    /* 13. Set the [[Construct]] internal property of F as described in 15.3.4.5.2. */
    /* 14. Set the [[HasInstance]] internal property of F as described in 15.3.4.5.3. */
    /* 15. If the [[Class]] internal property of Target is "Function", then */
    /*     a. Let L be the length property of Target minus the length of A. */
    /*     b. Set the length own property of F to either 0 or L, whichever is larger.  */
    /* 16. Else set the length own property of F to 0. */
    /* 17. Set the attributes of the length own property of F to the values specified in 15.3.5.1. */
    /* 18. Set the [[Extensible]] internal property of F to true. */
    /* 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). */
    /* 20. Call the [[DefineOwnProperty]] internal method of F with arguments "caller", PropertyDescriptor  */
    /*     {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, and false. */
    /* 21. Call the [[DefineOwnProperty]] internal method of F with arguments "arguments", PropertyDescriptor */
    /*     {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, and false. */
    /* 22. Return F. */
    return F;
}