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 /* JavaScript API. */
8
9 #ifndef jsapi_h
10 #define jsapi_h
11
12 #include "mozilla/AlreadyAddRefed.h"
13 #include "mozilla/FloatingPoint.h"
14 #include "mozilla/MemoryReporting.h"
15 #include "mozilla/Range.h"
16 #include "mozilla/RangedPtr.h"
17 #include "mozilla/RefPtr.h"
18
19 #include <stdarg.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <stdio.h>
23
24 #include "jsalloc.h"
25 #include "jspubtd.h"
26
27 #include "js/CallArgs.h"
28 #include "js/Class.h"
29 #include "js/HashTable.h"
30 #include "js/Id.h"
31 #include "js/Principals.h"
32 #include "js/RootingAPI.h"
33 #include "js/TraceableVector.h"
34 #include "js/TracingAPI.h"
35 #include "js/Utility.h"
36 #include "js/Value.h"
37 #include "js/Vector.h"
38
39 /************************************************************************/
40
41 namespace JS {
42
43 class TwoByteChars;
44
45 #ifdef JS_DEBUG
46
JS_PUBLIC_API(AutoCheckRequestDepth)47 class JS_PUBLIC_API(AutoCheckRequestDepth)
48 {
49 JSContext* cx;
50 public:
51 explicit AutoCheckRequestDepth(JSContext* cx);
52 explicit AutoCheckRequestDepth(js::ContextFriendFields* cx);
53 ~AutoCheckRequestDepth();
54 };
55
56 # define CHECK_REQUEST(cx) \
57 JS::AutoCheckRequestDepth _autoCheckRequestDepth(cx)
58
59 #else
60
61 # define CHECK_REQUEST(cx) \
62 ((void) 0)
63
64 #endif /* JS_DEBUG */
65
66 /** AutoValueArray roots an internal fixed-size array of Values. */
67 template <size_t N>
68 class MOZ_RAII AutoValueArray : public AutoGCRooter
69 {
70 const size_t length_;
71 Value elements_[N];
72
73 public:
AutoValueArray(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)74 explicit AutoValueArray(JSContext* cx
75 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
76 : AutoGCRooter(cx, VALARRAY), length_(N)
77 {
78 /* Always initialize in case we GC before assignment. */
79 mozilla::PodArrayZero(elements_);
80 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
81 }
82
length()83 unsigned length() const { return length_; }
begin()84 const Value* begin() const { return elements_; }
begin()85 Value* begin() { return elements_; }
86
87 HandleValue operator[](unsigned i) const {
88 MOZ_ASSERT(i < N);
89 return HandleValue::fromMarkedLocation(&elements_[i]);
90 }
91 MutableHandleValue operator[](unsigned i) {
92 MOZ_ASSERT(i < N);
93 return MutableHandleValue::fromMarkedLocation(&elements_[i]);
94 }
95
96 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
97 };
98
99 template<class T>
100 class MOZ_RAII AutoVectorRooterBase : protected AutoGCRooter
101 {
102 typedef js::Vector<T, 8> VectorImpl;
103 VectorImpl vector;
104
105 public:
AutoVectorRooterBase(JSContext * cx,ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM)106 explicit AutoVectorRooterBase(JSContext* cx, ptrdiff_t tag
107 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
108 : AutoGCRooter(cx, tag), vector(cx)
109 {
110 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
111 }
112
AutoVectorRooterBase(js::ContextFriendFields * cx,ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM)113 explicit AutoVectorRooterBase(js::ContextFriendFields* cx, ptrdiff_t tag
114 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
115 : AutoGCRooter(cx, tag), vector(cx)
116 {
117 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
118 }
119
120 typedef T ElementType;
121 typedef typename VectorImpl::Range Range;
122
length()123 size_t length() const { return vector.length(); }
empty()124 bool empty() const { return vector.empty(); }
125
append(const T & v)126 bool append(const T& v) { return vector.append(v); }
appendN(const T & v,size_t len)127 bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
append(const T * ptr,size_t len)128 bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
appendAll(const AutoVectorRooterBase<T> & other)129 bool appendAll(const AutoVectorRooterBase<T>& other) {
130 return vector.appendAll(other.vector);
131 }
132
insert(T * p,const T & val)133 bool insert(T* p, const T& val) { return vector.insert(p, val); }
134
135 /* For use when space has already been reserved. */
infallibleAppend(const T & v)136 void infallibleAppend(const T& v) { vector.infallibleAppend(v); }
137
popBack()138 void popBack() { vector.popBack(); }
popCopy()139 T popCopy() { return vector.popCopy(); }
140
growBy(size_t inc)141 bool growBy(size_t inc) {
142 size_t oldLength = vector.length();
143 if (!vector.growByUninitialized(inc))
144 return false;
145 makeRangeGCSafe(oldLength);
146 return true;
147 }
148
resize(size_t newLength)149 bool resize(size_t newLength) {
150 size_t oldLength = vector.length();
151 if (newLength <= oldLength) {
152 vector.shrinkBy(oldLength - newLength);
153 return true;
154 }
155 if (!vector.growByUninitialized(newLength - oldLength))
156 return false;
157 makeRangeGCSafe(oldLength);
158 return true;
159 }
160
clear()161 void clear() { vector.clear(); }
162
reserve(size_t newLength)163 bool reserve(size_t newLength) {
164 return vector.reserve(newLength);
165 }
166
167 JS::MutableHandle<T> operator[](size_t i) {
168 return JS::MutableHandle<T>::fromMarkedLocation(&vector[i]);
169 }
170 JS::Handle<T> operator[](size_t i) const {
171 return JS::Handle<T>::fromMarkedLocation(&vector[i]);
172 }
173
begin()174 const T* begin() const { return vector.begin(); }
begin()175 T* begin() { return vector.begin(); }
176
end()177 const T* end() const { return vector.end(); }
end()178 T* end() { return vector.end(); }
179
all()180 Range all() { return vector.all(); }
181
back()182 const T& back() const { return vector.back(); }
183
184 friend void AutoGCRooter::trace(JSTracer* trc);
185
186 private:
makeRangeGCSafe(size_t oldLength)187 void makeRangeGCSafe(size_t oldLength) {
188 T* t = vector.begin() + oldLength;
189 for (size_t i = oldLength; i < vector.length(); ++i, ++t)
190 memset(t, 0, sizeof(T));
191 }
192
193 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
194 };
195
196 template <typename T>
197 class MOZ_RAII AutoVectorRooter : public AutoVectorRooterBase<T>
198 {
199 public:
AutoVectorRooter(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)200 explicit AutoVectorRooter(JSContext* cx
201 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
202 : AutoVectorRooterBase<T>(cx, this->GetTag(T()))
203 {
204 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
205 }
206
AutoVectorRooter(js::ContextFriendFields * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)207 explicit AutoVectorRooter(js::ContextFriendFields* cx
208 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
209 : AutoVectorRooterBase<T>(cx, this->GetTag(T()))
210 {
211 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
212 }
213
214 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
215 };
216
217 typedef AutoVectorRooter<Value> AutoValueVector;
218 typedef AutoVectorRooter<jsid> AutoIdVector;
219 typedef AutoVectorRooter<JSObject*> AutoObjectVector;
220
221 using ValueVector = js::TraceableVector<JS::Value>;
222 using IdVector = js::TraceableVector<jsid>;
223 using ScriptVector = js::TraceableVector<JSScript*>;
224
225 template<class Key, class Value>
226 class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter
227 {
228 private:
229 typedef js::HashMap<Key, Value> HashMapImpl;
230
231 public:
AutoHashMapRooter(JSContext * cx,ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM)232 explicit AutoHashMapRooter(JSContext* cx, ptrdiff_t tag
233 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
234 : AutoGCRooter(cx, tag), map(cx)
235 {
236 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
237 }
238
239 typedef Key KeyType;
240 typedef Value ValueType;
241 typedef typename HashMapImpl::Entry Entry;
242 typedef typename HashMapImpl::Lookup Lookup;
243 typedef typename HashMapImpl::Ptr Ptr;
244 typedef typename HashMapImpl::AddPtr AddPtr;
245
246 bool init(uint32_t len = 16) {
247 return map.init(len);
248 }
initialized()249 bool initialized() const {
250 return map.initialized();
251 }
lookup(const Lookup & l)252 Ptr lookup(const Lookup& l) const {
253 return map.lookup(l);
254 }
remove(Ptr p)255 void remove(Ptr p) {
256 map.remove(p);
257 }
lookupForAdd(const Lookup & l)258 AddPtr lookupForAdd(const Lookup& l) const {
259 return map.lookupForAdd(l);
260 }
261
262 template<typename KeyInput, typename ValueInput>
add(AddPtr & p,const KeyInput & k,const ValueInput & v)263 bool add(AddPtr& p, const KeyInput& k, const ValueInput& v) {
264 return map.add(p, k, v);
265 }
266
add(AddPtr & p,const Key & k)267 bool add(AddPtr& p, const Key& k) {
268 return map.add(p, k);
269 }
270
271 template<typename KeyInput, typename ValueInput>
relookupOrAdd(AddPtr & p,const KeyInput & k,const ValueInput & v)272 bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) {
273 return map.relookupOrAdd(p, k, v);
274 }
275
276 typedef typename HashMapImpl::Range Range;
all()277 Range all() const {
278 return map.all();
279 }
280
281 typedef typename HashMapImpl::Enum Enum;
282
clear()283 void clear() {
284 map.clear();
285 }
286
finish()287 void finish() {
288 map.finish();
289 }
290
empty()291 bool empty() const {
292 return map.empty();
293 }
294
count()295 uint32_t count() const {
296 return map.count();
297 }
298
capacity()299 size_t capacity() const {
300 return map.capacity();
301 }
302
sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)303 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
304 return map.sizeOfExcludingThis(mallocSizeOf);
305 }
sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)306 size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
307 return map.sizeOfIncludingThis(mallocSizeOf);
308 }
309
310 /************************************************** Shorthand operations */
311
has(const Lookup & l)312 bool has(const Lookup& l) const {
313 return map.has(l);
314 }
315
316 template<typename KeyInput, typename ValueInput>
put(const KeyInput & k,const ValueInput & v)317 bool put(const KeyInput& k, const ValueInput& v) {
318 return map.put(k, v);
319 }
320
321 template<typename KeyInput, typename ValueInput>
putNew(const KeyInput & k,const ValueInput & v)322 bool putNew(const KeyInput& k, const ValueInput& v) {
323 return map.putNew(k, v);
324 }
325
lookupWithDefault(const Key & k,const Value & defaultValue)326 Ptr lookupWithDefault(const Key& k, const Value& defaultValue) {
327 return map.lookupWithDefault(k, defaultValue);
328 }
329
remove(const Lookup & l)330 void remove(const Lookup& l) {
331 map.remove(l);
332 }
333
334 friend void AutoGCRooter::trace(JSTracer* trc);
335
336 private:
337 AutoHashMapRooter(const AutoHashMapRooter& hmr) = delete;
338 AutoHashMapRooter& operator=(const AutoHashMapRooter& hmr) = delete;
339
340 HashMapImpl map;
341
342 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
343 };
344
345 template<class T>
346 class MOZ_RAII AutoHashSetRooter : protected AutoGCRooter
347 {
348 private:
349 typedef js::HashSet<T> HashSetImpl;
350
351 public:
AutoHashSetRooter(JSContext * cx,ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM)352 explicit AutoHashSetRooter(JSContext* cx, ptrdiff_t tag
353 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
354 : AutoGCRooter(cx, tag), set(cx)
355 {
356 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
357 }
358
359 typedef typename HashSetImpl::Lookup Lookup;
360 typedef typename HashSetImpl::Ptr Ptr;
361 typedef typename HashSetImpl::AddPtr AddPtr;
362
363 bool init(uint32_t len = 16) {
364 return set.init(len);
365 }
initialized()366 bool initialized() const {
367 return set.initialized();
368 }
lookup(const Lookup & l)369 Ptr lookup(const Lookup& l) const {
370 return set.lookup(l);
371 }
remove(Ptr p)372 void remove(Ptr p) {
373 set.remove(p);
374 }
lookupForAdd(const Lookup & l)375 AddPtr lookupForAdd(const Lookup& l) const {
376 return set.lookupForAdd(l);
377 }
378
add(AddPtr & p,const T & t)379 bool add(AddPtr& p, const T& t) {
380 return set.add(p, t);
381 }
382
relookupOrAdd(AddPtr & p,const Lookup & l,const T & t)383 bool relookupOrAdd(AddPtr& p, const Lookup& l, const T& t) {
384 return set.relookupOrAdd(p, l, t);
385 }
386
387 typedef typename HashSetImpl::Range Range;
all()388 Range all() const {
389 return set.all();
390 }
391
392 typedef typename HashSetImpl::Enum Enum;
393
clear()394 void clear() {
395 set.clear();
396 }
397
finish()398 void finish() {
399 set.finish();
400 }
401
empty()402 bool empty() const {
403 return set.empty();
404 }
405
count()406 uint32_t count() const {
407 return set.count();
408 }
409
capacity()410 size_t capacity() const {
411 return set.capacity();
412 }
413
sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)414 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
415 return set.sizeOfExcludingThis(mallocSizeOf);
416 }
sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)417 size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
418 return set.sizeOfIncludingThis(mallocSizeOf);
419 }
420
421 /************************************************** Shorthand operations */
422
has(const Lookup & l)423 bool has(const Lookup& l) const {
424 return set.has(l);
425 }
426
put(const T & t)427 bool put(const T& t) {
428 return set.put(t);
429 }
430
putNew(const T & t)431 bool putNew(const T& t) {
432 return set.putNew(t);
433 }
434
remove(const Lookup & l)435 void remove(const Lookup& l) {
436 set.remove(l);
437 }
438
439 friend void AutoGCRooter::trace(JSTracer* trc);
440
441 private:
442 AutoHashSetRooter(const AutoHashSetRooter& hmr) = delete;
443 AutoHashSetRooter& operator=(const AutoHashSetRooter& hmr) = delete;
444
445 HashSetImpl set;
446
447 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
448 };
449
450 /**
451 * Custom rooting behavior for internal and external clients.
452 */
JS_PUBLIC_API(CustomAutoRooter)453 class MOZ_RAII JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
454 {
455 public:
456 template <typename CX>
457 explicit CustomAutoRooter(CX* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
458 : AutoGCRooter(cx, CUSTOM)
459 {
460 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
461 }
462
463 friend void AutoGCRooter::trace(JSTracer* trc);
464
465 protected:
466 /** Supplied by derived class to trace roots. */
467 virtual void trace(JSTracer* trc) = 0;
468
469 private:
470 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
471 };
472
473 /** A handle to an array of rooted values. */
474 class HandleValueArray
475 {
476 const size_t length_;
477 const Value * const elements_;
478
HandleValueArray(size_t len,const Value * elements)479 HandleValueArray(size_t len, const Value* elements) : length_(len), elements_(elements) {}
480
481 public:
HandleValueArray(const RootedValue & value)482 explicit HandleValueArray(const RootedValue& value) : length_(1), elements_(value.address()) {}
483
HandleValueArray(const AutoValueVector & values)484 MOZ_IMPLICIT HandleValueArray(const AutoValueVector& values)
485 : length_(values.length()), elements_(values.begin()) {}
486
487 template <size_t N>
HandleValueArray(const AutoValueArray<N> & values)488 MOZ_IMPLICIT HandleValueArray(const AutoValueArray<N>& values) : length_(N), elements_(values.begin()) {}
489
490 /** CallArgs must already be rooted somewhere up the stack. */
HandleValueArray(const JS::CallArgs & args)491 MOZ_IMPLICIT HandleValueArray(const JS::CallArgs& args) : length_(args.length()), elements_(args.array()) {}
492
493 /** Use with care! Only call this if the data is guaranteed to be marked. */
fromMarkedLocation(size_t len,const Value * elements)494 static HandleValueArray fromMarkedLocation(size_t len, const Value* elements) {
495 return HandleValueArray(len, elements);
496 }
497
subarray(const HandleValueArray & values,size_t startIndex,size_t len)498 static HandleValueArray subarray(const HandleValueArray& values, size_t startIndex, size_t len) {
499 MOZ_ASSERT(startIndex + len <= values.length());
500 return HandleValueArray(len, values.begin() + startIndex);
501 }
502
empty()503 static HandleValueArray empty() {
504 return HandleValueArray(0, nullptr);
505 }
506
length()507 size_t length() const { return length_; }
begin()508 const Value* begin() const { return elements_; }
509
510 HandleValue operator[](size_t i) const {
511 MOZ_ASSERT(i < length_);
512 return HandleValue::fromMarkedLocation(&elements_[i]);
513 }
514 };
515
516 } /* namespace JS */
517
518 /************************************************************************/
519
520 struct JSFreeOp {
521 private:
522 JSRuntime* runtime_;
523
524 protected:
JSFreeOpJSFreeOp525 explicit JSFreeOp(JSRuntime* rt)
526 : runtime_(rt) { }
527
528 public:
runtimeJSFreeOp529 JSRuntime* runtime() const {
530 return runtime_;
531 }
532 };
533
534 /* Callbacks and their arguments. */
535
536 /************************************************************************/
537
538 typedef enum JSContextOp {
539 JSCONTEXT_NEW,
540 JSCONTEXT_DESTROY
541 } JSContextOp;
542
543 /**
544 * The possible values for contextOp when the runtime calls the callback are:
545 * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
546 * instance. The callback can initialize the instance as
547 * required. If the callback returns false, the instance
548 * will be destroyed and JS_NewContext returns null. In
549 * this case the callback is not called again.
550 * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
551 * callback may perform its own cleanup and must always
552 * return true.
553 * Any other value For future compatibility the callback must do nothing
554 * and return true in this case.
555 */
556 typedef bool
557 (* JSContextCallback)(JSContext* cx, unsigned contextOp, void* data);
558
559 typedef enum JSGCStatus {
560 JSGC_BEGIN,
561 JSGC_END
562 } JSGCStatus;
563
564 typedef void
565 (* JSGCCallback)(JSRuntime* rt, JSGCStatus status, void* data);
566
567 typedef enum JSFinalizeStatus {
568 /**
569 * Called when preparing to sweep a group of compartments, before anything
570 * has been swept. The collector will not yield to the mutator before
571 * calling the callback with JSFINALIZE_GROUP_END status.
572 */
573 JSFINALIZE_GROUP_START,
574
575 /**
576 * Called when preparing to sweep a group of compartments. Weak references
577 * to unmarked things have been removed and things that are not swept
578 * incrementally have been finalized at this point. The collector may yield
579 * to the mutator after this point.
580 */
581 JSFINALIZE_GROUP_END,
582
583 /**
584 * Called at the end of collection when everything has been swept.
585 */
586 JSFINALIZE_COLLECTION_END
587 } JSFinalizeStatus;
588
589 typedef void
590 (* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isCompartment, void* data);
591
592 typedef void
593 (* JSWeakPointerZoneGroupCallback)(JSRuntime* rt, void* data);
594
595 typedef void
596 (* JSWeakPointerCompartmentCallback)(JSRuntime* rt, JSCompartment* comp, void* data);
597
598 typedef bool
599 (* JSInterruptCallback)(JSContext* cx);
600
601 typedef void
602 (* JSErrorReporter)(JSContext* cx, const char* message, JSErrorReport* report);
603
604 /**
605 * Possible exception types. These types are part of a JSErrorFormatString
606 * structure. They define which error to throw in case of a runtime error.
607 * JSEXN_NONE marks an unthrowable error.
608 */
609 typedef enum JSExnType {
610 JSEXN_NONE = -1,
611 JSEXN_ERR,
612 JSEXN_INTERNALERR,
613 JSEXN_EVALERR,
614 JSEXN_RANGEERR,
615 JSEXN_REFERENCEERR,
616 JSEXN_SYNTAXERR,
617 JSEXN_TYPEERR,
618 JSEXN_URIERR,
619 JSEXN_LIMIT
620 } JSExnType;
621
622 typedef struct JSErrorFormatString {
623 /** The error format string in ASCII. */
624 const char* format;
625
626 /** The number of arguments to expand in the formatted error message. */
627 uint16_t argCount;
628
629 /** One of the JSExnType constants above. */
630 int16_t exnType;
631 } JSErrorFormatString;
632
633 typedef const JSErrorFormatString*
634 (* JSErrorCallback)(void* userRef, const unsigned errorNumber);
635
636 typedef bool
637 (* JSLocaleToUpperCase)(JSContext* cx, JS::HandleString src, JS::MutableHandleValue rval);
638
639 typedef bool
640 (* JSLocaleToLowerCase)(JSContext* cx, JS::HandleString src, JS::MutableHandleValue rval);
641
642 typedef bool
643 (* JSLocaleCompare)(JSContext* cx, JS::HandleString src1, JS::HandleString src2,
644 JS::MutableHandleValue rval);
645
646 typedef bool
647 (* JSLocaleToUnicode)(JSContext* cx, const char* src, JS::MutableHandleValue rval);
648
649 /**
650 * Callback used to ask the embedding for the cross compartment wrapper handler
651 * that implements the desired prolicy for this kind of object in the
652 * destination compartment. |obj| is the object to be wrapped. If |existing| is
653 * non-nullptr, it will point to an existing wrapper object that should be
654 * re-used if possible. |existing| is guaranteed to be a cross-compartment
655 * wrapper with a lazily-defined prototype and the correct global. It is
656 * guaranteed not to wrap a function.
657 */
658 typedef JSObject*
659 (* JSWrapObjectCallback)(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj);
660
661 /**
662 * Callback used by the wrap hook to ask the embedding to prepare an object
663 * for wrapping in a context. This might include unwrapping other wrappers
664 * or even finding a more suitable object for the new compartment.
665 */
666 typedef JSObject*
667 (* JSPreWrapCallback)(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj,
668 JS::HandleObject objectPassedToWrap);
669
670 struct JSWrapObjectCallbacks
671 {
672 JSWrapObjectCallback wrap;
673 JSPreWrapCallback preWrap;
674 };
675
676 typedef void
677 (* JSDestroyCompartmentCallback)(JSFreeOp* fop, JSCompartment* compartment);
678
679 typedef void
680 (* JSZoneCallback)(JS::Zone* zone);
681
682 typedef void
683 (* JSCompartmentNameCallback)(JSRuntime* rt, JSCompartment* compartment,
684 char* buf, size_t bufsize);
685
686 /************************************************************************/
687
688 static MOZ_ALWAYS_INLINE JS::Value
JS_NumberValue(double d)689 JS_NumberValue(double d)
690 {
691 int32_t i;
692 d = JS::CanonicalizeNaN(d);
693 if (mozilla::NumberIsInt32(d, &i))
694 return JS::Int32Value(i);
695 return JS::DoubleValue(d);
696 }
697
698 /************************************************************************/
699
700 JS_PUBLIC_API(bool)
701 JS_StringHasBeenPinned(JSContext* cx, JSString* str);
702
703 namespace JS {
704
705 /**
706 * Container class for passing in script source buffers to the JS engine. This
707 * not only groups the buffer and length values, it also provides a way to
708 * optionally pass ownership of the buffer to the JS engine without copying.
709 * Rules for use:
710 *
711 * 1) The data array must be allocated with js_malloc() or js_realloc() if
712 * ownership is being granted to the SourceBufferHolder.
713 * 2) If ownership is not given to the SourceBufferHolder, then the memory
714 * must be kept alive until the JS compilation is complete.
715 * 3) Any code calling SourceBufferHolder::take() must guarantee to keep the
716 * memory alive until JS compilation completes. Normally only the JS
717 * engine should be calling take().
718 *
719 * Example use:
720 *
721 * size_t length = 512;
722 * char16_t* chars = static_cast<char16_t*>(js_malloc(sizeof(char16_t) * length));
723 * JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
724 * JS::Compile(cx, options, srcBuf);
725 */
726 class MOZ_STACK_CLASS SourceBufferHolder final
727 {
728 public:
729 enum Ownership {
730 NoOwnership,
731 GiveOwnership
732 };
733
SourceBufferHolder(const char16_t * data,size_t dataLength,Ownership ownership)734 SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership)
735 : data_(data),
736 length_(dataLength),
737 ownsChars_(ownership == GiveOwnership)
738 {
739 // Ensure that null buffers properly return an unowned, empty,
740 // null-terminated string.
741 static const char16_t NullChar_ = 0;
742 if (!get()) {
743 data_ = &NullChar_;
744 length_ = 0;
745 ownsChars_ = false;
746 }
747 }
748
~SourceBufferHolder()749 ~SourceBufferHolder() {
750 if (ownsChars_)
751 js_free(const_cast<char16_t*>(data_));
752 }
753
754 // Access the underlying source buffer without affecting ownership.
get()755 const char16_t* get() const { return data_; }
756
757 // Length of the source buffer in char16_t code units (not bytes)
length()758 size_t length() const { return length_; }
759
760 // Returns true if the SourceBufferHolder owns the buffer and will free
761 // it upon destruction. If true, it is legal to call take().
ownsChars()762 bool ownsChars() const { return ownsChars_; }
763
764 // Retrieve and take ownership of the underlying data buffer. The caller
765 // is now responsible for calling js_free() on the returned value, *but only
766 // after JS script compilation has completed*.
767 //
768 // After the buffer has been taken the SourceBufferHolder functions as if
769 // it had been constructed on an unowned buffer; get() and length() still
770 // work. In order for this to be safe the taken buffer must be kept alive
771 // until after JS script compilation completes as noted above.
772 //
773 // Note, it's the caller's responsibility to check ownsChars() before taking
774 // the buffer. Taking and then free'ing an unowned buffer will have dire
775 // consequences.
take()776 char16_t* take() {
777 MOZ_ASSERT(ownsChars_);
778 ownsChars_ = false;
779 return const_cast<char16_t*>(data_);
780 }
781
782 private:
783 SourceBufferHolder(SourceBufferHolder&) = delete;
784 SourceBufferHolder& operator=(SourceBufferHolder&) = delete;
785
786 const char16_t* data_;
787 size_t length_;
788 bool ownsChars_;
789 };
790
791 } /* namespace JS */
792
793 /************************************************************************/
794
795 /* Property attributes, set in JSPropertySpec and passed to API functions.
796 *
797 * NB: The data structure in which some of these values are stored only uses
798 * a uint8_t to store the relevant information. Proceed with caution if
799 * trying to reorder or change the the first byte worth of flags.
800 */
801 #define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */
802 #define JSPROP_READONLY 0x02 /* not settable: assignment is no-op.
803 This flag is only valid when neither
804 JSPROP_GETTER nor JSPROP_SETTER is
805 set. */
806 #define JSPROP_PERMANENT 0x04 /* property cannot be deleted */
807 #define JSPROP_PROPOP_ACCESSORS 0x08 /* Passed to JS_Define(UC)Property* and
808 JS_DefineElement if getters/setters
809 are JSGetterOp/JSSetterOp */
810 #define JSPROP_GETTER 0x10 /* property holds getter function */
811 #define JSPROP_SETTER 0x20 /* property holds setter function */
812 #define JSPROP_SHARED 0x40 /* don't allocate a value slot for this
813 property; don't copy the property on
814 set of the same-named property in an
815 object that delegates to a prototype
816 containing this property */
817 #define JSPROP_INTERNAL_USE_BIT 0x80 /* internal JS engine use only */
818 #define JSPROP_DEFINE_LATE 0x100 /* Don't define property when initially creating
819 the constructor. Some objects like Function/Object
820 have self-hosted functions that can only be defined
821 after the initialization is already finished. */
822 #define JSFUN_STUB_GSOPS 0x200 /* use JS_PropertyStub getter/setter
823 instead of defaulting to class gsops
824 for property holding function */
825
826 #define JSFUN_CONSTRUCTOR 0x400 /* native that can be called as a ctor */
827
828 /*
829 * Specify a generic native prototype methods, i.e., methods of a class
830 * prototype that are exposed as static methods taking an extra leading
831 * argument: the generic |this| parameter.
832 *
833 * If you set this flag in a JSFunctionSpec struct's flags initializer, then
834 * that struct must live at least as long as the native static method object
835 * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically
836 * JSFunctionSpec structs are allocated in static arrays.
837 */
838 #define JSFUN_GENERIC_NATIVE 0x800
839
840 #define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */
841
842 /*
843 * If set, will allow redefining a non-configurable property, but only on a
844 * non-DOM global. This is a temporary hack that will need to go away in bug
845 * 1105518.
846 */
847 #define JSPROP_REDEFINE_NONCONFIGURABLE 0x1000
848
849 /*
850 * Resolve hooks and enumerate hooks must pass this flag when calling
851 * JS_Define* APIs to reify lazily-defined properties.
852 *
853 * JSPROP_RESOLVING is used only with property-defining APIs. It tells the
854 * engine to skip the resolve hook when performing the lookup at the beginning
855 * of property definition. This keeps the resolve hook from accidentally
856 * triggering itself: unchecked recursion.
857 *
858 * For enumerate hooks, triggering the resolve hook would be merely silly, not
859 * fatal, except in some cases involving non-configurable properties.
860 */
861 #define JSPROP_RESOLVING 0x2000
862
863 #define JSPROP_IGNORE_ENUMERATE 0x4000 /* ignore the value in JSPROP_ENUMERATE.
864 This flag only valid when defining over
865 an existing property. */
866 #define JSPROP_IGNORE_READONLY 0x8000 /* ignore the value in JSPROP_READONLY.
867 This flag only valid when defining over
868 an existing property. */
869 #define JSPROP_IGNORE_PERMANENT 0x10000 /* ignore the value in JSPROP_PERMANENT.
870 This flag only valid when defining over
871 an existing property. */
872 #define JSPROP_IGNORE_VALUE 0x20000 /* ignore the Value in the descriptor. Nothing was
873 specified when passed to Object.defineProperty
874 from script. */
875
876 /**
877 * The first call to JS_CallOnce by any thread in a process will call 'func'.
878 * Later calls to JS_CallOnce with the same JSCallOnceType object will be
879 * suppressed.
880 *
881 * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce
882 * to invoke its JSInitCallback.
883 */
884 extern JS_PUBLIC_API(bool)
885 JS_CallOnce(JSCallOnceType* once, JSInitCallback func);
886
887 /** Microseconds since the epoch, midnight, January 1, 1970 UTC. */
888 extern JS_PUBLIC_API(int64_t)
889 JS_Now(void);
890
891 /** Don't want to export data, so provide accessors for non-inline Values. */
892 extern JS_PUBLIC_API(JS::Value)
893 JS_GetNaNValue(JSContext* cx);
894
895 extern JS_PUBLIC_API(JS::Value)
896 JS_GetNegativeInfinityValue(JSContext* cx);
897
898 extern JS_PUBLIC_API(JS::Value)
899 JS_GetPositiveInfinityValue(JSContext* cx);
900
901 extern JS_PUBLIC_API(JS::Value)
902 JS_GetEmptyStringValue(JSContext* cx);
903
904 extern JS_PUBLIC_API(JSString*)
905 JS_GetEmptyString(JSRuntime* rt);
906
907 extern JS_PUBLIC_API(bool)
908 JS_ValueToObject(JSContext* cx, JS::HandleValue v, JS::MutableHandleObject objp);
909
910 extern JS_PUBLIC_API(JSFunction*)
911 JS_ValueToFunction(JSContext* cx, JS::HandleValue v);
912
913 extern JS_PUBLIC_API(JSFunction*)
914 JS_ValueToConstructor(JSContext* cx, JS::HandleValue v);
915
916 extern JS_PUBLIC_API(JSString*)
917 JS_ValueToSource(JSContext* cx, JS::Handle<JS::Value> v);
918
919 extern JS_PUBLIC_API(bool)
920 JS_DoubleIsInt32(double d, int32_t* ip);
921
922 extern JS_PUBLIC_API(JSType)
923 JS_TypeOfValue(JSContext* cx, JS::Handle<JS::Value> v);
924
925 extern JS_PUBLIC_API(bool)
926 JS_StrictlyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal);
927
928 extern JS_PUBLIC_API(bool)
929 JS_LooselyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal);
930
931 extern JS_PUBLIC_API(bool)
932 JS_SameValue(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* same);
933
934 /** True iff fun is the global eval function. */
935 extern JS_PUBLIC_API(bool)
936 JS_IsBuiltinEvalFunction(JSFunction* fun);
937
938 /** True iff fun is the Function constructor. */
939 extern JS_PUBLIC_API(bool)
940 JS_IsBuiltinFunctionConstructor(JSFunction* fun);
941
942 /************************************************************************/
943
944 /*
945 * Locking, contexts, and memory allocation.
946 *
947 * It is important that SpiderMonkey be initialized, and the first runtime and
948 * first context be created, in a single-threaded fashion. Otherwise the
949 * behavior of the library is undefined.
950 * See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
951 */
952
953 extern JS_PUBLIC_API(JSRuntime*)
954 JS_NewRuntime(uint32_t maxbytes,
955 uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
956 JSRuntime* parentRuntime = nullptr);
957
958 extern JS_PUBLIC_API(void)
959 JS_DestroyRuntime(JSRuntime* rt);
960
961 typedef double (*JS_CurrentEmbedderTimeFunction)();
962
963 /**
964 * The embedding can specify a time function that will be used in some
965 * situations. The function can return the time however it likes; but
966 * the norm is to return times in units of milliseconds since an
967 * arbitrary, but consistent, epoch. If the time function is not set,
968 * a built-in default will be used.
969 */
970 JS_PUBLIC_API(void)
971 JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn);
972
973 /**
974 * Return the time as computed using the current time function, or a
975 * suitable default if one has not been set.
976 */
977 JS_PUBLIC_API(double)
978 JS_GetCurrentEmbedderTime();
979
980 JS_PUBLIC_API(void*)
981 JS_GetRuntimePrivate(JSRuntime* rt);
982
983 extern JS_PUBLIC_API(JSRuntime*)
984 JS_GetRuntime(JSContext* cx);
985
986 extern JS_PUBLIC_API(JSRuntime*)
987 JS_GetParentRuntime(JSContext* cx);
988
989 JS_PUBLIC_API(void)
990 JS_SetRuntimePrivate(JSRuntime* rt, void* data);
991
992 extern JS_PUBLIC_API(void)
993 JS_BeginRequest(JSContext* cx);
994
995 extern JS_PUBLIC_API(void)
996 JS_EndRequest(JSContext* cx);
997
998 namespace js {
999
1000 void
1001 AssertHeapIsIdle(JSRuntime* rt);
1002
1003 void
1004 AssertHeapIsIdle(JSContext* cx);
1005
1006 } /* namespace js */
1007
1008 class MOZ_RAII JSAutoRequest
1009 {
1010 public:
JSAutoRequest(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)1011 explicit JSAutoRequest(JSContext* cx
1012 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
1013 : mContext(cx)
1014 {
1015 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
1016 JS_BeginRequest(mContext);
1017 }
~JSAutoRequest()1018 ~JSAutoRequest() {
1019 JS_EndRequest(mContext);
1020 }
1021
1022 protected:
1023 JSContext* mContext;
1024 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1025
1026 #if 0
1027 private:
1028 static void* operator new(size_t) CPP_THROW_NEW { return 0; }
1029 static void operator delete(void*, size_t) { }
1030 #endif
1031 };
1032
1033 extern JS_PUBLIC_API(void)
1034 JS_SetContextCallback(JSRuntime* rt, JSContextCallback cxCallback, void* data);
1035
1036 extern JS_PUBLIC_API(JSContext*)
1037 JS_NewContext(JSRuntime* rt, size_t stackChunkSize);
1038
1039 extern JS_PUBLIC_API(void)
1040 JS_DestroyContext(JSContext* cx);
1041
1042 extern JS_PUBLIC_API(void)
1043 JS_DestroyContextNoGC(JSContext* cx);
1044
1045 extern JS_PUBLIC_API(void*)
1046 JS_GetContextPrivate(JSContext* cx);
1047
1048 extern JS_PUBLIC_API(void)
1049 JS_SetContextPrivate(JSContext* cx, void* data);
1050
1051 extern JS_PUBLIC_API(void*)
1052 JS_GetSecondContextPrivate(JSContext* cx);
1053
1054 extern JS_PUBLIC_API(void)
1055 JS_SetSecondContextPrivate(JSContext* cx, void* data);
1056
1057 extern JS_PUBLIC_API(JSRuntime*)
1058 JS_GetRuntime(JSContext* cx);
1059
1060 extern JS_PUBLIC_API(JSContext*)
1061 JS_ContextIterator(JSRuntime* rt, JSContext** iterp);
1062
1063 extern JS_PUBLIC_API(JSVersion)
1064 JS_GetVersion(JSContext* cx);
1065
1066 /**
1067 * Mutate the version on the compartment. This is generally discouraged, but
1068 * necessary to support the version mutation in the js and xpc shell command
1069 * set.
1070 *
1071 * It would be nice to put this in jsfriendapi, but the linkage requirements
1072 * of the shells make that impossible.
1073 */
1074 JS_PUBLIC_API(void)
1075 JS_SetVersionForCompartment(JSCompartment* compartment, JSVersion version);
1076
1077 extern JS_PUBLIC_API(const char*)
1078 JS_VersionToString(JSVersion version);
1079
1080 extern JS_PUBLIC_API(JSVersion)
1081 JS_StringToVersion(const char* string);
1082
1083 namespace JS {
1084
JS_PUBLIC_API(RuntimeOptions)1085 class JS_PUBLIC_API(RuntimeOptions) {
1086 public:
1087 RuntimeOptions()
1088 : baseline_(true),
1089 ion_(true),
1090 asmJS_(true),
1091 throwOnAsmJSValidationFailure_(false),
1092 nativeRegExp_(true),
1093 unboxedArrays_(false),
1094 asyncStack_(true),
1095 werror_(false),
1096 strictMode_(false),
1097 extraWarnings_(false)
1098 {
1099 }
1100
1101 bool baseline() const { return baseline_; }
1102 RuntimeOptions& setBaseline(bool flag) {
1103 baseline_ = flag;
1104 return *this;
1105 }
1106 RuntimeOptions& toggleBaseline() {
1107 baseline_ = !baseline_;
1108 return *this;
1109 }
1110
1111 bool ion() const { return ion_; }
1112 RuntimeOptions& setIon(bool flag) {
1113 ion_ = flag;
1114 return *this;
1115 }
1116 RuntimeOptions& toggleIon() {
1117 ion_ = !ion_;
1118 return *this;
1119 }
1120
1121 bool asmJS() const { return asmJS_; }
1122 RuntimeOptions& setAsmJS(bool flag) {
1123 asmJS_ = flag;
1124 return *this;
1125 }
1126 RuntimeOptions& toggleAsmJS() {
1127 asmJS_ = !asmJS_;
1128 return *this;
1129 }
1130
1131 bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
1132 RuntimeOptions& setThrowOnAsmJSValidationFailure(bool flag) {
1133 throwOnAsmJSValidationFailure_ = flag;
1134 return *this;
1135 }
1136 RuntimeOptions& toggleThrowOnAsmJSValidationFailure() {
1137 throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
1138 return *this;
1139 }
1140
1141 bool nativeRegExp() const { return nativeRegExp_; }
1142 RuntimeOptions& setNativeRegExp(bool flag) {
1143 nativeRegExp_ = flag;
1144 return *this;
1145 }
1146
1147 bool unboxedArrays() const { return unboxedArrays_; }
1148 RuntimeOptions& setUnboxedArrays(bool flag) {
1149 unboxedArrays_ = flag;
1150 return *this;
1151 }
1152
1153 bool asyncStack() const { return asyncStack_; }
1154 RuntimeOptions& setAsyncStack(bool flag) {
1155 asyncStack_ = flag;
1156 return *this;
1157 }
1158
1159 bool werror() const { return werror_; }
1160 RuntimeOptions& setWerror(bool flag) {
1161 werror_ = flag;
1162 return *this;
1163 }
1164 RuntimeOptions& toggleWerror() {
1165 werror_ = !werror_;
1166 return *this;
1167 }
1168
1169 bool strictMode() const { return strictMode_; }
1170 RuntimeOptions& setStrictMode(bool flag) {
1171 strictMode_ = flag;
1172 return *this;
1173 }
1174 RuntimeOptions& toggleStrictMode() {
1175 strictMode_ = !strictMode_;
1176 return *this;
1177 }
1178
1179 bool extraWarnings() const { return extraWarnings_; }
1180 RuntimeOptions& setExtraWarnings(bool flag) {
1181 extraWarnings_ = flag;
1182 return *this;
1183 }
1184 RuntimeOptions& toggleExtraWarnings() {
1185 extraWarnings_ = !extraWarnings_;
1186 return *this;
1187 }
1188
1189 private:
1190 bool baseline_ : 1;
1191 bool ion_ : 1;
1192 bool asmJS_ : 1;
1193 bool throwOnAsmJSValidationFailure_ : 1;
1194 bool nativeRegExp_ : 1;
1195 bool unboxedArrays_ : 1;
1196 bool asyncStack_ : 1;
1197 bool werror_ : 1;
1198 bool strictMode_ : 1;
1199 bool extraWarnings_ : 1;
1200 };
1201
1202 JS_PUBLIC_API(RuntimeOptions&)
1203 RuntimeOptionsRef(JSRuntime* rt);
1204
1205 JS_PUBLIC_API(RuntimeOptions&)
1206 RuntimeOptionsRef(JSContext* cx);
1207
JS_PUBLIC_API(ContextOptions)1208 class JS_PUBLIC_API(ContextOptions) {
1209 public:
1210 ContextOptions()
1211 : privateIsNSISupports_(false),
1212 dontReportUncaught_(false),
1213 autoJSAPIOwnsErrorReporting_(false)
1214 {
1215 }
1216
1217 bool privateIsNSISupports() const { return privateIsNSISupports_; }
1218 ContextOptions& setPrivateIsNSISupports(bool flag) {
1219 privateIsNSISupports_ = flag;
1220 return *this;
1221 }
1222 ContextOptions& togglePrivateIsNSISupports() {
1223 privateIsNSISupports_ = !privateIsNSISupports_;
1224 return *this;
1225 }
1226
1227 bool dontReportUncaught() const { return dontReportUncaught_; }
1228 ContextOptions& setDontReportUncaught(bool flag) {
1229 dontReportUncaught_ = flag;
1230 return *this;
1231 }
1232 ContextOptions& toggleDontReportUncaught() {
1233 dontReportUncaught_ = !dontReportUncaught_;
1234 return *this;
1235 }
1236
1237 bool autoJSAPIOwnsErrorReporting() const { return autoJSAPIOwnsErrorReporting_; }
1238 ContextOptions& setAutoJSAPIOwnsErrorReporting(bool flag) {
1239 autoJSAPIOwnsErrorReporting_ = flag;
1240 return *this;
1241 }
1242 ContextOptions& toggleAutoJSAPIOwnsErrorReporting() {
1243 autoJSAPIOwnsErrorReporting_ = !autoJSAPIOwnsErrorReporting_;
1244 return *this;
1245 }
1246
1247
1248 private:
1249 bool privateIsNSISupports_ : 1;
1250 bool dontReportUncaught_ : 1;
1251 // dontReportUncaught isn't respected by all JSAPI codepaths, particularly the
1252 // JS_ReportError* functions that eventually report the error even when dontReportUncaught is
1253 // set, if script is not running. We want a way to indicate that the embedder will always
1254 // handle any exceptions, and that SpiderMonkey should just leave them on the context. This is
1255 // the way we want to do all future error handling in Gecko - stealing the exception explicitly
1256 // from the context and handling it as per the situation. This will eventually become the
1257 // default and these 2 flags should go away.
1258 bool autoJSAPIOwnsErrorReporting_ : 1;
1259 };
1260
1261 JS_PUBLIC_API(ContextOptions&)
1262 ContextOptionsRef(JSContext* cx);
1263
JS_PUBLIC_API(AutoSaveContextOptions)1264 class JS_PUBLIC_API(AutoSaveContextOptions) {
1265 public:
1266 explicit AutoSaveContextOptions(JSContext* cx)
1267 : cx_(cx),
1268 oldOptions_(ContextOptionsRef(cx_))
1269 {
1270 }
1271
1272 ~AutoSaveContextOptions()
1273 {
1274 ContextOptionsRef(cx_) = oldOptions_;
1275 }
1276
1277 private:
1278 JSContext* cx_;
1279 JS::ContextOptions oldOptions_;
1280 };
1281
1282 } /* namespace JS */
1283
1284 extern JS_PUBLIC_API(const char*)
1285 JS_GetImplementationVersion(void);
1286
1287 extern JS_PUBLIC_API(void)
1288 JS_SetDestroyCompartmentCallback(JSRuntime* rt, JSDestroyCompartmentCallback callback);
1289
1290 extern JS_PUBLIC_API(void)
1291 JS_SetDestroyZoneCallback(JSRuntime* rt, JSZoneCallback callback);
1292
1293 extern JS_PUBLIC_API(void)
1294 JS_SetSweepZoneCallback(JSRuntime* rt, JSZoneCallback callback);
1295
1296 extern JS_PUBLIC_API(void)
1297 JS_SetCompartmentNameCallback(JSRuntime* rt, JSCompartmentNameCallback callback);
1298
1299 extern JS_PUBLIC_API(void)
1300 JS_SetWrapObjectCallbacks(JSRuntime* rt, const JSWrapObjectCallbacks* callbacks);
1301
1302 extern JS_PUBLIC_API(void)
1303 JS_SetCompartmentPrivate(JSCompartment* compartment, void* data);
1304
1305 extern JS_PUBLIC_API(void*)
1306 JS_GetCompartmentPrivate(JSCompartment* compartment);
1307
1308 extern JS_PUBLIC_API(void)
1309 JS_SetZoneUserData(JS::Zone* zone, void* data);
1310
1311 extern JS_PUBLIC_API(void*)
1312 JS_GetZoneUserData(JS::Zone* zone);
1313
1314 extern JS_PUBLIC_API(bool)
1315 JS_WrapObject(JSContext* cx, JS::MutableHandleObject objp);
1316
1317 extern JS_PUBLIC_API(bool)
1318 JS_WrapValue(JSContext* cx, JS::MutableHandleValue vp);
1319
1320 extern JS_PUBLIC_API(JSObject*)
1321 JS_TransplantObject(JSContext* cx, JS::HandleObject origobj, JS::HandleObject target);
1322
1323 extern JS_PUBLIC_API(bool)
1324 JS_RefreshCrossCompartmentWrappers(JSContext* cx, JS::Handle<JSObject*> obj);
1325
1326 /*
1327 * At any time, a JSContext has a current (possibly-nullptr) compartment.
1328 * Compartments are described in:
1329 *
1330 * developer.mozilla.org/en-US/docs/SpiderMonkey/SpiderMonkey_compartments
1331 *
1332 * The current compartment of a context may be changed. The preferred way to do
1333 * this is with JSAutoCompartment:
1334 *
1335 * void foo(JSContext* cx, JSObject* obj) {
1336 * // in some compartment 'c'
1337 * {
1338 * JSAutoCompartment ac(cx, obj); // constructor enters
1339 * // in the compartment of 'obj'
1340 * } // destructor leaves
1341 * // back in compartment 'c'
1342 * }
1343 *
1344 * For more complicated uses that don't neatly fit in a C++ stack frame, the
1345 * compartment can entered and left using separate function calls:
1346 *
1347 * void foo(JSContext* cx, JSObject* obj) {
1348 * // in 'oldCompartment'
1349 * JSCompartment* oldCompartment = JS_EnterCompartment(cx, obj);
1350 * // in the compartment of 'obj'
1351 * JS_LeaveCompartment(cx, oldCompartment);
1352 * // back in 'oldCompartment'
1353 * }
1354 *
1355 * Note: these calls must still execute in a LIFO manner w.r.t all other
1356 * enter/leave calls on the context. Furthermore, only the return value of a
1357 * JS_EnterCompartment call may be passed as the 'oldCompartment' argument of
1358 * the corresponding JS_LeaveCompartment call.
1359 */
1360
JS_PUBLIC_API(JSAutoCompartment)1361 class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment)
1362 {
1363 JSContext* cx_;
1364 JSCompartment* oldCompartment_;
1365 public:
1366 JSAutoCompartment(JSContext* cx, JSObject* target
1367 MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
1368 JSAutoCompartment(JSContext* cx, JSScript* target
1369 MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
1370 ~JSAutoCompartment();
1371
1372 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1373 };
1374
JS_PUBLIC_API(JSAutoNullableCompartment)1375 class MOZ_RAII JS_PUBLIC_API(JSAutoNullableCompartment)
1376 {
1377 JSContext* cx_;
1378 JSCompartment* oldCompartment_;
1379 public:
1380 explicit JSAutoNullableCompartment(JSContext* cx, JSObject* targetOrNull
1381 MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
1382 ~JSAutoNullableCompartment();
1383
1384 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
1385 };
1386
1387 /** NB: This API is infallible; a nullptr return value does not indicate error. */
1388 extern JS_PUBLIC_API(JSCompartment*)
1389 JS_EnterCompartment(JSContext* cx, JSObject* target);
1390
1391 extern JS_PUBLIC_API(void)
1392 JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment);
1393
1394 typedef void (*JSIterateCompartmentCallback)(JSRuntime* rt, void* data, JSCompartment* compartment);
1395
1396 /**
1397 * This function calls |compartmentCallback| on every compartment. Beware that
1398 * there is no guarantee that the compartment will survive after the callback
1399 * returns. Also, barriers are disabled via the TraceSession.
1400 */
1401 extern JS_PUBLIC_API(void)
1402 JS_IterateCompartments(JSRuntime* rt, void* data,
1403 JSIterateCompartmentCallback compartmentCallback);
1404
1405 /**
1406 * Initialize standard JS class constructors, prototypes, and any top-level
1407 * functions and constants associated with the standard classes (e.g. isNaN
1408 * for Number).
1409 *
1410 * NB: This sets cx's global object to obj if it was null.
1411 */
1412 extern JS_PUBLIC_API(bool)
1413 JS_InitStandardClasses(JSContext* cx, JS::Handle<JSObject*> obj);
1414
1415 /**
1416 * Resolve id, which must contain either a string or an int, to a standard
1417 * class name in obj if possible, defining the class's constructor and/or
1418 * prototype and storing true in *resolved. If id does not name a standard
1419 * class or a top-level property induced by initializing a standard class,
1420 * store false in *resolved and just return true. Return false on error,
1421 * as usual for bool result-typed API entry points.
1422 *
1423 * This API can be called directly from a global object class's resolve op,
1424 * to define standard classes lazily. The class's enumerate op should call
1425 * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
1426 * loops any classes not yet resolved lazily.
1427 */
1428 extern JS_PUBLIC_API(bool)
1429 JS_ResolveStandardClass(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolved);
1430
1431 extern JS_PUBLIC_API(bool)
1432 JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj);
1433
1434 extern JS_PUBLIC_API(bool)
1435 JS_EnumerateStandardClasses(JSContext* cx, JS::HandleObject obj);
1436
1437 extern JS_PUBLIC_API(bool)
1438 JS_GetClassObject(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp);
1439
1440 extern JS_PUBLIC_API(bool)
1441 JS_GetClassPrototype(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp);
1442
1443 namespace JS {
1444
1445 /*
1446 * Determine if the given object is an instance/prototype/constructor for a standard
1447 * class. If so, return the associated JSProtoKey. If not, return JSProto_Null.
1448 */
1449
1450 extern JS_PUBLIC_API(JSProtoKey)
1451 IdentifyStandardInstance(JSObject* obj);
1452
1453 extern JS_PUBLIC_API(JSProtoKey)
1454 IdentifyStandardPrototype(JSObject* obj);
1455
1456 extern JS_PUBLIC_API(JSProtoKey)
1457 IdentifyStandardInstanceOrPrototype(JSObject* obj);
1458
1459 extern JS_PUBLIC_API(JSProtoKey)
1460 IdentifyStandardConstructor(JSObject* obj);
1461
1462 extern JS_PUBLIC_API(void)
1463 ProtoKeyToId(JSContext* cx, JSProtoKey key, JS::MutableHandleId idp);
1464
1465 } /* namespace JS */
1466
1467 extern JS_PUBLIC_API(JSProtoKey)
1468 JS_IdToProtoKey(JSContext* cx, JS::HandleId id);
1469
1470 /**
1471 * Returns the original value of |Function.prototype| from the global object in
1472 * which |forObj| was created.
1473 */
1474 extern JS_PUBLIC_API(JSObject*)
1475 JS_GetFunctionPrototype(JSContext* cx, JS::HandleObject forObj);
1476
1477 /**
1478 * Returns the original value of |Object.prototype| from the global object in
1479 * which |forObj| was created.
1480 */
1481 extern JS_PUBLIC_API(JSObject*)
1482 JS_GetObjectPrototype(JSContext* cx, JS::HandleObject forObj);
1483
1484 /**
1485 * Returns the original value of |Array.prototype| from the global object in
1486 * which |forObj| was created.
1487 */
1488 extern JS_PUBLIC_API(JSObject*)
1489 JS_GetArrayPrototype(JSContext* cx, JS::HandleObject forObj);
1490
1491 /**
1492 * Returns the original value of |Error.prototype| from the global
1493 * object of the current compartment of cx.
1494 */
1495 extern JS_PUBLIC_API(JSObject*)
1496 JS_GetErrorPrototype(JSContext* cx);
1497
1498 /**
1499 * Returns the %IteratorPrototype% object that all built-in iterator prototype
1500 * chains go through for the global object of the current compartment of cx.
1501 */
1502 extern JS_PUBLIC_API(JSObject*)
1503 JS_GetIteratorPrototype(JSContext* cx);
1504
1505 extern JS_PUBLIC_API(JSObject*)
1506 JS_GetGlobalForObject(JSContext* cx, JSObject* obj);
1507
1508 extern JS_PUBLIC_API(bool)
1509 JS_IsGlobalObject(JSObject* obj);
1510
1511 extern JS_PUBLIC_API(JSObject*)
1512 JS_GlobalLexicalScope(JSObject* obj);
1513
1514 extern JS_PUBLIC_API(bool)
1515 JS_HasExtensibleLexicalScope(JSObject* obj);
1516
1517 extern JS_PUBLIC_API(JSObject*)
1518 JS_ExtensibleLexicalScope(JSObject* obj);
1519
1520 /**
1521 * May return nullptr, if |c| never had a global (e.g. the atoms compartment),
1522 * or if |c|'s global has been collected.
1523 */
1524 extern JS_PUBLIC_API(JSObject*)
1525 JS_GetGlobalForCompartmentOrNull(JSContext* cx, JSCompartment* c);
1526
1527 namespace JS {
1528
1529 extern JS_PUBLIC_API(JSObject*)
1530 CurrentGlobalOrNull(JSContext* cx);
1531
1532 } // namespace JS
1533
1534 /**
1535 * Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the
1536 * given global.
1537 */
1538 extern JS_PUBLIC_API(bool)
1539 JS_InitReflectParse(JSContext* cx, JS::HandleObject global);
1540
1541 /**
1542 * Add various profiling-related functions as properties of the given object.
1543 * Defined in builtin/Profilers.cpp.
1544 */
1545 extern JS_PUBLIC_API(bool)
1546 JS_DefineProfilingFunctions(JSContext* cx, JS::HandleObject obj);
1547
1548 /* Defined in vm/Debugger.cpp. */
1549 extern JS_PUBLIC_API(bool)
1550 JS_DefineDebuggerObject(JSContext* cx, JS::HandleObject obj);
1551
1552 #ifdef JS_HAS_CTYPES
1553 /**
1554 * Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
1555 * object will be sealed.
1556 */
1557 extern JS_PUBLIC_API(bool)
1558 JS_InitCTypesClass(JSContext* cx, JS::HandleObject global);
1559
1560 /**
1561 * Convert a unicode string 'source' of length 'slen' to the platform native
1562 * charset, returning a null-terminated string allocated with JS_malloc. On
1563 * failure, this function should report an error.
1564 */
1565 typedef char*
1566 (* JSCTypesUnicodeToNativeFun)(JSContext* cx, const char16_t* source, size_t slen);
1567
1568 /**
1569 * Set of function pointers that ctypes can use for various internal functions.
1570 * See JS_SetCTypesCallbacks below. Providing nullptr for a function is safe,
1571 * and will result in the applicable ctypes functionality not being available.
1572 */
1573 struct JSCTypesCallbacks {
1574 JSCTypesUnicodeToNativeFun unicodeToNative;
1575 };
1576
1577 typedef struct JSCTypesCallbacks JSCTypesCallbacks;
1578
1579 /**
1580 * Set the callbacks on the provided 'ctypesObj' object. 'callbacks' should be a
1581 * pointer to static data that exists for the lifetime of 'ctypesObj', but it
1582 * may safely be altered after calling this function and without having
1583 * to call this function again.
1584 */
1585 extern JS_PUBLIC_API(void)
1586 JS_SetCTypesCallbacks(JSObject* ctypesObj, const JSCTypesCallbacks* callbacks);
1587 #endif
1588
1589 extern JS_PUBLIC_API(void*)
1590 JS_malloc(JSContext* cx, size_t nbytes);
1591
1592 extern JS_PUBLIC_API(void*)
1593 JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes);
1594
1595 /**
1596 * A wrapper for js_free(p) that may delay js_free(p) invocation as a
1597 * performance optimization.
1598 * cx may be nullptr.
1599 */
1600 extern JS_PUBLIC_API(void)
1601 JS_free(JSContext* cx, void* p);
1602
1603 /**
1604 * A wrapper for js_free(p) that may delay js_free(p) invocation as a
1605 * performance optimization as specified by the given JSFreeOp instance.
1606 */
1607 extern JS_PUBLIC_API(void)
1608 JS_freeop(JSFreeOp* fop, void* p);
1609
1610 extern JS_PUBLIC_API(JSFreeOp*)
1611 JS_GetDefaultFreeOp(JSRuntime* rt);
1612
1613 extern JS_PUBLIC_API(void)
1614 JS_updateMallocCounter(JSContext* cx, size_t nbytes);
1615
1616 extern JS_PUBLIC_API(char*)
1617 JS_strdup(JSContext* cx, const char* s);
1618
1619 /** Duplicate a string. Does not report an error on failure. */
1620 extern JS_PUBLIC_API(char*)
1621 JS_strdup(JSRuntime* rt, const char* s);
1622
1623 /**
1624 * Register externally maintained GC roots.
1625 *
1626 * traceOp: the trace operation. For each root the implementation should call
1627 * JS_CallTracer whenever the root contains a traceable thing.
1628 * data: the data argument to pass to each invocation of traceOp.
1629 */
1630 extern JS_PUBLIC_API(bool)
1631 JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
1632
1633 /** Undo a call to JS_AddExtraGCRootsTracer. */
1634 extern JS_PUBLIC_API(void)
1635 JS_RemoveExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
1636
1637 /*
1638 * Garbage collector API.
1639 */
1640 extern JS_PUBLIC_API(void)
1641 JS_GC(JSRuntime* rt);
1642
1643 extern JS_PUBLIC_API(void)
1644 JS_MaybeGC(JSContext* cx);
1645
1646 extern JS_PUBLIC_API(void)
1647 JS_SetGCCallback(JSRuntime* rt, JSGCCallback cb, void* data);
1648
1649 extern JS_PUBLIC_API(bool)
1650 JS_AddFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb, void* data);
1651
1652 extern JS_PUBLIC_API(void)
1653 JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb);
1654
1655 /*
1656 * Weak pointers and garbage collection
1657 *
1658 * Weak pointers are by their nature not marked as part of garbage collection,
1659 * but they may need to be updated in two cases after a GC:
1660 *
1661 * 1) Their referent was found not to be live and is about to be finalized
1662 * 2) Their referent has been moved by a compacting GC
1663 *
1664 * To handle this, any part of the system that maintain weak pointers to
1665 * JavaScript GC things must register a callback with
1666 * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback
1667 * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows
1668 * about.
1669 *
1670 * Since sweeping is incremental, we have several callbacks to avoid repeatedly
1671 * having to visit all embedder structures. The WeakPointerZoneGroupCallback is
1672 * called once for each strongly connected group of zones, whereas the
1673 * WeakPointerCompartmentCallback is called once for each compartment that is
1674 * visited while sweeping. Structures that cannot contain references in more
1675 * than one compartment should sweep the relevant per-compartment structures
1676 * using the latter callback to minimizer per-slice overhead.
1677 *
1678 * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the
1679 * referent is about to be finalized the pointer will be set to null. If the
1680 * referent has been moved then the pointer will be updated to point to the new
1681 * location.
1682 *
1683 * Callers of this method are responsible for updating any state that is
1684 * dependent on the object's address. For example, if the object's address is
1685 * used as a key in a hashtable, then the object must be removed and
1686 * re-inserted with the correct hash.
1687 */
1688
1689 extern JS_PUBLIC_API(bool)
1690 JS_AddWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb, void* data);
1691
1692 extern JS_PUBLIC_API(void)
1693 JS_RemoveWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb);
1694
1695 extern JS_PUBLIC_API(bool)
1696 JS_AddWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb,
1697 void* data);
1698
1699 extern JS_PUBLIC_API(void)
1700 JS_RemoveWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb);
1701
1702 extern JS_PUBLIC_API(void)
1703 JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp);
1704
1705 extern JS_PUBLIC_API(void)
1706 JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp);
1707
1708 typedef enum JSGCParamKey {
1709 /** Maximum nominal heap before last ditch GC. */
1710 JSGC_MAX_BYTES = 0,
1711
1712 /** Number of JS_malloc bytes before last ditch GC. */
1713 JSGC_MAX_MALLOC_BYTES = 1,
1714
1715 /** Amount of bytes allocated by the GC. */
1716 JSGC_BYTES = 3,
1717
1718 /** Number of times GC has been invoked. Includes both major and minor GC. */
1719 JSGC_NUMBER = 4,
1720
1721 /** Max size of the code cache in bytes. */
1722 JSGC_MAX_CODE_CACHE_BYTES = 5,
1723
1724 /** Select GC mode. */
1725 JSGC_MODE = 6,
1726
1727 /** Number of cached empty GC chunks. */
1728 JSGC_UNUSED_CHUNKS = 7,
1729
1730 /** Total number of allocated GC chunks. */
1731 JSGC_TOTAL_CHUNKS = 8,
1732
1733 /** Max milliseconds to spend in an incremental GC slice. */
1734 JSGC_SLICE_TIME_BUDGET = 9,
1735
1736 /** Maximum size the GC mark stack can grow to. */
1737 JSGC_MARK_STACK_LIMIT = 10,
1738
1739 /**
1740 * GCs less than this far apart in time will be considered 'high-frequency GCs'.
1741 * See setGCLastBytes in jsgc.cpp.
1742 */
1743 JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
1744
1745 /** Start of dynamic heap growth. */
1746 JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12,
1747
1748 /** End of dynamic heap growth. */
1749 JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13,
1750
1751 /** Upper bound of heap growth. */
1752 JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14,
1753
1754 /** Lower bound of heap growth. */
1755 JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15,
1756
1757 /** Heap growth for low frequency GCs. */
1758 JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
1759
1760 /**
1761 * If false, the heap growth factor is fixed at 3. If true, it is determined
1762 * based on whether GCs are high- or low- frequency.
1763 */
1764 JSGC_DYNAMIC_HEAP_GROWTH = 17,
1765
1766 /** If true, high-frequency GCs will use a longer mark slice. */
1767 JSGC_DYNAMIC_MARK_SLICE = 18,
1768
1769 /** Lower limit after which we limit the heap growth. */
1770 JSGC_ALLOCATION_THRESHOLD = 19,
1771
1772 /**
1773 * We decommit memory lazily. If more than this number of megabytes is
1774 * available to be decommitted, then JS_MaybeGC will trigger a shrinking GC
1775 * to decommit it.
1776 */
1777 JSGC_DECOMMIT_THRESHOLD = 20,
1778
1779 /**
1780 * We try to keep at least this many unused chunks in the free chunk pool at
1781 * all times, even after a shrinking GC.
1782 */
1783 JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
1784
1785 /** We never keep more than this many unused chunks in the free chunk pool. */
1786 JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
1787
1788 /** Whether compacting GC is enabled. */
1789 JSGC_COMPACTING_ENABLED = 23
1790 } JSGCParamKey;
1791
1792 extern JS_PUBLIC_API(void)
1793 JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value);
1794
1795 extern JS_PUBLIC_API(uint32_t)
1796 JS_GetGCParameter(JSRuntime* rt, JSGCParamKey key);
1797
1798 extern JS_PUBLIC_API(void)
1799 JS_SetGCParameterForThread(JSContext* cx, JSGCParamKey key, uint32_t value);
1800
1801 extern JS_PUBLIC_API(uint32_t)
1802 JS_GetGCParameterForThread(JSContext* cx, JSGCParamKey key);
1803
1804 extern JS_PUBLIC_API(void)
1805 JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem);
1806
1807 /**
1808 * Create a new JSString whose chars member refers to external memory, i.e.,
1809 * memory requiring application-specific finalization.
1810 */
1811 extern JS_PUBLIC_API(JSString*)
1812 JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length,
1813 const JSStringFinalizer* fin);
1814
1815 /**
1816 * Return whether 'str' was created with JS_NewExternalString or
1817 * JS_NewExternalStringWithClosure.
1818 */
1819 extern JS_PUBLIC_API(bool)
1820 JS_IsExternalString(JSString* str);
1821
1822 /**
1823 * Return the 'fin' arg passed to JS_NewExternalString.
1824 */
1825 extern JS_PUBLIC_API(const JSStringFinalizer*)
1826 JS_GetExternalStringFinalizer(JSString* str);
1827
1828 /**
1829 * Set the size of the native stack that should not be exceed. To disable
1830 * stack size checking pass 0.
1831 *
1832 * SpiderMonkey allows for a distinction between system code (such as GCs, which
1833 * may incidentally be triggered by script but are not strictly performed on
1834 * behalf of such script), trusted script (as determined by JS_SetTrustedPrincipals),
1835 * and untrusted script. Each kind of code may have a different stack quota,
1836 * allowing embedders to keep higher-priority machinery running in the face of
1837 * scripted stack exhaustion by something else.
1838 *
1839 * The stack quotas for each kind of code should be monotonically descending,
1840 * and may be specified with this function. If 0 is passed for a given kind
1841 * of code, it defaults to the value of the next-highest-priority kind.
1842 *
1843 * This function may only be called immediately after the runtime is initialized
1844 * and before any code is executed and/or interrupts requested.
1845 */
1846 extern JS_PUBLIC_API(void)
1847 JS_SetNativeStackQuota(JSRuntime* cx, size_t systemCodeStackSize,
1848 size_t trustedScriptStackSize = 0,
1849 size_t untrustedScriptStackSize = 0);
1850
1851 /************************************************************************/
1852
1853 extern JS_PUBLIC_API(bool)
1854 JS_ValueToId(JSContext* cx, JS::HandleValue v, JS::MutableHandleId idp);
1855
1856 extern JS_PUBLIC_API(bool)
1857 JS_StringToId(JSContext* cx, JS::HandleString s, JS::MutableHandleId idp);
1858
1859 extern JS_PUBLIC_API(bool)
1860 JS_IdToValue(JSContext* cx, jsid id, JS::MutableHandle<JS::Value> vp);
1861
1862 namespace JS {
1863
1864 /**
1865 * Convert obj to a primitive value. On success, store the result in vp and
1866 * return true.
1867 *
1868 * The hint argument must be JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID (no
1869 * hint).
1870 *
1871 * Implements: ES6 7.1.1 ToPrimitive(input, [PreferredType]).
1872 */
1873 extern JS_PUBLIC_API(bool)
1874 ToPrimitive(JSContext* cx, JS::HandleObject obj, JSType hint, JS::MutableHandleValue vp);
1875
1876 /**
1877 * If args.get(0) is one of the strings "string", "number", or "default", set
1878 * *result to JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID accordingly and
1879 * return true. Otherwise, return false with a TypeError pending.
1880 *
1881 * This can be useful in implementing a @@toPrimitive method.
1882 */
1883 extern JS_PUBLIC_API(bool)
1884 GetFirstArgumentAsTypeHint(JSContext* cx, CallArgs args, JSType *result);
1885
1886 } /* namespace JS */
1887
1888 extern JS_PUBLIC_API(bool)
1889 JS_PropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
1890 JS::MutableHandleValue vp);
1891
1892 extern JS_PUBLIC_API(bool)
1893 JS_StrictPropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
1894 JS::MutableHandleValue vp, JS::ObjectOpResult& result);
1895
1896 template<typename T>
1897 struct JSConstScalarSpec {
1898 const char* name;
1899 T val;
1900 };
1901
1902 typedef JSConstScalarSpec<double> JSConstDoubleSpec;
1903 typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
1904
1905 struct JSJitInfo;
1906
1907 /**
1908 * Wrapper to relace JSNative for JSPropertySpecs and JSFunctionSpecs. This will
1909 * allow us to pass one JSJitInfo per function with the property/function spec,
1910 * without additional field overhead.
1911 */
1912 typedef struct JSNativeWrapper {
1913 JSNative op;
1914 const JSJitInfo* info;
1915 } JSNativeWrapper;
1916
1917 /*
1918 * Macro static initializers which make it easy to pass no JSJitInfo as part of a
1919 * JSPropertySpec or JSFunctionSpec.
1920 */
1921 #define JSNATIVE_WRAPPER(native) { {native, nullptr} }
1922
1923 /**
1924 * Description of a property. JS_DefineProperties and JS_InitClass take arrays
1925 * of these and define many properties at once. JS_PSG, JS_PSGS and JS_PS_END
1926 * are helper macros for defining such arrays.
1927 */
1928 struct JSPropertySpec {
1929 struct SelfHostedWrapper {
1930 void* unused;
1931 const char* funname;
1932 };
1933
1934 const char* name;
1935 uint8_t flags;
1936 union {
1937 JSNativeWrapper native;
1938 SelfHostedWrapper selfHosted;
1939 } getter;
1940 union {
1941 JSNativeWrapper native;
1942 SelfHostedWrapper selfHosted;
1943 } setter;
1944
isSelfHostedJSPropertySpec1945 bool isSelfHosted() const {
1946 #ifdef DEBUG
1947 // Verify that our accessors match our JSPROP_GETTER flag.
1948 if (flags & JSPROP_GETTER)
1949 checkAccessorsAreSelfHosted();
1950 else
1951 checkAccessorsAreNative();
1952 #endif
1953 return (flags & JSPROP_GETTER);
1954 }
1955
1956 static_assert(sizeof(SelfHostedWrapper) == sizeof(JSNativeWrapper),
1957 "JSPropertySpec::getter/setter must be compact");
1958 static_assert(offsetof(SelfHostedWrapper, funname) == offsetof(JSNativeWrapper, info),
1959 "JS_SELF_HOSTED* macros below require that "
1960 "SelfHostedWrapper::funname overlay "
1961 "JSNativeWrapper::info");
1962 private:
checkAccessorsAreNativeJSPropertySpec1963 void checkAccessorsAreNative() const {
1964 MOZ_ASSERT(getter.native.op);
1965 // We may not have a setter at all. So all we can assert here, for the
1966 // native case is that if we have a jitinfo for the setter then we have
1967 // a setter op too. This is good enough to make sure we don't have a
1968 // SelfHostedWrapper for the setter.
1969 MOZ_ASSERT_IF(setter.native.info, setter.native.op);
1970 }
1971
checkAccessorsAreSelfHostedJSPropertySpec1972 void checkAccessorsAreSelfHosted() const {
1973 MOZ_ASSERT(!getter.selfHosted.unused);
1974 MOZ_ASSERT(!setter.selfHosted.unused);
1975 }
1976 };
1977
1978 namespace JS {
1979 namespace detail {
1980
1981 /* NEVER DEFINED, DON'T USE. For use by JS_CAST_NATIVE_TO only. */
1982 inline int CheckIsNative(JSNative native);
1983
1984 /* NEVER DEFINED, DON'T USE. For use by JS_CAST_STRING_TO only. */
1985 template<size_t N>
1986 inline int
1987 CheckIsCharacterLiteral(const char (&arr)[N]);
1988
1989 /* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_GETTER only. */
1990 inline int CheckIsGetterOp(JSGetterOp op);
1991
1992 /* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_SETTER only. */
1993 inline int CheckIsSetterOp(JSSetterOp op);
1994
1995
1996 } // namespace detail
1997 } // namespace JS
1998
1999 #define JS_CAST_NATIVE_TO(v, To) \
2000 (static_cast<void>(sizeof(JS::detail::CheckIsNative(v))), \
2001 reinterpret_cast<To>(v))
2002
2003 #define JS_CAST_STRING_TO(s, To) \
2004 (static_cast<void>(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \
2005 reinterpret_cast<To>(s))
2006
2007 #define JS_CHECK_ACCESSOR_FLAGS(flags) \
2008 (static_cast<mozilla::EnableIf<((flags) & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)) == 0>::Type>(0), \
2009 (flags))
2010
2011 #define JS_PROPERTYOP_GETTER(v) \
2012 (static_cast<void>(sizeof(JS::detail::CheckIsGetterOp(v))), \
2013 reinterpret_cast<JSNative>(v))
2014
2015 #define JS_PROPERTYOP_SETTER(v) \
2016 (static_cast<void>(sizeof(JS::detail::CheckIsSetterOp(v))), \
2017 reinterpret_cast<JSNative>(v))
2018
2019 #define JS_STUBGETTER JS_PROPERTYOP_GETTER(JS_PropertyStub)
2020
2021 #define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub)
2022
2023 /*
2024 * JSPropertySpec uses JSNativeWrapper. These macros encapsulate the definition
2025 * of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for
2026 * them.
2027 */
2028 #define JS_PSG(name, getter, flags) \
2029 {name, \
2030 uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
2031 JSNATIVE_WRAPPER(getter), \
2032 JSNATIVE_WRAPPER(nullptr)}
2033 #define JS_PSGS(name, getter, setter, flags) \
2034 {name, \
2035 uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
2036 JSNATIVE_WRAPPER(getter), \
2037 JSNATIVE_WRAPPER(setter)}
2038 #define JS_SELF_HOSTED_GET(name, getterName, flags) \
2039 {name, \
2040 uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
2041 { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
2042 JSNATIVE_WRAPPER(nullptr) }
2043 #define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
2044 {name, \
2045 uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \
2046 { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) }, \
2047 { nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo*) } }
2048 #define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) }
2049 #define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
2050 {reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
2051 uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
2052 { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
2053 JSNATIVE_WRAPPER(nullptr) }
2054
2055 /**
2056 * To define a native function, set call to a JSNativeWrapper. To define a
2057 * self-hosted function, set selfHostedName to the name of a function
2058 * compiled during JSRuntime::initSelfHosting.
2059 */
2060 struct JSFunctionSpec {
2061 const char* name;
2062 JSNativeWrapper call;
2063 uint16_t nargs;
2064 uint16_t flags;
2065 const char* selfHostedName;
2066 };
2067
2068 /*
2069 * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
2070 * that's passed to JS_DefineFunctions or JS_InitClass.
2071 */
2072 #define JS_FS_END JS_FS(nullptr,nullptr,0,0)
2073
2074 /*
2075 * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name pays
2076 * homage to the old JSNative/JSFastNative split) simply adds the flag
2077 * JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of
2078 * JSJitInfos. JS_SELF_HOSTED_FN declares a self-hosted function.
2079 * JS_INLINABLE_FN allows specifying an InlinableNative enum value for natives
2080 * inlined or specialized by the JIT. Finally JS_FNSPEC has slots for all the
2081 * fields.
2082 *
2083 * The _SYM variants allow defining a function with a symbol key rather than a
2084 * string key. For example, use JS_SYM_FN(iterator, ...) to define an
2085 * @@iterator method.
2086 */
2087 #define JS_FS(name,call,nargs,flags) \
2088 JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr)
2089 #define JS_FN(name,call,nargs,flags) \
2090 JS_FNSPEC(name, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
2091 #define JS_INLINABLE_FN(name,call,nargs,flags,native) \
2092 JS_FNSPEC(name, call, &js::jit::JitInfo_##native, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
2093 #define JS_SYM_FN(symbol,call,nargs,flags) \
2094 JS_SYM_FNSPEC(symbol, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
2095 #define JS_FNINFO(name,call,info,nargs,flags) \
2096 JS_FNSPEC(name, call, info, nargs, flags, nullptr)
2097 #define JS_SELF_HOSTED_FN(name,selfHostedName,nargs,flags) \
2098 JS_FNSPEC(name, nullptr, nullptr, nargs, flags, selfHostedName)
2099 #define JS_SELF_HOSTED_SYM_FN(symbol, selfHostedName, nargs, flags) \
2100 JS_SYM_FNSPEC(symbol, nullptr, nullptr, nargs, flags, selfHostedName)
2101 #define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \
2102 JS_FNSPEC(reinterpret_cast<const char*>( \
2103 uint32_t(::JS::SymbolCode::symbol) + 1), \
2104 call, info, nargs, flags, selfHostedName)
2105 #define JS_FNSPEC(name,call,info,nargs,flags,selfHostedName) \
2106 {name, {call, info}, nargs, flags, selfHostedName}
2107
2108 extern JS_PUBLIC_API(JSObject*)
2109 JS_InitClass(JSContext* cx, JS::HandleObject obj, JS::HandleObject parent_proto,
2110 const JSClass* clasp, JSNative constructor, unsigned nargs,
2111 const JSPropertySpec* ps, const JSFunctionSpec* fs,
2112 const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs);
2113
2114 /**
2115 * Set up ctor.prototype = proto and proto.constructor = ctor with the
2116 * right property flags.
2117 */
2118 extern JS_PUBLIC_API(bool)
2119 JS_LinkConstructorAndPrototype(JSContext* cx, JS::Handle<JSObject*> ctor,
2120 JS::Handle<JSObject*> proto);
2121
2122 extern JS_PUBLIC_API(const JSClass*)
2123 JS_GetClass(JSObject* obj);
2124
2125 extern JS_PUBLIC_API(bool)
2126 JS_InstanceOf(JSContext* cx, JS::Handle<JSObject*> obj, const JSClass* clasp, JS::CallArgs* args);
2127
2128 extern JS_PUBLIC_API(bool)
2129 JS_HasInstance(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> v, bool* bp);
2130
2131 extern JS_PUBLIC_API(void*)
2132 JS_GetPrivate(JSObject* obj);
2133
2134 extern JS_PUBLIC_API(void)
2135 JS_SetPrivate(JSObject* obj, void* data);
2136
2137 extern JS_PUBLIC_API(void*)
2138 JS_GetInstancePrivate(JSContext* cx, JS::Handle<JSObject*> obj, const JSClass* clasp,
2139 JS::CallArgs* args);
2140
2141 extern JS_PUBLIC_API(JSObject*)
2142 JS_GetConstructor(JSContext* cx, JS::Handle<JSObject*> proto);
2143
2144 namespace JS {
2145
2146 enum ZoneSpecifier {
2147 FreshZone = 0,
2148 SystemZone = 1
2149 };
2150
JS_PUBLIC_API(CompartmentOptions)2151 class JS_PUBLIC_API(CompartmentOptions)
2152 {
2153 public:
2154 class Override {
2155 public:
2156 Override() : mode_(Default) {}
2157
2158 bool get(bool defaultValue) const {
2159 if (mode_ == Default)
2160 return defaultValue;
2161 return mode_ == ForceTrue;
2162 }
2163
2164 void set(bool overrideValue) {
2165 mode_ = overrideValue ? ForceTrue : ForceFalse;
2166 }
2167
2168 void reset() {
2169 mode_ = Default;
2170 }
2171
2172 private:
2173 enum Mode {
2174 Default,
2175 ForceTrue,
2176 ForceFalse
2177 };
2178
2179 Mode mode_;
2180 };
2181
2182 explicit CompartmentOptions()
2183 : version_(JSVERSION_UNKNOWN)
2184 , invisibleToDebugger_(false)
2185 , mergeable_(false)
2186 , discardSource_(false)
2187 , disableLazyParsing_(false)
2188 , cloneSingletons_(false)
2189 , traceGlobal_(nullptr)
2190 , singletonsAsTemplates_(true)
2191 , addonId_(nullptr)
2192 , preserveJitCode_(false)
2193 {
2194 zone_.spec = JS::FreshZone;
2195 }
2196
2197 JSVersion version() const { return version_; }
2198 CompartmentOptions& setVersion(JSVersion aVersion) {
2199 MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN);
2200 version_ = aVersion;
2201 return *this;
2202 }
2203
2204 // Certain scopes (i.e. XBL compilation scopes) are implementation details
2205 // of the embedding, and references to them should never leak out to script.
2206 // This flag causes the this compartment to skip firing onNewGlobalObject
2207 // and makes addDebuggee a no-op for this global.
2208 bool invisibleToDebugger() const { return invisibleToDebugger_; }
2209 CompartmentOptions& setInvisibleToDebugger(bool flag) {
2210 invisibleToDebugger_ = flag;
2211 return *this;
2212 }
2213
2214 // Compartments used for off-thread compilation have their contents merged
2215 // into a target compartment when the compilation is finished. This is only
2216 // allowed if this flag is set. The invisibleToDebugger flag must also be
2217 // set for such compartments.
2218 bool mergeable() const { return mergeable_; }
2219 CompartmentOptions& setMergeable(bool flag) {
2220 mergeable_ = flag;
2221 return *this;
2222 }
2223
2224 // For certain globals, we know enough about the code that will run in them
2225 // that we can discard script source entirely.
2226 bool discardSource() const { return discardSource_; }
2227 CompartmentOptions& setDiscardSource(bool flag) {
2228 discardSource_ = flag;
2229 return *this;
2230 }
2231
2232 bool disableLazyParsing() const { return disableLazyParsing_; }
2233 CompartmentOptions& setDisableLazyParsing(bool flag) {
2234 disableLazyParsing_ = flag;
2235 return *this;
2236 }
2237
2238 bool cloneSingletons() const { return cloneSingletons_; }
2239 CompartmentOptions& setCloneSingletons(bool flag) {
2240 cloneSingletons_ = flag;
2241 return *this;
2242 }
2243
2244 bool extraWarnings(JSRuntime* rt) const;
2245 bool extraWarnings(JSContext* cx) const;
2246 Override& extraWarningsOverride() { return extraWarningsOverride_; }
2247
2248 void* zonePointer() const {
2249 MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
2250 return zone_.pointer;
2251 }
2252 ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
2253 CompartmentOptions& setZone(ZoneSpecifier spec);
2254 CompartmentOptions& setSameZoneAs(JSObject* obj);
2255
2256 void setSingletonsAsValues() {
2257 singletonsAsTemplates_ = false;
2258 }
2259 bool getSingletonsAsTemplates() const {
2260 return singletonsAsTemplates_;
2261 }
2262
2263 // A null add-on ID means that the compartment is not associated with an
2264 // add-on.
2265 JSAddonId* addonIdOrNull() const { return addonId_; }
2266 CompartmentOptions& setAddonId(JSAddonId* id) {
2267 addonId_ = id;
2268 return *this;
2269 }
2270
2271 CompartmentOptions& setTrace(JSTraceOp op) {
2272 traceGlobal_ = op;
2273 return *this;
2274 }
2275 JSTraceOp getTrace() const {
2276 return traceGlobal_;
2277 }
2278
2279 bool preserveJitCode() const { return preserveJitCode_; }
2280 CompartmentOptions& setPreserveJitCode(bool flag) {
2281 preserveJitCode_ = flag;
2282 return *this;
2283 }
2284
2285 private:
2286 JSVersion version_;
2287 bool invisibleToDebugger_;
2288 bool mergeable_;
2289 bool discardSource_;
2290 bool disableLazyParsing_;
2291 bool cloneSingletons_;
2292 Override extraWarningsOverride_;
2293 union {
2294 ZoneSpecifier spec;
2295 void* pointer; // js::Zone* is not exposed in the API.
2296 } zone_;
2297 JSTraceOp traceGlobal_;
2298
2299 // To XDR singletons, we need to ensure that all singletons are all used as
2300 // templates, by making JSOP_OBJECT return a clone of the JSScript
2301 // singleton, instead of returning the value which is baked in the JSScript.
2302 bool singletonsAsTemplates_;
2303
2304 JSAddonId* addonId_;
2305 bool preserveJitCode_;
2306 };
2307
2308 JS_PUBLIC_API(CompartmentOptions&)
2309 CompartmentOptionsRef(JSCompartment* compartment);
2310
2311 JS_PUBLIC_API(CompartmentOptions&)
2312 CompartmentOptionsRef(JSObject* obj);
2313
2314 JS_PUBLIC_API(CompartmentOptions&)
2315 CompartmentOptionsRef(JSContext* cx);
2316
2317 /**
2318 * During global creation, we fire notifications to callbacks registered
2319 * via the Debugger API. These callbacks are arbitrary script, and can touch
2320 * the global in arbitrary ways. When that happens, the global should not be
2321 * in a half-baked state. But this creates a problem for consumers that need
2322 * to set slots on the global to put it in a consistent state.
2323 *
2324 * This API provides a way for consumers to set slots atomically (immediately
2325 * after the global is created), before any debugger hooks are fired. It's
2326 * unfortunately on the clunky side, but that's the way the cookie crumbles.
2327 *
2328 * If callers have no additional state on the global to set up, they may pass
2329 * |FireOnNewGlobalHook| to JS_NewGlobalObject, which causes that function to
2330 * fire the hook as its final act before returning. Otherwise, callers should
2331 * pass |DontFireOnNewGlobalHook|, which means that they are responsible for
2332 * invoking JS_FireOnNewGlobalObject upon successfully creating the global. If
2333 * an error occurs and the operation aborts, callers should skip firing the
2334 * hook. But otherwise, callers must take care to fire the hook exactly once
2335 * before compiling any script in the global's scope (we have assertions in
2336 * place to enforce this). This lets us be sure that debugger clients never miss
2337 * breakpoints.
2338 */
2339 enum OnNewGlobalHookOption {
2340 FireOnNewGlobalHook,
2341 DontFireOnNewGlobalHook
2342 };
2343
2344 } /* namespace JS */
2345
2346 extern JS_PUBLIC_API(JSObject*)
2347 JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals,
2348 JS::OnNewGlobalHookOption hookOption,
2349 const JS::CompartmentOptions& options = JS::CompartmentOptions());
2350 /**
2351 * Spidermonkey does not have a good way of keeping track of what compartments should be marked on
2352 * their own. We can mark the roots unconditionally, but marking GC things only relevant in live
2353 * compartments is hard. To mitigate this, we create a static trace hook, installed on each global
2354 * object, from which we can be sure the compartment is relevant, and mark it.
2355 *
2356 * It is still possible to specify custom trace hooks for global object classes. They can be
2357 * provided via the CompartmentOptions passed to JS_NewGlobalObject.
2358 */
2359 extern JS_PUBLIC_API(void)
2360 JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global);
2361
2362 extern JS_PUBLIC_API(void)
2363 JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global);
2364
2365 extern JS_PUBLIC_API(JSObject*)
2366 JS_NewObject(JSContext* cx, const JSClass* clasp);
2367
2368 extern JS_PUBLIC_API(bool)
2369 JS_IsNative(JSObject* obj);
2370
2371 extern JS_PUBLIC_API(JSRuntime*)
2372 JS_GetObjectRuntime(JSObject* obj);
2373
2374 /**
2375 * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
2376 * proto. If proto is nullptr, the JS object will have `null` as [[Prototype]].
2377 */
2378 extern JS_PUBLIC_API(JSObject*)
2379 JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
2380
2381 /** Creates a new plain object, like `new Object()`, with Object.prototype as [[Prototype]]. */
2382 extern JS_PUBLIC_API(JSObject*)
2383 JS_NewPlainObject(JSContext* cx);
2384
2385 /**
2386 * Freeze obj, and all objects it refers to, recursively. This will not recurse
2387 * through non-extensible objects, on the assumption that those are already
2388 * deep-frozen.
2389 */
2390 extern JS_PUBLIC_API(bool)
2391 JS_DeepFreezeObject(JSContext* cx, JS::Handle<JSObject*> obj);
2392
2393 /**
2394 * Freezes an object; see ES5's Object.freeze(obj) method.
2395 */
2396 extern JS_PUBLIC_API(bool)
2397 JS_FreezeObject(JSContext* cx, JS::Handle<JSObject*> obj);
2398
2399
2400 /*** Property descriptors ************************************************************************/
2401
2402 struct JSPropertyDescriptor : public JS::Traceable {
2403 JSObject* obj;
2404 unsigned attrs;
2405 JSGetterOp getter;
2406 JSSetterOp setter;
2407 JS::Value value;
2408
JSPropertyDescriptorJSPropertyDescriptor2409 JSPropertyDescriptor()
2410 : obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue())
2411 {}
2412
traceJSPropertyDescriptor2413 static void trace(JSPropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
2414 void trace(JSTracer* trc);
2415 };
2416
2417 namespace JS {
2418
2419 template <typename Outer>
2420 class PropertyDescriptorOperations
2421 {
desc()2422 const JSPropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
2423
has(unsigned bit)2424 bool has(unsigned bit) const {
2425 MOZ_ASSERT(bit != 0);
2426 MOZ_ASSERT((bit & (bit - 1)) == 0); // only a single bit
2427 return (desc().attrs & bit) != 0;
2428 }
2429
hasAny(unsigned bits)2430 bool hasAny(unsigned bits) const {
2431 return (desc().attrs & bits) != 0;
2432 }
2433
hasAll(unsigned bits)2434 bool hasAll(unsigned bits) const {
2435 return (desc().attrs & bits) == bits;
2436 }
2437
2438 // Non-API attributes bit used internally for arguments objects.
2439 enum { SHADOWABLE = JSPROP_INTERNAL_USE_BIT };
2440
2441 public:
2442 // Descriptors with JSGetterOp/JSSetterOp are considered data
2443 // descriptors. It's complicated.
isAccessorDescriptor()2444 bool isAccessorDescriptor() const { return hasAny(JSPROP_GETTER | JSPROP_SETTER); }
isGenericDescriptor()2445 bool isGenericDescriptor() const {
2446 return (desc().attrs&
2447 (JSPROP_GETTER | JSPROP_SETTER | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE)) ==
2448 (JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE);
2449 }
isDataDescriptor()2450 bool isDataDescriptor() const { return !isAccessorDescriptor() && !isGenericDescriptor(); }
2451
hasConfigurable()2452 bool hasConfigurable() const { return !has(JSPROP_IGNORE_PERMANENT); }
configurable()2453 bool configurable() const { MOZ_ASSERT(hasConfigurable()); return !has(JSPROP_PERMANENT); }
2454
hasEnumerable()2455 bool hasEnumerable() const { return !has(JSPROP_IGNORE_ENUMERATE); }
enumerable()2456 bool enumerable() const { MOZ_ASSERT(hasEnumerable()); return has(JSPROP_ENUMERATE); }
2457
hasValue()2458 bool hasValue() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_VALUE); }
value()2459 JS::HandleValue value() const {
2460 return JS::HandleValue::fromMarkedLocation(&desc().value);
2461 }
2462
hasWritable()2463 bool hasWritable() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_READONLY); }
writable()2464 bool writable() const { MOZ_ASSERT(hasWritable()); return !has(JSPROP_READONLY); }
2465
hasGetterObject()2466 bool hasGetterObject() const { return has(JSPROP_GETTER); }
getterObject()2467 JS::HandleObject getterObject() const {
2468 MOZ_ASSERT(hasGetterObject());
2469 return JS::HandleObject::fromMarkedLocation(
2470 reinterpret_cast<JSObject* const*>(&desc().getter));
2471 }
hasSetterObject()2472 bool hasSetterObject() const { return has(JSPROP_SETTER); }
setterObject()2473 JS::HandleObject setterObject() const {
2474 MOZ_ASSERT(hasSetterObject());
2475 return JS::HandleObject::fromMarkedLocation(
2476 reinterpret_cast<JSObject* const*>(&desc().setter));
2477 }
2478
hasGetterOrSetter()2479 bool hasGetterOrSetter() const { return desc().getter || desc().setter; }
isShared()2480 bool isShared() const { return has(JSPROP_SHARED); }
2481
object()2482 JS::HandleObject object() const {
2483 return JS::HandleObject::fromMarkedLocation(&desc().obj);
2484 }
attributes()2485 unsigned attributes() const { return desc().attrs; }
getter()2486 JSGetterOp getter() const { return desc().getter; }
setter()2487 JSSetterOp setter() const { return desc().setter; }
2488
assertValid()2489 void assertValid() const {
2490 #ifdef DEBUG
2491 MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE |
2492 JSPROP_PERMANENT | JSPROP_IGNORE_PERMANENT |
2493 JSPROP_READONLY | JSPROP_IGNORE_READONLY |
2494 JSPROP_IGNORE_VALUE |
2495 JSPROP_GETTER |
2496 JSPROP_SETTER |
2497 JSPROP_SHARED |
2498 JSPROP_REDEFINE_NONCONFIGURABLE |
2499 JSPROP_RESOLVING |
2500 SHADOWABLE)) == 0);
2501 MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE));
2502 MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT));
2503 if (isAccessorDescriptor()) {
2504 MOZ_ASSERT(has(JSPROP_SHARED));
2505 MOZ_ASSERT(!has(JSPROP_READONLY));
2506 MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY));
2507 MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE));
2508 MOZ_ASSERT(!has(SHADOWABLE));
2509 MOZ_ASSERT(value().isUndefined());
2510 MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter());
2511 MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter());
2512 } else {
2513 MOZ_ASSERT(!hasAll(JSPROP_IGNORE_READONLY | JSPROP_READONLY));
2514 MOZ_ASSERT_IF(has(JSPROP_IGNORE_VALUE), value().isUndefined());
2515 }
2516 MOZ_ASSERT(getter() != JS_PropertyStub);
2517 MOZ_ASSERT(setter() != JS_StrictPropertyStub);
2518
2519 MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE));
2520 MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT));
2521 MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY));
2522 MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE));
2523 MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_REDEFINE_NONCONFIGURABLE));
2524 #endif
2525 }
2526
assertComplete()2527 void assertComplete() const {
2528 #ifdef DEBUG
2529 assertValid();
2530 MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE |
2531 JSPROP_PERMANENT |
2532 JSPROP_READONLY |
2533 JSPROP_GETTER |
2534 JSPROP_SETTER |
2535 JSPROP_SHARED |
2536 JSPROP_REDEFINE_NONCONFIGURABLE |
2537 JSPROP_RESOLVING |
2538 SHADOWABLE)) == 0);
2539 MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER));
2540 #endif
2541 }
2542
assertCompleteIfFound()2543 void assertCompleteIfFound() const {
2544 #ifdef DEBUG
2545 if (object())
2546 assertComplete();
2547 #endif
2548 }
2549 };
2550
2551 template <typename Outer>
2552 class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
2553 {
desc()2554 JSPropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
2555
2556 public:
clear()2557 void clear() {
2558 object().set(nullptr);
2559 setAttributes(0);
2560 setGetter(nullptr);
2561 setSetter(nullptr);
2562 value().setUndefined();
2563 }
2564
initFields(HandleObject obj,HandleValue v,unsigned attrs,JSGetterOp getterOp,JSSetterOp setterOp)2565 void initFields(HandleObject obj, HandleValue v, unsigned attrs,
2566 JSGetterOp getterOp, JSSetterOp setterOp) {
2567 MOZ_ASSERT(getterOp != JS_PropertyStub);
2568 MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
2569
2570 object().set(obj);
2571 value().set(v);
2572 setAttributes(attrs);
2573 setGetter(getterOp);
2574 setSetter(setterOp);
2575 }
2576
assign(JSPropertyDescriptor & other)2577 void assign(JSPropertyDescriptor& other) {
2578 object().set(other.obj);
2579 setAttributes(other.attrs);
2580 setGetter(other.getter);
2581 setSetter(other.setter);
2582 value().set(other.value);
2583 }
2584
setDataDescriptor(HandleValue v,unsigned attrs)2585 void setDataDescriptor(HandleValue v, unsigned attrs) {
2586 MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE |
2587 JSPROP_PERMANENT |
2588 JSPROP_READONLY |
2589 JSPROP_IGNORE_ENUMERATE |
2590 JSPROP_IGNORE_PERMANENT |
2591 JSPROP_IGNORE_READONLY)) == 0);
2592 object().set(nullptr);
2593 setAttributes(attrs);
2594 setGetter(nullptr);
2595 setSetter(nullptr);
2596 value().set(v);
2597 }
2598
object()2599 JS::MutableHandleObject object() {
2600 return JS::MutableHandleObject::fromMarkedLocation(&desc().obj);
2601 }
attributesRef()2602 unsigned& attributesRef() { return desc().attrs; }
getter()2603 JSGetterOp& getter() { return desc().getter; }
setter()2604 JSSetterOp& setter() { return desc().setter; }
value()2605 JS::MutableHandleValue value() {
2606 return JS::MutableHandleValue::fromMarkedLocation(&desc().value);
2607 }
setValue(JS::HandleValue v)2608 void setValue(JS::HandleValue v) {
2609 MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
2610 attributesRef() &= ~JSPROP_IGNORE_VALUE;
2611 value().set(v);
2612 }
2613
setConfigurable(bool configurable)2614 void setConfigurable(bool configurable) {
2615 setAttributes((desc().attrs & ~(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)) |
2616 (configurable ? 0 : JSPROP_PERMANENT));
2617 }
setEnumerable(bool enumerable)2618 void setEnumerable(bool enumerable) {
2619 setAttributes((desc().attrs & ~(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)) |
2620 (enumerable ? JSPROP_ENUMERATE : 0));
2621 }
setWritable(bool writable)2622 void setWritable(bool writable) {
2623 MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
2624 setAttributes((desc().attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) |
2625 (writable ? 0 : JSPROP_READONLY));
2626 }
setAttributes(unsigned attrs)2627 void setAttributes(unsigned attrs) { desc().attrs = attrs; }
2628
setGetter(JSGetterOp op)2629 void setGetter(JSGetterOp op) {
2630 MOZ_ASSERT(op != JS_PropertyStub);
2631 desc().getter = op;
2632 }
setSetter(JSSetterOp op)2633 void setSetter(JSSetterOp op) {
2634 MOZ_ASSERT(op != JS_StrictPropertyStub);
2635 desc().setter = op;
2636 }
setGetterObject(JSObject * obj)2637 void setGetterObject(JSObject* obj) {
2638 desc().getter = reinterpret_cast<JSGetterOp>(obj);
2639 desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
2640 desc().attrs |= JSPROP_GETTER | JSPROP_SHARED;
2641 }
setSetterObject(JSObject * obj)2642 void setSetterObject(JSObject* obj) {
2643 desc().setter = reinterpret_cast<JSSetterOp>(obj);
2644 desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
2645 desc().attrs |= JSPROP_SETTER | JSPROP_SHARED;
2646 }
2647
getterObject()2648 JS::MutableHandleObject getterObject() {
2649 MOZ_ASSERT(this->hasGetterObject());
2650 return JS::MutableHandleObject::fromMarkedLocation(
2651 reinterpret_cast<JSObject**>(&desc().getter));
2652 }
setterObject()2653 JS::MutableHandleObject setterObject() {
2654 MOZ_ASSERT(this->hasSetterObject());
2655 return JS::MutableHandleObject::fromMarkedLocation(
2656 reinterpret_cast<JSObject**>(&desc().setter));
2657 }
2658 };
2659
2660 } /* namespace JS */
2661
2662 namespace js {
2663
2664 template <>
2665 class RootedBase<JSPropertyDescriptor>
2666 : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>>
2667 {};
2668
2669 template <>
2670 class HandleBase<JSPropertyDescriptor>
2671 : public JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor>>
2672 {};
2673
2674 template <>
2675 class MutableHandleBase<JSPropertyDescriptor>
2676 : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>>
2677 {};
2678
2679 } /* namespace js */
2680
2681 namespace JS {
2682
2683 extern JS_PUBLIC_API(bool)
2684 ObjectToCompletePropertyDescriptor(JSContext* cx,
2685 JS::HandleObject obj,
2686 JS::HandleValue descriptor,
2687 JS::MutableHandle<JSPropertyDescriptor> desc);
2688
2689 } // namespace JS
2690
2691
2692 /*** Standard internal methods ********************************************************************
2693 *
2694 * The functions below are the fundamental operations on objects.
2695 *
2696 * ES6 specifies 14 internal methods that define how objects behave. The
2697 * standard is actually quite good on this topic, though you may have to read
2698 * it a few times. See ES6 sections 6.1.7.2 and 6.1.7.3.
2699 *
2700 * When 'obj' is an ordinary object, these functions have boring standard
2701 * behavior as specified by ES6 section 9.1; see the section about internal
2702 * methods in js/src/vm/NativeObject.h.
2703 *
2704 * Proxies override the behavior of internal methods. So when 'obj' is a proxy,
2705 * any one of the functions below could do just about anything. See
2706 * js/public/Proxy.h.
2707 */
2708
2709 /**
2710 * Get the prototype of obj, storing it in result.
2711 *
2712 * Implements: ES6 [[GetPrototypeOf]] internal method.
2713 */
2714 extern JS_PUBLIC_API(bool)
2715 JS_GetPrototype(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject result);
2716
2717 /**
2718 * Change the prototype of obj.
2719 *
2720 * Implements: ES6 [[SetPrototypeOf]] internal method.
2721 *
2722 * In cases where ES6 [[SetPrototypeOf]] returns false without an exception,
2723 * JS_SetPrototype throws a TypeError and returns false.
2724 *
2725 * Performance warning: JS_SetPrototype is very bad for performance. It may
2726 * cause compiled jit-code to be invalidated. It also causes not only obj but
2727 * all other objects in the same "group" as obj to be permanently deoptimized.
2728 * It's better to create the object with the right prototype from the start.
2729 */
2730 extern JS_PUBLIC_API(bool)
2731 JS_SetPrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
2732
2733 /**
2734 * Determine whether obj is extensible. Extensible objects can have new
2735 * properties defined on them. Inextensible objects can't, and their
2736 * [[Prototype]] slot is fixed as well.
2737 *
2738 * Implements: ES6 [[IsExtensible]] internal method.
2739 */
2740 extern JS_PUBLIC_API(bool)
2741 JS_IsExtensible(JSContext* cx, JS::HandleObject obj, bool* extensible);
2742
2743 /**
2744 * Attempt to make |obj| non-extensible.
2745 *
2746 * Not all failures are treated as errors. See the comment on
2747 * JS::ObjectOpResult in js/public/Class.h.
2748 *
2749 * Implements: ES6 [[PreventExtensions]] internal method.
2750 */
2751 extern JS_PUBLIC_API(bool)
2752 JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result);
2753
2754 /**
2755 * Attempt to make the [[Prototype]] of |obj| immutable, such that any attempt
2756 * to modify it will fail. If an error occurs during the attempt, return false
2757 * (with a pending exception set, depending upon the nature of the error). If
2758 * no error occurs, return true with |*succeeded| set to indicate whether the
2759 * attempt successfully made the [[Prototype]] immutable.
2760 *
2761 * This is a nonstandard internal method.
2762 */
2763 extern JS_PUBLIC_API(bool)
2764 JS_SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded);
2765
2766 /**
2767 * Get a description of one of obj's own properties. If no such property exists
2768 * on obj, return true with desc.object() set to null.
2769 *
2770 * Implements: ES6 [[GetOwnProperty]] internal method.
2771 */
2772 extern JS_PUBLIC_API(bool)
2773 JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2774 JS::MutableHandle<JSPropertyDescriptor> desc);
2775
2776 extern JS_PUBLIC_API(bool)
2777 JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
2778 JS::MutableHandle<JSPropertyDescriptor> desc);
2779
2780 extern JS_PUBLIC_API(bool)
2781 JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name,
2782 JS::MutableHandle<JSPropertyDescriptor> desc);
2783
2784 /**
2785 * Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain
2786 * if no own property is found directly on obj. The object on which the
2787 * property is found is returned in desc.object(). If the property is not found
2788 * on the prototype chain, this returns true with desc.object() set to null.
2789 */
2790 extern JS_PUBLIC_API(bool)
2791 JS_GetPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2792 JS::MutableHandle<JSPropertyDescriptor> desc);
2793
2794 extern JS_PUBLIC_API(bool)
2795 JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
2796 JS::MutableHandle<JSPropertyDescriptor> desc);
2797
2798 /**
2799 * Define a property on obj.
2800 *
2801 * This function uses JS::ObjectOpResult to indicate conditions that ES6
2802 * specifies as non-error failures. This is inconvenient at best, so use this
2803 * function only if you are implementing a proxy handler's defineProperty()
2804 * method. For all other purposes, use one of the many DefineProperty functions
2805 * below that throw an exception in all failure cases.
2806 *
2807 * Implements: ES6 [[DefineOwnProperty]] internal method.
2808 */
2809 extern JS_PUBLIC_API(bool)
2810 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2811 JS::Handle<JSPropertyDescriptor> desc,
2812 JS::ObjectOpResult& result);
2813
2814 /**
2815 * Define a property on obj, throwing a TypeError if the attempt fails.
2816 * This is the C++ equivalent of `Object.defineProperty(obj, id, desc)`.
2817 */
2818 extern JS_PUBLIC_API(bool)
2819 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2820 JS::Handle<JSPropertyDescriptor> desc);
2821
2822 extern JS_PUBLIC_API(bool)
2823 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
2824 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2825
2826 extern JS_PUBLIC_API(bool)
2827 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
2828 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2829
2830 extern JS_PUBLIC_API(bool)
2831 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
2832 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2833
2834 extern JS_PUBLIC_API(bool)
2835 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
2836 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2837
2838 extern JS_PUBLIC_API(bool)
2839 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
2840 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2841
2842 extern JS_PUBLIC_API(bool)
2843 JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value,
2844 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2845
2846 extern JS_PUBLIC_API(bool)
2847 JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value,
2848 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2849
2850 extern JS_PUBLIC_API(bool)
2851 JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value,
2852 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2853
2854 extern JS_PUBLIC_API(bool)
2855 JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value,
2856 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2857
2858 extern JS_PUBLIC_API(bool)
2859 JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value,
2860 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2861
2862 extern JS_PUBLIC_API(bool)
2863 JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value,
2864 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2865
2866 extern JS_PUBLIC_API(bool)
2867 JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value,
2868 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2869
2870 extern JS_PUBLIC_API(bool)
2871 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2872 JS::Handle<JSPropertyDescriptor> desc,
2873 JS::ObjectOpResult& result);
2874
2875 extern JS_PUBLIC_API(bool)
2876 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2877 JS::Handle<JSPropertyDescriptor> desc);
2878
2879 extern JS_PUBLIC_API(bool)
2880 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2881 JS::HandleValue value, unsigned attrs,
2882 JSNative getter = nullptr, JSNative setter = nullptr);
2883
2884 extern JS_PUBLIC_API(bool)
2885 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2886 JS::HandleObject value, unsigned attrs,
2887 JSNative getter = nullptr, JSNative setter = nullptr);
2888
2889 extern JS_PUBLIC_API(bool)
2890 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2891 JS::HandleString value, unsigned attrs,
2892 JSNative getter = nullptr, JSNative setter = nullptr);
2893
2894 extern JS_PUBLIC_API(bool)
2895 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2896 int32_t value, unsigned attrs,
2897 JSNative getter = nullptr, JSNative setter = nullptr);
2898
2899 extern JS_PUBLIC_API(bool)
2900 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2901 uint32_t value, unsigned attrs,
2902 JSNative getter = nullptr, JSNative setter = nullptr);
2903
2904 extern JS_PUBLIC_API(bool)
2905 JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2906 double value, unsigned attrs,
2907 JSNative getter = nullptr, JSNative setter = nullptr);
2908
2909 extern JS_PUBLIC_API(bool)
2910 JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
2911 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2912
2913 extern JS_PUBLIC_API(bool)
2914 JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value,
2915 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2916
2917 extern JS_PUBLIC_API(bool)
2918 JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString value,
2919 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2920
2921 extern JS_PUBLIC_API(bool)
2922 JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t value,
2923 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2924
2925 extern JS_PUBLIC_API(bool)
2926 JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t value,
2927 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2928
2929 extern JS_PUBLIC_API(bool)
2930 JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double value,
2931 unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
2932
2933 /**
2934 * Compute the expression `id in obj`.
2935 *
2936 * If obj has an own or inherited property obj[id], set *foundp = true and
2937 * return true. If not, set *foundp = false and return true. On error, return
2938 * false with an exception pending.
2939 *
2940 * Implements: ES6 [[Has]] internal method.
2941 */
2942 extern JS_PUBLIC_API(bool)
2943 JS_HasPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
2944
2945 extern JS_PUBLIC_API(bool)
2946 JS_HasProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
2947
2948 extern JS_PUBLIC_API(bool)
2949 JS_HasUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
2950 bool* vp);
2951
2952 extern JS_PUBLIC_API(bool)
2953 JS_HasElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp);
2954
2955 /**
2956 * Determine whether obj has an own property with the key `id`.
2957 *
2958 * Implements: ES6 7.3.11 HasOwnProperty(O, P).
2959 */
2960 extern JS_PUBLIC_API(bool)
2961 JS_HasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
2962
2963 extern JS_PUBLIC_API(bool)
2964 JS_HasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp);
2965
2966 /**
2967 * Get the value of the property `obj[id]`, or undefined if no such property
2968 * exists. This is the C++ equivalent of `vp = Reflect.get(obj, id, receiver)`.
2969 *
2970 * Most callers don't need the `receiver` argument. Consider using
2971 * JS_GetProperty instead. (But if you're implementing a proxy handler's set()
2972 * method, it's often correct to call this function and pass the receiver
2973 * through.)
2974 *
2975 * Implements: ES6 [[Get]] internal method.
2976 */
2977 extern JS_PUBLIC_API(bool)
2978 JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2979 JS::HandleValue receiver, JS::MutableHandleValue vp);
2980
2981 extern JS_PUBLIC_API(bool)
2982 JS_ForwardGetElementTo(JSContext* cx, JS::HandleObject obj, uint32_t index,
2983 JS::HandleObject receiver, JS::MutableHandleValue vp);
2984
2985 /**
2986 * Get the value of the property `obj[id]`, or undefined if no such property
2987 * exists. The result is stored in vp.
2988 *
2989 * Implements: ES6 7.3.1 Get(O, P).
2990 */
2991 extern JS_PUBLIC_API(bool)
2992 JS_GetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
2993 JS::MutableHandleValue vp);
2994
2995 extern JS_PUBLIC_API(bool)
2996 JS_GetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandleValue vp);
2997
2998 extern JS_PUBLIC_API(bool)
2999 JS_GetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
3000 JS::MutableHandleValue vp);
3001
3002 extern JS_PUBLIC_API(bool)
3003 JS_GetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp);
3004
3005 /**
3006 * Perform the same property assignment as `Reflect.set(obj, id, v, receiver)`.
3007 *
3008 * This function has a `receiver` argument that most callers don't need.
3009 * Consider using JS_SetProperty instead.
3010 *
3011 * Implements: ES6 [[Set]] internal method.
3012 */
3013 extern JS_PUBLIC_API(bool)
3014 JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
3015 JS::HandleValue receiver, JS::ObjectOpResult& result);
3016
3017 /**
3018 * Perform the assignment `obj[id] = v`.
3019 *
3020 * This function performs non-strict assignment, so if the property is
3021 * read-only, nothing happens and no error is thrown.
3022 */
3023 extern JS_PUBLIC_API(bool)
3024 JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
3025
3026 extern JS_PUBLIC_API(bool)
3027 JS_SetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue v);
3028
3029 extern JS_PUBLIC_API(bool)
3030 JS_SetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
3031 JS::HandleValue v);
3032
3033 extern JS_PUBLIC_API(bool)
3034 JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue v);
3035
3036 extern JS_PUBLIC_API(bool)
3037 JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject v);
3038
3039 extern JS_PUBLIC_API(bool)
3040 JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString v);
3041
3042 extern JS_PUBLIC_API(bool)
3043 JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t v);
3044
3045 extern JS_PUBLIC_API(bool)
3046 JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t v);
3047
3048 extern JS_PUBLIC_API(bool)
3049 JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double v);
3050
3051 /**
3052 * Delete a property. This is the C++ equivalent of
3053 * `result = Reflect.deleteProperty(obj, id)`.
3054 *
3055 * This function has a `result` out parameter that most callers don't need.
3056 * Unless you can pass through an ObjectOpResult provided by your caller, it's
3057 * probably best to use the JS_DeletePropertyById signature with just 3
3058 * arguments.
3059 *
3060 * Implements: ES6 [[Delete]] internal method.
3061 */
3062 extern JS_PUBLIC_API(bool)
3063 JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
3064 JS::ObjectOpResult& result);
3065
3066 extern JS_PUBLIC_API(bool)
3067 JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name,
3068 JS::ObjectOpResult& result);
3069
3070 extern JS_PUBLIC_API(bool)
3071 JS_DeleteUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
3072 JS::ObjectOpResult& result);
3073
3074 extern JS_PUBLIC_API(bool)
3075 JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::ObjectOpResult& result);
3076
3077 /**
3078 * Delete a property, ignoring strict failures. This is the C++ equivalent of
3079 * the JS `delete obj[id]` in non-strict mode code.
3080 */
3081 extern JS_PUBLIC_API(bool)
3082 JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, jsid id);
3083
3084 extern JS_PUBLIC_API(bool)
3085 JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name);
3086
3087 extern JS_PUBLIC_API(bool)
3088 JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index);
3089
3090 /**
3091 * Get an array of the non-symbol enumerable properties of obj.
3092 * This function is roughly equivalent to:
3093 *
3094 * var result = [];
3095 * for (key in obj)
3096 * result.push(key);
3097 * return result;
3098 *
3099 * This is the closest thing we currently have to the ES6 [[Enumerate]]
3100 * internal method.
3101 *
3102 * The JSIdArray returned by JS_Enumerate must be rooted to protect its
3103 * contents from garbage collection. Use JS::AutoIdArray.
3104 */
3105 extern JS_PUBLIC_API(bool)
3106 JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle<JS::IdVector> props);
3107
3108 /*
3109 * API for determining callability and constructability. [[Call]] and
3110 * [[Construct]] are internal methods that aren't present on all objects, so it
3111 * is useful to ask if they are there or not. The standard itself asks these
3112 * questions routinely.
3113 */
3114 namespace JS {
3115
3116 /**
3117 * Return true if the given object is callable. In ES6 terms, an object is
3118 * callable if it has a [[Call]] internal method.
3119 *
3120 * Implements: ES6 7.2.3 IsCallable(argument).
3121 *
3122 * Functions are callable. A scripted proxy or wrapper is callable if its
3123 * target is callable. Most other objects aren't callable.
3124 */
3125 extern JS_PUBLIC_API(bool)
3126 IsCallable(JSObject* obj);
3127
3128 /**
3129 * Return true if the given object is a constructor. In ES6 terms, an object is
3130 * a constructor if it has a [[Construct]] internal method. The expression
3131 * `new obj()` throws a TypeError if obj is not a constructor.
3132 *
3133 * Implements: ES6 7.2.4 IsConstructor(argument).
3134 *
3135 * JS functions and classes are constructors. Arrow functions and most builtin
3136 * functions are not. A scripted proxy or wrapper is a constructor if its
3137 * target is a constructor.
3138 */
3139 extern JS_PUBLIC_API(bool)
3140 IsConstructor(JSObject* obj);
3141
3142 } /* namespace JS */
3143
3144 /**
3145 * Call a function, passing a this-value and arguments. This is the C++
3146 * equivalent of `rval = Reflect.apply(fun, obj, args)`.
3147 *
3148 * Implements: ES6 7.3.12 Call(F, V, [argumentsList]).
3149 * Use this function to invoke the [[Call]] internal method.
3150 */
3151 extern JS_PUBLIC_API(bool)
3152 JS_CallFunctionValue(JSContext* cx, JS::HandleObject obj, JS::HandleValue fval,
3153 const JS::HandleValueArray& args, JS::MutableHandleValue rval);
3154
3155 extern JS_PUBLIC_API(bool)
3156 JS_CallFunction(JSContext* cx, JS::HandleObject obj, JS::HandleFunction fun,
3157 const JS::HandleValueArray& args, JS::MutableHandleValue rval);
3158
3159 /**
3160 * Perform the method call `rval = obj[name](args)`.
3161 */
3162 extern JS_PUBLIC_API(bool)
3163 JS_CallFunctionName(JSContext* cx, JS::HandleObject obj, const char* name,
3164 const JS::HandleValueArray& args, JS::MutableHandleValue rval);
3165
3166 namespace JS {
3167
3168 static inline bool
Call(JSContext * cx,JS::HandleObject thisObj,JS::HandleFunction fun,const JS::HandleValueArray & args,MutableHandleValue rval)3169 Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleFunction fun,
3170 const JS::HandleValueArray& args, MutableHandleValue rval)
3171 {
3172 return !!JS_CallFunction(cx, thisObj, fun, args, rval);
3173 }
3174
3175 static inline bool
Call(JSContext * cx,JS::HandleObject thisObj,JS::HandleValue fun,const JS::HandleValueArray & args,MutableHandleValue rval)3176 Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleValue fun, const JS::HandleValueArray& args,
3177 MutableHandleValue rval)
3178 {
3179 return !!JS_CallFunctionValue(cx, thisObj, fun, args, rval);
3180 }
3181
3182 static inline bool
Call(JSContext * cx,JS::HandleObject thisObj,const char * name,const JS::HandleValueArray & args,MutableHandleValue rval)3183 Call(JSContext* cx, JS::HandleObject thisObj, const char* name, const JS::HandleValueArray& args,
3184 MutableHandleValue rval)
3185 {
3186 return !!JS_CallFunctionName(cx, thisObj, name, args, rval);
3187 }
3188
3189 extern JS_PUBLIC_API(bool)
3190 Call(JSContext* cx, JS::HandleValue thisv, JS::HandleValue fun, const JS::HandleValueArray& args,
3191 MutableHandleValue rval);
3192
3193 static inline bool
Call(JSContext * cx,JS::HandleValue thisv,JS::HandleObject funObj,const JS::HandleValueArray & args,MutableHandleValue rval)3194 Call(JSContext* cx, JS::HandleValue thisv, JS::HandleObject funObj, const JS::HandleValueArray& args,
3195 MutableHandleValue rval)
3196 {
3197 MOZ_ASSERT(funObj);
3198 JS::RootedValue fun(cx, JS::ObjectValue(*funObj));
3199 return Call(cx, thisv, fun, args, rval);
3200 }
3201
3202 /**
3203 * Invoke a constructor. This is the C++ equivalent of
3204 * `rval = Reflect.construct(fun, args, newTarget)`.
3205 *
3206 * JS::Construct() takes a `newTarget` argument that most callers don't need.
3207 * Consider using the four-argument Construct signature instead. (But if you're
3208 * implementing a subclass or a proxy handler's construct() method, this is the
3209 * right function to call.)
3210 *
3211 * Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]).
3212 * Use this function to invoke the [[Construct]] internal method.
3213 */
3214 extern JS_PUBLIC_API(bool)
3215 Construct(JSContext* cx, JS::HandleValue fun, HandleObject newTarget,
3216 const JS::HandleValueArray &args, MutableHandleValue rval);
3217
3218 /**
3219 * Invoke a constructor. This is the C++ equivalent of
3220 * `rval = new fun(...args)`.
3221 *
3222 * The value left in rval on success is always an object in practice,
3223 * though at the moment this is not enforced by the C++ type system.
3224 *
3225 * Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]), when
3226 * newTarget is omitted.
3227 */
3228 extern JS_PUBLIC_API(bool)
3229 Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args,
3230 MutableHandleValue rval);
3231
3232 } /* namespace JS */
3233
3234 /**
3235 * Invoke a constructor, like the JS expression `new ctor(...args)`. Returns
3236 * the new object, or null on error.
3237 */
3238 extern JS_PUBLIC_API(JSObject*)
3239 JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
3240
3241
3242 /*** Other property-defining functions ***********************************************************/
3243
3244 extern JS_PUBLIC_API(JSObject*)
3245 JS_DefineObject(JSContext* cx, JS::HandleObject obj, const char* name,
3246 const JSClass* clasp = nullptr, unsigned attrs = 0);
3247
3248 extern JS_PUBLIC_API(bool)
3249 JS_DefineConstDoubles(JSContext* cx, JS::HandleObject obj, const JSConstDoubleSpec* cds);
3250
3251 extern JS_PUBLIC_API(bool)
3252 JS_DefineConstIntegers(JSContext* cx, JS::HandleObject obj, const JSConstIntegerSpec* cis);
3253
3254 extern JS_PUBLIC_API(bool)
3255 JS_DefineProperties(JSContext* cx, JS::HandleObject obj, const JSPropertySpec* ps);
3256
3257
3258 /* * */
3259
3260 extern JS_PUBLIC_API(bool)
3261 JS_AlreadyHasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
3262 bool* foundp);
3263
3264 extern JS_PUBLIC_API(bool)
3265 JS_AlreadyHasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name,
3266 bool* foundp);
3267
3268 extern JS_PUBLIC_API(bool)
3269 JS_AlreadyHasOwnUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name,
3270 size_t namelen, bool* foundp);
3271
3272 extern JS_PUBLIC_API(bool)
3273 JS_AlreadyHasOwnElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp);
3274
3275 extern JS_PUBLIC_API(JSObject*)
3276 JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents);
3277
3278 extern JS_PUBLIC_API(JSObject*)
3279 JS_NewArrayObject(JSContext* cx, size_t length);
3280
3281 /**
3282 * Returns true and sets |*isArray| indicating whether |value| is an Array
3283 * object or a wrapper around one, otherwise returns false on failure.
3284 *
3285 * This method returns true with |*isArray == false| when passed a proxy whose
3286 * target is an Array, or when passed a revoked proxy.
3287 */
3288 extern JS_PUBLIC_API(bool)
3289 JS_IsArrayObject(JSContext* cx, JS::HandleValue value, bool* isArray);
3290
3291 /**
3292 * Returns true and sets |*isArray| indicating whether |obj| is an Array object
3293 * or a wrapper around one, otherwise returns false on failure.
3294 *
3295 * This method returns true with |*isArray == false| when passed a proxy whose
3296 * target is an Array, or when passed a revoked proxy.
3297 */
3298 extern JS_PUBLIC_API(bool)
3299 JS_IsArrayObject(JSContext* cx, JS::HandleObject obj, bool* isArray);
3300
3301 extern JS_PUBLIC_API(bool)
3302 JS_GetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t* lengthp);
3303
3304 extern JS_PUBLIC_API(bool)
3305 JS_SetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t length);
3306
3307 /**
3308 * Assign 'undefined' to all of the object's non-reserved slots. Note: this is
3309 * done for all slots, regardless of the associated property descriptor.
3310 */
3311 JS_PUBLIC_API(void)
3312 JS_SetAllNonReservedSlotsToUndefined(JSContext* cx, JSObject* objArg);
3313
3314 /**
3315 * Create a new array buffer with the given contents. It must be legal to pass
3316 * these contents to free(). On success, the ownership is transferred to the
3317 * new array buffer.
3318 */
3319 extern JS_PUBLIC_API(JSObject*)
3320 JS_NewArrayBufferWithContents(JSContext* cx, size_t nbytes, void* contents);
3321
3322 /**
3323 * Steal the contents of the given array buffer. The array buffer has its
3324 * length set to 0 and its contents array cleared. The caller takes ownership
3325 * of the return value and must free it or transfer ownership via
3326 * JS_NewArrayBufferWithContents when done using it.
3327 */
3328 extern JS_PUBLIC_API(void*)
3329 JS_StealArrayBufferContents(JSContext* cx, JS::HandleObject obj);
3330
3331 /**
3332 * Create a new mapped array buffer with the given memory mapped contents. It
3333 * must be legal to free the contents pointer by unmapping it. On success,
3334 * ownership is transferred to the new mapped array buffer.
3335 */
3336 extern JS_PUBLIC_API(JSObject*)
3337 JS_NewMappedArrayBufferWithContents(JSContext* cx, size_t nbytes, void* contents);
3338
3339 /**
3340 * Create memory mapped array buffer contents.
3341 * Caller must take care of closing fd after calling this function.
3342 */
3343 extern JS_PUBLIC_API(void*)
3344 JS_CreateMappedArrayBufferContents(int fd, size_t offset, size_t length);
3345
3346 /**
3347 * Release the allocated resource of mapped array buffer contents before the
3348 * object is created.
3349 * If a new object has been created by JS_NewMappedArrayBufferWithContents()
3350 * with this content, then JS_NeuterArrayBuffer() should be used instead to
3351 * release the resource used by the object.
3352 */
3353 extern JS_PUBLIC_API(void)
3354 JS_ReleaseMappedArrayBufferContents(void* contents, size_t length);
3355
3356 extern JS_PUBLIC_API(JS::Value)
3357 JS_GetReservedSlot(JSObject* obj, uint32_t index);
3358
3359 extern JS_PUBLIC_API(void)
3360 JS_SetReservedSlot(JSObject* obj, uint32_t index, JS::Value v);
3361
3362
3363 /************************************************************************/
3364
3365 /*
3366 * Functions and scripts.
3367 */
3368 extern JS_PUBLIC_API(JSFunction*)
3369 JS_NewFunction(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
3370 const char* name);
3371
3372 namespace JS {
3373
3374 extern JS_PUBLIC_API(JSFunction*)
3375 GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id,
3376 unsigned nargs);
3377
3378 /**
3379 * Create a new function based on the given JSFunctionSpec, *fs.
3380 * id is the result of a successful call to
3381 * `PropertySpecNameToPermanentId(cx, fs->name, &id)`.
3382 *
3383 * Unlike JS_DefineFunctions, this does not treat fs as an array.
3384 * *fs must not be JS_FS_END.
3385 */
3386 extern JS_PUBLIC_API(JSFunction*)
3387 NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id);
3388
3389 } /* namespace JS */
3390
3391 extern JS_PUBLIC_API(JSObject*)
3392 JS_GetFunctionObject(JSFunction* fun);
3393
3394 /**
3395 * Return the function's identifier as a JSString, or null if fun is unnamed.
3396 * The returned string lives as long as fun, so you don't need to root a saved
3397 * reference to it if fun is well-connected or rooted, and provided you bound
3398 * the use of the saved reference by fun's lifetime.
3399 */
3400 extern JS_PUBLIC_API(JSString*)
3401 JS_GetFunctionId(JSFunction* fun);
3402
3403 /**
3404 * Return a function's display name. This is the defined name if one was given
3405 * where the function was defined, or it could be an inferred name by the JS
3406 * engine in the case that the function was defined to be anonymous. This can
3407 * still return nullptr if a useful display name could not be inferred. The
3408 * same restrictions on rooting as those in JS_GetFunctionId apply.
3409 */
3410 extern JS_PUBLIC_API(JSString*)
3411 JS_GetFunctionDisplayId(JSFunction* fun);
3412
3413 /*
3414 * Return the arity (length) of fun.
3415 */
3416 extern JS_PUBLIC_API(uint16_t)
3417 JS_GetFunctionArity(JSFunction* fun);
3418
3419 /**
3420 * Infallible predicate to test whether obj is a function object (faster than
3421 * comparing obj's class name to "Function", but equivalent unless someone has
3422 * overwritten the "Function" identifier with a different constructor and then
3423 * created instances using that constructor that might be passed in as obj).
3424 */
3425 extern JS_PUBLIC_API(bool)
3426 JS_ObjectIsFunction(JSContext* cx, JSObject* obj);
3427
3428 extern JS_PUBLIC_API(bool)
3429 JS_IsNativeFunction(JSObject* funobj, JSNative call);
3430
3431 /** Return whether the given function is a valid constructor. */
3432 extern JS_PUBLIC_API(bool)
3433 JS_IsConstructor(JSFunction* fun);
3434
3435 /**
3436 * This enum is used to select if properties with JSPROP_DEFINE_LATE flag
3437 * should be defined on the object.
3438 * Normal JSAPI consumers probably always want DefineAllProperties here.
3439 */
3440 enum PropertyDefinitionBehavior {
3441 DefineAllProperties,
3442 OnlyDefineLateProperties,
3443 DontDefineLateProperties
3444 };
3445
3446 extern JS_PUBLIC_API(bool)
3447 JS_DefineFunctions(JSContext* cx, JS::Handle<JSObject*> obj, const JSFunctionSpec* fs,
3448 PropertyDefinitionBehavior behavior = DefineAllProperties);
3449
3450 extern JS_PUBLIC_API(JSFunction*)
3451 JS_DefineFunction(JSContext* cx, JS::Handle<JSObject*> obj, const char* name, JSNative call,
3452 unsigned nargs, unsigned attrs);
3453
3454 extern JS_PUBLIC_API(JSFunction*)
3455 JS_DefineUCFunction(JSContext* cx, JS::Handle<JSObject*> obj,
3456 const char16_t* name, size_t namelen, JSNative call,
3457 unsigned nargs, unsigned attrs);
3458
3459 extern JS_PUBLIC_API(JSFunction*)
3460 JS_DefineFunctionById(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSNative call,
3461 unsigned nargs, unsigned attrs);
3462
3463 namespace JS {
3464
3465 /**
3466 * Clone a top-level function into cx's global. This function will dynamically
3467 * fail if funobj was lexically nested inside some other function.
3468 */
3469 extern JS_PUBLIC_API(JSObject*)
3470 CloneFunctionObject(JSContext* cx, HandleObject funobj);
3471
3472 /**
3473 * As above, but providing an explicit scope chain. scopeChain must not include
3474 * the global object on it; that's implicit. It needs to contain the other
3475 * objects that should end up on the clone's scope chain.
3476 */
3477 extern JS_PUBLIC_API(JSObject*)
3478 CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& scopeChain);
3479
3480 } // namespace JS
3481
3482 /**
3483 * Given a buffer, return false if the buffer might become a valid
3484 * javascript statement with the addition of more lines. Otherwise return
3485 * true. The intent is to support interactive compilation - accumulate
3486 * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
3487 * the compiler.
3488 */
3489 extern JS_PUBLIC_API(bool)
3490 JS_BufferIsCompilableUnit(JSContext* cx, JS::Handle<JSObject*> obj, const char* utf8,
3491 size_t length);
3492
3493 /**
3494 * |script| will always be set. On failure, it will be set to nullptr.
3495 */
3496 extern JS_PUBLIC_API(bool)
3497 JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
3498 const JS::CompileOptions& options,
3499 JS::MutableHandleScript script);
3500
3501 /**
3502 * |script| will always be set. On failure, it will be set to nullptr.
3503 */
3504 extern JS_PUBLIC_API(bool)
3505 JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
3506 const JS::CompileOptions& options,
3507 JS::MutableHandleScript script);
3508
3509 extern JS_PUBLIC_API(JSObject*)
3510 JS_GetGlobalFromScript(JSScript* script);
3511
3512 extern JS_PUBLIC_API(const char*)
3513 JS_GetScriptFilename(JSScript* script);
3514
3515 extern JS_PUBLIC_API(unsigned)
3516 JS_GetScriptBaseLineNumber(JSContext* cx, JSScript* script);
3517
3518 extern JS_PUBLIC_API(JSScript*)
3519 JS_GetFunctionScript(JSContext* cx, JS::HandleFunction fun);
3520
3521 namespace JS {
3522
3523 /* Options for JavaScript compilation. */
3524
3525 /*
3526 * In the most common use case, a CompileOptions instance is allocated on the
3527 * stack, and holds non-owning references to non-POD option values: strings;
3528 * principals; objects; and so on. The code declaring the instance guarantees
3529 * that such option values will outlive the CompileOptions itself: objects are
3530 * otherwise rooted; principals have had their reference counts bumped; strings
3531 * will not be freed until the CompileOptions goes out of scope. In this
3532 * situation, CompileOptions only refers to things others own, so it can be
3533 * lightweight.
3534 *
3535 * In some cases, however, we need to hold compilation options with a
3536 * non-stack-like lifetime. For example, JS::CompileOffThread needs to save
3537 * compilation options where a worker thread can find them, and then return
3538 * immediately. The worker thread will come along at some later point, and use
3539 * the options.
3540 *
3541 * The compiler itself just needs to be able to access a collection of options;
3542 * it doesn't care who owns them, or what's keeping them alive. It does its own
3543 * addrefs/copies/tracing/etc.
3544 *
3545 * Furthermore, in some cases compile options are propagated from one entity to
3546 * another (e.g. from a scriipt to a function defined in that script). This
3547 * involves copying over some, but not all, of the options.
3548 *
3549 * So, we have a class hierarchy that reflects these four use cases:
3550 *
3551 * - TransitiveCompileOptions is the common base class, representing options
3552 * that should get propagated from a script to functions defined in that
3553 * script. This is never instantiated directly.
3554 *
3555 * - ReadOnlyCompileOptions is the only subclass of TransitiveCompileOptions,
3556 * representing a full set of compile options. It can be used by code that
3557 * simply needs to access options set elsewhere, like the compiler. This,
3558 * again, is never instantiated directly.
3559 *
3560 * - The usual CompileOptions class must be stack-allocated, and holds
3561 * non-owning references to the filename, element, and so on. It's derived
3562 * from ReadOnlyCompileOptions, so the compiler can use it.
3563 *
3564 * - OwningCompileOptions roots / copies / reference counts of all its values,
3565 * and unroots / frees / releases them when it is destructed. It too is
3566 * derived from ReadOnlyCompileOptions, so the compiler accepts it.
3567 */
3568
3569 enum class AsmJSOption : uint8_t { Enabled, Disabled, DisabledByDebugger };
3570
3571 /**
3572 * The common base class for the CompileOptions hierarchy.
3573 *
3574 * Use this in code that needs to propagate compile options from one compilation
3575 * unit to another.
3576 */
JS_FRIEND_API(TransitiveCompileOptions)3577 class JS_FRIEND_API(TransitiveCompileOptions)
3578 {
3579 protected:
3580 // The Web Platform allows scripts to be loaded from arbitrary cross-origin
3581 // sources. This allows an attack by which a malicious website loads a
3582 // sensitive file (say, a bank statement) cross-origin (using the user's
3583 // cookies), and sniffs the generated syntax errors (via a window.onerror
3584 // handler) for juicy morsels of its contents.
3585 //
3586 // To counter this attack, HTML5 specifies that script errors should be
3587 // sanitized ("muted") when the script is not same-origin with the global
3588 // for which it is loaded. Callers should set this flag for cross-origin
3589 // scripts, and it will be propagated appropriately to child scripts and
3590 // passed back in JSErrorReports.
3591 bool mutedErrors_;
3592 const char* filename_;
3593 const char* introducerFilename_;
3594 const char16_t* sourceMapURL_;
3595
3596 // This constructor leaves 'version' set to JSVERSION_UNKNOWN. The structure
3597 // is unusable until that's set to something more specific; the derived
3598 // classes' constructors take care of that, in ways appropriate to their
3599 // purpose.
3600 TransitiveCompileOptions()
3601 : mutedErrors_(false),
3602 filename_(nullptr),
3603 introducerFilename_(nullptr),
3604 sourceMapURL_(nullptr),
3605 version(JSVERSION_UNKNOWN),
3606 versionSet(false),
3607 utf8(false),
3608 selfHostingMode(false),
3609 canLazilyParse(true),
3610 strictOption(false),
3611 extraWarningsOption(false),
3612 werrorOption(false),
3613 asmJSOption(AsmJSOption::Disabled),
3614 throwOnAsmJSValidationFailureOption(false),
3615 forceAsync(false),
3616 installedFile(false),
3617 sourceIsLazy(false),
3618 introductionType(nullptr),
3619 introductionLineno(0),
3620 introductionOffset(0),
3621 hasIntroductionInfo(false)
3622 { }
3623
3624 // Set all POD options (those not requiring reference counts, copies,
3625 // rooting, or other hand-holding) to their values in |rhs|.
3626 void copyPODTransitiveOptions(const TransitiveCompileOptions& rhs);
3627
3628 public:
3629 // Read-only accessors for non-POD options. The proper way to set these
3630 // depends on the derived type.
3631 bool mutedErrors() const { return mutedErrors_; }
3632 const char* filename() const { return filename_; }
3633 const char* introducerFilename() const { return introducerFilename_; }
3634 const char16_t* sourceMapURL() const { return sourceMapURL_; }
3635 virtual JSObject* element() const = 0;
3636 virtual JSString* elementAttributeName() const = 0;
3637 virtual JSScript* introductionScript() const = 0;
3638
3639 // POD options.
3640 JSVersion version;
3641 bool versionSet;
3642 bool utf8;
3643 bool selfHostingMode;
3644 bool canLazilyParse;
3645 bool strictOption;
3646 bool extraWarningsOption;
3647 bool werrorOption;
3648 AsmJSOption asmJSOption;
3649 bool throwOnAsmJSValidationFailureOption;
3650 bool forceAsync;
3651 bool installedFile; // 'true' iff pre-compiling js file in packaged app
3652 bool sourceIsLazy;
3653
3654 // |introductionType| is a statically allocated C string:
3655 // one of "eval", "Function", or "GeneratorFunction".
3656 const char* introductionType;
3657 unsigned introductionLineno;
3658 uint32_t introductionOffset;
3659 bool hasIntroductionInfo;
3660
3661 private:
3662 void operator=(const TransitiveCompileOptions&) = delete;
3663 };
3664
3665 /**
3666 * The class representing a full set of compile options.
3667 *
3668 * Use this in code that only needs to access compilation options created
3669 * elsewhere, like the compiler. Don't instantiate this class (the constructor
3670 * is protected anyway); instead, create instances only of the derived classes:
3671 * CompileOptions and OwningCompileOptions.
3672 */
JS_FRIEND_API(ReadOnlyCompileOptions)3673 class JS_FRIEND_API(ReadOnlyCompileOptions) : public TransitiveCompileOptions
3674 {
3675 friend class CompileOptions;
3676
3677 protected:
3678 ReadOnlyCompileOptions()
3679 : TransitiveCompileOptions(),
3680 lineno(1),
3681 column(0),
3682 isRunOnce(false),
3683 forEval(false),
3684 noScriptRval(false)
3685 { }
3686
3687 // Set all POD options (those not requiring reference counts, copies,
3688 // rooting, or other hand-holding) to their values in |rhs|.
3689 void copyPODOptions(const ReadOnlyCompileOptions& rhs);
3690
3691 public:
3692 // Read-only accessors for non-POD options. The proper way to set these
3693 // depends on the derived type.
3694 bool mutedErrors() const { return mutedErrors_; }
3695 const char* filename() const { return filename_; }
3696 const char* introducerFilename() const { return introducerFilename_; }
3697 const char16_t* sourceMapURL() const { return sourceMapURL_; }
3698 virtual JSObject* element() const = 0;
3699 virtual JSString* elementAttributeName() const = 0;
3700 virtual JSScript* introductionScript() const = 0;
3701
3702 // POD options.
3703 unsigned lineno;
3704 unsigned column;
3705 // isRunOnce only applies to non-function scripts.
3706 bool isRunOnce;
3707 bool forEval;
3708 bool noScriptRval;
3709
3710 private:
3711 void operator=(const ReadOnlyCompileOptions&) = delete;
3712 };
3713
3714 /**
3715 * Compilation options, with dynamic lifetime. An instance of this type
3716 * makes a copy of / holds / roots all dynamically allocated resources
3717 * (principals; elements; strings) that it refers to. Its destructor frees
3718 * / drops / unroots them. This is heavier than CompileOptions, below, but
3719 * unlike CompileOptions, it can outlive any given stack frame.
3720 *
3721 * Note that this *roots* any JS values it refers to - they're live
3722 * unconditionally. Thus, instances of this type can't be owned, directly
3723 * or indirectly, by a JavaScript object: if any value that this roots ever
3724 * comes to refer to the object that owns this, then the whole cycle, and
3725 * anything else it entrains, will never be freed.
3726 */
JS_FRIEND_API(OwningCompileOptions)3727 class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
3728 {
3729 JSRuntime* runtime;
3730 PersistentRootedObject elementRoot;
3731 PersistentRootedString elementAttributeNameRoot;
3732 PersistentRootedScript introductionScriptRoot;
3733
3734 public:
3735 // A minimal constructor, for use with OwningCompileOptions::copy. This
3736 // leaves |this.version| set to JSVERSION_UNKNOWN; the instance
3737 // shouldn't be used until we've set that to something real (as |copy|
3738 // will).
3739 explicit OwningCompileOptions(JSContext* cx);
3740 ~OwningCompileOptions();
3741
3742 JSObject* element() const override { return elementRoot; }
3743 JSString* elementAttributeName() const override { return elementAttributeNameRoot; }
3744 JSScript* introductionScript() const override { return introductionScriptRoot; }
3745
3746 // Set this to a copy of |rhs|. Return false on OOM.
3747 bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs);
3748
3749 /* These setters make copies of their string arguments, and are fallible. */
3750 bool setFile(JSContext* cx, const char* f);
3751 bool setFileAndLine(JSContext* cx, const char* f, unsigned l);
3752 bool setSourceMapURL(JSContext* cx, const char16_t* s);
3753 bool setIntroducerFilename(JSContext* cx, const char* s);
3754
3755 /* These setters are infallible, and can be chained. */
3756 OwningCompileOptions& setLine(unsigned l) { lineno = l; return *this; }
3757 OwningCompileOptions& setElement(JSObject* e) {
3758 elementRoot = e;
3759 return *this;
3760 }
3761 OwningCompileOptions& setElementAttributeName(JSString* p) {
3762 elementAttributeNameRoot = p;
3763 return *this;
3764 }
3765 OwningCompileOptions& setIntroductionScript(JSScript* s) {
3766 introductionScriptRoot = s;
3767 return *this;
3768 }
3769 OwningCompileOptions& setMutedErrors(bool mute) {
3770 mutedErrors_ = mute;
3771 return *this;
3772 }
3773 OwningCompileOptions& setVersion(JSVersion v) {
3774 version = v;
3775 versionSet = true;
3776 return *this;
3777 }
3778 OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
3779 OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
3780 OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
3781 OwningCompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
3782 OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
3783 OwningCompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
3784 OwningCompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
3785 OwningCompileOptions& setSourceIsLazy(bool l) { sourceIsLazy = l; return *this; }
3786 OwningCompileOptions& setIntroductionType(const char* t) { introductionType = t; return *this; }
3787 bool setIntroductionInfo(JSContext* cx, const char* introducerFn, const char* intro,
3788 unsigned line, JSScript* script, uint32_t offset)
3789 {
3790 if (!setIntroducerFilename(cx, introducerFn))
3791 return false;
3792 introductionType = intro;
3793 introductionLineno = line;
3794 introductionScriptRoot = script;
3795 introductionOffset = offset;
3796 hasIntroductionInfo = true;
3797 return true;
3798 }
3799
3800 private:
3801 void operator=(const CompileOptions& rhs) = delete;
3802 };
3803
3804 /**
3805 * Compilation options stored on the stack. An instance of this type
3806 * simply holds references to dynamically allocated resources (element;
3807 * filename; source map URL) that are owned by something else. If you
3808 * create an instance of this type, it's up to you to guarantee that
3809 * everything you store in it will outlive it.
3810 */
JS_FRIEND_API(CompileOptions)3811 class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOptions
3812 {
3813 RootedObject elementRoot;
3814 RootedString elementAttributeNameRoot;
3815 RootedScript introductionScriptRoot;
3816
3817 public:
3818 explicit CompileOptions(JSContext* cx, JSVersion version = JSVERSION_UNKNOWN);
3819 CompileOptions(js::ContextFriendFields* cx, const ReadOnlyCompileOptions& rhs)
3820 : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
3821 introductionScriptRoot(cx)
3822 {
3823 copyPODOptions(rhs);
3824
3825 filename_ = rhs.filename();
3826 introducerFilename_ = rhs.introducerFilename();
3827 sourceMapURL_ = rhs.sourceMapURL();
3828 elementRoot = rhs.element();
3829 elementAttributeNameRoot = rhs.elementAttributeName();
3830 introductionScriptRoot = rhs.introductionScript();
3831 }
3832
3833 CompileOptions(js::ContextFriendFields* cx, const TransitiveCompileOptions& rhs)
3834 : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
3835 introductionScriptRoot(cx)
3836 {
3837 copyPODTransitiveOptions(rhs);
3838
3839 filename_ = rhs.filename();
3840 introducerFilename_ = rhs.introducerFilename();
3841 sourceMapURL_ = rhs.sourceMapURL();
3842 elementRoot = rhs.element();
3843 elementAttributeNameRoot = rhs.elementAttributeName();
3844 introductionScriptRoot = rhs.introductionScript();
3845 }
3846
3847 JSObject* element() const override { return elementRoot; }
3848 JSString* elementAttributeName() const override { return elementAttributeNameRoot; }
3849 JSScript* introductionScript() const override { return introductionScriptRoot; }
3850
3851 CompileOptions& setFile(const char* f) { filename_ = f; return *this; }
3852 CompileOptions& setLine(unsigned l) { lineno = l; return *this; }
3853 CompileOptions& setFileAndLine(const char* f, unsigned l) {
3854 filename_ = f; lineno = l; return *this;
3855 }
3856 CompileOptions& setSourceMapURL(const char16_t* s) { sourceMapURL_ = s; return *this; }
3857 CompileOptions& setElement(JSObject* e) { elementRoot = e; return *this; }
3858 CompileOptions& setElementAttributeName(JSString* p) {
3859 elementAttributeNameRoot = p;
3860 return *this;
3861 }
3862 CompileOptions& setIntroductionScript(JSScript* s) {
3863 introductionScriptRoot = s;
3864 return *this;
3865 }
3866 CompileOptions& setMutedErrors(bool mute) {
3867 mutedErrors_ = mute;
3868 return *this;
3869 }
3870 CompileOptions& setVersion(JSVersion v) {
3871 version = v;
3872 versionSet = true;
3873 return *this;
3874 }
3875 CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
3876 CompileOptions& setColumn(unsigned c) { column = c; return *this; }
3877 CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
3878 CompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
3879 CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
3880 CompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
3881 CompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
3882 CompileOptions& setSourceIsLazy(bool l) { sourceIsLazy = l; return *this; }
3883 CompileOptions& setIntroductionType(const char* t) { introductionType = t; return *this; }
3884 CompileOptions& setIntroductionInfo(const char* introducerFn, const char* intro,
3885 unsigned line, JSScript* script, uint32_t offset)
3886 {
3887 introducerFilename_ = introducerFn;
3888 introductionType = intro;
3889 introductionLineno = line;
3890 introductionScriptRoot = script;
3891 introductionOffset = offset;
3892 hasIntroductionInfo = true;
3893 return *this;
3894 }
3895 CompileOptions& maybeMakeStrictMode(bool strict) {
3896 strictOption = strictOption || strict;
3897 return *this;
3898 }
3899
3900 private:
3901 void operator=(const CompileOptions& rhs) = delete;
3902 };
3903
3904 /**
3905 * |script| will always be set. On failure, it will be set to nullptr.
3906 */
3907 extern JS_PUBLIC_API(bool)
3908 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3909 SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
3910
3911 extern JS_PUBLIC_API(bool)
3912 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3913 const char* bytes, size_t length, JS::MutableHandleScript script);
3914
3915 extern JS_PUBLIC_API(bool)
3916 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3917 const char16_t* chars, size_t length, JS::MutableHandleScript script);
3918
3919 extern JS_PUBLIC_API(bool)
3920 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3921 FILE* file, JS::MutableHandleScript script);
3922
3923 extern JS_PUBLIC_API(bool)
3924 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3925 const char* filename, JS::MutableHandleScript script);
3926
3927 extern JS_PUBLIC_API(bool)
3928 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
3929 SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
3930
3931 extern JS_PUBLIC_API(bool)
3932 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
3933 const char* bytes, size_t length, JS::MutableHandleScript script);
3934
3935 extern JS_PUBLIC_API(bool)
3936 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
3937 const char16_t* chars, size_t length, JS::MutableHandleScript script);
3938
3939 extern JS_PUBLIC_API(bool)
3940 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
3941 FILE* file, JS::MutableHandleScript script);
3942
3943 extern JS_PUBLIC_API(bool)
3944 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
3945 const char* filename, JS::MutableHandleScript script);
3946
3947 extern JS_PUBLIC_API(bool)
3948 CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
3949
3950 /*
3951 * Off thread compilation control flow.
3952 *
3953 * After successfully triggering an off thread compile of a script, the
3954 * callback will eventually be invoked with the specified data and a token
3955 * for the compilation. The callback will be invoked while off the main thread,
3956 * so must ensure that its operations are thread safe. Afterwards,
3957 * FinishOffThreadScript must be invoked on the main thread to get the result
3958 * script or nullptr. If maybecx is not specified, the resources will be freed,
3959 * but no script will be returned.
3960 *
3961 * The characters passed in to CompileOffThread must remain live until the
3962 * callback is invoked, and the resulting script will be rooted until the call
3963 * to FinishOffThreadScript.
3964 */
3965
3966 extern JS_PUBLIC_API(bool)
3967 CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
3968 const char16_t* chars, size_t length,
3969 OffThreadCompileCallback callback, void* callbackData);
3970
3971 extern JS_PUBLIC_API(JSScript*)
3972 FinishOffThreadScript(JSContext* maybecx, JSRuntime* rt, void* token);
3973
3974 /**
3975 * Compile a function with scopeChain plus the global as its scope chain.
3976 * scopeChain must contain objects in the current compartment of cx. The actual
3977 * scope chain used for the function will consist of With wrappers for those
3978 * objects, followed by the current global of the compartment cx is in. This
3979 * global must not be explicitly included in the scope chain.
3980 */
3981 extern JS_PUBLIC_API(bool)
3982 CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
3983 const ReadOnlyCompileOptions& options,
3984 const char* name, unsigned nargs, const char* const* argnames,
3985 const char16_t* chars, size_t length, JS::MutableHandleFunction fun);
3986
3987 /**
3988 * Same as above, but taking a SourceBufferHolder for the function body.
3989 */
3990 extern JS_PUBLIC_API(bool)
3991 CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
3992 const ReadOnlyCompileOptions& options,
3993 const char* name, unsigned nargs, const char* const* argnames,
3994 SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun);
3995
3996 /**
3997 * Same as above, but taking a const char * for the function body.
3998 */
3999 extern JS_PUBLIC_API(bool)
4000 CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
4001 const ReadOnlyCompileOptions& options,
4002 const char* name, unsigned nargs, const char* const* argnames,
4003 const char* bytes, size_t length, JS::MutableHandleFunction fun);
4004
4005 } /* namespace JS */
4006
4007 extern JS_PUBLIC_API(JSString*)
4008 JS_DecompileScript(JSContext* cx, JS::Handle<JSScript*> script, const char* name, unsigned indent);
4009
4010 /*
4011 * API extension: OR this into indent to avoid pretty-printing the decompiled
4012 * source resulting from JS_DecompileFunction.
4013 */
4014 #define JS_DONT_PRETTY_PRINT ((unsigned)0x8000)
4015
4016 extern JS_PUBLIC_API(JSString*)
4017 JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned indent);
4018
4019
4020 /*
4021 * NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either
4022 * they use the global as the scope, or they take an AutoObjectVector of objects
4023 * to use as the scope chain. In the former case, the global is also used as
4024 * the "this" keyword value and the variables object (ECMA parlance for where
4025 * 'var' and 'function' bind names) of the execution context for script. In the
4026 * latter case, the first object in the provided list is used, unless the list
4027 * is empty, in which case the global is used.
4028 *
4029 * Why a runtime option? The alternative is to add APIs duplicating those
4030 * for the other value of flags, and that doesn't seem worth the code bloat
4031 * cost. Such new entry points would probably have less obvious names, too, so
4032 * would not tend to be used. The RuntimeOptionsRef adjustment, OTOH, can be
4033 * more easily hacked into existing code that does not depend on the bug; such
4034 * code can continue to use the familiar JS::Evaluate, etc., entry points.
4035 */
4036
4037 /**
4038 * Evaluate a script in the scope of the current global of cx.
4039 */
4040 extern JS_PUBLIC_API(bool)
4041 JS_ExecuteScript(JSContext* cx, JS::HandleScript script, JS::MutableHandleValue rval);
4042
4043 extern JS_PUBLIC_API(bool)
4044 JS_ExecuteScript(JSContext* cx, JS::HandleScript script);
4045
4046 /**
4047 * As above, but providing an explicit scope chain. scopeChain must not include
4048 * the global object on it; that's implicit. It needs to contain the other
4049 * objects that should end up on the script's scope chain.
4050 */
4051 extern JS_PUBLIC_API(bool)
4052 JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& scopeChain,
4053 JS::HandleScript script, JS::MutableHandleValue rval);
4054
4055 extern JS_PUBLIC_API(bool)
4056 JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& scopeChain, JS::HandleScript script);
4057
4058 namespace JS {
4059
4060 /**
4061 * Like the above, but handles a cross-compartment script. If the script is
4062 * cross-compartment, it is cloned into the current compartment before executing.
4063 */
4064 extern JS_PUBLIC_API(bool)
4065 CloneAndExecuteScript(JSContext* cx, JS::Handle<JSScript*> script);
4066
4067 } /* namespace JS */
4068
4069 namespace JS {
4070
4071 /**
4072 * Evaluate the given source buffer in the scope of the current global of cx.
4073 */
4074 extern JS_PUBLIC_API(bool)
4075 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
4076 SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
4077
4078 /**
4079 * As above, but providing an explicit scope chain. scopeChain must not include
4080 * the global object on it; that's implicit. It needs to contain the other
4081 * objects that should end up on the script's scope chain.
4082 */
4083 extern JS_PUBLIC_API(bool)
4084 Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptions& options,
4085 SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
4086
4087 /**
4088 * Evaluate the given character buffer in the scope of the current global of cx.
4089 */
4090 extern JS_PUBLIC_API(bool)
4091 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
4092 const char16_t* chars, size_t length, JS::MutableHandleValue rval);
4093
4094 /**
4095 * As above, but providing an explicit scope chain. scopeChain must not include
4096 * the global object on it; that's implicit. It needs to contain the other
4097 * objects that should end up on the script's scope chain.
4098 */
4099 extern JS_PUBLIC_API(bool)
4100 Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptions& options,
4101 const char16_t* chars, size_t length, JS::MutableHandleValue rval);
4102
4103 /**
4104 * Evaluate the given byte buffer in the scope of the current global of cx.
4105 */
4106 extern JS_PUBLIC_API(bool)
4107 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
4108 const char* bytes, size_t length, JS::MutableHandleValue rval);
4109
4110 /**
4111 * Evaluate the given file in the scope of the current global of cx.
4112 */
4113 extern JS_PUBLIC_API(bool)
4114 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
4115 const char* filename, JS::MutableHandleValue rval);
4116
4117 } /* namespace JS */
4118
4119 extern JS_PUBLIC_API(bool)
4120 JS_CheckForInterrupt(JSContext* cx);
4121
4122 /*
4123 * These functions allow setting an interrupt callback that will be called
4124 * from the JS thread some time after any thread triggered the callback using
4125 * JS_RequestInterruptCallback(rt).
4126 *
4127 * To schedule the GC and for other activities the engine internally triggers
4128 * interrupt callbacks. The embedding should thus not rely on callbacks being
4129 * triggered through the external API only.
4130 *
4131 * Important note: Additional callbacks can occur inside the callback handler
4132 * if it re-enters the JS engine. The embedding must ensure that the callback
4133 * is disconnected before attempting such re-entry.
4134 */
4135 extern JS_PUBLIC_API(JSInterruptCallback)
4136 JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback);
4137
4138 extern JS_PUBLIC_API(JSInterruptCallback)
4139 JS_GetInterruptCallback(JSRuntime* rt);
4140
4141 extern JS_PUBLIC_API(void)
4142 JS_RequestInterruptCallback(JSRuntime* rt);
4143
4144 extern JS_PUBLIC_API(bool)
4145 JS_IsRunning(JSContext* cx);
4146
4147 /*
4148 * Saving and restoring frame chains.
4149 *
4150 * These two functions are used to set aside cx's call stack while that stack
4151 * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no
4152 * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack
4153 * must be balanced and all nested calls to JS_SaveFrameChain must have had
4154 * matching JS_RestoreFrameChain calls.
4155 *
4156 * JS_SaveFrameChain deals with cx not having any code running on it.
4157 */
4158 extern JS_PUBLIC_API(bool)
4159 JS_SaveFrameChain(JSContext* cx);
4160
4161 extern JS_PUBLIC_API(void)
4162 JS_RestoreFrameChain(JSContext* cx);
4163
4164 namespace JS {
4165
4166 /**
4167 * This class can be used to store a pointer to the youngest frame of a saved
4168 * stack in the specified JSContext. This reference will be picked up by any new
4169 * calls performed until the class is destroyed, with the specified asyncCause,
4170 * that must not be empty.
4171 *
4172 * Any stack capture initiated during these new calls will go through the async
4173 * stack instead of the current stack.
4174 *
4175 * Capturing the stack before a new call is performed will not be affected.
4176 *
4177 * The provided chain of SavedFrame objects can live in any compartment,
4178 * although it will be copied to the compartment where the stack is captured.
4179 *
4180 * See also `js/src/doc/SavedFrame/SavedFrame.md` for documentation on async
4181 * stack frames.
4182 */
JS_PUBLIC_API(AutoSetAsyncStackForNewCalls)4183 class MOZ_STACK_CLASS JS_PUBLIC_API(AutoSetAsyncStackForNewCalls)
4184 {
4185 JSContext* cx;
4186 RootedObject oldAsyncStack;
4187 RootedString oldAsyncCause;
4188 bool oldAsyncCallIsExplicit;
4189
4190 public:
4191 enum class AsyncCallKind {
4192 // The ordinary kind of call, where we may apply an async
4193 // parent if there is no ordinary parent.
4194 IMPLICIT,
4195 // An explicit async parent, e.g., callFunctionWithAsyncStack,
4196 // where we always want to override any ordinary parent.
4197 EXPLICIT
4198 };
4199
4200 // The stack parameter cannot be null by design, because it would be
4201 // ambiguous whether that would clear any scheduled async stack and make the
4202 // normal stack reappear in the new call, or just keep the async stack
4203 // already scheduled for the new call, if any.
4204 AutoSetAsyncStackForNewCalls(JSContext* cx, HandleObject stack,
4205 HandleString asyncCause,
4206 AsyncCallKind kind = AsyncCallKind::IMPLICIT);
4207 ~AutoSetAsyncStackForNewCalls();
4208 };
4209
4210 } // namespace JS
4211
4212 /************************************************************************/
4213
4214 /*
4215 * Strings.
4216 *
4217 * NB: JS_NewUCString takes ownership of bytes on success, avoiding a copy;
4218 * but on error (signified by null return), it leaves chars owned by the
4219 * caller. So the caller must free bytes in the error case, if it has no use
4220 * for them. In contrast, all the JS_New*StringCopy* functions do not take
4221 * ownership of the character memory passed to them -- they copy it.
4222 */
4223 extern JS_PUBLIC_API(JSString*)
4224 JS_NewStringCopyN(JSContext* cx, const char* s, size_t n);
4225
4226 extern JS_PUBLIC_API(JSString*)
4227 JS_NewStringCopyZ(JSContext* cx, const char* s);
4228
4229 extern JS_PUBLIC_API(JSString*)
4230 JS_AtomizeAndPinJSString(JSContext* cx, JS::HandleString str);
4231
4232 extern JS_PUBLIC_API(JSString*)
4233 JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length);
4234
4235 extern JS_PUBLIC_API(JSString*)
4236 JS_AtomizeAndPinString(JSContext* cx, const char* s);
4237
4238 extern JS_PUBLIC_API(JSString*)
4239 JS_NewUCString(JSContext* cx, char16_t* chars, size_t length);
4240
4241 extern JS_PUBLIC_API(JSString*)
4242 JS_NewUCStringCopyN(JSContext* cx, const char16_t* s, size_t n);
4243
4244 extern JS_PUBLIC_API(JSString*)
4245 JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s);
4246
4247 extern JS_PUBLIC_API(JSString*)
4248 JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length);
4249
4250 extern JS_PUBLIC_API(JSString*)
4251 JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s);
4252
4253 extern JS_PUBLIC_API(bool)
4254 JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result);
4255
4256 extern JS_PUBLIC_API(bool)
4257 JS_StringEqualsAscii(JSContext* cx, JSString* str, const char* asciiBytes, bool* match);
4258
4259 extern JS_PUBLIC_API(size_t)
4260 JS_PutEscapedString(JSContext* cx, char* buffer, size_t size, JSString* str, char quote);
4261
4262 extern JS_PUBLIC_API(bool)
4263 JS_FileEscapedString(FILE* fp, JSString* str, char quote);
4264
4265 /*
4266 * Extracting string characters and length.
4267 *
4268 * While getting the length of a string is infallible, getting the chars can
4269 * fail. As indicated by the lack of a JSContext parameter, there are two
4270 * special cases where getting the chars is infallible:
4271 *
4272 * The first case is for strings that have been atomized, e.g. directly by
4273 * JS_AtomizeAndPinString or implicitly because it is stored in a jsid.
4274 *
4275 * The second case is "flat" strings that have been explicitly prepared in a
4276 * fallible context by JS_FlattenString. To catch errors, a separate opaque
4277 * JSFlatString type is returned by JS_FlattenString and expected by
4278 * JS_GetFlatStringChars. Note, though, that this is purely a syntactic
4279 * distinction: the input and output of JS_FlattenString are the same actual
4280 * GC-thing. If a JSString is known to be flat, JS_ASSERT_STRING_IS_FLAT can be
4281 * used to make a debug-checked cast. Example:
4282 *
4283 * // in a fallible context
4284 * JSFlatString* fstr = JS_FlattenString(cx, str);
4285 * if (!fstr)
4286 * return false;
4287 * MOZ_ASSERT(fstr == JS_ASSERT_STRING_IS_FLAT(str));
4288 *
4289 * // in an infallible context, for the same 'str'
4290 * AutoCheckCannotGC nogc;
4291 * const char16_t* chars = JS_GetTwoByteFlatStringChars(nogc, fstr)
4292 * MOZ_ASSERT(chars);
4293 *
4294 * Flat strings and interned strings are always null-terminated, so
4295 * JS_FlattenString can be used to get a null-terminated string.
4296 *
4297 * Additionally, string characters are stored as either Latin1Char (8-bit)
4298 * or char16_t (16-bit). Clients can use JS_StringHasLatin1Chars and can then
4299 * call either the Latin1* or TwoByte* functions. Some functions like
4300 * JS_CopyStringChars and JS_GetStringCharAt accept both Latin1 and TwoByte
4301 * strings.
4302 */
4303
4304 extern JS_PUBLIC_API(size_t)
4305 JS_GetStringLength(JSString* str);
4306
4307 extern JS_PUBLIC_API(bool)
4308 JS_StringIsFlat(JSString* str);
4309
4310 /** Returns true iff the string's characters are stored as Latin1. */
4311 extern JS_PUBLIC_API(bool)
4312 JS_StringHasLatin1Chars(JSString* str);
4313
4314 extern JS_PUBLIC_API(const JS::Latin1Char*)
4315 JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
4316 size_t* length);
4317
4318 extern JS_PUBLIC_API(const char16_t*)
4319 JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
4320 size_t* length);
4321
4322 extern JS_PUBLIC_API(bool)
4323 JS_GetStringCharAt(JSContext* cx, JSString* str, size_t index, char16_t* res);
4324
4325 extern JS_PUBLIC_API(char16_t)
4326 JS_GetFlatStringCharAt(JSFlatString* str, size_t index);
4327
4328 extern JS_PUBLIC_API(const char16_t*)
4329 JS_GetTwoByteExternalStringChars(JSString* str);
4330
4331 extern JS_PUBLIC_API(bool)
4332 JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str);
4333
4334 extern JS_PUBLIC_API(JSFlatString*)
4335 JS_FlattenString(JSContext* cx, JSString* str);
4336
4337 extern JS_PUBLIC_API(const JS::Latin1Char*)
4338 JS_GetLatin1FlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str);
4339
4340 extern JS_PUBLIC_API(const char16_t*)
4341 JS_GetTwoByteFlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str);
4342
4343 static MOZ_ALWAYS_INLINE JSFlatString*
JSID_TO_FLAT_STRING(jsid id)4344 JSID_TO_FLAT_STRING(jsid id)
4345 {
4346 MOZ_ASSERT(JSID_IS_STRING(id));
4347 return (JSFlatString*)(JSID_BITS(id));
4348 }
4349
4350 static MOZ_ALWAYS_INLINE JSFlatString*
JS_ASSERT_STRING_IS_FLAT(JSString * str)4351 JS_ASSERT_STRING_IS_FLAT(JSString* str)
4352 {
4353 MOZ_ASSERT(JS_StringIsFlat(str));
4354 return (JSFlatString*)str;
4355 }
4356
4357 static MOZ_ALWAYS_INLINE JSString*
JS_FORGET_STRING_FLATNESS(JSFlatString * fstr)4358 JS_FORGET_STRING_FLATNESS(JSFlatString* fstr)
4359 {
4360 return (JSString*)fstr;
4361 }
4362
4363 /*
4364 * Additional APIs that avoid fallibility when given a flat string.
4365 */
4366
4367 extern JS_PUBLIC_API(bool)
4368 JS_FlatStringEqualsAscii(JSFlatString* str, const char* asciiBytes);
4369
4370 extern JS_PUBLIC_API(size_t)
4371 JS_PutEscapedFlatString(char* buffer, size_t size, JSFlatString* str, char quote);
4372
4373 /**
4374 * Create a dependent string, i.e., a string that owns no character storage,
4375 * but that refers to a slice of another string's chars. Dependent strings
4376 * are mutable by definition, so the thread safety comments above apply.
4377 */
4378 extern JS_PUBLIC_API(JSString*)
4379 JS_NewDependentString(JSContext* cx, JS::HandleString str, size_t start,
4380 size_t length);
4381
4382 /**
4383 * Concatenate two strings, possibly resulting in a rope.
4384 * See above for thread safety comments.
4385 */
4386 extern JS_PUBLIC_API(JSString*)
4387 JS_ConcatStrings(JSContext* cx, JS::HandleString left, JS::HandleString right);
4388
4389 /**
4390 * For JS_DecodeBytes, set *dstlenp to the size of the destination buffer before
4391 * the call; on return, *dstlenp contains the number of characters actually
4392 * stored. To determine the necessary destination buffer size, make a sizing
4393 * call that passes nullptr for dst.
4394 *
4395 * On errors, the functions report the error. In that case, *dstlenp contains
4396 * the number of characters or bytes transferred so far. If cx is nullptr, no
4397 * error is reported on failure, and the functions simply return false.
4398 *
4399 * NB: This function does not store an additional zero byte or char16_t after the
4400 * transcoded string.
4401 */
4402 JS_PUBLIC_API(bool)
4403 JS_DecodeBytes(JSContext* cx, const char* src, size_t srclen, char16_t* dst,
4404 size_t* dstlenp);
4405
4406 /**
4407 * A variation on JS_EncodeCharacters where a null terminated string is
4408 * returned that you are expected to call JS_free on when done.
4409 */
4410 JS_PUBLIC_API(char*)
4411 JS_EncodeString(JSContext* cx, JSString* str);
4412
4413 /**
4414 * Same behavior as JS_EncodeString(), but encode into UTF-8 string
4415 */
4416 JS_PUBLIC_API(char*)
4417 JS_EncodeStringToUTF8(JSContext* cx, JS::HandleString str);
4418
4419 /**
4420 * Get number of bytes in the string encoding (without accounting for a
4421 * terminating zero bytes. The function returns (size_t) -1 if the string
4422 * can not be encoded into bytes and reports an error using cx accordingly.
4423 */
4424 JS_PUBLIC_API(size_t)
4425 JS_GetStringEncodingLength(JSContext* cx, JSString* str);
4426
4427 /**
4428 * Encode string into a buffer. The function does not stores an additional
4429 * zero byte. The function returns (size_t) -1 if the string can not be
4430 * encoded into bytes with no error reported. Otherwise it returns the number
4431 * of bytes that are necessary to encode the string. If that exceeds the
4432 * length parameter, the string will be cut and only length bytes will be
4433 * written into the buffer.
4434 */
4435 JS_PUBLIC_API(size_t)
4436 JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length);
4437
4438 class MOZ_RAII JSAutoByteString
4439 {
4440 public:
JSAutoByteString(JSContext * cx,JSString * str MOZ_GUARD_OBJECT_NOTIFIER_PARAM)4441 JSAutoByteString(JSContext* cx, JSString* str
4442 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
4443 : mBytes(JS_EncodeString(cx, str))
4444 {
4445 MOZ_ASSERT(cx);
4446 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
4447 }
4448
JSAutoByteString(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)4449 explicit JSAutoByteString(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
4450 : mBytes(nullptr)
4451 {
4452 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
4453 }
4454
~JSAutoByteString()4455 ~JSAutoByteString() {
4456 JS_free(nullptr, mBytes);
4457 }
4458
4459 /* Take ownership of the given byte array. */
initBytes(char * bytes)4460 void initBytes(char* bytes) {
4461 MOZ_ASSERT(!mBytes);
4462 mBytes = bytes;
4463 }
4464
encodeLatin1(JSContext * cx,JSString * str)4465 char* encodeLatin1(JSContext* cx, JSString* str) {
4466 MOZ_ASSERT(!mBytes);
4467 MOZ_ASSERT(cx);
4468 mBytes = JS_EncodeString(cx, str);
4469 return mBytes;
4470 }
4471
4472 char* encodeLatin1(js::ExclusiveContext* cx, JSString* str);
4473
encodeUtf8(JSContext * cx,JS::HandleString str)4474 char* encodeUtf8(JSContext* cx, JS::HandleString str) {
4475 MOZ_ASSERT(!mBytes);
4476 MOZ_ASSERT(cx);
4477 mBytes = JS_EncodeStringToUTF8(cx, str);
4478 return mBytes;
4479 }
4480
clear()4481 void clear() {
4482 js_free(mBytes);
4483 mBytes = nullptr;
4484 }
4485
ptr()4486 char* ptr() const {
4487 return mBytes;
4488 }
4489
4490 bool operator!() const {
4491 return !mBytes;
4492 }
4493
length()4494 size_t length() const {
4495 if (!mBytes)
4496 return 0;
4497 return strlen(mBytes);
4498 }
4499
4500 private:
4501 char* mBytes;
4502 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
4503
4504 /* Copy and assignment are not supported. */
4505 JSAutoByteString(const JSAutoByteString& another);
4506 JSAutoByteString& operator=(const JSAutoByteString& another);
4507 };
4508
4509 namespace JS {
4510
4511 extern JS_PUBLIC_API(JSAddonId*)
4512 NewAddonId(JSContext* cx, JS::HandleString str);
4513
4514 extern JS_PUBLIC_API(JSString*)
4515 StringOfAddonId(JSAddonId* id);
4516
4517 extern JS_PUBLIC_API(JSAddonId*)
4518 AddonIdOfObject(JSObject* obj);
4519
4520 } // namespace JS
4521
4522 /************************************************************************/
4523 /*
4524 * Symbols
4525 */
4526
4527 namespace JS {
4528
4529 /**
4530 * Create a new Symbol with the given description. This function never returns
4531 * a Symbol that is in the Runtime-wide symbol registry.
4532 *
4533 * If description is null, the new Symbol's [[Description]] attribute is
4534 * undefined.
4535 */
4536 JS_PUBLIC_API(Symbol*)
4537 NewSymbol(JSContext* cx, HandleString description);
4538
4539 /**
4540 * Symbol.for as specified in ES6.
4541 *
4542 * Get a Symbol with the description 'key' from the Runtime-wide symbol registry.
4543 * If there is not already a Symbol with that description in the registry, a new
4544 * Symbol is created and registered. 'key' must not be null.
4545 */
4546 JS_PUBLIC_API(Symbol*)
4547 GetSymbolFor(JSContext* cx, HandleString key);
4548
4549 /**
4550 * Get the [[Description]] attribute of the given symbol.
4551 *
4552 * This function is infallible. If it returns null, that means the symbol's
4553 * [[Description]] is undefined.
4554 */
4555 JS_PUBLIC_API(JSString*)
4556 GetSymbolDescription(HandleSymbol symbol);
4557
4558 /* Well-known symbols. */
4559 enum class SymbolCode : uint32_t {
4560 iterator, // well-known symbols
4561 match,
4562 species,
4563 toPrimitive,
4564 InSymbolRegistry = 0xfffffffe, // created by Symbol.for() or JS::GetSymbolFor()
4565 UniqueSymbol = 0xffffffff // created by Symbol() or JS::NewSymbol()
4566 };
4567
4568 /* For use in loops that iterate over the well-known symbols. */
4569 const size_t WellKnownSymbolLimit = 4;
4570
4571 /**
4572 * Return the SymbolCode telling what sort of symbol `symbol` is.
4573 *
4574 * A symbol's SymbolCode never changes once it is created.
4575 */
4576 JS_PUBLIC_API(SymbolCode)
4577 GetSymbolCode(Handle<Symbol*> symbol);
4578
4579 /**
4580 * Get one of the well-known symbols defined by ES6. A single set of well-known
4581 * symbols is shared by all compartments in a JSRuntime.
4582 *
4583 * `which` must be in the range [0, WellKnownSymbolLimit).
4584 */
4585 JS_PUBLIC_API(Symbol*)
4586 GetWellKnownSymbol(JSContext* cx, SymbolCode which);
4587
4588 /**
4589 * Return true if the given JSPropertySpec::name or JSFunctionSpec::name value
4590 * is actually a symbol code and not a string. See JS_SYM_FN.
4591 */
4592 inline bool
PropertySpecNameIsSymbol(const char * name)4593 PropertySpecNameIsSymbol(const char* name)
4594 {
4595 uintptr_t u = reinterpret_cast<uintptr_t>(name);
4596 return u != 0 && u - 1 < WellKnownSymbolLimit;
4597 }
4598
4599 JS_PUBLIC_API(bool)
4600 PropertySpecNameEqualsId(const char* name, HandleId id);
4601
4602 /**
4603 * Create a jsid that does not need to be marked for GC.
4604 *
4605 * 'name' is a JSPropertySpec::name or JSFunctionSpec::name value. The
4606 * resulting jsid, on success, is either an interned string or a well-known
4607 * symbol; either way it is immune to GC so there is no need to visit *idp
4608 * during GC marking.
4609 */
4610 JS_PUBLIC_API(bool)
4611 PropertySpecNameToPermanentId(JSContext* cx, const char* name, jsid* idp);
4612
4613 } /* namespace JS */
4614
4615 /************************************************************************/
4616 /*
4617 * JSON functions
4618 */
4619 typedef bool (* JSONWriteCallback)(const char16_t* buf, uint32_t len, void* data);
4620
4621 /**
4622 * JSON.stringify as specified by ES5.
4623 */
4624 JS_PUBLIC_API(bool)
4625 JS_Stringify(JSContext* cx, JS::MutableHandleValue value, JS::HandleObject replacer,
4626 JS::HandleValue space, JSONWriteCallback callback, void* data);
4627
4628 /**
4629 * JSON.parse as specified by ES5.
4630 */
4631 JS_PUBLIC_API(bool)
4632 JS_ParseJSON(JSContext* cx, const char16_t* chars, uint32_t len, JS::MutableHandleValue vp);
4633
4634 JS_PUBLIC_API(bool)
4635 JS_ParseJSON(JSContext* cx, JS::HandleString str, JS::MutableHandleValue vp);
4636
4637 JS_PUBLIC_API(bool)
4638 JS_ParseJSONWithReviver(JSContext* cx, const char16_t* chars, uint32_t len, JS::HandleValue reviver,
4639 JS::MutableHandleValue vp);
4640
4641 JS_PUBLIC_API(bool)
4642 JS_ParseJSONWithReviver(JSContext* cx, JS::HandleString str, JS::HandleValue reviver,
4643 JS::MutableHandleValue vp);
4644
4645 /************************************************************************/
4646
4647 /**
4648 * The default locale for the ECMAScript Internationalization API
4649 * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
4650 * Note that the Internationalization API encourages clients to
4651 * specify their own locales.
4652 * The locale string remains owned by the caller.
4653 */
4654 extern JS_PUBLIC_API(bool)
4655 JS_SetDefaultLocale(JSRuntime* rt, const char* locale);
4656
4657 /**
4658 * Reset the default locale to OS defaults.
4659 */
4660 extern JS_PUBLIC_API(void)
4661 JS_ResetDefaultLocale(JSRuntime* rt);
4662
4663 /**
4664 * Locale specific string conversion and error message callbacks.
4665 */
4666 struct JSLocaleCallbacks {
4667 JSLocaleToUpperCase localeToUpperCase;
4668 JSLocaleToLowerCase localeToLowerCase;
4669 JSLocaleCompare localeCompare; // not used #if EXPOSE_INTL_API
4670 JSLocaleToUnicode localeToUnicode;
4671 };
4672
4673 /**
4674 * Establish locale callbacks. The pointer must persist as long as the
4675 * JSRuntime. Passing nullptr restores the default behaviour.
4676 */
4677 extern JS_PUBLIC_API(void)
4678 JS_SetLocaleCallbacks(JSRuntime* rt, const JSLocaleCallbacks* callbacks);
4679
4680 /**
4681 * Return the address of the current locale callbacks struct, which may
4682 * be nullptr.
4683 */
4684 extern JS_PUBLIC_API(const JSLocaleCallbacks*)
4685 JS_GetLocaleCallbacks(JSRuntime* rt);
4686
4687 /************************************************************************/
4688
4689 /*
4690 * Error reporting.
4691 */
4692
4693 namespace JS {
4694 const uint16_t MaxNumErrorArguments = 10;
4695 };
4696
4697 /**
4698 * Report an exception represented by the sprintf-like conversion of format
4699 * and its arguments. This exception message string is passed to a pre-set
4700 * JSErrorReporter function (set by JS_SetErrorReporter).
4701 */
4702 extern JS_PUBLIC_API(void)
4703 JS_ReportError(JSContext* cx, const char* format, ...);
4704
4705 /*
4706 * Use an errorNumber to retrieve the format string, args are char*
4707 */
4708 extern JS_PUBLIC_API(void)
4709 JS_ReportErrorNumber(JSContext* cx, JSErrorCallback errorCallback,
4710 void* userRef, const unsigned errorNumber, ...);
4711
4712 #ifdef va_start
4713 extern JS_PUBLIC_API(void)
4714 JS_ReportErrorNumberVA(JSContext* cx, JSErrorCallback errorCallback,
4715 void* userRef, const unsigned errorNumber, va_list ap);
4716 #endif
4717
4718 /*
4719 * Use an errorNumber to retrieve the format string, args are char16_t*
4720 */
4721 extern JS_PUBLIC_API(void)
4722 JS_ReportErrorNumberUC(JSContext* cx, JSErrorCallback errorCallback,
4723 void* userRef, const unsigned errorNumber, ...);
4724
4725 extern JS_PUBLIC_API(void)
4726 JS_ReportErrorNumberUCArray(JSContext* cx, JSErrorCallback errorCallback,
4727 void* userRef, const unsigned errorNumber,
4728 const char16_t** args);
4729
4730 /**
4731 * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
4732 * Return true if there was no error trying to issue the warning, and if the
4733 * warning was not converted into an error due to the JSOPTION_WERROR option
4734 * being set, false otherwise.
4735 */
4736 extern JS_PUBLIC_API(bool)
4737 JS_ReportWarning(JSContext* cx, const char* format, ...);
4738
4739 extern JS_PUBLIC_API(bool)
4740 JS_ReportErrorFlagsAndNumber(JSContext* cx, unsigned flags,
4741 JSErrorCallback errorCallback, void* userRef,
4742 const unsigned errorNumber, ...);
4743
4744 extern JS_PUBLIC_API(bool)
4745 JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags,
4746 JSErrorCallback errorCallback, void* userRef,
4747 const unsigned errorNumber, ...);
4748
4749 /**
4750 * Complain when out of memory.
4751 */
4752 extern JS_PUBLIC_API(void)
4753 JS_ReportOutOfMemory(JSContext* cx);
4754
4755 /**
4756 * Complain when an allocation size overflows the maximum supported limit.
4757 */
4758 extern JS_PUBLIC_API(void)
4759 JS_ReportAllocationOverflow(JSContext* cx);
4760
4761 class JSErrorReport
4762 {
4763 // Offending source line without final '\n'.
4764 const char16_t* linebuf_;
4765
4766 // Number of chars in linebuf_. Does not include trailing '\0'.
4767 size_t linebufLength_;
4768
4769 // The 0-based offset of error token in linebuf_.
4770 size_t tokenOffset_;
4771
4772 public:
JSErrorReport()4773 JSErrorReport()
4774 : linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
4775 filename(nullptr), lineno(0), column(0), isMuted(false),
4776 flags(0), errorNumber(0), ucmessage(nullptr),
4777 messageArgs(nullptr), exnType(0)
4778 {}
4779
4780 const char* filename; /* source file name, URL, etc., or null */
4781 unsigned lineno; /* source line number */
4782 unsigned column; /* zero-based column index in line */
4783 bool isMuted; /* See the comment in ReadOnlyCompileOptions. */
4784 unsigned flags; /* error/warning, etc. */
4785 unsigned errorNumber; /* the error number, e.g. see js.msg */
4786 const char16_t* ucmessage; /* the (default) error message */
4787 const char16_t** messageArgs; /* arguments for the error message */
4788 int16_t exnType; /* One of the JSExnType constants */
4789
linebuf()4790 const char16_t* linebuf() const {
4791 return linebuf_;
4792 }
linebufLength()4793 size_t linebufLength() const {
4794 return linebufLength_;
4795 }
tokenOffset()4796 size_t tokenOffset() const {
4797 return tokenOffset_;
4798 }
4799 void initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset);
4800 };
4801
4802 /*
4803 * JSErrorReport flag values. These may be freely composed.
4804 */
4805 #define JSREPORT_ERROR 0x0 /* pseudo-flag for default case */
4806 #define JSREPORT_WARNING 0x1 /* reported via JS_ReportWarning */
4807 #define JSREPORT_EXCEPTION 0x2 /* exception was thrown */
4808 #define JSREPORT_STRICT 0x4 /* error or warning due to strict option */
4809
4810 /*
4811 * This condition is an error in strict mode code, a warning if
4812 * JS_HAS_STRICT_OPTION(cx), and otherwise should not be reported at
4813 * all. We check the strictness of the context's top frame's script;
4814 * where that isn't appropriate, the caller should do the right checks
4815 * itself instead of using this flag.
4816 */
4817 #define JSREPORT_STRICT_MODE_ERROR 0x8
4818
4819 /*
4820 * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
4821 * has been thrown for this runtime error, and the host should ignore it.
4822 * Exception-aware hosts should also check for JS_IsExceptionPending if
4823 * JS_ExecuteScript returns failure, and signal or propagate the exception, as
4824 * appropriate.
4825 */
4826 #define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0)
4827 #define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0)
4828 #define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0)
4829 #define JSREPORT_IS_STRICT_MODE_ERROR(flags) (((flags) & \
4830 JSREPORT_STRICT_MODE_ERROR) != 0)
4831 extern JS_PUBLIC_API(JSErrorReporter)
4832 JS_GetErrorReporter(JSRuntime* rt);
4833
4834 extern JS_PUBLIC_API(JSErrorReporter)
4835 JS_SetErrorReporter(JSRuntime* rt, JSErrorReporter er);
4836
4837 namespace JS {
4838
4839 extern JS_PUBLIC_API(bool)
4840 CreateError(JSContext* cx, JSExnType type, HandleObject stack,
4841 HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
4842 JSErrorReport* report, HandleString message, MutableHandleValue rval);
4843
4844 /************************************************************************/
4845
4846 /*
4847 * Weak Maps.
4848 */
4849
4850 extern JS_PUBLIC_API(JSObject*)
4851 NewWeakMapObject(JSContext* cx);
4852
4853 extern JS_PUBLIC_API(bool)
4854 IsWeakMapObject(JSObject* obj);
4855
4856 extern JS_PUBLIC_API(bool)
4857 GetWeakMapEntry(JSContext* cx, JS::HandleObject mapObj, JS::HandleObject key,
4858 JS::MutableHandleValue val);
4859
4860 extern JS_PUBLIC_API(bool)
4861 SetWeakMapEntry(JSContext* cx, JS::HandleObject mapObj, JS::HandleObject key,
4862 JS::HandleValue val);
4863
4864 /*
4865 * Map
4866 */
4867 extern JS_PUBLIC_API(JSObject*)
4868 NewMapObject(JSContext* cx);
4869
4870 extern JS_PUBLIC_API(uint32_t)
4871 MapSize(JSContext* cx, HandleObject obj);
4872
4873 extern JS_PUBLIC_API(bool)
4874 MapGet(JSContext* cx, HandleObject obj,
4875 HandleValue key, MutableHandleValue rval);
4876
4877 extern JS_PUBLIC_API(bool)
4878 MapHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval);
4879
4880 extern JS_PUBLIC_API(bool)
4881 MapSet(JSContext* cx, HandleObject obj, HandleValue key, HandleValue val);
4882
4883 extern JS_PUBLIC_API(bool)
4884 MapDelete(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
4885
4886 extern JS_PUBLIC_API(bool)
4887 MapClear(JSContext* cx, HandleObject obj);
4888
4889 extern JS_PUBLIC_API(bool)
4890 MapKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval);
4891
4892 extern JS_PUBLIC_API(bool)
4893 MapValues(JSContext* cx, HandleObject obj, MutableHandleValue rval);
4894
4895 extern JS_PUBLIC_API(bool)
4896 MapEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval);
4897
4898 extern JS_PUBLIC_API(bool)
4899 MapForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal);
4900
4901 /*
4902 * Set
4903 */
4904 extern JS_PUBLIC_API(JSObject *)
4905 NewSetObject(JSContext *cx);
4906
4907 extern JS_PUBLIC_API(uint32_t)
4908 SetSize(JSContext *cx, HandleObject obj);
4909
4910 extern JS_PUBLIC_API(bool)
4911 SetHas(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
4912
4913 extern JS_PUBLIC_API(bool)
4914 SetDelete(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
4915
4916 extern JS_PUBLIC_API(bool)
4917 SetAdd(JSContext *cx, HandleObject obj, HandleValue key);
4918
4919 extern JS_PUBLIC_API(bool)
4920 SetClear(JSContext *cx, HandleObject obj);
4921
4922 extern JS_PUBLIC_API(bool)
4923 SetKeys(JSContext *cx, HandleObject obj, MutableHandleValue rval);
4924
4925 extern JS_PUBLIC_API(bool)
4926 SetValues(JSContext *cx, HandleObject obj, MutableHandleValue rval);
4927
4928 extern JS_PUBLIC_API(bool)
4929 SetEntries(JSContext *cx, HandleObject obj, MutableHandleValue rval);
4930
4931 extern JS_PUBLIC_API(bool)
4932 SetForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal);
4933
4934 } /* namespace JS */
4935
4936 /*
4937 * Dates.
4938 */
4939
4940 extern JS_PUBLIC_API(JSObject*)
4941 JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec);
4942
4943 /**
4944 * Returns true and sets |*isDate| indicating whether |obj| is a Date object or
4945 * a wrapper around one, otherwise returns false on failure.
4946 *
4947 * This method returns true with |*isDate == false| when passed a proxy whose
4948 * target is a Date, or when passed a revoked proxy.
4949 */
4950 extern JS_PUBLIC_API(bool)
4951 JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate);
4952
4953 /************************************************************************/
4954
4955 /*
4956 * Regular Expressions.
4957 */
4958 #define JSREG_FOLD 0x01u /* fold uppercase to lowercase */
4959 #define JSREG_GLOB 0x02u /* global exec, creates array of matches */
4960 #define JSREG_MULTILINE 0x04u /* treat ^ and $ as begin and end of line */
4961 #define JSREG_STICKY 0x08u /* only match starting at lastIndex */
4962
4963 extern JS_PUBLIC_API(JSObject*)
4964 JS_NewRegExpObject(JSContext* cx, JS::HandleObject obj, const char* bytes, size_t length,
4965 unsigned flags);
4966
4967 extern JS_PUBLIC_API(JSObject*)
4968 JS_NewUCRegExpObject(JSContext* cx, JS::HandleObject obj, const char16_t* chars, size_t length,
4969 unsigned flags);
4970
4971 extern JS_PUBLIC_API(bool)
4972 JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input,
4973 bool multiline);
4974
4975 extern JS_PUBLIC_API(bool)
4976 JS_ClearRegExpStatics(JSContext* cx, JS::HandleObject obj);
4977
4978 extern JS_PUBLIC_API(bool)
4979 JS_ExecuteRegExp(JSContext* cx, JS::HandleObject obj, JS::HandleObject reobj,
4980 char16_t* chars, size_t length, size_t* indexp, bool test,
4981 JS::MutableHandleValue rval);
4982
4983 /* RegExp interface for clients without a global object. */
4984
4985 extern JS_PUBLIC_API(JSObject*)
4986 JS_NewRegExpObjectNoStatics(JSContext* cx, char* bytes, size_t length, unsigned flags);
4987
4988 extern JS_PUBLIC_API(JSObject*)
4989 JS_NewUCRegExpObjectNoStatics(JSContext* cx, char16_t* chars, size_t length, unsigned flags);
4990
4991 extern JS_PUBLIC_API(bool)
4992 JS_ExecuteRegExpNoStatics(JSContext* cx, JS::HandleObject reobj, char16_t* chars, size_t length,
4993 size_t* indexp, bool test, JS::MutableHandleValue rval);
4994
4995 /**
4996 * Returns true and sets |*isRegExp| indicating whether |obj| is a RegExp
4997 * object or a wrapper around one, otherwise returns false on failure.
4998 *
4999 * This method returns true with |*isRegExp == false| when passed a proxy whose
5000 * target is a RegExp, or when passed a revoked proxy.
5001 */
5002 extern JS_PUBLIC_API(bool)
5003 JS_ObjectIsRegExp(JSContext* cx, JS::HandleObject obj, bool* isRegExp);
5004
5005 extern JS_PUBLIC_API(unsigned)
5006 JS_GetRegExpFlags(JSContext* cx, JS::HandleObject obj);
5007
5008 extern JS_PUBLIC_API(JSString*)
5009 JS_GetRegExpSource(JSContext* cx, JS::HandleObject obj);
5010
5011 /************************************************************************/
5012
5013 extern JS_PUBLIC_API(bool)
5014 JS_IsExceptionPending(JSContext* cx);
5015
5016 extern JS_PUBLIC_API(bool)
5017 JS_GetPendingException(JSContext* cx, JS::MutableHandleValue vp);
5018
5019 extern JS_PUBLIC_API(void)
5020 JS_SetPendingException(JSContext* cx, JS::HandleValue v);
5021
5022 extern JS_PUBLIC_API(void)
5023 JS_ClearPendingException(JSContext* cx);
5024
5025 extern JS_PUBLIC_API(bool)
5026 JS_ReportPendingException(JSContext* cx);
5027
5028 namespace JS {
5029
5030 /**
5031 * Save and later restore the current exception state of a given JSContext.
5032 * This is useful for implementing behavior in C++ that's like try/catch
5033 * or try/finally in JS.
5034 *
5035 * Typical usage:
5036 *
5037 * bool ok = JS::Evaluate(cx, ...);
5038 * AutoSaveExceptionState savedExc(cx);
5039 * ... cleanup that might re-enter JS ...
5040 * return ok;
5041 */
JS_PUBLIC_API(AutoSaveExceptionState)5042 class JS_PUBLIC_API(AutoSaveExceptionState)
5043 {
5044 private:
5045 JSContext* context;
5046 bool wasPropagatingForcedReturn;
5047 bool wasOverRecursed;
5048 bool wasThrowing;
5049 RootedValue exceptionValue;
5050
5051 public:
5052 /*
5053 * Take a snapshot of cx's current exception state. Then clear any current
5054 * pending exception in cx.
5055 */
5056 explicit AutoSaveExceptionState(JSContext* cx);
5057
5058 /*
5059 * If neither drop() nor restore() was called, restore the exception
5060 * state only if no exception is currently pending on cx.
5061 */
5062 ~AutoSaveExceptionState();
5063
5064 /*
5065 * Discard any stored exception state.
5066 * If this is called, the destructor is a no-op.
5067 */
5068 void drop() {
5069 wasPropagatingForcedReturn = false;
5070 wasOverRecursed = false;
5071 wasThrowing = false;
5072 exceptionValue.setUndefined();
5073 }
5074
5075 /*
5076 * Replace cx's exception state with the stored exception state. Then
5077 * discard the stored exception state. If this is called, the
5078 * destructor is a no-op.
5079 */
5080 void restore();
5081 };
5082
5083 } /* namespace JS */
5084
5085 /* Deprecated API. Use AutoSaveExceptionState instead. */
5086 extern JS_PUBLIC_API(JSExceptionState*)
5087 JS_SaveExceptionState(JSContext* cx);
5088
5089 extern JS_PUBLIC_API(void)
5090 JS_RestoreExceptionState(JSContext* cx, JSExceptionState* state);
5091
5092 extern JS_PUBLIC_API(void)
5093 JS_DropExceptionState(JSContext* cx, JSExceptionState* state);
5094
5095 /**
5096 * If the given object is an exception object, the exception will have (or be
5097 * able to lazily create) an error report struct, and this function will return
5098 * the address of that struct. Otherwise, it returns nullptr. The lifetime
5099 * of the error report struct that might be returned is the same as the
5100 * lifetime of the exception object.
5101 */
5102 extern JS_PUBLIC_API(JSErrorReport*)
5103 JS_ErrorFromException(JSContext* cx, JS::HandleObject obj);
5104
5105 extern JS_PUBLIC_API(JSObject*)
5106 ExceptionStackOrNull(JSContext* cx, JS::HandleObject obj);
5107
5108 /*
5109 * Throws a StopIteration exception on cx.
5110 */
5111 extern JS_PUBLIC_API(bool)
5112 JS_ThrowStopIteration(JSContext* cx);
5113
5114 extern JS_PUBLIC_API(bool)
5115 JS_IsStopIteration(JS::Value v);
5116
5117 extern JS_PUBLIC_API(intptr_t)
5118 JS_GetCurrentThread();
5119
5120 /**
5121 * A JS runtime always has an "owner thread". The owner thread is set when the
5122 * runtime is created (to the current thread) and practically all entry points
5123 * into the JS engine check that a runtime (or anything contained in the
5124 * runtime: context, compartment, object, etc) is only touched by its owner
5125 * thread. Embeddings may check this invariant outside the JS engine by calling
5126 * JS_AbortIfWrongThread (which will abort if not on the owner thread, even for
5127 * non-debug builds).
5128 */
5129
5130 extern JS_PUBLIC_API(void)
5131 JS_AbortIfWrongThread(JSRuntime* rt);
5132
5133 /************************************************************************/
5134
5135 /**
5136 * A constructor can request that the JS engine create a default new 'this'
5137 * object of the given class, using the callee to determine parentage and
5138 * [[Prototype]].
5139 */
5140 extern JS_PUBLIC_API(JSObject*)
5141 JS_NewObjectForConstructor(JSContext* cx, const JSClass* clasp, const JS::CallArgs& args);
5142
5143 /************************************************************************/
5144
5145 #ifdef JS_GC_ZEAL
5146 #define JS_DEFAULT_ZEAL_FREQ 100
5147
5148 extern JS_PUBLIC_API(void)
5149 JS_GetGCZeal(JSContext* cx, uint8_t* zeal, uint32_t* frequency, uint32_t* nextScheduled);
5150
5151 extern JS_PUBLIC_API(void)
5152 JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency);
5153
5154 extern JS_PUBLIC_API(void)
5155 JS_ScheduleGC(JSContext* cx, uint32_t count);
5156 #endif
5157
5158 extern JS_PUBLIC_API(void)
5159 JS_SetParallelParsingEnabled(JSRuntime* rt, bool enabled);
5160
5161 extern JS_PUBLIC_API(void)
5162 JS_SetOffthreadIonCompilationEnabled(JSRuntime* rt, bool enabled);
5163
5164 #define JIT_COMPILER_OPTIONS(Register) \
5165 Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \
5166 Register(ION_WARMUP_TRIGGER, "ion.warmup.trigger") \
5167 Register(ION_GVN_ENABLE, "ion.gvn.enable") \
5168 Register(ION_FORCE_IC, "ion.forceinlineCaches") \
5169 Register(ION_ENABLE, "ion.enable") \
5170 Register(BASELINE_ENABLE, "baseline.enable") \
5171 Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
5172 Register(SIGNALS_ENABLE, "signals.enable")
5173
5174 typedef enum JSJitCompilerOption {
5175 #define JIT_COMPILER_DECLARE(key, str) \
5176 JSJITCOMPILER_ ## key,
5177
5178 JIT_COMPILER_OPTIONS(JIT_COMPILER_DECLARE)
5179 #undef JIT_COMPILER_DECLARE
5180
5181 JSJITCOMPILER_NOT_AN_OPTION
5182 } JSJitCompilerOption;
5183
5184 extern JS_PUBLIC_API(void)
5185 JS_SetGlobalJitCompilerOption(JSRuntime* rt, JSJitCompilerOption opt, uint32_t value);
5186 extern JS_PUBLIC_API(int)
5187 JS_GetGlobalJitCompilerOption(JSRuntime* rt, JSJitCompilerOption opt);
5188
5189 /**
5190 * Convert a uint32_t index into a jsid.
5191 */
5192 extern JS_PUBLIC_API(bool)
5193 JS_IndexToId(JSContext* cx, uint32_t index, JS::MutableHandleId);
5194
5195 /**
5196 * Convert chars into a jsid.
5197 *
5198 * |chars| may not be an index.
5199 */
5200 extern JS_PUBLIC_API(bool)
5201 JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, JS::MutableHandleId);
5202
5203 /**
5204 * Test if the given string is a valid ECMAScript identifier
5205 */
5206 extern JS_PUBLIC_API(bool)
5207 JS_IsIdentifier(JSContext* cx, JS::HandleString str, bool* isIdentifier);
5208
5209 /**
5210 * Test whether the given chars + length are a valid ECMAScript identifier.
5211 * This version is infallible, so just returns whether the chars are an
5212 * identifier.
5213 */
5214 extern JS_PUBLIC_API(bool)
5215 JS_IsIdentifier(const char16_t* chars, size_t length);
5216
5217 namespace JS {
5218
5219 /**
5220 * AutoFilename encapsulates a pointer to a C-string and keeps the C-string
5221 * alive for as long as the associated AutoFilename object is alive.
5222 */
JS_PUBLIC_API(AutoFilename)5223 class MOZ_STACK_CLASS JS_PUBLIC_API(AutoFilename)
5224 {
5225 void* scriptSource_;
5226
5227 AutoFilename(const AutoFilename&) = delete;
5228 void operator=(const AutoFilename&) = delete;
5229
5230 public:
5231 AutoFilename() : scriptSource_(nullptr) {}
5232 ~AutoFilename() { reset(nullptr); }
5233
5234 const char* get() const;
5235
5236 void reset(void* newScriptSource);
5237 };
5238
5239 /**
5240 * Return the current filename, line number and column number of the most
5241 * currently running frame. Returns true if a scripted frame was found, false
5242 * otherwise.
5243 *
5244 * If a the embedding has hidden the scripted caller for the topmost activation
5245 * record, this will also return false.
5246 */
5247 extern JS_PUBLIC_API(bool)
5248 DescribeScriptedCaller(JSContext* cx, AutoFilename* filename = nullptr,
5249 unsigned* lineno = nullptr, unsigned* column = nullptr);
5250
5251 extern JS_PUBLIC_API(JSObject*)
5252 GetScriptedCallerGlobal(JSContext* cx);
5253
5254 /**
5255 * Informs the JS engine that the scripted caller should be hidden. This can be
5256 * used by the embedding to maintain an override of the scripted caller in its
5257 * calculations, by hiding the scripted caller in the JS engine and pushing data
5258 * onto a separate stack, which it inspects when DescribeScriptedCaller returns
5259 * null.
5260 *
5261 * We maintain a counter on each activation record. Add() increments the counter
5262 * of the topmost activation, and Remove() decrements it. The count may never
5263 * drop below zero, and must always be exactly zero when the activation is
5264 * popped from the stack.
5265 */
5266 extern JS_PUBLIC_API(void)
5267 HideScriptedCaller(JSContext* cx);
5268
5269 extern JS_PUBLIC_API(void)
5270 UnhideScriptedCaller(JSContext* cx);
5271
5272 class MOZ_RAII AutoHideScriptedCaller
5273 {
5274 public:
AutoHideScriptedCaller(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)5275 explicit AutoHideScriptedCaller(JSContext* cx
5276 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
5277 : mContext(cx)
5278 {
5279 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
5280 HideScriptedCaller(mContext);
5281 }
~AutoHideScriptedCaller()5282 ~AutoHideScriptedCaller() {
5283 UnhideScriptedCaller(mContext);
5284 }
5285
5286 protected:
5287 JSContext* mContext;
5288 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
5289 };
5290
5291 } /* namespace JS */
5292
5293 /*
5294 * Encode/Decode interpreted scripts and functions to/from memory.
5295 */
5296
5297 extern JS_PUBLIC_API(void*)
5298 JS_EncodeScript(JSContext* cx, JS::HandleScript script, uint32_t* lengthp);
5299
5300 extern JS_PUBLIC_API(void*)
5301 JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj, uint32_t* lengthp);
5302
5303 extern JS_PUBLIC_API(JSScript*)
5304 JS_DecodeScript(JSContext* cx, const void* data, uint32_t length);
5305
5306 extern JS_PUBLIC_API(JSObject*)
5307 JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length);
5308
5309 namespace JS {
5310
5311 /*
5312 * This callback represents a request by the JS engine to open for reading the
5313 * existing cache entry for the given global and char range that may contain a
5314 * module. If a cache entry exists, the callback shall return 'true' and return
5315 * the size, base address and an opaque file handle as outparams. If the
5316 * callback returns 'true', the JS engine guarantees a call to
5317 * CloseAsmJSCacheEntryForReadOp, passing the same base address, size and
5318 * handle.
5319 */
5320 typedef bool
5321 (* OpenAsmJSCacheEntryForReadOp)(HandleObject global, const char16_t* begin, const char16_t* limit,
5322 size_t* size, const uint8_t** memory, intptr_t* handle);
5323 typedef void
5324 (* CloseAsmJSCacheEntryForReadOp)(size_t size, const uint8_t* memory, intptr_t handle);
5325
5326 /** The list of reasons why an asm.js module may not be stored in the cache. */
5327 enum AsmJSCacheResult
5328 {
5329 AsmJSCache_MIN,
5330 AsmJSCache_Success = AsmJSCache_MIN,
5331 AsmJSCache_ModuleTooSmall,
5332 AsmJSCache_SynchronousScript,
5333 AsmJSCache_QuotaExceeded,
5334 AsmJSCache_StorageInitFailure,
5335 AsmJSCache_Disabled_Internal,
5336 AsmJSCache_Disabled_ShellFlags,
5337 AsmJSCache_Disabled_JitInspector,
5338 AsmJSCache_InternalError,
5339 AsmJSCache_LIMIT
5340 };
5341
5342 /*
5343 * This callback represents a request by the JS engine to open for writing a
5344 * cache entry of the given size for the given global and char range containing
5345 * the just-compiled module. If cache entry space is available, the callback
5346 * shall return 'true' and return the base address and an opaque file handle as
5347 * outparams. If the callback returns 'true', the JS engine guarantees a call
5348 * to CloseAsmJSCacheEntryForWriteOp passing the same base address, size and
5349 * handle.
5350 *
5351 * If 'installed' is true, then the cache entry is associated with a permanently
5352 * installed JS file (e.g., in a packaged webapp). This information allows the
5353 * embedding to store the cache entry in a installed location associated with
5354 * the principal of 'global' where it will not be evicted until the associated
5355 * installed JS file is removed.
5356 */
5357 typedef AsmJSCacheResult
5358 (* OpenAsmJSCacheEntryForWriteOp)(HandleObject global, bool installed,
5359 const char16_t* begin, const char16_t* end,
5360 size_t size, uint8_t** memory, intptr_t* handle);
5361 typedef void
5362 (* CloseAsmJSCacheEntryForWriteOp)(size_t size, uint8_t* memory, intptr_t handle);
5363
5364 typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
5365
5366 /**
5367 * Return the buildId (represented as a sequence of characters) associated with
5368 * the currently-executing build. If the JS engine is embedded such that a
5369 * single cache entry can be observed by different compiled versions of the JS
5370 * engine, it is critical that the buildId shall change for each new build of
5371 * the JS engine.
5372 */
5373 typedef bool
5374 (* BuildIdOp)(BuildIdCharVector* buildId);
5375
5376 struct AsmJSCacheOps
5377 {
5378 OpenAsmJSCacheEntryForReadOp openEntryForRead;
5379 CloseAsmJSCacheEntryForReadOp closeEntryForRead;
5380 OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
5381 CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
5382 BuildIdOp buildId;
5383 };
5384
5385 extern JS_PUBLIC_API(void)
5386 SetAsmJSCacheOps(JSRuntime* rt, const AsmJSCacheOps* callbacks);
5387
5388 /**
5389 * Convenience class for imitating a JS level for-of loop. Typical usage:
5390 *
5391 * ForOfIterator it(cx);
5392 * if (!it.init(iterable))
5393 * return false;
5394 * RootedValue val(cx);
5395 * while (true) {
5396 * bool done;
5397 * if (!it.next(&val, &done))
5398 * return false;
5399 * if (done)
5400 * break;
5401 * if (!DoStuff(cx, val))
5402 * return false;
5403 * }
5404 */
JS_PUBLIC_API(ForOfIterator)5405 class MOZ_STACK_CLASS JS_PUBLIC_API(ForOfIterator) {
5406 protected:
5407 JSContext* cx_;
5408 /*
5409 * Use the ForOfPIC on the global object (see vm/GlobalObject.h) to try
5410 * to optimize iteration across arrays.
5411 *
5412 * Case 1: Regular Iteration
5413 * iterator - pointer to the iterator object.
5414 * index - fixed to NOT_ARRAY (== UINT32_MAX)
5415 *
5416 * Case 2: Optimized Array Iteration
5417 * iterator - pointer to the array object.
5418 * index - current position in array.
5419 *
5420 * The cases are distinguished by whether or not |index| is equal to NOT_ARRAY.
5421 */
5422 JS::RootedObject iterator;
5423 uint32_t index;
5424
5425 static const uint32_t NOT_ARRAY = UINT32_MAX;
5426
5427 ForOfIterator(const ForOfIterator&) = delete;
5428 ForOfIterator& operator=(const ForOfIterator&) = delete;
5429
5430 public:
5431 explicit ForOfIterator(JSContext* cx) : cx_(cx), iterator(cx_), index(NOT_ARRAY) { }
5432
5433 enum NonIterableBehavior {
5434 ThrowOnNonIterable,
5435 AllowNonIterable
5436 };
5437
5438 /**
5439 * Initialize the iterator. If AllowNonIterable is passed then if getting
5440 * the @@iterator property from iterable returns undefined init() will just
5441 * return true instead of throwing. Callers must then check
5442 * valueIsIterable() before continuing with the iteration.
5443 */
5444 bool init(JS::HandleValue iterable,
5445 NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
5446
5447 /**
5448 * Get the next value from the iterator. If false *done is true
5449 * after this call, do not examine val.
5450 */
5451 bool next(JS::MutableHandleValue val, bool* done);
5452
5453 /**
5454 * If initialized with throwOnNonCallable = false, check whether
5455 * the value is iterable.
5456 */
5457 bool valueIsIterable() const {
5458 return iterator;
5459 }
5460
5461 private:
5462 inline bool nextFromOptimizedArray(MutableHandleValue val, bool* done);
5463 bool materializeArrayIterator();
5464 };
5465
5466
5467 /**
5468 * If a large allocation fails when calling pod_{calloc,realloc}CanGC, the JS
5469 * engine may call the large-allocation- failure callback, if set, to allow the
5470 * embedding to flush caches, possibly perform shrinking GCs, etc. to make some
5471 * room. The allocation will then be retried (and may still fail.)
5472 */
5473
5474 typedef void
5475 (* LargeAllocationFailureCallback)(void* data);
5476
5477 extern JS_PUBLIC_API(void)
5478 SetLargeAllocationFailureCallback(JSRuntime* rt, LargeAllocationFailureCallback afc, void* data);
5479
5480 /**
5481 * Unlike the error reporter, which is only called if the exception for an OOM
5482 * bubbles up and is not caught, the OutOfMemoryCallback is called immediately
5483 * at the OOM site to allow the embedding to capture the current state of heap
5484 * allocation before anything is freed. If the large-allocation-failure callback
5485 * is called at all (not all allocation sites call the large-allocation-failure
5486 * callback on failure), it is called before the out-of-memory callback; the
5487 * out-of-memory callback is only called if the allocation still fails after the
5488 * large-allocation-failure callback has returned.
5489 */
5490
5491 typedef void
5492 (* OutOfMemoryCallback)(JSContext* cx, void* data);
5493
5494 extern JS_PUBLIC_API(void)
5495 SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data);
5496
5497
5498 /**
5499 * Capture the current call stack as a chain of SavedFrame JSObjects, and set
5500 * |stackp| to the SavedFrame for the youngest stack frame, or nullptr if there
5501 * are no JS frames on the stack. If |maxFrameCount| is non-zero, capture at
5502 * most the youngest |maxFrameCount| frames.
5503 */
5504 extern JS_PUBLIC_API(bool)
5505 CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp, unsigned maxFrameCount = 0);
5506
5507 /*
5508 * This is a utility function for preparing an async stack to be used
5509 * by some other object. This may be used when you need to treat a
5510 * given stack trace as an async parent. If you just need to capture
5511 * the current stack, async parents and all, use CaptureCurrentStack
5512 * instead.
5513 *
5514 * Here |asyncStack| is the async stack to prepare. It is copied into
5515 * |cx|'s current compartment, and the newest frame is given
5516 * |asyncCause| as its asynchronous cause. If |maxFrameCount| is
5517 * non-zero, capture at most the youngest |maxFrameCount| frames. The
5518 * new stack object is written to |stackp|. Returns true on success,
5519 * or sets an exception and returns |false| on error.
5520 */
5521 extern JS_PUBLIC_API(bool)
5522 CopyAsyncStack(JSContext* cx, HandleObject asyncStack,
5523 HandleString asyncCause, MutableHandleObject stackp,
5524 unsigned maxFrameCount);
5525
5526 /*
5527 * Accessors for working with SavedFrame JSObjects
5528 *
5529 * Each of these functions assert that if their `HandleObject savedFrame`
5530 * argument is non-null, its JSClass is the SavedFrame class (or it is a
5531 * cross-compartment or Xray wrapper around an object with the SavedFrame class)
5532 * and the object is not the SavedFrame.prototype object.
5533 *
5534 * Each of these functions will find the first SavedFrame object in the chain
5535 * whose underlying stack frame principals are subsumed by the cx's current
5536 * compartment's principals, and operate on that SavedFrame object. This
5537 * prevents leaking information about privileged frames to un-privileged
5538 * callers. As a result, the SavedFrame in parameters do _NOT_ need to be in the
5539 * same compartment as the cx, and the various out parameters are _NOT_
5540 * guaranteed to be in the same compartment as cx.
5541 *
5542 * You may consider or skip over self-hosted frames by passing
5543 * `SavedFrameSelfHosted::Include` or `SavedFrameSelfHosted::Exclude`
5544 * respectively.
5545 *
5546 * Additionally, it may be the case that there is no such SavedFrame object
5547 * whose captured frame's principals are subsumed by the caller's compartment's
5548 * principals! If the `HandleObject savedFrame` argument is null, or the
5549 * caller's principals do not subsume any of the chained SavedFrame object's
5550 * principals, `SavedFrameResult::AccessDenied` is returned and a (hopefully)
5551 * sane default value is chosen for the out param.
5552 *
5553 * See also `js/src/doc/SavedFrame/SavedFrame.md`.
5554 */
5555
5556 enum class SavedFrameResult {
5557 Ok,
5558 AccessDenied
5559 };
5560
5561 enum class SavedFrameSelfHosted {
5562 Include,
5563 Exclude
5564 };
5565
5566 /**
5567 * Given a SavedFrame JSObject, get its source property. Defaults to the empty
5568 * string.
5569 */
5570 extern JS_PUBLIC_API(SavedFrameResult)
5571 GetSavedFrameSource(JSContext* cx, HandleObject savedFrame, MutableHandleString sourcep,
5572 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5573
5574 /**
5575 * Given a SavedFrame JSObject, get its line property. Defaults to 0.
5576 */
5577 extern JS_PUBLIC_API(SavedFrameResult)
5578 GetSavedFrameLine(JSContext* cx, HandleObject savedFrame, uint32_t* linep,
5579 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5580
5581 /**
5582 * Given a SavedFrame JSObject, get its column property. Defaults to 0.
5583 */
5584 extern JS_PUBLIC_API(SavedFrameResult)
5585 GetSavedFrameColumn(JSContext* cx, HandleObject savedFrame, uint32_t* columnp,
5586 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5587
5588 /**
5589 * Given a SavedFrame JSObject, get its functionDisplayName string, or nullptr
5590 * if SpiderMonkey was unable to infer a name for the captured frame's
5591 * function. Defaults to nullptr.
5592 */
5593 extern JS_PUBLIC_API(SavedFrameResult)
5594 GetSavedFrameFunctionDisplayName(JSContext* cx, HandleObject savedFrame, MutableHandleString namep,
5595 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5596
5597 /**
5598 * Given a SavedFrame JSObject, get its asyncCause string. Defaults to nullptr.
5599 */
5600 extern JS_PUBLIC_API(SavedFrameResult)
5601 GetSavedFrameAsyncCause(JSContext* cx, HandleObject savedFrame, MutableHandleString asyncCausep,
5602 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5603
5604 /**
5605 * Given a SavedFrame JSObject, get its asyncParent SavedFrame object or nullptr
5606 * if there is no asyncParent. The `asyncParentp` out parameter is _NOT_
5607 * guaranteed to be in the cx's compartment. Defaults to nullptr.
5608 */
5609 extern JS_PUBLIC_API(SavedFrameResult)
5610 GetSavedFrameAsyncParent(JSContext* cx, HandleObject savedFrame, MutableHandleObject asyncParentp,
5611 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5612
5613 /**
5614 * Given a SavedFrame JSObject, get its parent SavedFrame object or nullptr if
5615 * it is the oldest frame in the stack. The `parentp` out parameter is _NOT_
5616 * guaranteed to be in the cx's compartment. Defaults to nullptr.
5617 */
5618 extern JS_PUBLIC_API(SavedFrameResult)
5619 GetSavedFrameParent(JSContext* cx, HandleObject savedFrame, MutableHandleObject parentp,
5620 SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
5621
5622 /**
5623 * Given a SavedFrame JSObject stack, stringify it in the same format as
5624 * Error.prototype.stack. The stringified stack out parameter is placed in the
5625 * cx's compartment. Defaults to the empty string.
5626 *
5627 * The same notes above about SavedFrame accessors applies here as well: cx
5628 * doesn't need to be in stack's compartment, and stack can be null, a
5629 * SavedFrame object, or a wrapper (CCW or Xray) around a SavedFrame object.
5630 *
5631 * Optional indent parameter specifies the number of white spaces to indent
5632 * each line.
5633 */
5634 extern JS_PUBLIC_API(bool)
5635 BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp, size_t indent = 0);
5636
5637 } /* namespace JS */
5638
5639
5640 /* Stopwatch-based performance monitoring. */
5641
5642 namespace js {
5643
5644 class AutoStopwatch;
5645
5646 /**
5647 * Abstract base class for a representation of the performance of a
5648 * component. Embeddings interested in performance monitoring should
5649 * provide a concrete implementation of this class, as well as the
5650 * relevant callbacks (see below).
5651 */
5652 struct PerformanceGroup {
5653 PerformanceGroup();
5654
5655 // The current iteration of the event loop.
5656 uint64_t iteration() const;
5657
5658 // `true` if an instance of `AutoStopwatch` is already monitoring
5659 // the performance of this performance group for this iteration
5660 // of the event loop, `false` otherwise.
5661 bool isAcquired(uint64_t it) const;
5662
5663 // `true` if a specific instance of `AutoStopwatch` is already monitoring
5664 // the performance of this performance group for this iteration
5665 // of the event loop, `false` otherwise.
5666 bool isAcquired(uint64_t it, const AutoStopwatch* owner) const;
5667
5668 // Mark that an instance of `AutoStopwatch` is monitoring
5669 // the performance of this group for a given iteration.
5670 void acquire(uint64_t it, const AutoStopwatch* owner);
5671
5672 // Mark that no `AutoStopwatch` is monitoring the
5673 // performance of this group for the iteration.
5674 void release(uint64_t it, const AutoStopwatch* owner);
5675
5676 // The number of cycles spent in this group during this iteration
5677 // of the event loop. Note that cycles are not a reliable measure,
5678 // especially over short intervals. See Stopwatch.* for a more
5679 // complete discussion on the imprecision of cycle measurement.
5680 uint64_t recentCycles(uint64_t iteration) const;
5681 void addRecentCycles(uint64_t iteration, uint64_t cycles);
5682
5683 // The number of times this group has been activated during this
5684 // iteration of the event loop.
5685 uint64_t recentTicks(uint64_t iteration) const;
5686 void addRecentTicks(uint64_t iteration, uint64_t ticks);
5687
5688 // The number of microseconds spent doing CPOW during this
5689 // iteration of the event loop.
5690 uint64_t recentCPOW(uint64_t iteration) const;
5691 void addRecentCPOW(uint64_t iteration, uint64_t CPOW);
5692
5693 // Get rid of any data that pretends to be recent.
5694 void resetRecentData();
5695
5696 // `true` if new measures should be added to this group, `false`
5697 // otherwise.
5698 bool isActive() const;
5699 void setIsActive(bool);
5700
5701 // `true` if this group has been used in the current iteration,
5702 // `false` otherwise.
5703 bool isUsedInThisIteration() const;
5704 void setIsUsedInThisIteration(bool);
5705 protected:
5706 // An implementation of `delete` for this object. Must be provided
5707 // by the embedding.
5708 virtual void Delete() = 0;
5709
5710 private:
5711 // The number of cycles spent in this group during this iteration
5712 // of the event loop. Note that cycles are not a reliable measure,
5713 // especially over short intervals. See Runtime.cpp for a more
5714 // complete discussion on the imprecision of cycle measurement.
5715 uint64_t recentCycles_;
5716
5717 // The number of times this group has been activated during this
5718 // iteration of the event loop.
5719 uint64_t recentTicks_;
5720
5721 // The number of microseconds spent doing CPOW during this
5722 // iteration of the event loop.
5723 uint64_t recentCPOW_;
5724
5725 // The current iteration of the event loop. If necessary,
5726 // may safely overflow.
5727 uint64_t iteration_;
5728
5729 // `true` if new measures should be added to this group, `false`
5730 // otherwise.
5731 bool isActive_;
5732
5733 // `true` if this group has been used in the current iteration,
5734 // `false` otherwise.
5735 bool isUsedInThisIteration_;
5736
5737 // The stopwatch currently monitoring the group,
5738 // or `nullptr` if none. Used ony for comparison.
5739 const AutoStopwatch* owner_;
5740
5741 public:
5742 // Compatibility with RefPtr<>
5743 void AddRef();
5744 void Release();
5745 uint64_t refCount_;
5746 };
5747
5748 /**
5749 * Commit any Performance Monitoring data.
5750 *
5751 * Until `FlushMonitoring` has been called, all PerformanceMonitoring data is invisible
5752 * to the outside world and can cancelled with a call to `ResetMonitoring`.
5753 */
5754 extern JS_PUBLIC_API(bool)
5755 FlushPerformanceMonitoring(JSRuntime*);
5756
5757 /**
5758 * Cancel any measurement that hasn't been committed.
5759 */
5760 extern JS_PUBLIC_API(void)
5761 ResetPerformanceMonitoring(JSRuntime*);
5762
5763 /**
5764 * Cleanup any memory used by performance monitoring.
5765 */
5766 extern JS_PUBLIC_API(void)
5767 DisposePerformanceMonitoring(JSRuntime*);
5768
5769 /**
5770 * Turn on/off stopwatch-based CPU monitoring.
5771 *
5772 * `SetStopwatchIsMonitoringCPOW` or `SetStopwatchIsMonitoringJank`
5773 * may return `false` if monitoring could not be activated, which may
5774 * happen if we are out of memory.
5775 */
5776 extern JS_PUBLIC_API(bool)
5777 SetStopwatchIsMonitoringCPOW(JSRuntime*, bool);
5778 extern JS_PUBLIC_API(bool)
5779 GetStopwatchIsMonitoringCPOW(JSRuntime*);
5780 extern JS_PUBLIC_API(bool)
5781 SetStopwatchIsMonitoringJank(JSRuntime*, bool);
5782 extern JS_PUBLIC_API(bool)
5783 GetStopwatchIsMonitoringJank(JSRuntime*);
5784
5785 extern JS_PUBLIC_API(bool)
5786 IsStopwatchActive(JSRuntime*);
5787
5788 // Extract the CPU rescheduling data.
5789 extern JS_PUBLIC_API(void)
5790 GetPerfMonitoringTestCpuRescheduling(JSRuntime*, uint64_t* stayed, uint64_t* moved);
5791
5792
5793 /**
5794 * Add a number of microseconds to the time spent waiting on CPOWs
5795 * since process start.
5796 */
5797 extern JS_PUBLIC_API(void)
5798 AddCPOWPerformanceDelta(JSRuntime*, uint64_t delta);
5799
5800 typedef bool
5801 (*StopwatchStartCallback)(uint64_t, void*);
5802 extern JS_PUBLIC_API(bool)
5803 SetStopwatchStartCallback(JSRuntime*, StopwatchStartCallback, void*);
5804
5805 typedef bool
5806 (*StopwatchCommitCallback)(uint64_t, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
5807 extern JS_PUBLIC_API(bool)
5808 SetStopwatchCommitCallback(JSRuntime*, StopwatchCommitCallback, void*);
5809
5810 typedef bool
5811 (*GetGroupsCallback)(JSContext*, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
5812 extern JS_PUBLIC_API(bool)
5813 SetGetPerformanceGroupsCallback(JSRuntime*, GetGroupsCallback, void*);
5814
5815 } /* namespace js */
5816
5817
5818 #endif /* jsapi_h */
5819