Ejemplo n.º 1
0
// ECMA262: 15.3.5.3
static EJSBool
_ejs_function_specop_has_instance (ejsval F, ejsval V)
{
    /* 1. If V is not an object, return false. */
    if (!EJSVAL_IS_OBJECT(V))
        return EJS_FALSE;

    /* 2. Let O be the result of calling the [[Get]] internal method of F with property name "prototype". */
    ejsval O = OP(EJSVAL_TO_OBJECT(F),Get)(F, _ejs_atom_prototype, F);

    /* 3. If Type(O) is not Object, throw a TypeError exception. */
    if (!EJSVAL_IS_OBJECT(O)) {
        printf ("throw TypeError, O is not an object\n");
        EJS_NOT_IMPLEMENTED();
    }

    /* 4. Repeat */
    while (1) {
        /*    a. Let V be the value of the [[Prototype]] internal property of V. */
        V = EJSVAL_TO_OBJECT(V)->proto;
        /*    b. If V is null, return false. */
        if (EJSVAL_IS_NULL(V)) return EJS_FALSE;
        /*    c. If O and V refer to the same object, return true. */
        if (EJSVAL_EQ(O, V)) return EJS_TRUE;
    }
}
Ejemplo n.º 2
0
// ES6: 23.1.3.1
// Map.prototype.clear ()
ejsval
_ejs_Set_prototype_clear (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    // 1. Let S be 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.clear 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.clear called with non-Set this.");

    // 4. If S’s [[SetData]] internal slot is undefined, then throw a TypeError exception. 

    // 5. Let entries be the List that is the value of S’s [[SetData]] internal slot. 
    EJSSetValueEntry* entries = EJSVAL_TO_SET(S)->head_insert;
    // 6. Repeat for each e that is an element of entries, 
    for (EJSSetValueEntry* e = entries; e; e = e->next_insert) {
        //    a. Replace the element of entries whose value is e with an element whose value is empty. 
        e->value = MAGIC_TO_EJSVAL_IMPL(EJS_NO_ITER_VALUE);
    }
    // 7. Return undefined. 
    return _ejs_undefined;
}
Ejemplo n.º 3
0
// ES6: 23.2.3.9
// get Set.prototype.size
static ejsval
_ejs_Set_prototype_get_size (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    // 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 size getter 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 size getter called with non-Set this.");
    }

    EJSSet* _set = EJSVAL_TO_SET(S);

    // 4. If S’s [[SetData]] internal slot is undefined, then throw a TypeError exception.

    // 5. Let entries be the List that is the value of S’s [[SetData]] internal slot.
    EJSSetValueEntry* entries = _set->head_insert;

    // 6. Let count be 0.
    uint32_t count = 0;
    // 7. For each e that is an element of entries
    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))
            //      i. Set count to count+1.
            count ++;
    }
    // 8. Return count.
    return NUMBER_TO_EJSVAL(count);
}
Ejemplo n.º 4
0
// ES6: 23.2.3.7
// Set.prototype.has ( value )
ejsval
_ejs_Set_prototype_has (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    ejsval value = _ejs_undefined;
    if (argc > 0) value = args[0];

    // 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.has 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.has called with non-Set this.");

    // 4. If S’s [[SetData]] internal slot is undefined, then throw a TypeError exception. 

    EJSSet* _set = EJSVAL_TO_SET(S);

    // 5. Let entries be the List that is the value of S’s [[SetData]] internal slot. 
    EJSSetValueEntry* entries = _set->head_insert;

    // 6. Repeat for each e that is an element of entries, 
    for (EJSSetValueEntry* e = entries; e; e = e->next_insert) {
        // a. If e is not empty and SameValueZero(e, value) is true, then return true.
        if (SameValueZero (e->value, value))
            return _ejs_true;
    }
    // 7. Return false. 
    return _ejs_false;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
// 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();
}
Ejemplo n.º 8
0
ejsval
_ejs_set_iterator_new (ejsval set, EJSSetIteratorKind kind)
{
    /* 1. If Type(set) is not Object, throw a TypeError exception. */
    if (!EJSVAL_IS_OBJECT(set))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "set is not a Object");

    /* 2. If set does not have a [[SetData]] internal slot throw a TypeError exception. */
    if (!EJSVAL_IS_SET(set))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "value is not a Set");

    /* 3. If set’s [[SetData]] internal slot is undefined, then throw a TypeError exception. */

    /* 4. Let iterator be the result of ObjectCreate(%SetIteratorPrototype%,
     * ([[IteratedSet]], [[SetNextIndex]], [[SetIterationKind]])). */
    EJSSetIterator *iter = _ejs_gc_new (EJSSetIterator);
    _ejs_init_object ((EJSObject*) iter, _ejs_SetIterator_prototype, &_ejs_SetIterator_specops);

    /* 5. Set iterator’s [[IteratedSet]] internal slot to set. */
    iter->iterated = set;

    /* 6. Set iterator’s [[SetNextIndex]] internal slot to 0. */
    iter->next_index = 0;

    /* 7. Set iterator’s [[SetIterationKind]] internal slot to kind. */
    iter->kind = kind;

    /* 8. Return iterator */
    return OBJECT_TO_EJSVAL(iter);
}
Ejemplo n.º 9
0
ejsval ToPrimitive(ejsval exp)
{
    if (EJSVAL_IS_OBJECT(exp)) {
        return OP(EJSVAL_TO_OBJECT(exp),default_value) (exp, "PreferredType");
    }
    else
        return exp;
}
Ejemplo n.º 10
0
static EJS_NATIVE_FUNC(_ejs_Generator_prototype_next) {
    ejsval O = *_this;
    if (!EJSVAL_IS_OBJECT(O))
        _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, ".next called on non-object");

    if (!EJSVAL_IS_GENERATOR(O))
        _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, ".next called on non-generator");

    return _ejs_generator_send(O, argc > 0 ? args[0] : _ejs_undefined);
}
Ejemplo n.º 11
0
// ES6: 23.4.3.3
// WeakSet.prototype.delete ( value )
static EJS_NATIVE_FUNC(_ejs_WeakSet_prototype_delete) {
    ejsval value = _ejs_undefined;
    if (argc > 0) value = args[0];

    // 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, "delete called with non-object this.");

    // 3. If S does not have a [[WeakSetData]] internal slot throw a TypeError exception.
    if (!EJSVAL_IS_WEAKSET(S))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "delete called with non-WeakSet this.");

    // 4. If S’s [[WeakSetData]] internal slot is undefined, then throw a TypeError exception.

    // 5. If Type(value) is not Object, then return false.
    if (!EJSVAL_IS_OBJECT(value))
        return _ejs_false;

    // 6. Let entries be the List that is the value of M’s [[WeakSetData]] internal slot.

#if WEAK_COLLECTIONS_USE_INVERTED_REP
    ejsval iset = _ejs_object_getprop(value, _ejs_WeakSetData_symbol);
    if (EJSVAL_IS_NULL_OR_UNDEFINED(iset))
        return _ejs_false;

    if (!EJSVAL_IS_SET(iset))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "[[WeakSetData]] internal error");

    return _ejs_set_delete (iset, S);
#else    
    // 7. Repeat for each e that is an element of entries,
    //    a. If e is not empty and SameValue(e, value) is true, then
    //       i. Replace the element of entries whose value is e with an element whose value is empty.
    //       ii. Return true.
    // 8. Return false.
    return _ejs_false;
#endif
}
Ejemplo n.º 12
0
// ES6: 23.4.3.1
// WeakSet.prototype.add ( value )
static EJS_NATIVE_FUNC(_ejs_WeakSet_prototype_add) {
    ejsval value = _ejs_undefined;
    if (argc > 0) value = args[0];

    // 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, "add called with non-object this.");

    // 3. If S does not have a [[WeakSetData]] internal slot throw a TypeError exception.
    if (!EJSVAL_IS_WEAKSET(S))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "add called with non-WeakSet this.");

    // 4. If S’s [[WeakSetData]] internal slot is undefined, then throw a TypeError exception.

    // 6. If Type(value) is not Object, then throw a TypeError exception.
    if (!EJSVAL_IS_OBJECT(value))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "add called with non-Object value.");

#if WEAK_COLLECTIONS_USE_INVERTED_REP
    ejsval iset = _ejs_object_getprop(value, _ejs_WeakSetData_symbol);
    if (EJSVAL_IS_NULL_OR_UNDEFINED(iset)) {
        iset = _ejs_set_new();
        _ejs_object_setprop(value, _ejs_WeakSetData_symbol, iset);
    }

    if (!EJSVAL_IS_SET(iset))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "[[WeakSetData]] internal error");

    _ejs_set_add (iset, S);
    return S;
#else
    // 7. Let entries be the List that is the value of S’s [[WeakSetData]] internal slot.
    //    a. If e is not empty and SameValue(e, value) is true, then
    //       1. Return S.
    // 8. Append value as the last element of entries.
    // 9. Return S.
#endif
}
Ejemplo n.º 13
0
// 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;
}
Ejemplo n.º 14
0
static ejsval
_ejs_Generator_prototype_throw (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    ejsval O = _this;
    if (!EJSVAL_IS_OBJECT(O))
        _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, ".throw called on non-object");

    if (!EJSVAL_IS_GENERATOR(O))
        _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, ".throw called on non-generator");

    return _ejs_generator_throw(O, argc > 0 ? args[0] : _ejs_undefined);
}
Ejemplo n.º 15
0
// ES6: 23.2.3.1 Set.prototype.add ( value )
ejsval
_ejs_Set_prototype_add (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    ejsval value = _ejs_undefined;
    if (argc > 0) value = args[0];

    // 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.add 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.set called with non-Set this.");

    // 4. If S’s [[SetData]] internal slot is undefined, then throw a TypeError exception. 
    EJSSet* _set = EJSVAL_TO_SET(S);

    // 5. Let entries be the List that is the value of S’s [[SetData]] internal slot. 
    EJSSetValueEntry* entries = _set->head_insert;

    EJSSetValueEntry* e;
    // 6. Repeat for each e that is an element of entries, 
    for (e = entries; e; e = e->next_insert) {
        //    a. If e is not empty and SameValueZero(e, value) is true, then 
        if (SameValueZero(e->value, value))
        //       i. Return S. 
            return S;
    }
    // 7. If value is −0, then let value be +0. 
    if (EJSVAL_IS_NUMBER(value) && EJSDOUBLE_IS_NEGZERO(EJSVAL_TO_NUMBER(value)))
        value = NUMBER_TO_EJSVAL(0);
    // 8. Append value as the last element of entries. 
    e = calloc (1, sizeof (EJSSetValueEntry));
    e->value = value;

    if (!_set->head_insert)
        _set->head_insert = e;

    if (_set->tail_insert) {
        _set->tail_insert->next_insert = e;
        _set->tail_insert = e;
    }
    else {
        _set->tail_insert = e;
    }

    // 9. Return S.
    return S;
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
EJSBool ToEJSBool(ejsval exp)
{
    if (EJSVAL_IS_NULL(exp) || EJSVAL_IS_UNDEFINED(exp))
        return EJS_FALSE;
    else if (EJSVAL_IS_BOOLEAN(exp))
        return EJSVAL_TO_BOOLEAN(exp);
    else if (EJSVAL_IS_NUMBER(exp))
        return EJSVAL_TO_NUMBER(exp) != 0;
    else if (EJSVAL_IS_STRING(exp))
        return EJSVAL_TO_STRLEN(exp) != 0;
    else if (EJSVAL_IS_OBJECT(exp))
        return EJS_TRUE;
    else
        EJS_NOT_IMPLEMENTED();
}
Ejemplo n.º 18
0
// 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);
}
Ejemplo n.º 19
0
static EJS_NATIVE_FUNC(_ejs_Error_prototype_toString) {
    ejsval O = *_this;
    if (!EJSVAL_IS_OBJECT(O)) {
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Error.prototype.toString called on non-object");
    }

    EJSObject *_thisobj = EJSVAL_TO_OBJECT(O);
    ejsval name = OP(_thisobj,Get)(O, _ejs_atom_name, O);
    if (EJSVAL_IS_NULL_OR_UNDEFINED(name))
        name = _ejs_atom_Error;

    ejsval message = OP(_thisobj,Get)(O, _ejs_atom_message, O);
    if (EJSVAL_IS_NULL_OR_UNDEFINED(message))
        return name;

    ejsval sep = _ejs_string_new_utf8(": ");
    return _ejs_string_concatv (name, sep, message, _ejs_null);
}
Ejemplo n.º 20
0
// 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();
}
Ejemplo n.º 21
0
// ES2015, June 2015
// 19.4.3.3 Symbol.prototype.valueOf ( )
static EJS_NATIVE_FUNC(_ejs_Symbol_prototype_valueOf) {
    // 1. Let s be the this value.
    ejsval s = *_this;

    // 2. If Type(s) is Symbol, return s.
    if (EJSVAL_IS_SYMBOL(s))
        return s;

    // 3. If Type(s) is not Object, throw a TypeError exception.
    if (!EJSVAL_IS_OBJECT(s))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Symbol.prototype.valueOf called with non-object this");
        
    // 4. If s does not have a [[SymbolData]] internal slot, throw a TypeError exception.
    if (!EJSVAL_IS_SYMBOL_OBJECT(s))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Symbol.prototype.valueOf called with non-symbol this");

    // 5. Return the value of s’s [[SymbolData]] internal slot.
    return EJSVAL_TO_SYMBOL_OBJECT(s)->primSymbol;
}
Ejemplo n.º 22
0
static ejsval
_ejs_Error_prototype_toString (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    if (!EJSVAL_IS_OBJECT(_this)) {
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "Error.prototype.toString called on non-object");
    }

    EJSObject *_thisobj = EJSVAL_TO_OBJECT(_this);
    ejsval name = OP(_thisobj,Get)(_this, _ejs_atom_name, _this);
    if (EJSVAL_IS_NULL_OR_UNDEFINED(name))
        name = _ejs_atom_Error;

    ejsval message = OP(_thisobj,Get)(_this, _ejs_atom_message, _this);
    if (EJSVAL_IS_NULL_OR_UNDEFINED(message))
        return name;

    ejsval sep = _ejs_string_new_utf8(": ");
    return _ejs_string_concatv (name, sep, message, _ejs_null);
}
Ejemplo n.º 23
0
// ECMA262: 26.1.14 Reflect.setPrototypeOf ( target, proto ) 
static ejsval
_ejs_Reflect_setPrototypeOf (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    ejsval target = _ejs_undefined;
    ejsval proto = _ejs_undefined;

    if (argc > 0) target = args[0];
    if (argc > 1) proto  = args[1];

    // 1. Let obj be ToObject(target). 
    // 2. ReturnIfAbrupt(obj). 
    ejsval obj = ToObject(target);

    // 3. If Type(proto) is not Object and proto is not null, then throw a TypeError exception 
    if (!EJSVAL_IS_OBJECT(proto) && !EJSVAL_IS_NULL(proto))
        _ejs_throw_nativeerror_utf8(EJS_TYPE_ERROR, "prototype argument must be an object or null");

    // 4. Return the result of calling the [[SetPrototypeOf]] internal method of obj with argument proto. 
    return BOOLEAN_TO_EJSVAL(OP(EJSVAL_TO_OBJECT(obj), SetPrototypeOf)(target, proto));
}
Ejemplo n.º 24
0
// 23.2.3.4 Set.prototype.delete ( value ) 
ejsval
_ejs_Set_prototype_delete (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    // NOTE The value empty is used as a specification device to
    // indicate that an entry has been deleted. Actual implementations
    // may take other actions such as physically removing the entry
    // from internal data structures.

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

    // 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.delete 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.delete called with non-Set this.");

    // 4. If S’s [[SetData]] internal slot is undefined, then throw a TypeError exception. 

    // 5. Let entries be the List that is the value of S’s [[SetData]] internal slot. 
    EJSSetValueEntry* entries = EJSVAL_TO_SET(S)->head_insert;
    // 6. Repeat for each e that is an element of entries, 
    for (EJSSetValueEntry* e = entries; e; e = e->next_insert) {
        //    a. If e is not empty and SameValueZero(e, value) is true, then 
        if (SameValueZero(e->value, value)) {
            // i. Replace the element of entries whose value is e with an element whose value is empty. 
            e->value = MAGIC_TO_EJSVAL_IMPL(EJS_NO_ITER_VALUE);
            // ii. Return true. 
            return _ejs_true;
        }
    }
    // 7. Return false. 
    return _ejs_false;
}
Ejemplo n.º 25
0
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();
}
Ejemplo n.º 26
0
static ejsval
_ejs_Function_prototype_create(ejsval env, ejsval _this, uint32_t argc, ejsval* args)
{
    ejsval F = _this;

    if (!EJSVAL_IS_CONSTRUCTOR(F)) 
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "'this' in Function.prototype[Symbol.create] is not a constructor");
        
    EJSObject* F_ = EJSVAL_TO_OBJECT(F);

    ejsval proto = OP(F_,Get)(F, _ejs_atom_prototype, F);
    if (EJSVAL_IS_UNDEFINED(proto)) {
        proto = _ejs_Function_prototype;
    }

    if (!EJSVAL_IS_OBJECT(proto)) {
        EJS_NOT_IMPLEMENTED(); // cross-realm doesn't exist in ejs yet
    }

    EJSObject* obj = (EJSObject*)_ejs_gc_new (EJSObject);
    _ejs_init_object (obj, proto, &_ejs_Object_specops);
    return OBJECT_TO_EJSVAL(obj);
}
Ejemplo n.º 27
0
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();
}
Ejemplo n.º 28
0
ejsval
_ejs_op_typeof (ejsval exp)
{
    if (EJSVAL_IS_NULL(exp))
        return _ejs_atom_null;
    else if (EJSVAL_IS_BOOLEAN(exp))
        return _ejs_atom_boolean;
    else if (EJSVAL_IS_STRING(exp))
        return _ejs_atom_string;
    else if (EJSVAL_IS_SYMBOL(exp))
        return _ejs_atom_symbol;
    else if (EJSVAL_IS_NUMBER(exp))
        return _ejs_atom_number;
    else if (EJSVAL_IS_UNDEFINED(exp))
        return _ejs_atom_undefined;
    else if (EJSVAL_IS_OBJECT(exp)) {
        if (EJSVAL_IS_FUNCTION(exp))
            return _ejs_atom_function;
        else
            return _ejs_atom_object;
    }
    else
        EJS_NOT_IMPLEMENTED();
}
Ejemplo n.º 29
0
static ejsval
_ejs_SetIterator_prototype_next (ejsval env, ejsval _this, uint32_t argc, ejsval *args)
{
    /* 1. Let O be the this value. */
    ejsval O = _this;

    /* 2. If Type(O) is not Object, throw a TypeError exception. */
    if (!EJSVAL_IS_OBJECT(O))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, ".next called on non-object");

    /* 3. If O does not have all of the internal slots of a Set Iterator Instance (23.2.5.3),
     * throw a TypeError exception. */
    if (!EJSVAL_IS_SETITERATOR(O))
        _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, ".next called on non-SetIterator instance");

    EJSSetIterator *OObj = (EJSSetIterator*)EJSVAL_TO_OBJECT(O);

    /* 4. Let s be the value of the [[IteratedSet]] internal slot of O. */
    ejsval s = OObj->iterated;

    /* 5. Let index be the value of the [[SetNextIndex]] internal slot of O. */
    uint32_t index = OObj->next_index;

    /* 6. Let itemKind be the value of the [[SetIterationKind]] internal slot of O. */
    EJSSetIteratorKind itemKind = OObj->kind;

    /* 7. If s is undefined, then return CreateIterResultObject(undefined, true). */
    if (EJSVAL_IS_UNDEFINED(s))
        return _ejs_create_iter_result (_ejs_undefined, _ejs_true);

    /* 8. Assert: s has a [[SetData]] internal slot and s has been initialized so the value of
     * [[SetData]] is not undefined. */

    /* 9. Let entries be the List that is the value of the [[SetData]] internal slot of s. */
    EJSSetValueEntry *entries = EJSVAL_TO_SET(s)->head_insert;

    /* 10. Repeat while index is less than the total number of elements of entries. The number of elements must
     * be redetermined each time this method is evaluated. */
    uint32_t i = 0;
    for (EJSSetValueEntry *entry = entries; entry; entry = entry->next_insert) {

        /* Ignore this item if is marked as empty */
        if (EJSVAL_IS_NO_ITER_VALUE_MAGIC(entry->value))
            continue;

        /* Ignore this item if we haven't reached the initial needed point/index */
        if (index > i++)
            continue;

        /* a. Let e be entries[index]. */
        ejsval e = entry->value;

        /* b. Set index to index+1; */
        index = index + 1;

        /* c. Set the [[SetNextIndex]] internal slot of O to index. */
        OObj->next_index = index;

        /* d. If e is not empty, then */
        /*  (see EJSVAL_IS_NO_ITER_VALUE_MAGIC check at the beginning of the loop */

        /*      i. If itemKind is "key+value" then, */
        if (itemKind == EJS_SET_ITER_KIND_KEYVALUE) {
            /* 1. Let result be the result of performing ArrayCreate(2). */
            /* 2. Assert: result is a new, well-formed Array object so the following operations will never fail. */
            ejsval result = _ejs_array_new (2, EJS_FALSE);

            /* 3. Call CreateDataProperty(result, "0", e) . */
            _ejs_object_setprop (result, NUMBER_TO_EJSVAL(0), e);

            /* 4. Call CreateDataProperty(result, "1", e) . */
            _ejs_object_setprop (result, NUMBER_TO_EJSVAL(1), e);

            return _ejs_create_iter_result (result, _ejs_false);
        }

        /*      ii. Return CreateIterResultObject(e, false). */
        return _ejs_create_iter_result (e, _ejs_false);
    }

    /* 11. Set the [[IteratedSet]] internal slot of O to undefined. */
    OObj->iterated = _ejs_undefined;

    /* 12. Return CreateIterResultObject(undefined, true). */
    return _ejs_create_iter_result (_ejs_undefined, _ejs_true);
}
Ejemplo n.º 30
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;
}