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