Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / js / src / jsiter.h
blob9ae01d356f45acb9bbbc180fa84da7f06636f2d0
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef jsiter_h___
41 #define jsiter_h___
44 * JavaScript iterators.
46 #include "jscntxt.h"
47 #include "jsprvtd.h"
48 #include "jspubtd.h"
49 #include "jsversion.h"
52 * NB: these flag bits are encoded into the bytecode stream in the immediate
53 * operand of JSOP_ITER, so don't change them without advancing jsxdrapi.h's
54 * JSXDR_BYTECODE_VERSION.
56 #define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
57 #define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
58 #define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */
59 #define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
60 #define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
63 * For cacheable native iterators, whether the iterator is currently active.
64 * Not serialized by XDR.
66 #define JSITER_ACTIVE 0x1000
67 #define JSITER_UNREUSABLE 0x2000
69 namespace js {
71 struct NativeIterator {
72 JSObject *obj;
73 jsid *props_array;
74 jsid *props_cursor;
75 jsid *props_end;
76 uint32 *shapes_array;
77 uint32 shapes_length;
78 uint32 shapes_key;
79 uint32 flags;
80 JSObject *next; /* Forms cx->enumerators list, garbage otherwise. */
82 bool isKeyIter() const { return (flags & JSITER_FOREACH) == 0; }
84 inline jsid *begin() const {
85 return props_array;
88 inline jsid *end() const {
89 return props_end;
92 size_t numKeys() const {
93 return end() - begin();
96 jsid *current() const {
97 JS_ASSERT(props_cursor < props_end);
98 return props_cursor;
101 void incCursor() {
102 props_cursor = props_cursor + 1;
105 static NativeIterator *allocateIterator(JSContext *cx, uint32 slength,
106 const js::AutoIdVector &props);
107 void init(JSObject *obj, uintN flags, uint32 slength, uint32 key);
109 void mark(JSTracer *trc);
112 bool
113 VectorToIdArray(JSContext *cx, js::AutoIdVector &props, JSIdArray **idap);
115 JS_FRIEND_API(bool)
116 GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVector *props);
118 bool
119 GetIterator(JSContext *cx, JSObject *obj, uintN flags, js::Value *vp);
121 bool
122 VectorToKeyIterator(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVector &props, js::Value *vp);
124 bool
125 VectorToValueIterator(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVector &props, js::Value *vp);
128 * Creates either a key or value iterator, depending on flags. For a value
129 * iterator, performs value-lookup to convert the given list of jsids.
131 bool
132 EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVector &props, js::Value *vp);
137 * Convert the value stored in *vp to its iteration object. The flags should
138 * contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating
139 * for-in semantics are required, and when the caller can guarantee that the
140 * iterator will never be exposed to scripts.
142 extern JS_FRIEND_API(JSBool)
143 js_ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
145 extern JS_FRIEND_API(JSBool)
146 js_CloseIterator(JSContext *cx, JSObject *iterObj);
148 bool
149 js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id);
151 bool
152 js_SuppressDeletedIndexProperties(JSContext *cx, JSObject *obj, jsint begin, jsint end);
155 * IteratorMore() indicates whether another value is available. It might
156 * internally call iterobj.next() and then cache the value until its
157 * picked up by IteratorNext(). The value is cached in the current context.
159 extern JSBool
160 js_IteratorMore(JSContext *cx, JSObject *iterobj, js::Value *rval);
162 extern JSBool
163 js_IteratorNext(JSContext *cx, JSObject *iterobj, js::Value *rval);
165 extern JSBool
166 js_ThrowStopIteration(JSContext *cx);
168 #if JS_HAS_GENERATORS
171 * Generator state codes.
173 typedef enum JSGeneratorState {
174 JSGEN_NEWBORN, /* not yet started */
175 JSGEN_OPEN, /* started by a .next() or .send(undefined) call */
176 JSGEN_RUNNING, /* currently executing via .next(), etc., call */
177 JSGEN_CLOSING, /* close method is doing asynchronous return */
178 JSGEN_CLOSED /* closed, cannot be started or closed again */
179 } JSGeneratorState;
181 struct JSGenerator {
182 JSObject *obj;
183 JSGeneratorState state;
184 JSFrameRegs regs;
185 JSObject *enumerators;
186 JSStackFrame *floating;
187 js::Value floatingStack[1];
189 JSStackFrame *floatingFrame() {
190 return floating;
193 JSStackFrame *liveFrame() {
194 JS_ASSERT((state == JSGEN_RUNNING || state == JSGEN_CLOSING) ==
195 (regs.fp != floatingFrame()));
196 return regs.fp;
200 extern JSObject *
201 js_NewGenerator(JSContext *cx);
204 * Generator stack frames do not have stable pointers since they get copied to
205 * and from the generator object and the stack (see SendToGenerator). This is a
206 * problem for Block and With objects, which need to store a pointer to the
207 * enclosing stack frame. The solution is for Block and With objects to store
208 * a pointer to the "floating" stack frame stored in the generator object,
209 * since it is stable, and maintain, in the generator object, a pointer to the
210 * "live" stack frame (either a copy on the stack or the floating frame). Thus,
211 * Block and With objects must "normalize" to and from the floating/live frames
212 * in the case of generators using the following functions.
214 inline JSStackFrame *
215 js_FloatingFrameIfGenerator(JSContext *cx, JSStackFrame *fp)
217 JS_ASSERT(cx->stack().contains(fp));
218 if (JS_UNLIKELY(fp->isGeneratorFrame()))
219 return cx->generatorFor(fp)->floatingFrame();
220 return fp;
223 /* Given a floating frame, given the JSGenerator containing it. */
224 extern JSGenerator *
225 js_FloatingFrameToGenerator(JSStackFrame *fp);
227 inline JSStackFrame *
228 js_LiveFrameIfGenerator(JSStackFrame *fp)
230 return fp->isGeneratorFrame() ? js_FloatingFrameToGenerator(fp)->liveFrame() : fp;
233 #endif
235 extern js::Class js_GeneratorClass;
236 extern js::Class js_IteratorClass;
237 extern js::Class js_StopIterationClass;
239 static inline bool
240 js_ValueIsStopIteration(const js::Value &v)
242 return v.isObject() && v.toObject().getClass() == &js_StopIterationClass;
245 extern JSObject *
246 js_InitIteratorClasses(JSContext *cx, JSObject *obj);
248 #endif /* jsiter_h___ */