diff options
Diffstat (limited to 'js/src/jsiter.h')
-rw-r--r-- | js/src/jsiter.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/js/src/jsiter.h b/js/src/jsiter.h new file mode 100644 index 000000000..35d7ef118 --- /dev/null +++ b/js/src/jsiter.h @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jsiter_h +#define jsiter_h + +/* + * JavaScript iterators. + */ + +#include "mozilla/MemoryReporting.h" + +#include "jscntxt.h" + +#include "gc/Barrier.h" +#include "vm/ReceiverGuard.h" +#include "vm/Stack.h" + +/* + * For cacheable native iterators, whether the iterator is currently active. + * Not serialized by XDR. + */ +#define JSITER_ACTIVE 0x1000 +#define JSITER_UNREUSABLE 0x2000 + +namespace js { + +class PropertyIteratorObject; + +struct NativeIterator +{ + GCPtrObject obj; // Object being iterated. + JSObject* iterObj_; // Internal iterator object. + GCPtrFlatString* props_array; + GCPtrFlatString* props_cursor; + GCPtrFlatString* props_end; + HeapReceiverGuard* guard_array; + uint32_t guard_length; + uint32_t guard_key; + uint32_t flags; + + private: + /* While in compartment->enumerators, these form a doubly linked list. */ + NativeIterator* next_; + NativeIterator* prev_; + + public: + bool isKeyIter() const { + return (flags & JSITER_FOREACH) == 0; + } + + inline GCPtrFlatString* begin() const { + return props_array; + } + + inline GCPtrFlatString* end() const { + return props_end; + } + + size_t numKeys() const { + return end() - begin(); + } + + JSObject* iterObj() const { + return iterObj_; + } + GCPtrFlatString* current() const { + MOZ_ASSERT(props_cursor < props_end); + return props_cursor; + } + + NativeIterator* next() { + return next_; + } + + static inline size_t offsetOfNext() { + return offsetof(NativeIterator, next_); + } + static inline size_t offsetOfPrev() { + return offsetof(NativeIterator, prev_); + } + + void incCursor() { + props_cursor = props_cursor + 1; + } + void link(NativeIterator* other) { + /* A NativeIterator cannot appear in the enumerator list twice. */ + MOZ_ASSERT(!next_ && !prev_); + MOZ_ASSERT(flags & JSITER_ENUMERATE); + + this->next_ = other; + this->prev_ = other->prev_; + other->prev_->next_ = this; + other->prev_ = this; + } + void unlink() { + MOZ_ASSERT(flags & JSITER_ENUMERATE); + + next_->prev_ = prev_; + prev_->next_ = next_; + next_ = nullptr; + prev_ = nullptr; + } + + static NativeIterator* allocateSentinel(JSContext* maybecx); + static NativeIterator* allocateIterator(JSContext* cx, uint32_t slength, uint32_t plength); + void init(JSObject* obj, JSObject* iterObj, unsigned flags, uint32_t slength, uint32_t key); + bool initProperties(JSContext* cx, Handle<PropertyIteratorObject*> obj, + const js::AutoIdVector& props); + + void trace(JSTracer* trc); + + static void destroy(NativeIterator* iter) { + js_free(iter); + } +}; + +class PropertyIteratorObject : public NativeObject +{ + static const ClassOps classOps_; + + public: + static const Class class_; + + NativeIterator* getNativeIterator() const { + return static_cast<js::NativeIterator*>(getPrivate()); + } + void setNativeIterator(js::NativeIterator* ni) { + setPrivate(ni); + } + + size_t sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const; + + private: + static void trace(JSTracer* trc, JSObject* obj); + static void finalize(FreeOp* fop, JSObject* obj); +}; + +class ArrayIteratorObject : public JSObject +{ + public: + static const Class class_; +}; + +class StringIteratorObject : public JSObject +{ + public: + static const Class class_; +}; + +class ListIteratorObject : public JSObject +{ + public: + static const Class class_; +}; + +bool +GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp); + +JSObject* +GetIteratorObject(JSContext* cx, HandleObject obj, unsigned flags); + +/* + * Creates either a key or value iterator, depending on flags. For a value + * iterator, performs value-lookup to convert the given list of jsids. + */ +bool +EnumeratedIdVectorToIterator(JSContext* cx, HandleObject obj, unsigned flags, AutoIdVector& props, + MutableHandleObject objp); + +bool +NewEmptyPropertyIterator(JSContext* cx, unsigned flags, MutableHandleObject objp); + +/* + * Convert the value stored in *vp to its iteration object. The flags should + * contain JSITER_ENUMERATE if js::ValueToIterator is called when enumerating + * for-in semantics are required, and when the caller can guarantee that the + * iterator will never be exposed to scripts. + */ +JSObject* +ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp); + +bool +CloseIterator(JSContext* cx, HandleObject iterObj); + +bool +UnwindIteratorForException(JSContext* cx, HandleObject obj); + +void +UnwindIteratorForUncatchableException(JSContext* cx, JSObject* obj); + +bool +IteratorConstructor(JSContext* cx, unsigned argc, Value* vp); + +extern bool +SuppressDeletedProperty(JSContext* cx, HandleObject obj, jsid id); + +extern bool +SuppressDeletedElement(JSContext* cx, HandleObject obj, uint32_t index); + +/* + * IteratorMore() returns the next iteration value. If no value is available, + * MagicValue(JS_NO_ITER_VALUE) is returned. + */ +extern bool +IteratorMore(JSContext* cx, HandleObject iterobj, MutableHandleValue rval); + +extern bool +ThrowStopIteration(JSContext* cx); + +/* + * Create an object of the form { value: VALUE, done: DONE }. + * ES6 draft from 2013-09-05, section 25.4.3.4. + */ +extern JSObject* +CreateItrResultObject(JSContext* cx, HandleValue value, bool done); + +extern JSObject* +InitLegacyIteratorClass(JSContext* cx, HandleObject obj); + +extern JSObject* +InitStopIterationClass(JSContext* cx, HandleObject obj); + +} /* namespace js */ + +#endif /* jsiter_h */ |