Пример #1
0
// 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;
}
Пример #2
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);
    }
}