1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsiter.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,258 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jsiter_h 1.11 +#define jsiter_h 1.12 + 1.13 +/* 1.14 + * JavaScript iterators. 1.15 + */ 1.16 + 1.17 +#include "mozilla/MemoryReporting.h" 1.18 + 1.19 +#include "jscntxt.h" 1.20 + 1.21 +#include "gc/Barrier.h" 1.22 +#include "vm/Stack.h" 1.23 + 1.24 +/* 1.25 + * For cacheable native iterators, whether the iterator is currently active. 1.26 + * Not serialized by XDR. 1.27 + */ 1.28 +#define JSITER_ACTIVE 0x1000 1.29 +#define JSITER_UNREUSABLE 0x2000 1.30 + 1.31 +namespace js { 1.32 + 1.33 +struct NativeIterator 1.34 +{ 1.35 + HeapPtrObject obj; // Object being iterated. 1.36 + JSObject *iterObj_; // Internal iterator object. 1.37 + HeapPtr<JSFlatString> *props_array; 1.38 + HeapPtr<JSFlatString> *props_cursor; 1.39 + HeapPtr<JSFlatString> *props_end; 1.40 + Shape **shapes_array; 1.41 + uint32_t shapes_length; 1.42 + uint32_t shapes_key; 1.43 + uint32_t flags; 1.44 + 1.45 + private: 1.46 + /* While in compartment->enumerators, these form a doubly linked list. */ 1.47 + NativeIterator *next_; 1.48 + NativeIterator *prev_; 1.49 + 1.50 + public: 1.51 + bool isKeyIter() const { 1.52 + return (flags & JSITER_FOREACH) == 0; 1.53 + } 1.54 + 1.55 + inline HeapPtr<JSFlatString> *begin() const { 1.56 + return props_array; 1.57 + } 1.58 + 1.59 + inline HeapPtr<JSFlatString> *end() const { 1.60 + return props_end; 1.61 + } 1.62 + 1.63 + size_t numKeys() const { 1.64 + return end() - begin(); 1.65 + } 1.66 + 1.67 + JSObject *iterObj() const { 1.68 + return iterObj_; 1.69 + } 1.70 + HeapPtr<JSFlatString> *current() const { 1.71 + JS_ASSERT(props_cursor < props_end); 1.72 + return props_cursor; 1.73 + } 1.74 + 1.75 + NativeIterator *next() { 1.76 + return next_; 1.77 + } 1.78 + 1.79 + static inline size_t offsetOfNext() { 1.80 + return offsetof(NativeIterator, next_); 1.81 + } 1.82 + static inline size_t offsetOfPrev() { 1.83 + return offsetof(NativeIterator, prev_); 1.84 + } 1.85 + 1.86 + void incCursor() { 1.87 + props_cursor = props_cursor + 1; 1.88 + } 1.89 + void link(NativeIterator *other) { 1.90 + /* A NativeIterator cannot appear in the enumerator list twice. */ 1.91 + JS_ASSERT(!next_ && !prev_); 1.92 + JS_ASSERT(flags & JSITER_ENUMERATE); 1.93 + 1.94 + this->next_ = other; 1.95 + this->prev_ = other->prev_; 1.96 + other->prev_->next_ = this; 1.97 + other->prev_ = this; 1.98 + } 1.99 + void unlink() { 1.100 + JS_ASSERT(flags & JSITER_ENUMERATE); 1.101 + 1.102 + next_->prev_ = prev_; 1.103 + prev_->next_ = next_; 1.104 + next_ = nullptr; 1.105 + prev_ = nullptr; 1.106 + } 1.107 + 1.108 + static NativeIterator *allocateSentinel(JSContext *cx); 1.109 + static NativeIterator *allocateIterator(JSContext *cx, uint32_t slength, 1.110 + const js::AutoIdVector &props); 1.111 + void init(JSObject *obj, JSObject *iterObj, unsigned flags, uint32_t slength, uint32_t key); 1.112 + 1.113 + void mark(JSTracer *trc); 1.114 + 1.115 + static void destroy(NativeIterator *iter) { 1.116 + js_free(iter); 1.117 + } 1.118 +}; 1.119 + 1.120 +class PropertyIteratorObject : public JSObject 1.121 +{ 1.122 + public: 1.123 + static const Class class_; 1.124 + 1.125 + NativeIterator *getNativeIterator() const { 1.126 + return static_cast<js::NativeIterator *>(getPrivate()); 1.127 + } 1.128 + void setNativeIterator(js::NativeIterator *ni) { 1.129 + setPrivate(ni); 1.130 + } 1.131 + 1.132 + size_t sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf) const; 1.133 + 1.134 + private: 1.135 + static void trace(JSTracer *trc, JSObject *obj); 1.136 + static void finalize(FreeOp *fop, JSObject *obj); 1.137 +}; 1.138 + 1.139 +class ArrayIteratorObject : public JSObject 1.140 +{ 1.141 + public: 1.142 + static const Class class_; 1.143 +}; 1.144 + 1.145 +class StringIteratorObject : public JSObject 1.146 +{ 1.147 + public: 1.148 + static const Class class_; 1.149 +}; 1.150 + 1.151 +bool 1.152 +VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap); 1.153 + 1.154 +bool 1.155 +GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp); 1.156 + 1.157 +JSObject * 1.158 +GetIteratorObject(JSContext *cx, HandleObject obj, unsigned flags); 1.159 + 1.160 +bool 1.161 +VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, 1.162 + MutableHandleValue vp); 1.163 + 1.164 +bool 1.165 +VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, 1.166 + MutableHandleValue vp); 1.167 + 1.168 +/* 1.169 + * Creates either a key or value iterator, depending on flags. For a value 1.170 + * iterator, performs value-lookup to convert the given list of jsids. 1.171 + */ 1.172 +bool 1.173 +EnumeratedIdVectorToIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &props, 1.174 + MutableHandleValue vp); 1.175 + 1.176 +/* 1.177 + * Convert the value stored in *vp to its iteration object. The flags should 1.178 + * contain JSITER_ENUMERATE if js::ValueToIterator is called when enumerating 1.179 + * for-in semantics are required, and when the caller can guarantee that the 1.180 + * iterator will never be exposed to scripts. 1.181 + */ 1.182 +bool 1.183 +ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp); 1.184 + 1.185 +bool 1.186 +CloseIterator(JSContext *cx, HandleObject iterObj); 1.187 + 1.188 +bool 1.189 +UnwindIteratorForException(JSContext *cx, js::HandleObject obj); 1.190 + 1.191 +void 1.192 +UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj); 1.193 + 1.194 +bool 1.195 +IteratorConstructor(JSContext *cx, unsigned argc, Value *vp); 1.196 + 1.197 +} /* namespace js */ 1.198 + 1.199 +extern bool 1.200 +js_SuppressDeletedProperty(JSContext *cx, js::HandleObject obj, jsid id); 1.201 + 1.202 +extern bool 1.203 +js_SuppressDeletedElement(JSContext *cx, js::HandleObject obj, uint32_t index); 1.204 + 1.205 +extern bool 1.206 +js_SuppressDeletedElements(JSContext *cx, js::HandleObject obj, uint32_t begin, uint32_t end); 1.207 + 1.208 +/* 1.209 + * IteratorMore() indicates whether another value is available. It might 1.210 + * internally call iterobj.next() and then cache the value until its 1.211 + * picked up by IteratorNext(). The value is cached in the current context. 1.212 + */ 1.213 +extern bool 1.214 +js_IteratorMore(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval); 1.215 + 1.216 +extern bool 1.217 +js_IteratorNext(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval); 1.218 + 1.219 +extern bool 1.220 +js_ThrowStopIteration(JSContext *cx); 1.221 + 1.222 +namespace js { 1.223 + 1.224 +/* 1.225 + * Create an object of the form { value: VALUE, done: DONE }. 1.226 + * ES6 draft from 2013-09-05, section 25.4.3.4. 1.227 + */ 1.228 +extern JSObject * 1.229 +CreateItrResultObject(JSContext *cx, js::HandleValue value, bool done); 1.230 + 1.231 +} /* namespace js */ 1.232 + 1.233 +/* 1.234 + * Generator state codes. 1.235 + */ 1.236 +enum JSGeneratorState 1.237 +{ 1.238 + JSGEN_NEWBORN, /* not yet started */ 1.239 + JSGEN_OPEN, /* started by a .next() or .send(undefined) call */ 1.240 + JSGEN_RUNNING, /* currently executing via .next(), etc., call */ 1.241 + JSGEN_CLOSING, /* close method is doing asynchronous return */ 1.242 + JSGEN_CLOSED /* closed, cannot be started or closed again */ 1.243 +}; 1.244 + 1.245 +struct JSGenerator 1.246 +{ 1.247 + js::HeapPtrObject obj; 1.248 + JSGeneratorState state; 1.249 + js::InterpreterRegs regs; 1.250 + JSGenerator *prevGenerator; 1.251 + js::InterpreterFrame *fp; 1.252 + js::HeapValue stackSnapshot[1]; 1.253 +}; 1.254 + 1.255 +extern JSObject * 1.256 +js_NewGenerator(JSContext *cx, const js::InterpreterRegs ®s); 1.257 + 1.258 +extern JSObject * 1.259 +js_InitIteratorClasses(JSContext *cx, js::HandleObject obj); 1.260 + 1.261 +#endif /* jsiter_h */