LCOV - code coverage report
Current view: top level - js/src - jsfriendapi.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 128 726 17.6 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          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             : #include "jsfriendapi.h"
       8             : 
       9             : #include "mozilla/Atomics.h"
      10             : #include "mozilla/PodOperations.h"
      11             : 
      12             : #include <stdint.h>
      13             : 
      14             : #ifdef ENABLE_BIGINT
      15             : #include "builtin/BigInt.h"
      16             : #endif
      17             : #include "builtin/Promise.h"
      18             : #include "builtin/TestingFunctions.h"
      19             : #include "gc/GCInternals.h"
      20             : #include "gc/PublicIterators.h"
      21             : #include "gc/WeakMap.h"
      22             : #include "js/Printf.h"
      23             : #include "js/Proxy.h"
      24             : #include "js/Wrapper.h"
      25             : #include "proxy/DeadObjectProxy.h"
      26             : #include "vm/ArgumentsObject.h"
      27             : #include "vm/JSContext.h"
      28             : #include "vm/JSObject.h"
      29             : #include "vm/Realm.h"
      30             : #include "vm/Time.h"
      31             : #include "vm/WrapperObject.h"
      32             : 
      33             : #include "gc/Nursery-inl.h"
      34             : #include "vm/EnvironmentObject-inl.h"
      35             : #include "vm/JSObject-inl.h"
      36             : #include "vm/JSScript-inl.h"
      37             : #include "vm/NativeObject-inl.h"
      38             : 
      39             : using namespace js;
      40             : 
      41             : using mozilla::PodArrayZero;
      42             : 
      43           0 : JS::RootingContext::RootingContext()
      44           0 :   : autoGCRooters_(nullptr), realm_(nullptr), zone_(nullptr)
      45             : {
      46           0 :     for (auto& stackRootPtr : stackRoots_)
      47           0 :         stackRootPtr = nullptr;
      48             : 
      49           0 :     PodArrayZero(nativeStackLimit);
      50             : #if JS_STACK_GROWTH_DIRECTION > 0
      51             :     for (int i=0; i<StackKindCount; i++)
      52             :         nativeStackLimit[i] = UINTPTR_MAX;
      53             : #endif
      54           0 : }
      55             : 
      56             : JS_FRIEND_API(void)
      57           0 : js::SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook)
      58             : {
      59           0 :     cx->runtime()->sourceHook.ref() = std::move(hook);
      60           0 : }
      61             : 
      62             : JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
      63           0 : js::ForgetSourceHook(JSContext* cx)
      64             : {
      65           0 :     return std::move(cx->runtime()->sourceHook.ref());
      66             : }
      67             : 
      68             : JS_FRIEND_API(void)
      69           0 : JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
      70             : {
      71           0 :     cx->runtime()->gc.setGrayRootsTracer(traceOp, data);
      72           0 : }
      73             : 
      74             : JS_FRIEND_API(JSObject*)
      75           0 : JS_FindCompilationScope(JSContext* cx, HandleObject objArg)
      76             : {
      77           0 :     assertSameCompartment(cx, objArg);
      78             : 
      79           0 :     RootedObject obj(cx, objArg);
      80             : 
      81             :     /*
      82             :      * We unwrap wrappers here. This is a little weird, but it's what's being
      83             :      * asked of us.
      84             :      */
      85           0 :     if (obj->is<WrapperObject>())
      86           0 :         obj = UncheckedUnwrap(obj);
      87             : 
      88             :     /*
      89             :      * Get the Window if `obj` is a WindowProxy so that we compile in the
      90             :      * correct (global) scope.
      91             :      */
      92           0 :     return ToWindowIfWindowProxy(obj);
      93             : }
      94             : 
      95             : JS_FRIEND_API(JSFunction*)
      96           0 : JS_GetObjectFunction(JSObject* obj)
      97             : {
      98           0 :     if (obj->is<JSFunction>())
      99           0 :         return &obj->as<JSFunction>();
     100             :     return nullptr;
     101             : }
     102             : 
     103             : JS_FRIEND_API(bool)
     104           0 : JS_SplicePrototype(JSContext* cx, HandleObject obj, HandleObject proto)
     105             : {
     106             :     /*
     107             :      * Change the prototype of an object which hasn't been used anywhere
     108             :      * and does not share its type with another object. Unlike JS_SetPrototype,
     109             :      * does not nuke type information for the object.
     110             :      */
     111           0 :     CHECK_REQUEST(cx);
     112           0 :     assertSameCompartment(cx, obj, proto);
     113             : 
     114           0 :     if (!obj->isSingleton()) {
     115             :         /*
     116             :          * We can see non-singleton objects when trying to splice prototypes
     117             :          * due to mutable __proto__ (ugh).
     118             :          */
     119           0 :         return JS_SetPrototype(cx, obj, proto);
     120             :     }
     121             : 
     122           0 :     Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
     123           0 :     return JSObject::splicePrototype(cx, obj, obj->getClass(), tagged);
     124             : }
     125             : 
     126             : JS_FRIEND_API(JSObject*)
     127           0 : JS_NewObjectWithUniqueType(JSContext* cx, const JSClass* clasp, HandleObject proto)
     128             : {
     129             :     /*
     130             :      * Create our object with a null proto and then splice in the correct proto
     131             :      * after we setSingleton, so that we don't pollute the default
     132             :      * ObjectGroup attached to our proto with information about our object, since
     133             :      * we're not going to be using that ObjectGroup anyway.
     134             :      */
     135           0 :     RootedObject obj(cx, NewObjectWithGivenProto(cx, Valueify(clasp), nullptr, SingletonObject));
     136           0 :     if (!obj)
     137             :         return nullptr;
     138           0 :     if (!JS_SplicePrototype(cx, obj, proto))
     139             :         return nullptr;
     140           0 :     return obj;
     141             : }
     142             : 
     143             : JS_FRIEND_API(JSObject*)
     144           0 : JS_NewObjectWithoutMetadata(JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto)
     145             : {
     146           0 :     assertSameCompartment(cx, proto);
     147           0 :     AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
     148           0 :     return JS_NewObjectWithGivenProto(cx, clasp, proto);
     149             : }
     150             : 
     151             : JS_FRIEND_API(bool)
     152           0 : JS::GetIsSecureContext(JS::Realm* realm)
     153             : {
     154           0 :     return realm->creationOptions().secureContext();
     155             : }
     156             : 
     157             : JS_FRIEND_API(JSPrincipals*)
     158           0 : JS_GetCompartmentPrincipals(JS::Compartment* compartment)
     159             : {
     160             :     // Note: for now we assume a single realm per compartment. This API will go
     161             :     // away after we remove the remaining callers. See bug 1465700.
     162       89980 :     MOZ_RELEASE_ASSERT(compartment->realms().length() == 1);
     163             : 
     164       89980 :     return compartment->realms()[0]->principals();
     165             : }
     166             : 
     167             : JS_FRIEND_API(JSPrincipals*)
     168       15231 : JS::GetRealmPrincipals(JS::Realm* realm)
     169             : {
     170       15231 :     return realm->principals();
     171             : }
     172             : 
     173             : JS_FRIEND_API(void)
     174           0 : JS::SetRealmPrincipals(JS::Realm* realm, JSPrincipals* principals)
     175             : {
     176             :     // Short circuit if there's no change.
     177          53 :     if (principals == realm->principals())
     178             :         return;
     179             : 
     180             :     // Any realm with the trusted principals -- and there can be
     181             :     // multiple -- is a system realm.
     182          92 :     const JSPrincipals* trusted = realm->runtimeFromMainThread()->trustedPrincipals();
     183           0 :     bool isSystem = principals && principals == trusted;
     184             : 
     185             :     // Clear out the old principals, if any.
     186          46 :     if (realm->principals()) {
     187           0 :         JS_DropPrincipals(TlsContext.get(), realm->principals());
     188           0 :         realm->setPrincipals(nullptr);
     189             :         // We'd like to assert that our new principals is always same-origin
     190             :         // with the old one, but JSPrincipals doesn't give us a way to do that.
     191             :         // But we can at least assert that we're not switching between system
     192             :         // and non-system.
     193           0 :         MOZ_ASSERT(realm->isSystem() == isSystem);
     194             :     }
     195             : 
     196             :     // Set up the new principals.
     197          46 :     if (principals) {
     198          46 :         JS_HoldPrincipals(principals);
     199             :         realm->setPrincipals(principals);
     200             :     }
     201             : 
     202             :     // Update the system flag.
     203          46 :     realm->setIsSystem(isSystem);
     204             : }
     205             : 
     206             : JS_FRIEND_API(JSPrincipals*)
     207         265 : JS_GetScriptPrincipals(JSScript* script)
     208             : {
     209         265 :     return script->principals();
     210             : }
     211             : 
     212             : JS_FRIEND_API(JS::Realm*)
     213           0 : js::GetScriptRealm(JSScript* script)
     214             : {
     215           0 :     return script->realm();
     216             : }
     217             : 
     218             : JS_FRIEND_API(bool)
     219           0 : JS_ScriptHasMutedErrors(JSScript* script)
     220             : {
     221           0 :     return script->mutedErrors();
     222             : }
     223             : 
     224             : JS_FRIEND_API(bool)
     225          54 : JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<js::PropertyDescriptor> desc)
     226             : {
     227          54 :     return cx->compartment()->wrap(cx, desc);
     228             : }
     229             : 
     230             : JS_FRIEND_API(void)
     231           0 : JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr shape)
     232             : {
     233           0 :     MOZ_ASSERT(shape.is<Shape>());
     234           0 :     TraceCycleCollectorChildren(trc, &shape.as<Shape>());
     235           0 : }
     236             : 
     237             : JS_FRIEND_API(void)
     238           0 : JS_TraceObjectGroupCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr group)
     239             : {
     240           0 :     MOZ_ASSERT(group.is<ObjectGroup>());
     241           0 :     TraceCycleCollectorChildren(trc, &group.as<ObjectGroup>());
     242           0 : }
     243             : 
     244             : static bool
     245           0 : DefineHelpProperty(JSContext* cx, HandleObject obj, const char* prop, const char* value)
     246             : {
     247           0 :     RootedAtom atom(cx, Atomize(cx, value, strlen(value)));
     248           0 :     if (!atom)
     249             :         return false;
     250           0 :     return JS_DefineProperty(cx, obj, prop, atom, JSPROP_READONLY | JSPROP_PERMANENT);
     251             : }
     252             : 
     253             : JS_FRIEND_API(bool)
     254           0 : JS_DefineFunctionsWithHelp(JSContext* cx, HandleObject obj, const JSFunctionSpecWithHelp* fs)
     255             : {
     256           0 :     MOZ_ASSERT(!cx->zone()->isAtomsZone());
     257             : 
     258           0 :     CHECK_REQUEST(cx);
     259           0 :     assertSameCompartment(cx, obj);
     260           0 :     for (; fs->name; fs++) {
     261           0 :         JSAtom* atom = Atomize(cx, fs->name, strlen(fs->name));
     262           0 :         if (!atom)
     263           0 :             return false;
     264             : 
     265           0 :         Rooted<jsid> id(cx, AtomToId(atom));
     266           0 :         RootedFunction fun(cx, DefineFunction(cx, obj, id, fs->call, fs->nargs,
     267           0 :                                               fs->flags | JSPROP_RESOLVING));
     268           0 :         if (!fun)
     269           0 :             return false;
     270             : 
     271           0 :         if (fs->jitInfo)
     272           0 :             fun->setJitInfo(fs->jitInfo);
     273             : 
     274           0 :         if (fs->usage) {
     275           0 :             if (!DefineHelpProperty(cx, fun, "usage", fs->usage))
     276             :                 return false;
     277             :         }
     278             : 
     279           0 :         if (fs->help) {
     280           0 :             if (!DefineHelpProperty(cx, fun, "help", fs->help))
     281             :                 return false;
     282             :         }
     283             :     }
     284             : 
     285             :     return true;
     286             : }
     287             : 
     288             : JS_FRIEND_API(bool)
     289           0 : js::GetBuiltinClass(JSContext* cx, HandleObject obj, ESClass* cls)
     290             : {
     291           0 :     if (MOZ_UNLIKELY(obj->is<ProxyObject>()))
     292           0 :         return Proxy::getBuiltinClass(cx, obj, cls);
     293             : 
     294           0 :     if (obj->is<PlainObject>() || obj->is<UnboxedPlainObject>())
     295           0 :         *cls = ESClass::Object;
     296           0 :     else if (obj->is<ArrayObject>())
     297           0 :         *cls = ESClass::Array;
     298           0 :     else if (obj->is<NumberObject>())
     299           0 :         *cls = ESClass::Number;
     300           0 :     else if (obj->is<StringObject>())
     301           0 :         *cls = ESClass::String;
     302           0 :     else if (obj->is<BooleanObject>())
     303           0 :         *cls = ESClass::Boolean;
     304           0 :     else if (obj->is<RegExpObject>())
     305           0 :         *cls = ESClass::RegExp;
     306           0 :     else if (obj->is<ArrayBufferObject>())
     307           0 :         *cls = ESClass::ArrayBuffer;
     308           0 :     else if (obj->is<SharedArrayBufferObject>())
     309           0 :         *cls = ESClass::SharedArrayBuffer;
     310           0 :     else if (obj->is<DateObject>())
     311           0 :         *cls = ESClass::Date;
     312           0 :     else if (obj->is<SetObject>())
     313           0 :         *cls = ESClass::Set;
     314           0 :     else if (obj->is<MapObject>())
     315           0 :         *cls = ESClass::Map;
     316           0 :     else if (obj->is<PromiseObject>())
     317           0 :         *cls = ESClass::Promise;
     318           0 :     else if (obj->is<MapIteratorObject>())
     319           0 :         *cls = ESClass::MapIterator;
     320           0 :     else if (obj->is<SetIteratorObject>())
     321           0 :         *cls = ESClass::SetIterator;
     322           0 :     else if (obj->is<ArgumentsObject>())
     323           0 :         *cls = ESClass::Arguments;
     324         106 :     else if (obj->is<ErrorObject>())
     325           0 :         *cls = ESClass::Error;
     326             : #ifdef ENABLE_BIGINT
     327             :     else if (obj->is<BigIntObject>())
     328             :         *cls = ESClass::BigInt;
     329             : #endif
     330             :     else
     331          53 :         *cls = ESClass::Other;
     332             : 
     333             :     return true;
     334             : }
     335             : 
     336             : JS_FRIEND_API(const char*)
     337           0 : js::ObjectClassName(JSContext* cx, HandleObject obj)
     338             : {
     339           0 :     assertSameCompartment(cx, obj);
     340           0 :     return GetObjectClassName(cx, obj);
     341             : }
     342             : 
     343             : JS_FRIEND_API(JS::Zone*)
     344     3319545 : js::GetRealmZone(JS::Realm* realm)
     345             : {
     346     3319545 :     return realm->zone();
     347             : }
     348             : 
     349             : JS_FRIEND_API(bool)
     350           0 : js::IsSystemCompartment(JS::Compartment* comp)
     351             : {
     352             :     // Note: for now we assume a single realm per compartment. This API will
     353             :     // hopefully go away once Gecko supports same-compartment realms. Another
     354             :     // option is to return comp->zone()->isSystem here, but we'd have to make
     355             :     // sure that's equivalent.
     356           0 :     MOZ_RELEASE_ASSERT(comp->realms().length() == 1);
     357             : 
     358           0 :     return comp->realms()[0]->isSystem();
     359             : }
     360             : 
     361             : JS_FRIEND_API(bool)
     362           8 : js::IsSystemRealm(JS::Realm* realm)
     363             : {
     364           8 :     return realm->isSystem();
     365             : }
     366             : 
     367             : JS_FRIEND_API(bool)
     368           0 : js::IsSystemZone(Zone* zone)
     369             : {
     370           0 :     return zone->isSystem;
     371             : }
     372             : 
     373             : JS_FRIEND_API(bool)
     374           0 : js::IsAtomsZone(JS::Zone* zone)
     375             : {
     376           0 :     return zone->runtimeFromAnyThread()->isAtomsZone(zone);
     377             : }
     378             : 
     379             : JS_FRIEND_API(bool)
     380           1 : js::IsFunctionObject(JSObject* obj)
     381             : {
     382        2313 :     return obj->is<JSFunction>();
     383             : }
     384             : 
     385             : JS_FRIEND_API(JSObject*)
     386           0 : js::GetGlobalForObjectCrossCompartment(JSObject* obj)
     387             : {
     388       55182 :     return &obj->deprecatedGlobal();
     389             : }
     390             : 
     391             : JS_FRIEND_API(JSObject*)
     392           0 : js::GetPrototypeNoProxy(JSObject* obj)
     393             : {
     394           0 :     MOZ_ASSERT(!obj->is<js::ProxyObject>());
     395           0 :     return obj->staticPrototype();
     396             : }
     397             : 
     398             : JS_FRIEND_API(void)
     399           0 : js::AssertSameCompartment(JSContext* cx, JSObject* obj)
     400             : {
     401        7180 :     assertSameCompartment(cx, obj);
     402        7180 : }
     403             : 
     404             : JS_FRIEND_API(void)
     405           0 : js::AssertSameCompartment(JSContext* cx, JS::HandleValue v)
     406             : {
     407           0 :     assertSameCompartment(cx, v);
     408           0 : }
     409             : 
     410             : #ifdef DEBUG
     411             : JS_FRIEND_API(void)
     412           1 : js::AssertSameCompartment(JSObject* objA, JSObject* objB)
     413             : {
     414           1 :     MOZ_ASSERT(objA->compartment() == objB->compartment());
     415         297 : }
     416             : #endif
     417             : 
     418             : JS_FRIEND_API(void)
     419           2 : js::NotifyAnimationActivity(JSObject* obj)
     420             : {
     421           2 :     int64_t timeNow = PRMJ_Now();
     422           2 :     obj->realm()->lastAnimationTime = timeNow;
     423           4 :     obj->runtimeFromMainThread()->lastAnimationTime = timeNow;
     424           0 : }
     425             : 
     426             : JS_FRIEND_API(uint32_t)
     427           0 : js::GetObjectSlotSpan(JSObject* obj)
     428             : {
     429           0 :     return obj->as<NativeObject>().slotSpan();
     430             : }
     431             : 
     432             : JS_FRIEND_API(bool)
     433           0 : js::IsObjectInContextCompartment(JSObject* obj, const JSContext* cx)
     434             : {
     435           0 :     return obj->compartment() == cx->compartment();
     436             : }
     437             : 
     438             : JS_FRIEND_API(bool)
     439        2040 : js::RunningWithTrustedPrincipals(JSContext* cx)
     440             : {
     441           0 :     return cx->runningWithTrustedPrincipals();
     442             : }
     443             : 
     444             : JS_FRIEND_API(JSFunction*)
     445           0 : js::DefineFunctionWithReserved(JSContext* cx, JSObject* objArg, const char* name, JSNative call,
     446             :                                unsigned nargs, unsigned attrs)
     447             : {
     448           0 :     RootedObject obj(cx, objArg);
     449          48 :     MOZ_ASSERT(!cx->zone()->isAtomsZone());
     450           0 :     CHECK_REQUEST(cx);
     451          24 :     assertSameCompartment(cx, obj);
     452           0 :     JSAtom* atom = Atomize(cx, name, strlen(name));
     453           0 :     if (!atom)
     454             :         return nullptr;
     455           0 :     Rooted<jsid> id(cx, AtomToId(atom));
     456          48 :     return DefineFunction(cx, obj, id, call, nargs, attrs, gc::AllocKind::FUNCTION_EXTENDED);
     457             : }
     458             : 
     459             : JS_FRIEND_API(JSFunction*)
     460           0 : js::NewFunctionWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
     461             :                             const char* name)
     462             : {
     463         188 :     MOZ_ASSERT(!cx->zone()->isAtomsZone());
     464             : 
     465           0 :     CHECK_REQUEST(cx);
     466             : 
     467         188 :     RootedAtom atom(cx);
     468           0 :     if (name) {
     469           0 :         atom = Atomize(cx, name, strlen(name));
     470           0 :         if (!atom)
     471             :             return nullptr;
     472             :     }
     473             : 
     474           0 :     return (flags & JSFUN_CONSTRUCTOR) ?
     475           0 :         NewNativeConstructor(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED) :
     476           0 :         NewNativeFunction(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED);
     477             : }
     478             : 
     479             : JS_FRIEND_API(JSFunction*)
     480           0 : js::NewFunctionByIdWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
     481             :                                 jsid id)
     482             : {
     483           0 :     MOZ_ASSERT(JSID_IS_STRING(id));
     484        8314 :     MOZ_ASSERT(!cx->zone()->isAtomsZone());
     485        8314 :     CHECK_REQUEST(cx);
     486        4157 :     assertSameCompartment(cx, id);
     487             : 
     488        8314 :     RootedAtom atom(cx, JSID_TO_ATOM(id));
     489           0 :     return (flags & JSFUN_CONSTRUCTOR) ?
     490           0 :         NewNativeConstructor(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED) :
     491           0 :         NewNativeFunction(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED);
     492             : }
     493             : 
     494             : JS_FRIEND_API(const Value&)
     495           0 : js::GetFunctionNativeReserved(JSObject* fun, size_t which)
     496             : {
     497           0 :     MOZ_ASSERT(fun->as<JSFunction>().isNative());
     498           0 :     return fun->as<JSFunction>().getExtendedSlot(which);
     499             : }
     500             : 
     501             : JS_FRIEND_API(void)
     502           0 : js::SetFunctionNativeReserved(JSObject* fun, size_t which, const Value& val)
     503             : {
     504           0 :     MOZ_ASSERT(fun->as<JSFunction>().isNative());
     505       14261 :     MOZ_ASSERT_IF(val.isObject(), val.toObject().compartment() == fun->compartment());
     506           0 :     fun->as<JSFunction>().setExtendedSlot(which, val);
     507           0 : }
     508             : 
     509             : JS_FRIEND_API(bool)
     510           0 : js::FunctionHasNativeReserved(JSObject* fun)
     511             : {
     512        4626 :     MOZ_ASSERT(fun->as<JSFunction>().isNative());
     513        2313 :     return fun->as<JSFunction>().isExtended();
     514             : }
     515             : 
     516             : JS_FRIEND_API(bool)
     517           0 : js::GetObjectProto(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> proto)
     518             : {
     519       11997 :     assertSameCompartment(cx, obj);
     520             : 
     521           0 :     if (IsProxy(obj))
     522       11763 :         return JS_GetPrototype(cx, obj, proto);
     523             : 
     524           0 :     proto.set(reinterpret_cast<const shadow::Object*>(obj.get())->group->proto);
     525           0 :     return true;
     526             : }
     527             : 
     528             : JS_FRIEND_API(JSObject*)
     529           0 : js::GetStaticPrototype(JSObject* obj)
     530             : {
     531           0 :     MOZ_ASSERT(obj->hasStaticPrototype());
     532           0 :     return obj->staticPrototype();
     533             : }
     534             : 
     535             : JS_FRIEND_API(bool)
     536           0 : js::GetRealmOriginalEval(JSContext* cx, MutableHandleObject eval)
     537             : {
     538           0 :     return GlobalObject::getOrCreateEval(cx, cx->global(), eval);
     539           0 : }
     540           0 : 
     541             : JS_FRIEND_API(void)
     542             : js::SetReservedSlotWithBarrier(JSObject* obj, size_t slot, const js::Value& value)
     543             : {
     544           0 :     if (IsProxy(obj))
     545             :         obj->as<ProxyObject>().setReservedSlot(slot, value);
     546           0 :     else
     547           0 :         obj->as<NativeObject>().setSlot(slot, value);
     548             : }
     549         248 : 
     550           0 : void
     551             : js::SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback)
     552             : {
     553           4 :     cx->runtime()->preserveWrapperCallback = callback;
     554             : }
     555           8 : 
     556           0 : JS_FRIEND_API(unsigned)
     557             : JS_PCToLineNumber(JSScript* script, jsbytecode* pc, unsigned* columnp)
     558             : {
     559           0 :     return PCToLineNumber(script, pc, columnp);
     560             : }
     561           0 : 
     562             : JS_FRIEND_API(bool)
     563             : JS_IsDeadWrapper(JSObject* obj)
     564             : {
     565       22953 :     return IsDeadProxyObject(obj);
     566             : }
     567       22953 : 
     568             : JS_FRIEND_API(JSObject*)
     569             : JS_NewDeadWrapper(JSContext* cx, JSObject* origObj)
     570             : {
     571           0 :     return NewDeadProxyObject(cx, origObj);
     572             : }
     573           0 : 
     574             : JS_FRIEND_API(bool)
     575             : JS_IsScriptSourceObject(JSObject* obj)
     576             : {
     577       34057 :     return obj->is<ScriptSourceObject>();
     578             : }
     579       34057 : 
     580             : void
     581             : js::TraceWeakMaps(WeakMapTracer* trc)
     582             : {
     583           0 :     WeakMapBase::traceAllMappings(trc);
     584             : }
     585           0 : 
     586           0 : extern JS_FRIEND_API(bool)
     587             : js::AreGCGrayBitsValid(JSRuntime* rt)
     588             : {
     589           0 :     return rt->gc.areGrayBitsValid();
     590             : }
     591           0 : 
     592             : JS_FRIEND_API(bool)
     593             : js::ZoneGlobalsAreAllGray(JS::Zone* zone)
     594             : {
     595           0 :     for (RealmsInZoneIter realm(zone); !realm.done(); realm.next()) {
     596             :         JSObject* obj = realm->unsafeUnbarrieredMaybeGlobal();
     597           0 :         if (!obj || !JS::ObjectIsMarkedGray(obj))
     598           0 :             return false;
     599           0 :     }
     600           0 :     return true;
     601             : }
     602           0 : 
     603             : JS_FRIEND_API(bool)
     604             : js::IsObjectZoneSweepingOrCompacting(JSObject* obj)
     605             : {
     606           0 :     MOZ_ASSERT(obj);
     607             :     return MaybeForwarded(obj)->zone()->isGCSweepingOrCompacting();
     608           0 : }
     609           0 : 
     610             : namespace {
     611             : struct VisitGrayCallbackFunctor {
     612             :     GCThingCallback callback_;
     613             :     void* closure_;
     614             :     VisitGrayCallbackFunctor(GCThingCallback callback, void* closure)
     615             :       : callback_(callback), closure_(closure)
     616             :     {}
     617             : 
     618             :     template <class T>
     619             :     void operator()(T tp) const {
     620             :         if ((*tp)->isMarkedGray())
     621           0 :             callback_(closure_, JS::GCCellPtr(*tp));
     622           0 :     }
     623           0 : };
     624           0 : } // namespace (anonymous)
     625             : 
     626             : JS_FRIEND_API(void)
     627             : js::VisitGrayWrapperTargets(Zone* zone, GCThingCallback callback, void* closure)
     628             : {
     629           0 :     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
     630             :         for (Compartment::WrapperEnum e(comp); !e.empty(); e.popFront())
     631           0 :             e.front().mutableKey().applyToWrapped(VisitGrayCallbackFunctor(callback, closure));
     632           0 :     }
     633           0 : }
     634             : 
     635           0 : JS_FRIEND_API(JSObject*)
     636             : js::GetWeakmapKeyDelegate(JSObject* key)
     637             : {
     638           0 :     if (JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp())
     639             :         return op(key);
     640           0 :     return nullptr;
     641           0 : }
     642             : 
     643             : JS_FRIEND_API(JSLinearString*)
     644             : js::StringToLinearStringSlow(JSContext* cx, JSString* str)
     645             : {
     646           0 :     return str->ensureLinear(cx);
     647             : }
     648          58 : 
     649             : JS_FRIEND_API(void)
     650             : JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback)
     651             : {
     652           0 :     cx->runtime()->setTelemetryCallback(cx->runtime(), callback);
     653             : }
     654           0 : 
     655           1 : JS_FRIEND_API(void)
     656             : JS_SetSetUseCounterCallback(JSContext* cx, JSSetUseCounterCallback callback)
     657             : {
     658           1 :     cx->runtime()->setUseCounterCallback(cx->runtime(), callback);
     659             : }
     660           2 : 
     661           1 : JS_FRIEND_API(JSObject*)
     662             : JS_CloneObject(JSContext* cx, HandleObject obj, HandleObject protoArg)
     663             : {
     664           0 :     // |obj| might be in a different compartment.
     665             :     assertSameCompartment(cx, protoArg);
     666             :     Rooted<TaggedProto> proto(cx, TaggedProto(protoArg.get()));
     667           0 :     return CloneObject(cx, obj, proto);
     668           0 : }
     669           0 : 
     670             : #ifdef DEBUG
     671             : 
     672             : // We don't want jsfriendapi.h to depend on GenericPrinter,
     673             : // so these functions are declared directly in the cpp.
     674             : 
     675             : namespace js {
     676             : 
     677             : extern JS_FRIEND_API(void)
     678             : DumpString(JSString* str, js::GenericPrinter& out);
     679             : 
     680             : extern JS_FRIEND_API(void)
     681             : DumpAtom(JSAtom* atom, js::GenericPrinter& out);
     682             : 
     683             : extern JS_FRIEND_API(void)
     684             : DumpObject(JSObject* obj, js::GenericPrinter& out);
     685             : 
     686             : extern JS_FRIEND_API(void)
     687             : DumpChars(const char16_t* s, size_t n, js::GenericPrinter& out);
     688             : 
     689             : extern JS_FRIEND_API(void)
     690             : DumpValue(const JS::Value& val, js::GenericPrinter& out);
     691             : 
     692             : extern JS_FRIEND_API(void)
     693             : DumpId(jsid id, js::GenericPrinter& out);
     694             : 
     695             : extern JS_FRIEND_API(void)
     696             : DumpInterpreterFrame(JSContext* cx, js::GenericPrinter& out, InterpreterFrame* start = nullptr);
     697             : 
     698             : } // namespace js
     699             : 
     700             : JS_FRIEND_API(void)
     701             : js::DumpString(JSString* str, js::GenericPrinter& out)
     702             : {
     703           0 :     str->dump(out);
     704             : }
     705           0 : 
     706           0 : JS_FRIEND_API(void)
     707             : js::DumpAtom(JSAtom* atom, js::GenericPrinter& out)
     708             : {
     709           0 :     atom->dump(out);
     710             : }
     711           0 : 
     712           0 : JS_FRIEND_API(void)
     713             : js::DumpChars(const char16_t* s, size_t n, js::GenericPrinter& out)
     714             : {
     715           0 :     out.printf("char16_t * (%p) = ", (void*) s);
     716             :     JSString::dumpChars(s, n, out);
     717           0 :     out.putChar('\n');
     718           0 : }
     719           0 : 
     720           0 : JS_FRIEND_API(void)
     721             : js::DumpObject(JSObject* obj, js::GenericPrinter& out)
     722             : {
     723           0 :     if (!obj) {
     724             :         out.printf("NULL\n");
     725           0 :         return;
     726           0 :     }
     727           0 :     obj->dump(out);
     728             : }
     729           0 : 
     730             : JS_FRIEND_API(void)
     731             : js::DumpString(JSString* str, FILE* fp)
     732             : {
     733           0 :     Fprinter out(fp);
     734             :     js::DumpString(str, out);
     735           0 : }
     736           0 : 
     737           0 : JS_FRIEND_API(void)
     738             : js::DumpAtom(JSAtom* atom, FILE* fp)
     739             : {
     740           0 :     Fprinter out(fp);
     741             :     js::DumpAtom(atom, out);
     742           0 : }
     743           0 : 
     744           0 : JS_FRIEND_API(void)
     745             : js::DumpChars(const char16_t* s, size_t n, FILE* fp)
     746             : {
     747           0 :     Fprinter out(fp);
     748             :     js::DumpChars(s, n, out);
     749           0 : }
     750           0 : 
     751           0 : JS_FRIEND_API(void)
     752             : js::DumpObject(JSObject* obj, FILE* fp)
     753             : {
     754           0 :     Fprinter out(fp);
     755             :     js::DumpObject(obj, out);
     756           0 : }
     757           0 : 
     758           0 : JS_FRIEND_API(void)
     759             : js::DumpId(jsid id, FILE* fp)
     760             : {
     761           0 :     Fprinter out(fp);
     762             :     js::DumpId(id, out);
     763           0 : }
     764           0 : 
     765           0 : JS_FRIEND_API(void)
     766             : js::DumpValue(const JS::Value& val, FILE* fp) {
     767             :     Fprinter out(fp);
     768           0 :     js::DumpValue(val, out);
     769           0 : }
     770           0 : 
     771           0 : JS_FRIEND_API(void)
     772             : js::DumpString(JSString* str) {
     773             :     DumpString(str, stderr);
     774           0 : }
     775           0 : JS_FRIEND_API(void)
     776           0 : js::DumpAtom(JSAtom* atom) {
     777             :     DumpAtom(atom, stderr);
     778           0 : }
     779           0 : JS_FRIEND_API(void)
     780           0 : js::DumpObject(JSObject* obj) {
     781             :     DumpObject(obj, stderr);
     782           0 : }
     783           0 : JS_FRIEND_API(void)
     784           0 : js::DumpChars(const char16_t* s, size_t n) {
     785             :     DumpChars(s, n, stderr);
     786           0 : }
     787           0 : JS_FRIEND_API(void)
     788           0 : js::DumpValue(const JS::Value& val) {
     789             :     DumpValue(val, stderr);
     790           0 : }
     791           0 : JS_FRIEND_API(void)
     792           0 : js::DumpId(jsid id) {
     793             :     DumpId(id, stderr);
     794           0 : }
     795           0 : JS_FRIEND_API(void)
     796           0 : js::DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start)
     797             : {
     798           0 :     Fprinter out(stderr);
     799             :     DumpInterpreterFrame(cx, out, start);
     800           0 : }
     801           0 : JS_FRIEND_API(bool)
     802           0 : js::DumpPC(JSContext* cx) {
     803             :     return DumpPC(cx, stdout);
     804           0 : }
     805           0 : JS_FRIEND_API(bool)
     806             : js::DumpScript(JSContext* cx, JSScript* scriptArg)
     807             : {
     808           0 :     return DumpScript(cx, scriptArg, stdout);
     809             : }
     810           0 : 
     811             : #endif
     812             : 
     813             : static const char*
     814             : FormatValue(JSContext* cx, const Value& vArg, JSAutoByteString& bytes)
     815             : {
     816           0 :     RootedValue v(cx, vArg);
     817             : 
     818           0 :     if (v.isMagic(JS_OPTIMIZED_OUT))
     819             :         return "[unavailable]";
     820           0 : 
     821             :     /*
     822             :      * We could use Maybe<AutoRealm> here, but G++ can't quite follow
     823             :      * that, and warns about uninitialized members being used in the
     824             :      * destructor.
     825             :      */
     826             :     RootedString str(cx);
     827             :     if (v.isObject()) {
     828           0 :         AutoRealm ar(cx, &v.toObject());
     829           0 :         str = ToString<CanGC>(cx, v);
     830           0 :     } else {
     831           0 :         str = ToString<CanGC>(cx, v);
     832             :     }
     833           0 : 
     834             :     if (!str)
     835             :         return nullptr;
     836           0 :     const char* buf = bytes.encodeLatin1(cx, str);
     837             :     if (!buf)
     838           0 :         return nullptr;
     839           0 :     const char* found = strstr(buf, "function ");
     840             :     if (found && (found - buf <= 2))
     841           0 :         return "[function]";
     842           0 :     return buf;
     843             : }
     844           0 : 
     845             : // Wrapper for JS_sprintf_append() that reports allocation failure to the
     846             : // context.
     847             : static JS::UniqueChars
     848             : MOZ_FORMAT_PRINTF(3, 4)
     849             : sprintf_append(JSContext* cx, JS::UniqueChars&& buf, const char* fmt, ...)
     850             : {
     851          68 :     va_list ap;
     852             : 
     853             :     va_start(ap, fmt);
     854             :     JS::UniqueChars result = JS_vsprintf_append(std::move(buf), fmt, ap);
     855          68 :     va_end(ap);
     856           0 : 
     857           0 :     if (!result) {
     858             :         ReportOutOfMemory(cx);
     859          68 :         return nullptr;
     860           0 :     }
     861             : 
     862             :     return result;
     863             : }
     864             : 
     865             : static JS::UniqueChars
     866             : FormatFrame(JSContext* cx, const FrameIter& iter, JS::UniqueChars&& inBuf, int num,
     867             :             bool showArgs, bool showLocals, bool showThisProps)
     868           0 : {
     869             :     MOZ_ASSERT(!cx->isExceptionPending());
     870             :     RootedScript script(cx, iter.script());
     871           0 :     jsbytecode* pc = iter.pc();
     872           0 : 
     873           0 :     RootedObject envChain(cx, iter.environmentChain(cx));
     874             :     JSAutoRealm ar(cx, envChain);
     875          68 : 
     876           0 :     const char* filename = script->filename();
     877             :     unsigned lineno = PCToLineNumber(script, pc);
     878          68 :     RootedFunction fun(cx, iter.maybeCallee(cx));
     879          34 :     RootedString funname(cx);
     880          68 :     if (fun)
     881           0 :         funname = fun->displayAtom();
     882           0 : 
     883           0 :     RootedValue thisVal(cx);
     884             :     if (iter.hasUsableAbstractFramePtr() &&
     885           0 :         iter.isFunctionFrame() &&
     886           1 :         fun && !fun->isArrow() && !fun->isDerivedClassConstructor() &&
     887           0 :         !(fun->isBoundFunction() && iter.isConstructing()))
     888           0 :     {
     889           0 :         if (!GetFunctionThis(cx, iter.abstractFramePtr(), &thisVal))
     890             :             return nullptr;
     891           0 :     }
     892             : 
     893             :     // print the frame number and function name
     894             :     JS::UniqueChars buf(std::move(inBuf));
     895             :     if (funname) {
     896           0 :         JSAutoByteString funbytes;
     897           0 :         char* str = funbytes.encodeLatin1(cx, funname);
     898           0 :         if (!str)
     899           0 :             return nullptr;
     900           0 :         buf = sprintf_append(cx, std::move(buf), "%d %s(", num, str);
     901           0 :     } else if (fun) {
     902           0 :         buf = sprintf_append(cx, std::move(buf), "%d anonymous(", num);
     903           0 :     } else {
     904           0 :         buf = sprintf_append(cx, std::move(buf), "%d <TOP LEVEL>", num);
     905             :     }
     906           0 :     if (!buf)
     907             :         return nullptr;
     908           0 : 
     909             :     if (showArgs && iter.hasArgs()) {
     910             :         PositionalFormalParameterIter fi(script);
     911          34 :         bool first = true;
     912           0 :         for (unsigned i = 0; i < iter.numActualArgs(); i++) {
     913           0 :             RootedValue arg(cx);
     914           0 :             if (i < iter.numFormalArgs() && fi.closedOver()) {
     915           0 :                 arg = iter.callObj(cx).aliasedBinding(fi);
     916           0 :             } else if (iter.hasUsableAbstractFramePtr()) {
     917           0 :                 if (script->analyzedArgsUsage() &&
     918           0 :                     script->argsObjAliasesFormals() &&
     919           0 :                     iter.hasArgsObj())
     920           0 :                 {
     921           0 :                     arg = iter.argsObj().arg(i);
     922             :                 } else {
     923           0 :                     arg = iter.unaliasedActual(i, DONT_CHECK_ALIASING);
     924             :                 }
     925           0 :             } else {
     926             :                 arg = MagicValue(JS_OPTIMIZED_OUT);
     927             :             }
     928           0 : 
     929             :             JSAutoByteString valueBytes;
     930             :             const char* value = FormatValue(cx, arg, valueBytes);
     931           0 :             if (!value) {
     932           0 :                 if (cx->isThrowingOutOfMemory())
     933           0 :                     return nullptr;
     934           0 :                 cx->clearPendingException();
     935           0 :             }
     936           0 : 
     937             :             JSAutoByteString nameBytes;
     938             :             const char* name = nullptr;
     939           0 : 
     940           0 :             if (i < iter.numFormalArgs()) {
     941             :                 MOZ_ASSERT(fi.argumentSlot() == i);
     942           0 :                 if (!fi.isDestructured()) {
     943           0 :                     name = nameBytes.encodeLatin1(cx, fi.name());
     944           0 :                     if (!name)
     945           0 :                         return nullptr;
     946           0 :                 } else {
     947             :                     name = "(destructured parameter)";
     948             :                 }
     949             :                 fi++;
     950             :             }
     951           0 : 
     952             :             if (value) {
     953             :                 buf = sprintf_append(cx, std::move(buf), "%s%s%s%s%s%s",
     954           0 :                                      !first ? ", " : "",
     955           0 :                                      name ? name :"",
     956             :                                      name ? " = " : "",
     957             :                                      arg.isString() ? "\"" : "",
     958             :                                      value,
     959           0 :                                      arg.isString() ? "\"" : "");
     960             :                 if (!buf)
     961           0 :                     return nullptr;
     962           0 : 
     963             :                 first = false;
     964             :             } else {
     965             :                 buf = sprintf_append(cx, std::move(buf),
     966             :                                      "    <Failed to get argument while inspecting stack frame>\n");
     967           0 :                 if (!buf)
     968           0 :                     return nullptr;
     969           0 : 
     970             :             }
     971             :         }
     972             :     }
     973             : 
     974             :     // print filename and line number
     975             :     buf = sprintf_append(cx, std::move(buf), "%s [\"%s\":%d]\n",
     976             :                          fun ? ")" : "",
     977           0 :                          filename ? filename : "<unknown>",
     978           0 :                          lineno);
     979             :     if (!buf)
     980           1 :         return nullptr;
     981           1 : 
     982             : 
     983             :     // Note: Right now we don't dump the local variables anymore, because
     984             :     // that is hard to support across all the JITs etc.
     985             : 
     986             :     // print the value of 'this'
     987             :     if (showLocals) {
     988             :         if (!thisVal.isUndefined()) {
     989           1 :             JSAutoByteString thisValBytes;
     990           0 :             RootedString thisValStr(cx, ToString<CanGC>(cx, thisVal));
     991           0 :             if (!thisValStr) {
     992           0 :                 if (cx->isThrowingOutOfMemory())
     993           0 :                     return nullptr;
     994           0 :                 cx->clearPendingException();
     995           0 :             }
     996           0 :             if (thisValStr) {
     997             :                 const char* str = thisValBytes.encodeLatin1(cx, thisValStr);
     998           0 :                 if (!str)
     999           0 :                     return nullptr;
    1000           0 :                 buf = sprintf_append(cx, std::move(buf), "    this = %s\n", str);
    1001             :             } else {
    1002           0 :                 buf = sprintf_append(cx, std::move(buf), "    <failed to get 'this' value>\n");
    1003             :             }
    1004           0 :             if (!buf)
    1005             :                 return nullptr;
    1006           0 :         }
    1007             :     }
    1008             : 
    1009             :     if (showThisProps && thisVal.isObject()) {
    1010             :         RootedObject obj(cx, &thisVal.toObject());
    1011          34 : 
    1012           0 :         AutoIdVector keys(cx);
    1013             :         if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &keys)) {
    1014           0 :             if (cx->isThrowingOutOfMemory())
    1015           0 :                 return nullptr;
    1016           0 :             cx->clearPendingException();
    1017           0 :         }
    1018           0 : 
    1019             :         RootedId id(cx);
    1020             :         for (size_t i = 0; i < keys.length(); i++) {
    1021           0 :             RootedId id(cx, keys[i]);
    1022           0 :             RootedValue key(cx, IdToValue(id));
    1023           0 :             RootedValue v(cx);
    1024           0 : 
    1025           0 :             if (!GetProperty(cx, obj, obj, id, &v)) {
    1026             :                 if (cx->isThrowingOutOfMemory())
    1027           0 :                     return nullptr;
    1028           0 :                 cx->clearPendingException();
    1029           0 :                 buf = sprintf_append(cx, std::move(buf),
    1030           0 :                                      "    <Failed to fetch property while inspecting stack frame>\n");
    1031           0 :                 if (!buf)
    1032           0 :                     return nullptr;
    1033           0 :                 continue;
    1034             :             }
    1035           0 : 
    1036             :             JSAutoByteString nameBytes;
    1037             :             const char* name = FormatValue(cx, key, nameBytes);
    1038           0 :             if (!name) {
    1039           0 :                 if (cx->isThrowingOutOfMemory())
    1040           0 :                     return nullptr;
    1041           0 :                 cx->clearPendingException();
    1042             :             }
    1043           0 : 
    1044             :             JSAutoByteString valueBytes;
    1045             :             const char* value = FormatValue(cx, v, valueBytes);
    1046           0 :             if (!value) {
    1047           0 :                 if (cx->isThrowingOutOfMemory())
    1048           0 :                     return nullptr;
    1049           0 :                 cx->clearPendingException();
    1050             :             }
    1051           0 : 
    1052             :             if (name && value) {
    1053             :                 buf = sprintf_append(cx, std::move(buf), "    this.%s = %s%s%s\n",
    1054           0 :                                      name,
    1055           0 :                                      v.isString() ? "\"" : "",
    1056             :                                      value,
    1057           0 :                                      v.isString() ? "\"" : "");
    1058             :             } else {
    1059           0 :                 buf = sprintf_append(cx, std::move(buf),
    1060             :                                      "    <Failed to format values while inspecting stack frame>\n");
    1061           0 :             }
    1062           0 :             if (!buf)
    1063             :                 return nullptr;
    1064           0 :         }
    1065             :     }
    1066             : 
    1067             :     MOZ_ASSERT(!cx->isExceptionPending());
    1068             :     return buf;
    1069          68 : }
    1070             : 
    1071             : static JS::UniqueChars
    1072             : FormatWasmFrame(JSContext* cx, const FrameIter& iter, JS::UniqueChars&& inBuf, int num)
    1073             : {
    1074           0 :     UniqueChars nameStr;
    1075             :     if (JSAtom* functionDisplayAtom = iter.maybeFunctionDisplayAtom()) {
    1076           0 :         nameStr = StringToNewUTF8CharsZ(cx, *functionDisplayAtom);
    1077           0 :         if (!nameStr)
    1078           0 :             return nullptr;
    1079           0 :     }
    1080             : 
    1081             :     JS::UniqueChars buf = sprintf_append(cx, std::move(inBuf), "%d %s()",
    1082             :                                          num,
    1083           0 :                                          nameStr ? nameStr.get() : "<wasm-function>");
    1084             :     if (!buf)
    1085           0 :         return nullptr;
    1086           0 : 
    1087             :     buf = sprintf_append(cx, std::move(buf), " [\"%s\":wasm-function[%d]:0x%x]\n",
    1088             :                          iter.filename() ? iter.filename() : "<unknown>",
    1089           0 :                          iter.wasmFuncIndex(),
    1090           0 :                          iter.wasmBytecodeOffset());
    1091             :     if (!buf)
    1092           0 :         return nullptr;
    1093           0 : 
    1094             :     MOZ_ASSERT(!cx->isExceptionPending());
    1095             :     return buf;
    1096           0 : }
    1097             : 
    1098             : JS_FRIEND_API(JS::UniqueChars)
    1099             : JS::FormatStackDump(JSContext* cx, JS::UniqueChars&& inBuf, bool showArgs, bool showLocals,
    1100             :                     bool showThisProps)
    1101           1 : {
    1102             :     int num = 0;
    1103             : 
    1104           1 :     JS::UniqueChars buf(std::move(inBuf));
    1105             :     for (AllFramesIter i(cx); !i.done(); ++i) {
    1106           3 :         if (i.hasScript())
    1107          70 :             buf = FormatFrame(cx, i, std::move(buf), num, showArgs, showLocals, showThisProps);
    1108          34 :         else
    1109           0 :             buf = FormatWasmFrame(cx, i, std::move(buf), num);
    1110             :         if (!buf)
    1111           0 :             return nullptr;
    1112           0 :         num++;
    1113           0 :     }
    1114          34 : 
    1115             :     if (!num)
    1116             :         buf = JS_sprintf_append(std::move(buf), "JavaScript stack is empty\n");
    1117           1 : 
    1118           0 :     return buf;
    1119             : }
    1120             : 
    1121             : extern JS_FRIEND_API(bool)
    1122             : JS::ForceLexicalInitialization(JSContext *cx, HandleObject obj)
    1123             : {
    1124           0 :     AssertHeapIsIdle();
    1125             :     CHECK_REQUEST(cx);
    1126           0 :     assertSameCompartment(cx, obj);
    1127           0 : 
    1128           0 :     bool initializedAny = false;
    1129             :     NativeObject* nobj = &obj->as<NativeObject>();
    1130           0 : 
    1131           0 :     for (Shape::Range<NoGC> r(nobj->lastProperty()); !r.empty(); r.popFront()) {
    1132             :         Shape* s = &r.front();
    1133           0 :         Value v = nobj->getSlot(s->slot());
    1134           0 :         if (s->isDataProperty() && v.isMagic() && v.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
    1135           0 :             nobj->setSlot(s->slot(), UndefinedValue());
    1136           0 :             initializedAny = true;
    1137           0 :         }
    1138           0 : 
    1139             :     }
    1140             :     return initializedAny;
    1141             : }
    1142           0 : 
    1143             : extern JS_FRIEND_API(int)
    1144             : JS::IsGCPoisoning()
    1145             : {
    1146           0 : #ifdef JS_GC_POISONING
    1147             :     static bool disablePoison = bool(getenv("JSGC_DISABLE_POISONING"));
    1148             :     return !disablePoison;
    1149           0 : #else
    1150           0 :     return false;
    1151             : #endif
    1152             : }
    1153             : 
    1154             : struct DumpHeapTracer : public JS::CallbackTracer, public WeakMapTracer
    1155             : {
    1156             :     const char* prefix;
    1157             :     FILE* output;
    1158             : 
    1159             :     DumpHeapTracer(FILE* fp, JSContext* cx)
    1160             :       : JS::CallbackTracer(cx, DoNotTraceWeakMaps),
    1161           0 :         js::WeakMapTracer(cx->runtime()), prefix(""), output(fp)
    1162           0 :     {}
    1163           0 : 
    1164           0 :   private:
    1165             :     void trace(JSObject* map, JS::GCCellPtr key, JS::GCCellPtr value) override {
    1166             :         JSObject* kdelegate = nullptr;
    1167           0 :         if (key.is<JSObject>())
    1168           0 :             kdelegate = js::GetWeakmapKeyDelegate(&key.as<JSObject>());
    1169           0 : 
    1170           0 :         fprintf(output, "WeakMapEntry map=%p key=%p keyDelegate=%p value=%p\n",
    1171             :                 map, key.asCell(), kdelegate, value.asCell());
    1172           0 :     }
    1173           0 : 
    1174           0 :     void onChild(const JS::GCCellPtr& thing) override;
    1175             : };
    1176             : 
    1177             : static char
    1178             : MarkDescriptor(void* thing)
    1179             : {
    1180           0 :     gc::TenuredCell* cell = gc::TenuredCell::fromPointer(thing);
    1181             :     if (cell->isMarkedBlack())
    1182           0 :         return 'B';
    1183           0 :     if (cell->isMarkedGray())
    1184             :         return 'G';
    1185           0 :     if (cell->isMarkedAny())
    1186             :         return 'X';
    1187           0 :     return 'W';
    1188             : }
    1189           0 : 
    1190             : static void
    1191             : DumpHeapVisitZone(JSRuntime* rt, void* data, Zone* zone)
    1192             : {
    1193           0 :     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
    1194             :     fprintf(dtrc->output, "# zone %p\n", (void*)zone);
    1195           0 : }
    1196           0 : 
    1197           0 : static void
    1198             : DumpHeapVisitRealm(JSContext* cx, void* data, Handle<Realm*> realm)
    1199             : {
    1200           0 :     char name[1024];
    1201             :     if (auto nameCallback = cx->runtime()->realmNameCallback)
    1202             :         nameCallback(cx, realm, name, sizeof(name));
    1203           0 :     else
    1204           0 :         strcpy(name, "<unknown>");
    1205             : 
    1206             :     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
    1207             :     fprintf(dtrc->output, "# realm %s [in compartment %p, zone %p]\n", name,
    1208           0 :             (void*)realm->compartment(), (void*)realm->zone());
    1209           0 : }
    1210           0 : 
    1211           0 : static void
    1212             : DumpHeapVisitArena(JSRuntime* rt, void* data, gc::Arena* arena,
    1213             :                    JS::TraceKind traceKind, size_t thingSize)
    1214           0 : {
    1215             :     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
    1216             :     fprintf(dtrc->output, "# arena allockind=%u size=%u\n",
    1217           0 :             unsigned(arena->getAllocKind()), unsigned(thingSize));
    1218           0 : }
    1219           0 : 
    1220           0 : static void
    1221             : DumpHeapVisitCell(JSRuntime* rt, void* data, void* thing,
    1222             :                   JS::TraceKind traceKind, size_t thingSize)
    1223           0 : {
    1224             :     DumpHeapTracer* dtrc = static_cast<DumpHeapTracer*>(data);
    1225             :     char cellDesc[1024 * 32];
    1226           0 :     JS_GetTraceThingInfo(cellDesc, sizeof(cellDesc), dtrc, thing, traceKind, true);
    1227             :     fprintf(dtrc->output, "%p %c %s\n", thing, MarkDescriptor(thing), cellDesc);
    1228           0 :     js::TraceChildren(dtrc, thing, traceKind);
    1229           0 : }
    1230           0 : 
    1231           0 : void
    1232             : DumpHeapTracer::onChild(const JS::GCCellPtr& thing)
    1233             : {
    1234           0 :     if (gc::IsInsideNursery(thing.asCell()))
    1235             :         return;
    1236           0 : 
    1237           0 :     char buffer[1024];
    1238             :     getTracingEdgeName(buffer, sizeof(buffer));
    1239             :     fprintf(output, "%s%p %c %s\n", prefix, thing.asCell(), MarkDescriptor(thing.asCell()), buffer);
    1240           0 : }
    1241           0 : 
    1242             : void
    1243             : js::DumpHeap(JSContext* cx, FILE* fp, js::DumpHeapNurseryBehaviour nurseryBehaviour)
    1244             : {
    1245           0 :     if (nurseryBehaviour == js::CollectNurseryBeforeDump)
    1246             :         cx->runtime()->gc.evictNursery(JS::gcreason::API);
    1247           0 : 
    1248           0 :     DumpHeapTracer dtrc(fp, cx);
    1249             : 
    1250           0 :     fprintf(dtrc.output, "# Roots.\n");
    1251             :     {
    1252           0 :         JSRuntime* rt = cx->runtime();
    1253             :         js::gc::AutoPrepareForTracing prep(cx);
    1254           0 :         gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::TRACE_HEAP);
    1255           0 :         rt->gc.traceRuntime(&dtrc, prep.session());
    1256           0 :     }
    1257           0 : 
    1258             :     fprintf(dtrc.output, "# Weak maps.\n");
    1259             :     WeakMapBase::traceAllMappings(&dtrc);
    1260           0 : 
    1261           0 :     fprintf(dtrc.output, "==========\n");
    1262             : 
    1263           0 :     dtrc.prefix = "> ";
    1264             :     IterateHeapUnbarriered(cx, &dtrc,
    1265           0 :                            DumpHeapVisitZone,
    1266             :                            DumpHeapVisitRealm,
    1267             :                            DumpHeapVisitArena,
    1268             :                            DumpHeapVisitCell);
    1269             : 
    1270           0 :     fflush(dtrc.output);
    1271             : }
    1272           0 : 
    1273           0 : JS_FRIEND_API(void)
    1274             : js::SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg)
    1275             : {
    1276           0 :     cx->activityCallback = cb;
    1277             :     cx->activityCallbackArg = arg;
    1278           2 : }
    1279           0 : 
    1280           0 : JS_FRIEND_API(void)
    1281             : JS::NotifyGCRootsRemoved(JSContext* cx)
    1282             : {
    1283         244 :     cx->runtime()->gc.notifyRootsRemoved();
    1284             : }
    1285           0 : 
    1286         244 : JS_FRIEND_API(JS::Realm*)
    1287             : js::GetAnyRealmInZone(JS::Zone* zone)
    1288             : {
    1289           0 :     if (zone->isAtomsZone())
    1290             :         return nullptr;
    1291           0 : 
    1292             :     RealmsInZoneIter realm(zone);
    1293             :     MOZ_ASSERT(!realm.done());
    1294           0 :     return realm.get();
    1295           0 : }
    1296           0 : 
    1297             : void
    1298             : JS::ObjectPtr::finalize(JSRuntime* rt)
    1299             : {
    1300           0 :     if (IsIncrementalBarrierNeeded(rt->mainContextFromOwnThread()))
    1301             :         IncrementalPreWriteBarrier(value);
    1302           0 :     value = nullptr;
    1303           0 : }
    1304           0 : 
    1305           0 : void
    1306             : JS::ObjectPtr::finalize(JSContext* cx)
    1307             : {
    1308           0 :     finalize(cx->runtime());
    1309             : }
    1310           0 : 
    1311           0 : void
    1312             : JS::ObjectPtr::updateWeakPointerAfterGC()
    1313             : {
    1314           0 :     if (js::gc::IsAboutToBeFinalizedUnbarriered(value.unsafeGet()))
    1315             :         value = nullptr;
    1316           0 : }
    1317           0 : 
    1318           0 : void
    1319             : JS::ObjectPtr::trace(JSTracer* trc, const char* name)
    1320             : {
    1321           0 :     JS::TraceEdge(trc, &value, name);
    1322             : }
    1323           0 : 
    1324           0 : JS_FRIEND_API(JSObject*)
    1325             : js::GetTestingFunctions(JSContext* cx)
    1326             : {
    1327           0 :     RootedObject obj(cx, JS_NewPlainObject(cx));
    1328             :     if (!obj)
    1329           0 :         return nullptr;
    1330           0 : 
    1331             :     if (!DefineTestingFunctions(cx, obj, false, false))
    1332             :         return nullptr;
    1333           0 : 
    1334             :     return obj;
    1335             : }
    1336           0 : 
    1337             : JS_FRIEND_API(void)
    1338             : js::SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks)
    1339             : {
    1340           4 :     cx->runtime()->DOMcallbacks = callbacks;
    1341             : }
    1342           8 : 
    1343           4 : JS_FRIEND_API(const DOMCallbacks*)
    1344             : js::GetDOMCallbacks(JSContext* cx)
    1345             : {
    1346           0 :     return cx->runtime()->DOMcallbacks;
    1347             : }
    1348           0 : 
    1349             : static const void* gDOMProxyHandlerFamily = nullptr;
    1350             : static DOMProxyShadowsCheck gDOMProxyShadowsCheck;
    1351             : 
    1352             : JS_FRIEND_API(void)
    1353             : js::SetDOMProxyInformation(const void* domProxyHandlerFamily,
    1354             :                            DOMProxyShadowsCheck domProxyShadowsCheck)
    1355           1 : {
    1356             :     gDOMProxyHandlerFamily = domProxyHandlerFamily;
    1357             :     gDOMProxyShadowsCheck = domProxyShadowsCheck;
    1358           0 : }
    1359           1 : 
    1360           1 : const void*
    1361             : js::GetDOMProxyHandlerFamily()
    1362             : {
    1363         308 :     return gDOMProxyHandlerFamily;
    1364             : }
    1365         308 : 
    1366             : DOMProxyShadowsCheck
    1367             : js::GetDOMProxyShadowsCheck()
    1368             : {
    1369          12 :     return gDOMProxyShadowsCheck;
    1370             : }
    1371          12 : 
    1372             : static XrayJitInfo* gXrayJitInfo = nullptr;
    1373             : 
    1374             : JS_FRIEND_API(void)
    1375             : js::SetXrayJitInfo(XrayJitInfo* info)
    1376             : {
    1377           1 :     gXrayJitInfo = info;
    1378             : }
    1379           1 : 
    1380           1 : XrayJitInfo*
    1381             : js::GetXrayJitInfo()
    1382             : {
    1383         216 :     return gXrayJitInfo;
    1384             : }
    1385         216 : 
    1386             : bool
    1387             : js::detail::IdMatchesAtom(jsid id, JSAtom* atom)
    1388             : {
    1389      545893 :     return id == INTERNED_STRING_TO_JSID(nullptr, atom);
    1390             : }
    1391     1091893 : 
    1392             : bool
    1393             : js::detail::IdMatchesAtom(jsid id, JSString* atom)
    1394             : {
    1395           0 :     return id == INTERNED_STRING_TO_JSID(nullptr, atom);
    1396             : }
    1397           0 : 
    1398             : JS_FRIEND_API(void)
    1399             : js::PrepareScriptEnvironmentAndInvoke(JSContext* cx, HandleObject scope, ScriptEnvironmentPreparer::Closure& closure)
    1400             : {
    1401           0 :     MOZ_ASSERT(!cx->isExceptionPending());
    1402             : 
    1403           0 :     MOZ_RELEASE_ASSERT(cx->runtime()->scriptEnvironmentPreparer,
    1404             :                        "Embedding needs to set a scriptEnvironmentPreparer callback");
    1405           0 : 
    1406             :     cx->runtime()->scriptEnvironmentPreparer->invoke(scope, closure);
    1407             : }
    1408           0 : 
    1409           0 : JS_FRIEND_API(void)
    1410             : js::SetScriptEnvironmentPreparer(JSContext* cx, ScriptEnvironmentPreparer* preparer)
    1411             : {
    1412           4 :     cx->runtime()->scriptEnvironmentPreparer = preparer;
    1413             : }
    1414           0 : 
    1415           4 : JS_FRIEND_API(void)
    1416             : js::SetCTypesActivityCallback(JSContext* cx, CTypesActivityCallback cb)
    1417             : {
    1418           3 :     cx->runtime()->ctypesActivityCallback = cb;
    1419             : }
    1420           0 : 
    1421           3 : js::AutoCTypesActivityCallback::AutoCTypesActivityCallback(JSContext* cx,
    1422             :                                                            js::CTypesActivityType beginType,
    1423          59 :                                                            js::CTypesActivityType endType
    1424             :                                                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
    1425             :   : cx(cx), callback(cx->runtime()->ctypesActivityCallback), endType(endType)
    1426           0 : {
    1427         236 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1428             : 
    1429           0 :     if (callback)
    1430             :         callback(cx, beginType);
    1431           0 : }
    1432           0 : 
    1433          59 : JS_FRIEND_API(void)
    1434             : js::SetAllocationMetadataBuilder(JSContext* cx, const AllocationMetadataBuilder* callback)
    1435             : {
    1436           0 :     cx->realm()->setAllocationMetadataBuilder(callback);
    1437             : }
    1438           0 : 
    1439           0 : JS_FRIEND_API(JSObject*)
    1440             : js::GetAllocationMetadata(JSObject* obj)
    1441             : {
    1442           0 :     ObjectWeakMap* map = ObjectRealm::get(obj).objectMetadataTable.get();
    1443             :     if (map)
    1444           0 :         return map->lookup(obj);
    1445           0 :     return nullptr;
    1446           0 : }
    1447             : 
    1448             : JS_FRIEND_API(bool)
    1449             : js::ReportIsNotFunction(JSContext* cx, HandleValue v)
    1450             : {
    1451           0 :     assertSameCompartment(cx, v);
    1452             :     return ReportIsNotFunction(cx, v, -1);
    1453           0 : }
    1454           0 : 
    1455             : #ifdef DEBUG
    1456             : bool
    1457             : js::HasObjectMovedOp(JSObject* obj) {
    1458             :     return !!GetObjectClass(obj)->extObjectMovedOp();
    1459        7963 : }
    1460           0 : #endif
    1461             : 
    1462             : JS_FRIEND_API(bool)
    1463             : js::ForwardToNative(JSContext* cx, JSNative native, const CallArgs& args)
    1464             : {
    1465           0 :     return native(cx, args.length(), args.base());
    1466             : }
    1467           0 : 
    1468             : JS_FRIEND_API(JSObject*)
    1469             : js::ConvertArgsToArray(JSContext* cx, const CallArgs& args)
    1470             : {
    1471           0 :     RootedObject argsArray(cx, NewDenseCopiedArray(cx, args.length(), args.array()));
    1472             :     return argsArray;
    1473           0 : }
    1474           0 : 
    1475             : JS_FRIEND_API(JSAtom*)
    1476             : js::GetPropertyNameFromPC(JSScript* script, jsbytecode* pc)
    1477             : {
    1478           0 :     if (!IsGetPropPC(pc) && !IsSetPropPC(pc))
    1479             :         return nullptr;
    1480           0 :     return script->getName(pc);
    1481             : }
    1482           0 : 
    1483             : JS_FRIEND_API(void)
    1484             : js::SetWindowProxyClass(JSContext* cx, const js::Class* clasp)
    1485             : {
    1486           0 :     MOZ_ASSERT(!cx->runtime()->maybeWindowProxyClass());
    1487             :     cx->runtime()->setWindowProxyClass(clasp);
    1488           0 : }
    1489           0 : 
    1490           1 : JS_FRIEND_API(void)
    1491             : js::SetWindowProxy(JSContext* cx, HandleObject global, HandleObject windowProxy)
    1492             : {
    1493           0 :     AssertHeapIsIdle();
    1494             :     CHECK_REQUEST(cx);
    1495           0 : 
    1496          28 :     assertSameCompartment(cx, global, windowProxy);
    1497             : 
    1498           0 :     MOZ_ASSERT(IsWindowProxy(windowProxy));
    1499             :     global->as<GlobalObject>().setWindowProxy(windowProxy);
    1500           0 : }
    1501           0 : 
    1502          14 : JS_FRIEND_API(JSObject*)
    1503             : js::ToWindowIfWindowProxy(JSObject* obj)
    1504             : {
    1505          61 :     if (IsWindowProxy(obj))
    1506             :         return &obj->nonCCWGlobal();
    1507          61 :     return obj;
    1508           0 : }
    1509             : 
    1510             : JS_FRIEND_API(JSObject*)
    1511             : js::detail::ToWindowProxyIfWindowSlow(JSObject* obj)
    1512             : {
    1513         638 :     if (JSObject* windowProxy = obj->as<GlobalObject>().maybeWindowProxy())
    1514             :         return windowProxy;
    1515         638 :     return obj;
    1516             : }
    1517         448 : 
    1518             : JS_FRIEND_API(bool)
    1519             : js::IsWindowProxy(JSObject* obj)
    1520             : {
    1521       62228 :     // Note: simply checking `obj == obj->global().windowProxy()` is not
    1522             :     // sufficient: we may have transplanted the window proxy with a CCW.
    1523             :     // Check the Class to ensure we really have a window proxy.
    1524             :     return obj->getClass() == obj->runtimeFromAnyThread()->maybeWindowProxyClass();
    1525             : }
    1526      186909 : 
    1527             : JS_FRIEND_API(bool)
    1528             : js::detail::IsWindowSlow(JSObject* obj)
    1529             : {
    1530           0 :     return obj->as<GlobalObject>().maybeWindowProxy();
    1531             : }
    1532           0 : 
    1533             : AutoAssertNoContentJS::AutoAssertNoContentJS(JSContext* cx)
    1534             :   : context_(cx),
    1535           0 :     prevAllowContentJS_(cx->runtime()->allowContentJS_)
    1536             : {
    1537           0 :     cx->runtime()->allowContentJS_ = false;
    1538             : }
    1539           8 : 
    1540           8 : AutoAssertNoContentJS::~AutoAssertNoContentJS()
    1541             : {
    1542          16 :     context_->runtime()->allowContentJS_ = prevAllowContentJS_;
    1543             : }
    1544           0 : 
    1545           8 : JS_FRIEND_API(void)
    1546             : js::EnableAccessValidation(JSContext* cx, bool enabled)
    1547             : {
    1548           0 :     cx->enableAccessValidation = enabled;
    1549             : }
    1550           0 : 
    1551           0 : JS_FRIEND_API(void)
    1552             : js::SetRealmValidAccessPtr(JSContext* cx, JS::HandleObject global, bool* accessp)
    1553             : {
    1554           1 :     MOZ_ASSERT(global->is<GlobalObject>());
    1555             :     global->realm()->setValidAccessPtr(accessp);
    1556           1 : }
    1557          15 : 
    1558           5 : JS_FRIEND_API(bool)
    1559             : js::SystemZoneAvailable(JSContext* cx)
    1560             : {
    1561           0 :     return true;
    1562             : }
    1563           0 : 
    1564             : static LogCtorDtor sLogCtor = nullptr;
    1565             : static LogCtorDtor sLogDtor = nullptr;
    1566             : 
    1567             : JS_FRIEND_API(void)
    1568             : js::SetLogCtorDtorFunctions(LogCtorDtor ctor, LogCtorDtor dtor)
    1569             : {
    1570           1 :     MOZ_ASSERT(!sLogCtor && !sLogDtor);
    1571             :     MOZ_ASSERT(ctor && dtor);
    1572           0 :     sLogCtor = ctor;
    1573           1 :     sLogDtor = dtor;
    1574           0 : }
    1575           0 : 
    1576           0 : JS_FRIEND_API(void)
    1577             : js::LogCtor(void* self, const char* type, uint32_t sz)
    1578             : {
    1579           0 :     if (LogCtorDtor fun = sLogCtor)
    1580             :         fun(self, type, sz);
    1581           0 : }
    1582           0 : 
    1583           0 : JS_FRIEND_API(void)
    1584             : js::LogDtor(void* self, const char* type, uint32_t sz)
    1585             : {
    1586             :     if (LogCtorDtor fun = sLogDtor)
    1587             :         fun(self, type, sz);
    1588             : }

Generated by: LCOV version 1.13-14-ga5dd952