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

Generated by: LCOV version 1.13