diff -r 000000000000 -r 6474c204b198 js/src/jsiter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/jsiter.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,258 @@ +/* -*- 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/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 { + +struct NativeIterator +{ + HeapPtrObject obj; // Object being iterated. + JSObject *iterObj_; // Internal iterator object. + HeapPtr *props_array; + HeapPtr *props_cursor; + HeapPtr *props_end; + Shape **shapes_array; + uint32_t shapes_length; + uint32_t shapes_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 HeapPtr *begin() const { + return props_array; + } + + inline HeapPtr *end() const { + return props_end; + } + + size_t numKeys() const { + return end() - begin(); + } + + JSObject *iterObj() const { + return iterObj_; + } + HeapPtr *current() const { + JS_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. */ + JS_ASSERT(!next_ && !prev_); + JS_ASSERT(flags & JSITER_ENUMERATE); + + this->next_ = other; + this->prev_ = other->prev_; + other->prev_->next_ = this; + other->prev_ = this; + } + void unlink() { + JS_ASSERT(flags & JSITER_ENUMERATE); + + next_->prev_ = prev_; + prev_->next_ = next_; + next_ = nullptr; + prev_ = nullptr; + } + + static NativeIterator *allocateSentinel(JSContext *cx); + static NativeIterator *allocateIterator(JSContext *cx, uint32_t slength, + const js::AutoIdVector &props); + void init(JSObject *obj, JSObject *iterObj, unsigned flags, uint32_t slength, uint32_t key); + + void mark(JSTracer *trc); + + static void destroy(NativeIterator *iter) { + js_free(iter); + } +}; + +class PropertyIteratorObject : public JSObject +{ + public: + static const Class class_; + + NativeIterator *getNativeIterator() const { + return static_cast(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_; +}; + +bool +VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap); + +bool +GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp); + +JSObject * +GetIteratorObject(JSContext *cx, HandleObject obj, unsigned flags); + +bool +VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, + MutableHandleValue vp); + +bool +VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, + MutableHandleValue vp); + +/* + * 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, + MutableHandleValue vp); + +/* + * 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. + */ +bool +ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp); + +bool +CloseIterator(JSContext *cx, HandleObject iterObj); + +bool +UnwindIteratorForException(JSContext *cx, js::HandleObject obj); + +void +UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj); + +bool +IteratorConstructor(JSContext *cx, unsigned argc, Value *vp); + +} /* namespace js */ + +extern bool +js_SuppressDeletedProperty(JSContext *cx, js::HandleObject obj, jsid id); + +extern bool +js_SuppressDeletedElement(JSContext *cx, js::HandleObject obj, uint32_t index); + +extern bool +js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin, uint32_t end); + +/* + * IteratorMore() indicates whether another value is available. It might + * internally call iterobj.next() and then cache the value until its + * picked up by IteratorNext(). The value is cached in the current context. + */ +extern bool +js_IteratorMore(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval); + +extern bool +js_IteratorNext(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval); + +extern bool +js_ThrowStopIteration(JSContext *cx); + +namespace js { + +/* + * 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, js::HandleValue value, bool done); + +} /* namespace js */ + +/* + * Generator state codes. + */ +enum JSGeneratorState +{ + JSGEN_NEWBORN, /* not yet started */ + JSGEN_OPEN, /* started by a .next() or .send(undefined) call */ + JSGEN_RUNNING, /* currently executing via .next(), etc., call */ + JSGEN_CLOSING, /* close method is doing asynchronous return */ + JSGEN_CLOSED /* closed, cannot be started or closed again */ +}; + +struct JSGenerator +{ + js::HeapPtrObject obj; + JSGeneratorState state; + js::InterpreterRegs regs; + JSGenerator *prevGenerator; + js::InterpreterFrame *fp; + js::HeapValue stackSnapshot[1]; +}; + +extern JSObject * +js_NewGenerator(JSContext *cx, const js::InterpreterRegs ®s); + +extern JSObject * +js_InitIteratorClasses(JSContext *cx, js::HandleObject obj); + +#endif /* jsiter_h */