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