~ubuntu-branches/ubuntu/trusty/mozjs24/trusty-proposed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* -*- 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 builtin_MapObject_h
#define builtin_MapObject_h

#include "jsapi.h"
#include "jscntxt.h"
#include "jsobj.h"

namespace js {

/*
 * Comparing two ropes for equality can fail. The js::HashTable template
 * requires infallible hash() and match() operations. Therefore we require
 * all values to be converted to hashable form before being used as a key
 * in a Map or Set object.
 *
 * All values except ropes are hashable as-is.
 */
class HashableValue {
    EncapsulatedValue value;

  public:
    struct Hasher {
        typedef HashableValue Lookup;
        static HashNumber hash(const Lookup &v) { return v.hash(); }
        static bool match(const HashableValue &k, const Lookup &l) { return k == l; }
        static bool isEmpty(const HashableValue &v) { return v.value.isMagic(JS_HASH_KEY_EMPTY); }
        static void makeEmpty(HashableValue *vp) { vp->value = MagicValue(JS_HASH_KEY_EMPTY); }
    };

    HashableValue() : value(UndefinedValue()) {}

    bool setValue(JSContext *cx, const Value &v);
    HashNumber hash() const;
    bool operator==(const HashableValue &other) const;
    HashableValue mark(JSTracer *trc) const;
    Value get() const { return value.get(); }
};

class AutoHashableValueRooter : private AutoGCRooter
{
  public:
    explicit AutoHashableValueRooter(JSContext *cx
                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
        : AutoGCRooter(cx, HASHABLEVALUE)
        {
            MOZ_GUARD_OBJECT_NOTIFIER_INIT;
        }

    bool setValue(JSContext *cx, const Value &v) {
        return value.setValue(cx, v);
    }

    operator const HashableValue & () {
        return value;
    }

    friend void AutoGCRooter::trace(JSTracer *trc);
    void trace(JSTracer *trc);

  private:
    HashableValue value;
    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};

template <class Key, class Value, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashMap;

template <class T, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashSet;

typedef OrderedHashMap<HashableValue,
                       RelocatableValue,
                       HashableValue::Hasher,
                       RuntimeAllocPolicy> ValueMap;

typedef OrderedHashSet<HashableValue,
                       HashableValue::Hasher,
                       RuntimeAllocPolicy> ValueSet;

class MapObject : public JSObject {
  public:
    enum IteratorKind { Keys, Values, Entries };

    static JSObject *initClass(JSContext *cx, JSObject *obj);
    static Class class_;
  private:
    static const JSPropertySpec properties[];
    static const JSFunctionSpec methods[];
    ValueMap *getData() { return static_cast<ValueMap *>(getPrivate()); }
    static ValueMap & extract(CallReceiver call);
    static void mark(JSTracer *trc, JSObject *obj);
    static void finalize(FreeOp *fop, JSObject *obj);
    static JSBool construct(JSContext *cx, unsigned argc, Value *vp);

    static bool is(const Value &v);

    static bool iterator_impl(JSContext *cx, CallArgs args, IteratorKind kind);

    static bool size_impl(JSContext *cx, CallArgs args);
    static JSBool size(JSContext *cx, unsigned argc, Value *vp);
    static bool get_impl(JSContext *cx, CallArgs args);
    static JSBool get(JSContext *cx, unsigned argc, Value *vp);
    static bool has_impl(JSContext *cx, CallArgs args);
    static JSBool has(JSContext *cx, unsigned argc, Value *vp);
    static bool set_impl(JSContext *cx, CallArgs args);
    static JSBool set(JSContext *cx, unsigned argc, Value *vp);
    static bool delete_impl(JSContext *cx, CallArgs args);
    static JSBool delete_(JSContext *cx, unsigned argc, Value *vp);
    static bool keys_impl(JSContext *cx, CallArgs args);
    static JSBool keys(JSContext *cx, unsigned argc, Value *vp);
    static bool values_impl(JSContext *cx, CallArgs args);
    static JSBool values(JSContext *cx, unsigned argc, Value *vp);
    static bool entries_impl(JSContext *cx, CallArgs args);
    static JSBool entries(JSContext *cx, unsigned argc, Value *vp);
    static bool clear_impl(JSContext *cx, CallArgs args);
    static JSBool clear(JSContext *cx, unsigned argc, Value *vp);
};

class SetObject : public JSObject {
  public:
    enum IteratorKind { Values, Entries };
    static JSObject *initClass(JSContext *cx, JSObject *obj);
    static Class class_;
  private:
    static const JSPropertySpec properties[];
    static const JSFunctionSpec methods[];
    ValueSet *getData() { return static_cast<ValueSet *>(getPrivate()); }
    static ValueSet & extract(CallReceiver call);
    static void mark(JSTracer *trc, JSObject *obj);
    static void finalize(FreeOp *fop, JSObject *obj);
    static JSBool construct(JSContext *cx, unsigned argc, Value *vp);

    static bool is(const Value &v);

    static bool iterator_impl(JSContext *cx, CallArgs args, IteratorKind kind);

    static bool size_impl(JSContext *cx, CallArgs args);
    static JSBool size(JSContext *cx, unsigned argc, Value *vp);
    static bool has_impl(JSContext *cx, CallArgs args);
    static JSBool has(JSContext *cx, unsigned argc, Value *vp);
    static bool add_impl(JSContext *cx, CallArgs args);
    static JSBool add(JSContext *cx, unsigned argc, Value *vp);
    static bool delete_impl(JSContext *cx, CallArgs args);
    static JSBool delete_(JSContext *cx, unsigned argc, Value *vp);
    static bool values_impl(JSContext *cx, CallArgs args);
    static JSBool values(JSContext *cx, unsigned argc, Value *vp);
    static bool entries_impl(JSContext *cx, CallArgs args);
    static JSBool entries(JSContext *cx, unsigned argc, Value *vp);
    static bool clear_impl(JSContext *cx, CallArgs args);
    static JSBool clear(JSContext *cx, unsigned argc, Value *vp);
};

} /* namespace js */

extern JSObject *
js_InitMapClass(JSContext *cx, js::HandleObject obj);

extern JSObject *
js_InitSetClass(JSContext *cx, js::HandleObject obj);

#endif /* builtin_MapObject_h */