summaryrefslogtreecommitdiffstats
path: root/js/src/jsiter.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsiter.h')
-rw-r--r--js/src/jsiter.h229
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 */