// 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; }
// 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); } }