1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
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 #ifndef jsfriendapi_h
8 #define jsfriendapi_h
9 
10 #include "mozilla/MemoryReporting.h"
11 #include "mozilla/PodOperations.h"
12 
13 #include "jspubtd.h"
14 
15 #include "js/CallArgs.h"
16 #include "js/CharacterEncoding.h"
17 #include "js/Class.h"
18 #include "js/ErrorReport.h"
19 #include "js/Exception.h"
20 #include "js/friend/PerformanceHint.h"
21 #include "js/GCAPI.h"
22 #include "js/HeapAPI.h"
23 #include "js/Object.h"           // JS::GetClass
24 #include "js/shadow/Function.h"  // JS::shadow::Function
25 #include "js/shadow/Object.h"    // JS::shadow::Object
26 #include "js/TypeDecls.h"
27 #include "js/Utility.h"
28 
29 class JSJitInfo;
30 
31 namespace JS {
32 template <class T>
33 class Heap;
34 
35 class ExceptionStack;
36 } /* namespace JS */
37 
38 extern JS_PUBLIC_API void JS_SetGrayGCRootsTracer(JSContext* cx,
39                                                   JSTraceDataOp traceOp,
40                                                   void* data);
41 
42 extern JS_PUBLIC_API JSObject* JS_FindCompilationScope(JSContext* cx,
43                                                        JS::HandleObject obj);
44 
45 extern JS_PUBLIC_API JSFunction* JS_GetObjectFunction(JSObject* obj);
46 
47 /**
48  * Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
49  * without invoking the metadata callback on it.  This allows creation of
50  * internal bookkeeping objects that are guaranteed to not have metadata
51  * attached to them.
52  */
53 extern JS_PUBLIC_API JSObject* JS_NewObjectWithoutMetadata(
54     JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
55 
56 extern JS_PUBLIC_API bool JS_NondeterministicGetWeakMapKeys(
57     JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
58 
59 extern JS_PUBLIC_API bool JS_NondeterministicGetWeakSetKeys(
60     JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
61 
62 // Raw JSScript* because this needs to be callable from a signal handler.
63 extern JS_PUBLIC_API unsigned JS_PCToLineNumber(JSScript* script,
64                                                 jsbytecode* pc,
65                                                 unsigned* columnp = nullptr);
66 
67 /**
68  * Determine whether the given object is backed by a DeadObjectProxy.
69  *
70  * Such objects hold no other objects (they have no outgoing reference edges)
71  * and will throw if you touch them (e.g. by reading/writing a property).
72  */
73 extern JS_PUBLIC_API bool JS_IsDeadWrapper(JSObject* obj);
74 
75 /**
76  * Creates a new dead wrapper object in the given scope. To be used when
77  * attempting to wrap objects from scopes which are already dead.
78  *
79  * If origObject is passed, it must be an proxy object, and will be
80  * used to determine the characteristics of the new dead wrapper.
81  */
82 extern JS_PUBLIC_API JSObject* JS_NewDeadWrapper(
83     JSContext* cx, JSObject* origObject = nullptr);
84 
85 namespace js {
86 
87 /**
88  * Get the script private value associated with an object, if any.
89  *
90  * The private value is set with SetScriptPrivate() or SetModulePrivate() and is
91  * internally stored on the relevant ScriptSourceObject.
92  *
93  * This is used by the cycle collector to trace through
94  * ScriptSourceObjects. This allows private values to contain an nsISupports
95  * pointer and hence support references to cycle collected C++ objects.
96  */
97 JS_PUBLIC_API JS::Value MaybeGetScriptPrivate(JSObject* object);
98 
99 }  // namespace js
100 
101 /*
102  * Used by the cycle collector to trace through a shape or object group and
103  * all cycle-participating data it reaches, using bounded stack space.
104  */
105 extern JS_PUBLIC_API void JS_TraceShapeCycleCollectorChildren(
106     JS::CallbackTracer* trc, JS::GCCellPtr shape);
107 extern JS_PUBLIC_API void JS_TraceObjectGroupCycleCollectorChildren(
108     JS::CallbackTracer* trc, JS::GCCellPtr group);
109 
110 extern JS_PUBLIC_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script);
111 
112 extern JS_PUBLIC_API bool JS_ScriptHasMutedErrors(JSScript* script);
113 
114 extern JS_PUBLIC_API JSObject* JS_CloneObject(JSContext* cx,
115                                               JS::HandleObject obj,
116                                               JS::HandleObject proto);
117 
118 /**
119  * Copy the own properties of src to dst in a fast way.  src and dst must both
120  * be native and must be in the compartment of cx.  They must have the same
121  * class, the same parent, and the same prototype.  Class reserved slots will
122  * NOT be copied.
123  *
124  * dst must not have any properties on it before this function is called.
125  *
126  * src must have been allocated via JS_NewObjectWithoutMetadata so that we can
127  * be sure it has no metadata that needs copying to dst.  This also means that
128  * dst needs to have the compartment global as its parent.  This function will
129  * preserve the existing metadata on dst, if any.
130  */
131 extern JS_PUBLIC_API bool JS_InitializePropertiesFromCompatibleNativeObject(
132     JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
133 
134 namespace js {
135 
136 JS_PUBLIC_API bool IsArgumentsObject(JS::HandleObject obj);
137 
138 JS_PUBLIC_API bool AddRawValueRoot(JSContext* cx, JS::Value* vp,
139                                    const char* name);
140 
141 JS_PUBLIC_API void RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
142 
143 }  // namespace js
144 
145 namespace JS {
146 
147 /**
148  * Set all of the uninitialized lexicals on an object to undefined. Return
149  * true if any lexicals were initialized and false otherwise.
150  * */
151 extern JS_PUBLIC_API bool ForceLexicalInitialization(JSContext* cx,
152                                                      HandleObject obj);
153 
154 /**
155  * Whether we are poisoning unused/released data for error detection. Governed
156  * by the JS_GC_ALLOW_EXTRA_POISONING #ifdef as well as the
157  * $JSGC_EXTRA_POISONING environment variable.
158  */
159 extern JS_PUBLIC_API int IsGCPoisoning();
160 
161 extern JS_PUBLIC_API JSPrincipals* GetRealmPrincipals(JS::Realm* realm);
162 
163 extern JS_PUBLIC_API void SetRealmPrincipals(JS::Realm* realm,
164                                              JSPrincipals* principals);
165 
166 extern JS_PUBLIC_API bool GetIsSecureContext(JS::Realm* realm);
167 
168 }  // namespace JS
169 
170 /**
171  * Copies all own properties and private fields from |obj| to |target|. Both
172  * |obj| and |target| must not be cross-compartment wrappers because we have to
173  * enter their realms.
174  *
175  * This function immediately enters a realm, and does not impose any
176  * restrictions on the realm of |cx|.
177  */
178 extern JS_PUBLIC_API bool JS_CopyOwnPropertiesAndPrivateFields(
179     JSContext* cx, JS::HandleObject target, JS::HandleObject obj);
180 
181 extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
182     JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
183 
184 extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
185     JSContext* cx,
186     JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc);
187 
188 struct JSFunctionSpecWithHelp {
189   const char* name;
190   JSNative call;
191   uint16_t nargs;
192   uint16_t flags;
193   const JSJitInfo* jitInfo;
194   const char* usage;
195   const char* help;
196 };
197 
198 #define JS_FN_HELP(name, call, nargs, flags, usage, help) \
199   { name, call, nargs, (flags) | JSPROP_ENUMERATE, nullptr, usage, help }
200 #define JS_INLINABLE_FN_HELP(name, call, nargs, flags, native, usage, help)    \
201   {                                                                            \
202     name, call, nargs, (flags) | JSPROP_ENUMERATE, &js::jit::JitInfo_##native, \
203         usage, help                                                            \
204   }
205 #define JS_FS_HELP_END \
206   { nullptr, nullptr, 0, 0, nullptr, nullptr }
207 
208 extern JS_PUBLIC_API bool JS_DefineFunctionsWithHelp(
209     JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs);
210 
211 namespace js {
212 
213 /**
214  * Use the runtime's internal handling of job queues for Promise jobs.
215  *
216  * Most embeddings, notably web browsers, will have their own task scheduling
217  * systems and need to integrate handling of Promise jobs into that, so they
218  * will want to manage job queues themselves. For basic embeddings such as the
219  * JS shell that don't have an event loop of their own, it's easier to have
220  * SpiderMonkey handle job queues internally.
221  *
222  * Note that the embedding still has to trigger processing of job queues at
223  * right time(s), such as after evaluation of a script has run to completion.
224  */
225 extern JS_PUBLIC_API bool UseInternalJobQueues(JSContext* cx);
226 
227 /**
228  * Enqueue |job| on the internal job queue.
229  *
230  * This is useful in tests for creating situations where a call occurs with no
231  * other JavaScript on the stack.
232  */
233 extern JS_PUBLIC_API bool EnqueueJob(JSContext* cx, JS::HandleObject job);
234 
235 /**
236  * Instruct the runtime to stop draining the internal job queue.
237  *
238  * Useful if the embedding is in the process of quitting in reaction to a
239  * builtin being called, or if it wants to resume executing jobs later on.
240  */
241 extern JS_PUBLIC_API void StopDrainingJobQueue(JSContext* cx);
242 
243 extern JS_PUBLIC_API void RunJobs(JSContext* cx);
244 
245 extern JS_PUBLIC_API JS::Zone* GetRealmZone(JS::Realm* realm);
246 
247 using PreserveWrapperCallback = bool (*)(JSContext*, JS::HandleObject);
248 using HasReleasedWrapperCallback = bool (*)(JS::HandleObject);
249 
250 extern JS_PUBLIC_API bool IsSystemRealm(JS::Realm* realm);
251 
252 extern JS_PUBLIC_API bool IsSystemCompartment(JS::Compartment* comp);
253 
254 extern JS_PUBLIC_API bool IsSystemZone(JS::Zone* zone);
255 
256 struct WeakMapTracer {
257   JSRuntime* runtime;
258 
WeakMapTracerWeakMapTracer259   explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
260 
261   // Weak map tracer callback, called once for every binding of every
262   // weak map that was live at the time of the last garbage collection.
263   //
264   // m will be nullptr if the weak map is not contained in a JS Object.
265   //
266   // The callback should not GC (and will assert in a debug build if it does
267   // so.)
268   virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0;
269 };
270 
271 extern JS_PUBLIC_API void TraceWeakMaps(WeakMapTracer* trc);
272 
273 extern JS_PUBLIC_API bool AreGCGrayBitsValid(JSRuntime* rt);
274 
275 extern JS_PUBLIC_API bool ZoneGlobalsAreAllGray(JS::Zone* zone);
276 
277 extern JS_PUBLIC_API bool IsCompartmentZoneSweepingOrCompacting(
278     JS::Compartment* comp);
279 
280 using IterateGCThingCallback = void (*)(void*, JS::GCCellPtr,
281                                         const JS::AutoRequireNoGC&);
282 
283 extern JS_PUBLIC_API void TraceGrayWrapperTargets(JSTracer* trc,
284                                                   JS::Zone* zone);
285 
286 /**
287  * Invoke cellCallback on every gray JSObject in the given zone.
288  */
289 extern JS_PUBLIC_API void IterateGrayObjects(
290     JS::Zone* zone, IterateGCThingCallback cellCallback, void* data);
291 
292 #if defined(JS_GC_ZEAL) || defined(DEBUG)
293 // Trace the heap and check there are no black to gray edges. These are
294 // not allowed since the cycle collector could throw away the gray thing and
295 // leave a dangling pointer.
296 //
297 // This doesn't trace weak maps as these are handled separately.
298 extern JS_PUBLIC_API bool CheckGrayMarkingState(JSRuntime* rt);
299 #endif
300 
301 // Note: this returns nullptr iff |zone| is the atoms zone.
302 extern JS_PUBLIC_API JS::Realm* GetAnyRealmInZone(JS::Zone* zone);
303 
304 // Returns the first realm's global in a compartment. Note: this is not
305 // guaranteed to always be the same realm because individual realms can be
306 // collected by the GC.
307 extern JS_PUBLIC_API JSObject* GetFirstGlobalInCompartment(
308     JS::Compartment* comp);
309 
310 // Returns true if the compartment contains a global object and this global is
311 // not being collected.
312 extern JS_PUBLIC_API bool CompartmentHasLiveGlobal(JS::Compartment* comp);
313 
314 // Returns true if this compartment can be shared across multiple Realms.  Used
315 // when we're looking for an existing compartment to place a new Realm in.
316 extern JS_PUBLIC_API bool IsSharableCompartment(JS::Compartment* comp);
317 
318 // This is equal to |&JSObject::class_|.  Use it in places where you don't want
319 // to #include vm/JSObject.h.
320 extern JS_PUBLIC_DATA const JSClass* const ObjectClassPtr;
321 
322 JS_PUBLIC_API const JSClass* ProtoKeyToClass(JSProtoKey key);
323 
324 // Returns the key for the class inherited by a given standard class (that
325 // is to say, the prototype of this standard class's prototype).
326 //
327 // You must be sure that this corresponds to a standard class with a cached
328 // JSProtoKey before calling this function. In general |key| will match the
329 // cached proto key, except in cases where multiple JSProtoKeys share a
330 // JSClass.
InheritanceProtoKeyForStandardClass(JSProtoKey key)331 inline JSProtoKey InheritanceProtoKeyForStandardClass(JSProtoKey key) {
332   // [Object] has nothing to inherit from.
333   if (key == JSProto_Object) {
334     return JSProto_Null;
335   }
336 
337   // If we're ClassSpec defined return the proto key from that
338   if (ProtoKeyToClass(key)->specDefined()) {
339     return ProtoKeyToClass(key)->specInheritanceProtoKey();
340   }
341 
342   // Otherwise, we inherit [Object].
343   return JSProto_Object;
344 }
345 
346 JS_PUBLIC_API bool ShouldIgnorePropertyDefinition(JSContext* cx, JSProtoKey key,
347                                                   jsid id);
348 
349 JS_PUBLIC_API bool IsFunctionObject(JSObject* obj);
350 
351 JS_PUBLIC_API bool UninlinedIsCrossCompartmentWrapper(const JSObject* obj);
352 
353 // CrossCompartmentWrappers are shared by all realms within the compartment, so
354 // getting a wrapper's realm usually doesn't make sense.
GetNonCCWObjectRealm(JSObject * obj)355 static MOZ_ALWAYS_INLINE JS::Realm* GetNonCCWObjectRealm(JSObject* obj) {
356   MOZ_ASSERT(!js::UninlinedIsCrossCompartmentWrapper(obj));
357   return reinterpret_cast<JS::shadow::Object*>(obj)->shape->base->realm;
358 }
359 
360 JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JSObject* obj);
361 
362 JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JS::HandleValue v);
363 
364 #ifdef JS_DEBUG
365 JS_PUBLIC_API void AssertSameCompartment(JSObject* objA, JSObject* objB);
366 #else
AssertSameCompartment(JSObject * objA,JSObject * objB)367 inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
368 #endif
369 
370 JS_PUBLIC_API void NotifyAnimationActivity(JSObject* obj);
371 
372 JS_PUBLIC_API JSFunction* DefineFunctionWithReserved(
373     JSContext* cx, JSObject* obj, const char* name, JSNative call,
374     unsigned nargs, unsigned attrs);
375 
376 JS_PUBLIC_API JSFunction* NewFunctionWithReserved(JSContext* cx, JSNative call,
377                                                   unsigned nargs,
378                                                   unsigned flags,
379                                                   const char* name);
380 
381 JS_PUBLIC_API JSFunction* NewFunctionByIdWithReserved(JSContext* cx,
382                                                       JSNative native,
383                                                       unsigned nargs,
384                                                       unsigned flags, jsid id);
385 
386 JS_PUBLIC_API const JS::Value& GetFunctionNativeReserved(JSObject* fun,
387                                                          size_t which);
388 
389 JS_PUBLIC_API void SetFunctionNativeReserved(JSObject* fun, size_t which,
390                                              const JS::Value& val);
391 
392 JS_PUBLIC_API bool FunctionHasNativeReserved(JSObject* fun);
393 
394 JS_PUBLIC_API bool GetObjectProto(JSContext* cx, JS::HandleObject obj,
395                                   JS::MutableHandleObject proto);
396 
397 extern JS_PUBLIC_API JSObject* GetStaticPrototype(JSObject* obj);
398 
399 JS_PUBLIC_API bool GetRealmOriginalEval(JSContext* cx,
400                                         JS::MutableHandleObject eval);
401 
402 /**
403  * Add some or all property keys of obj to the id vector *props.
404  *
405  * The flags parameter controls which property keys are added. Pass a
406  * combination of the following bits:
407  *
408  *     JSITER_OWNONLY - Don't also search the prototype chain; only consider
409  *       obj's own properties.
410  *
411  *     JSITER_HIDDEN - Include nonenumerable properties.
412  *
413  *     JSITER_SYMBOLS - Include property keys that are symbols. The default
414  *       behavior is to filter out symbols.
415  *
416  *     JSITER_SYMBOLSONLY - Exclude non-symbol property keys.
417  *
418  * This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or
419  * equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass
420  * `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get
421  * results that match the output of Reflect.ownKeys.
422  */
423 JS_PUBLIC_API bool GetPropertyKeys(JSContext* cx, JS::HandleObject obj,
424                                    unsigned flags,
425                                    JS::MutableHandleIdVector props);
426 
427 JS_PUBLIC_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base,
428                                 JS::HandleIdVector others);
429 
430 /**
431  * Determine whether the given string is an array index in the sense of
432  * <https://tc39.github.io/ecma262/#array-index>.
433  *
434  * If it isn't, returns false.
435  *
436  * If it is, returns true and outputs the index in *indexp.
437  */
438 JS_PUBLIC_API bool StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
439 
440 /**
441  * Overload of StringIsArrayIndex taking a (char16_t*,length) pair. Behaves
442  * the same as the JSLinearString version.
443  */
444 JS_PUBLIC_API bool StringIsArrayIndex(const char16_t* str, uint32_t length,
445                                       uint32_t* indexp);
446 
447 JS_PUBLIC_API void SetPreserveWrapperCallbacks(
448     JSContext* cx, PreserveWrapperCallback preserveWrapper,
449     HasReleasedWrapperCallback hasReleasedWrapper);
450 
451 JS_PUBLIC_API bool IsObjectInContextCompartment(JSObject* obj,
452                                                 const JSContext* cx);
453 
454 /*
455  * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
456  */
457 /* 0x1 is no longer used */
458 /* 0x2 is no longer used */
459 #define JSITER_PRIVATE 0x4      /* Include private names in iteration */
460 #define JSITER_OWNONLY 0x8      /* iterate over obj's own properties only */
461 #define JSITER_HIDDEN 0x10      /* also enumerate non-enumerable properties */
462 #define JSITER_SYMBOLS 0x20     /* also include symbol property keys */
463 #define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
464 #define JSITER_FORAWAITOF 0x80  /* for-await-of */
465 
466 using DOMInstanceClassHasProtoAtDepth = bool (*)(const JSClass*, uint32_t,
467                                                  uint32_t);
468 struct JSDOMCallbacks {
469   DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto;
470 };
471 using DOMCallbacks = struct JSDOMCallbacks;
472 
473 extern JS_PUBLIC_API void SetDOMCallbacks(JSContext* cx,
474                                           const DOMCallbacks* callbacks);
475 
476 extern JS_PUBLIC_API const DOMCallbacks* GetDOMCallbacks(JSContext* cx);
477 
478 extern JS_PUBLIC_API JSObject* GetTestingFunctions(JSContext* cx);
479 
480 /* Implemented in jsexn.cpp. */
481 
482 /**
483  * Get an error type name from a JSExnType constant.
484  * Returns nullptr for invalid arguments and JSEXN_INTERNALERR
485  */
486 extern JS_PUBLIC_API JSLinearString* GetErrorTypeName(JSContext* cx,
487                                                       int16_t exnType);
488 
489 /* Implemented in CrossCompartmentWrapper.cpp. */
490 typedef enum NukeReferencesToWindow {
491   NukeWindowReferences,
492   DontNukeWindowReferences
493 } NukeReferencesToWindow;
494 
495 typedef enum NukeReferencesFromTarget {
496   NukeAllReferences,
497   NukeIncomingReferences,
498 } NukeReferencesFromTarget;
499 
500 /*
501  * These filters are designed to be ephemeral stack classes, and thus don't
502  * do any rooting or holding of their members.
503  */
504 struct CompartmentFilter {
505   virtual bool match(JS::Compartment* c) const = 0;
506 };
507 
508 struct AllCompartments : public CompartmentFilter {
matchAllCompartments509   virtual bool match(JS::Compartment* c) const override { return true; }
510 };
511 
512 struct SingleCompartment : public CompartmentFilter {
513   JS::Compartment* ours;
SingleCompartmentSingleCompartment514   explicit SingleCompartment(JS::Compartment* c) : ours(c) {}
matchSingleCompartment515   virtual bool match(JS::Compartment* c) const override { return c == ours; }
516 };
517 
518 extern JS_PUBLIC_API bool NukeCrossCompartmentWrappers(
519     JSContext* cx, const CompartmentFilter& sourceFilter, JS::Realm* target,
520     NukeReferencesToWindow nukeReferencesToWindow,
521     NukeReferencesFromTarget nukeReferencesFromTarget);
522 
523 extern JS_PUBLIC_API bool AllowNewWrapper(JS::Compartment* target,
524                                           JSObject* obj);
525 
526 extern JS_PUBLIC_API bool NukedObjectRealm(JSObject* obj);
527 
528 /* Implemented in jsdate.cpp. */
529 
530 /** Detect whether the internal date value is NaN. */
531 extern JS_PUBLIC_API bool DateIsValid(JSContext* cx, JS::HandleObject obj,
532                                       bool* isValid);
533 
534 extern JS_PUBLIC_API bool DateGetMsecSinceEpoch(JSContext* cx,
535                                                 JS::HandleObject obj,
536                                                 double* msecSinceEpoch);
537 
538 } /* namespace js */
539 
540 namespace js {
541 
542 /* Implemented in vm/StructuredClone.cpp. */
543 extern JS_PUBLIC_API uint64_t GetSCOffset(JSStructuredCloneWriter* writer);
544 
545 }  // namespace js
546 
547 namespace js {
548 
549 /* Statically asserted in FunctionFlags.cpp. */
550 static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x0060;
551 
552 }  // namespace js
553 
FUNCTION_VALUE_TO_JITINFO(const JS::Value & v)554 static MOZ_ALWAYS_INLINE const JSJitInfo* FUNCTION_VALUE_TO_JITINFO(
555     const JS::Value& v) {
556   JSObject* obj = &v.toObject();
557   MOZ_ASSERT(JS::GetClass(obj) == js::FunctionClassPtr);
558 
559   auto* fun = reinterpret_cast<JS::shadow::Function*>(obj);
560   MOZ_ASSERT(!(fun->flags & js::JS_FUNCTION_INTERPRETED_BITS),
561              "Unexpected non-native function");
562 
563   return fun->jitinfo;
564 }
565 
SET_JITINFO(JSFunction * func,const JSJitInfo * info)566 static MOZ_ALWAYS_INLINE void SET_JITINFO(JSFunction* func,
567                                           const JSJitInfo* info) {
568   auto* fun = reinterpret_cast<JS::shadow::Function*>(func);
569   MOZ_ASSERT(!(fun->flags & js::JS_FUNCTION_INTERPRETED_BITS));
570   fun->jitinfo = info;
571 }
572 
573 static_assert(sizeof(jsid) == sizeof(void*));
574 
575 namespace js {
576 
IdToValue(jsid id)577 static MOZ_ALWAYS_INLINE JS::Value IdToValue(jsid id) {
578   if (id.isString()) {
579     return JS::StringValue(id.toString());
580   }
581   if (id.isInt()) {
582     return JS::Int32Value(id.toInt());
583   }
584   if (id.isSymbol()) {
585     return JS::SymbolValue(id.toSymbol());
586   }
587   MOZ_ASSERT(id.isVoid());
588   return JS::UndefinedValue();
589 }
590 
591 /**
592  * PrepareScriptEnvironmentAndInvoke asserts the embedder has registered a
593  * ScriptEnvironmentPreparer and then it calls the preparer's 'invoke' method
594  * with the given |closure|, with the assumption that the preparer will set up
595  * any state necessary to run script in |global|, invoke |closure| with a valid
596  * JSContext*, report any exceptions thrown from the closure, and return.
597  *
598  * PrepareScriptEnvironmentAndInvoke will report any exceptions that are thrown
599  * by the closure.  Consumers who want to propagate back whether the closure
600  * succeeded should do so via members of the closure itself.
601  */
602 
603 struct ScriptEnvironmentPreparer {
604   struct Closure {
605     virtual bool operator()(JSContext* cx) = 0;
606   };
607 
608   virtual void invoke(JS::HandleObject global, Closure& closure) = 0;
609 };
610 
611 extern JS_PUBLIC_API void PrepareScriptEnvironmentAndInvoke(
612     JSContext* cx, JS::HandleObject global,
613     ScriptEnvironmentPreparer::Closure& closure);
614 
615 JS_PUBLIC_API void SetScriptEnvironmentPreparer(
616     JSContext* cx, ScriptEnvironmentPreparer* preparer);
617 
618 // Abstract base class for objects that build allocation metadata for JavaScript
619 // values.
620 struct AllocationMetadataBuilder {
621   AllocationMetadataBuilder() = default;
622 
623   // Return a metadata object for the newly constructed object |obj|, or
624   // nullptr if there's no metadata to attach.
625   //
626   // Implementations should treat all errors as fatal; there is no way to
627   // report errors from this callback. In particular, the caller provides an
628   // oomUnsafe for overriding implementations to use.
buildAllocationMetadataBuilder629   virtual JSObject* build(JSContext* cx, JS::HandleObject obj,
630                           AutoEnterOOMUnsafeRegion& oomUnsafe) const {
631     return nullptr;
632   }
633 };
634 
635 /**
636  * Specify a callback to invoke when creating each JS object in the current
637  * compartment, which may return a metadata object to associate with the
638  * object.
639  */
640 JS_PUBLIC_API void SetAllocationMetadataBuilder(
641     JSContext* cx, const AllocationMetadataBuilder* callback);
642 
643 /** Get the metadata associated with an object. */
644 JS_PUBLIC_API JSObject* GetAllocationMetadata(JSObject* obj);
645 
646 JS_PUBLIC_API bool GetElementsWithAdder(JSContext* cx, JS::HandleObject obj,
647                                         JS::HandleObject receiver,
648                                         uint32_t begin, uint32_t end,
649                                         js::ElementAdder* adder);
650 
651 JS_PUBLIC_API bool ForwardToNative(JSContext* cx, JSNative native,
652                                    const JS::CallArgs& args);
653 
654 /**
655  * Helper function for HTMLDocument and HTMLFormElement.
656  *
657  * These are the only two interfaces that have [OverrideBuiltins], a named
658  * getter, and no named setter. They're implemented as proxies with a custom
659  * getOwnPropertyDescriptor() method. Unfortunately, overriding
660  * getOwnPropertyDescriptor() automatically affects the behavior of set(),
661  * which normally is just common sense but is *not* desired for these two
662  * interfaces.
663  *
664  * The fix is for these two interfaces to override set() to ignore the
665  * getOwnPropertyDescriptor() override.
666  *
667  * SetPropertyIgnoringNamedGetter is exposed to make it easier to override
668  * set() in this way.  It carries out all the steps of BaseProxyHandler::set()
669  * except the initial getOwnPropertyDescriptor() call.  The caller must supply
670  * that descriptor as the 'ownDesc' parameter.
671  *
672  * Implemented in proxy/BaseProxyHandler.cpp.
673  */
674 JS_PUBLIC_API bool SetPropertyIgnoringNamedGetter(
675     JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
676     JS::HandleValue receiver,
677     JS::Handle<mozilla::Maybe<JS::PropertyDescriptor>> ownDesc,
678     JS::ObjectOpResult& result);
679 
680 // This function is for one specific use case, please don't use this for
681 // anything else!
682 extern JS_PUBLIC_API bool ExecuteInFrameScriptEnvironment(
683     JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
684     JS::MutableHandleObject scope);
685 
686 extern JS_PUBLIC_API bool IsSavedFrame(JSObject* obj);
687 
688 // Matches the condition in js/src/jit/ProcessExecutableMemory.cpp
689 #if defined(XP_WIN)
690 // Parameters use void* types to avoid #including windows.h. The return value of
691 // this function is returned from the exception handler.
692 typedef long (*JitExceptionHandler)(void* exceptionRecord,  // PEXECTION_RECORD
693                                     void* context);         // PCONTEXT
694 
695 /**
696  * Windows uses "structured exception handling" to handle faults. When a fault
697  * occurs, the stack is searched for a handler (similar to C++ exception
698  * handling). If the search does not find a handler, the "unhandled exception
699  * filter" is called. Breakpad uses the unhandled exception filter to do crash
700  * reporting. Unfortunately, on Win64, JIT code on the stack completely throws
701  * off this unwinding process and prevents the unhandled exception filter from
702  * being called. The reason is that Win64 requires unwind information be
703  * registered for all code regions and JIT code has none. While it is possible
704  * to register full unwind information for JIT code, this is a lot of work (one
705  * has to be able to recover the frame pointer at any PC) so instead we register
706  * a handler for all JIT code that simply calls breakpad's unhandled exception
707  * filter (which will perform crash reporting and then terminate the process).
708  * This would be wrong if there was an outer __try block that expected to handle
709  * the fault, but this is not generally allowed.
710  *
711  * Gecko must call SetJitExceptionFilter before any JIT code is compiled and
712  * only once per process.
713  */
714 extern JS_PUBLIC_API void SetJitExceptionHandler(JitExceptionHandler handler);
715 #endif
716 
717 extern JS_PUBLIC_API bool ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
718 
719 class MOZ_STACK_CLASS JS_PUBLIC_API AutoAssertNoContentJS {
720  public:
721   explicit AutoAssertNoContentJS(JSContext* cx);
722   ~AutoAssertNoContentJS();
723 
724  private:
725   JSContext* context_;
726   bool prevAllowContentJS_;
727 };
728 
729 /**
730  * This function only reports GC heap memory,
731  * and not malloc allocated memory associated with GC things.
732  */
733 extern JS_PUBLIC_API uint64_t GetGCHeapUsageForObjectZone(JSObject* obj);
734 
735 class JS_PUBLIC_API CompartmentTransplantCallback {
736  public:
737   virtual JSObject* getObjectToTransplant(JS::Compartment* compartment) = 0;
738 };
739 
740 // Gather a set of remote window proxies by calling the callback on every
741 // compartment, then transform them into cross-compartment wrappers to newTarget
742 // via brain transplants. If there's a proxy in newTarget's compartment, it will
743 // get swapped with newTarget, and the value of newTarget will be updated. If
744 // the callback returns null for a compartment, no cross-compartment wrapper
745 // will be created for that compartment. Any non-null values it returns must be
746 // DOM remote proxies from the compartment that was passed in.
747 extern JS_PUBLIC_API void RemapRemoteWindowProxies(
748     JSContext* cx, CompartmentTransplantCallback* callback,
749     JS::MutableHandleObject newTarget);
750 
751 extern JS_PUBLIC_API JS::Zone* GetObjectZoneFromAnyThread(const JSObject* obj);
752 
753 } /* namespace js */
754 
755 #endif /* jsfriendapi_h */
756