1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* JS Array interface. */
8 
9 #ifndef jsarray_h
10 #define jsarray_h
11 
12 #include "jsobj.h"
13 #include "jspubtd.h"
14 
15 #include "vm/ArrayObject.h"
16 
17 namespace js {
18 /* 2^32-2, inclusive */
19 const uint32_t MAX_ARRAY_INDEX = 4294967294u;
20 
21 inline bool
IdIsIndex(jsid id,uint32_t * indexp)22 IdIsIndex(jsid id, uint32_t* indexp)
23 {
24     if (JSID_IS_INT(id)) {
25         int32_t i = JSID_TO_INT(id);
26         MOZ_ASSERT(i >= 0);
27         *indexp = (uint32_t)i;
28         return true;
29     }
30 
31     if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
32         return false;
33 
34     return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp);
35 }
36 
37 extern JSObject*
38 InitArrayClass(JSContext* cx, js::HandleObject obj);
39 
40 // The methods below only create dense boxed arrays.
41 
42 /* Create a dense array with no capacity allocated, length set to 0. */
43 extern ArrayObject * JS_FASTCALL
44 NewDenseEmptyArray(JSContext* cx, HandleObject proto = nullptr,
45                    NewObjectKind newKind = GenericObject);
46 
47 /*
48  * Create a dense array with a set length, but without allocating space for the
49  * contents. This is useful, e.g., when accepting length from the user.
50  */
51 extern ArrayObject * JS_FASTCALL
52 NewDenseUnallocatedArray(ExclusiveContext* cx, uint32_t length, HandleObject proto = nullptr,
53                          NewObjectKind newKind = GenericObject);
54 
55 /*
56  * Create a dense array with length and capacity == |length|, initialized length set to 0,
57  * but with only |EagerAllocationMaxLength| elements allocated.
58  */
59 extern ArrayObject * JS_FASTCALL
60 NewDensePartlyAllocatedArray(ExclusiveContext* cx, uint32_t length, HandleObject proto = nullptr,
61                              NewObjectKind newKind = GenericObject);
62 
63 /* Create a dense array with length and capacity == 'length', initialized length set to 0. */
64 extern ArrayObject * JS_FASTCALL
65 NewDenseFullyAllocatedArray(ExclusiveContext* cx, uint32_t length, HandleObject proto = nullptr,
66                             NewObjectKind newKind = GenericObject);
67 
68 /* Create a dense array from the given array values, which must be rooted */
69 extern ArrayObject*
70 NewDenseCopiedArray(ExclusiveContext* cx, uint32_t length, const Value* values,
71                     HandleObject proto = nullptr, NewObjectKind newKind = GenericObject);
72 
73 /* Create a dense array based on templateObject with the given length. */
74 extern ArrayObject*
75 NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject);
76 
77 /* Create a dense array with the same copy-on-write elements as another object. */
78 extern JSObject*
79 NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
80 
81 // The methods below can create either boxed or unboxed arrays.
82 
83 extern JSObject*
84 NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
85                                   NewObjectKind newKind = GenericObject, bool forceAnalyze = false);
86 
87 extern JSObject*
88 NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
89 
90 extern JSObject*
91 NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
92                                     NewObjectKind newKind = GenericObject,
93                                     bool forceAnalyze = false);
94 
95 extern JSObject*
96 NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length);
97 
98 extern JSObject*
99 NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
100                                                NewObjectKind newKind = GenericObject,
101                                                bool forceAnalyze = false);
102 
103 extern JSObject*
104 NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
105 
106 enum class ShouldUpdateTypes
107 {
108     Update,
109     DontUpdate
110 };
111 
112 extern JSObject*
113 NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
114                           const Value* vp, size_t length,
115                           NewObjectKind newKind = GenericObject,
116                           ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
117 
118 extern JSObject*
119 NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
120                                        HandleObject proto = nullptr);
121 
122 /*
123  * Determines whether a write to the given element on |obj| should fail because
124  * |obj| is an Array with a non-writable length, and writing that element would
125  * increase the length of the array.
126  */
127 extern bool
128 WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
129 
130 /*
131  * Canonicalize |vp| to a uint32_t value potentially suitable for use as an
132  * array length.
133  */
134 extern bool
135 CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* canonicalized);
136 
137 extern bool
138 GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp);
139 
140 extern bool
141 SetLengthProperty(JSContext* cx, HandleObject obj, double length);
142 
143 extern bool
144 ObjectMayHaveExtraIndexedProperties(JSObject* obj);
145 
146 /*
147  * Copy 'length' elements from aobj to vp.
148  *
149  * This function assumes 'length' is effectively the result of calling
150  * GetLengthProperty on aobj. vp must point to rooted memory.
151  */
152 extern bool
153 GetElements(JSContext* cx, HandleObject aobj, uint32_t length, js::Value* vp);
154 
155 /* Natives exposed for optimization by the interpreter and JITs. */
156 
157 extern bool
158 array_sort(JSContext* cx, unsigned argc, js::Value* vp);
159 
160 extern bool
161 array_push(JSContext* cx, unsigned argc, js::Value* vp);
162 
163 extern bool
164 array_pop(JSContext* cx, unsigned argc, js::Value* vp);
165 
166 extern bool
167 array_splice_impl(JSContext* cx, unsigned argc, js::Value* vp, bool pop);
168 
169 extern bool
170 array_concat(JSContext* cx, unsigned argc, js::Value* vp);
171 
172 template <bool Locale>
173 JSString*
174 ArrayJoin(JSContext* cx, HandleObject obj, HandleLinearString sepstr, uint32_t length);
175 
176 extern bool
177 array_concat_dense(JSContext* cx, HandleObject arr1, HandleObject arr2,
178                    HandleObject result);
179 
180 extern bool
181 array_join(JSContext* cx, unsigned argc, js::Value* vp);
182 
183 extern JSString*
184 array_join_impl(JSContext* cx, HandleValue array, HandleString sep);
185 
186 extern void
187 ArrayShiftMoveElements(JSObject* obj);
188 
189 extern bool
190 array_shift(JSContext* cx, unsigned argc, js::Value* vp);
191 
192 extern bool
193 array_unshift(JSContext* cx, unsigned argc, js::Value* vp);
194 
195 extern bool
196 array_slice(JSContext* cx, unsigned argc, js::Value* vp);
197 
198 extern JSObject*
199 array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end, HandleObject result);
200 
201 /*
202  * Append the given (non-hole) value to the end of an array.  The array must be
203  * a newborn array -- that is, one which has not been exposed to script for
204  * arbitrary manipulation.  (This method optimizes on the assumption that
205  * extending the array to accommodate the element will never make the array
206  * sparse, which requires that the array be completely filled.)
207  */
208 extern bool
209 NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v);
210 
211 extern JSObject*
212 ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt);
213 
214 #ifdef DEBUG
215 extern bool
216 ArrayInfo(JSContext* cx, unsigned argc, Value* vp);
217 #endif
218 
219 /* Array constructor native. Exposed only so the JIT can know its address. */
220 extern bool
221 ArrayConstructor(JSContext* cx, unsigned argc, Value* vp);
222 
223 } /* namespace js */
224 
225 #endif /* jsarray_h */
226