Bug 1716250 - Remove JS_FRIEND_API. r=jandem,sfink
authorTed Campbell <tcampbell@mozilla.com>
Wed, 16 Jun 2021 19:38:10 +0000
changeset 583580 36647ef6f014ee7199a0bad93851750ead132473
parent 583579 1d02b246fe1639af1830848daa294856311f113d
child 583581 5e2e918dd53d27ce45caea15d0295efe6fc30e1f
push id38543
push userapavel@mozilla.com
push dateWed, 16 Jun 2021 21:42:00 +0000
treeherdermozilla-central@36647ef6f014 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, sfink
bugs1716250
milestone91.0a1
first release with
nightly linux32
36647ef6f014 / 91.0a1 / 20210616214200 / files
nightly linux64
36647ef6f014 / 91.0a1 / 20210616214200 / files
nightly mac
36647ef6f014 / 91.0a1 / 20210616214200 / files
nightly win32
36647ef6f014 / 91.0a1 / 20210616214200 / files
nightly win64
36647ef6f014 / 91.0a1 / 20210616214200 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1716250 - Remove JS_FRIEND_API. r=jandem,sfink Convert all JS_FRIEND_API to JS_PUBLIC_API. At this point, the JS_PUBLIC_API has no formal curation process and in practice we add a lot of new features to JS_FRIEND_API without giving much thought to if they should be public. The result is that all embedders need to use the friend API in some form and the distinction has lost meaning. Going forward, we should continue to use the js/public/experimental directory as a place to expose new APIs, and in general should strive for high quality of the APIs that are exposed. If a particular API is tricky or discouraged, comments explaining that will be more helpful that a losely applied FRIEND_API marker. Differential Revision: https://phabricator.services.mozilla.com/D117607
js/public/AllocPolicy.h
js/public/AllocationRecording.h
js/public/ArrayBufferMaybeShared.h
js/public/Class.h
js/public/GCAPI.h
js/public/HeapAPI.h
js/public/MemoryMetrics.h
js/public/Object.h
js/public/ProfilingCategory.h
js/public/ProfilingFrameIterator.h
js/public/ProfilingStack.h
js/public/Proxy.h
js/public/RootingAPI.h
js/public/SavedFrameAPI.h
js/public/StableStringChars.h
js/public/String.h
js/public/TracingAPI.h
js/public/Utility.h
js/public/Wrapper.h
js/public/experimental/CTypes.h
js/public/experimental/CodeCoverage.h
js/public/experimental/Intl.h
js/public/experimental/JSStencil.h
js/public/experimental/SourceHook.h
js/public/experimental/TypedData.h
js/public/friend/DOMProxy.h
js/public/friend/DumpFunctions.h
js/public/friend/ErrorMessages.h
js/public/friend/JSMEnvironment.h
js/public/friend/PerformanceHint.h
js/public/friend/StackLimits.h
js/public/friend/UsageStatistics.h
js/public/friend/WindowProxy.h
js/public/friend/XrayJitInfo.h
js/src/builtin/Array.cpp
js/src/builtin/DataViewObject.cpp
js/src/builtin/Eval.cpp
js/src/builtin/Profilers.cpp
js/src/builtin/Profilers.h
js/src/builtin/WeakMapObject.cpp
js/src/builtin/WeakSetObject.cpp
js/src/builtin/streams/StreamAPI.cpp
js/src/debugger/Debugger.h
js/src/gc/GC.cpp
js/src/gc/Heap.h
js/src/gc/Marking.cpp
js/src/gc/Verifier.cpp
js/src/jit/ProcessExecutableMemory.cpp
js/src/jsapi.cpp
js/src/jsdate.cpp
js/src/jsdate.h
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jspubtd.h
js/src/jstypes.h
js/src/proxy/BaseProxyHandler.cpp
js/src/proxy/CrossCompartmentWrapper.cpp
js/src/proxy/Proxy.cpp
js/src/proxy/Wrapper.cpp
js/src/util/DumpFunctions.cpp
js/src/vm/ArrayBufferObject.cpp
js/src/vm/ArrayBufferViewObject.cpp
js/src/vm/BytecodeUtil.cpp
js/src/vm/Compartment.cpp
js/src/vm/GeckoProfiler.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/Iteration.cpp
js/src/vm/JSContext.cpp
js/src/vm/JSObject.cpp
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
js/src/vm/MemoryMetrics.cpp
js/src/vm/ProxyObject.cpp
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/SavedStacks.cpp
js/src/vm/SharedArrayObject.cpp
js/src/vm/SourceHook.cpp
js/src/vm/StringType.h
js/src/vm/StructuredClone.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/public/AllocPolicy.h
+++ b/js/public/AllocPolicy.h
@@ -86,17 +86,17 @@ class AllocPolicyBase {
 
 /* Policy for using system memory functions and doing no error reporting. */
 class SystemAllocPolicy : public AllocPolicyBase {
  public:
   void reportAllocOverflow() const {}
   bool checkSimulatedOOM() const { return !js::oom::ShouldFailWithOOM(); }
 };
 
-MOZ_COLD JS_FRIEND_API void ReportOutOfMemory(JSContext* cx);
+MOZ_COLD JS_PUBLIC_API void ReportOutOfMemory(JSContext* cx);
 
 /*
  * Allocation policy that calls the system memory functions and reports errors
  * to the context. Since the JSContext given on construction is stored for
  * the lifetime of the container, this policy may only be used for containers
  * whose lifetime is a shorter than the given JSContext.
  *
  * FIXME bug 647103 - rewrite this in terms of temporary allocation functions,
@@ -104,17 +104,17 @@ MOZ_COLD JS_FRIEND_API void ReportOutOfM
  */
 class TempAllocPolicy : public AllocPolicyBase {
   JSContext* const cx_;
 
   /*
    * Non-inline helper to call JSRuntime::onOutOfMemory with minimal
    * code bloat.
    */
-  JS_FRIEND_API void* onOutOfMemory(arena_id_t arenaId, AllocFunction allocFunc,
+  JS_PUBLIC_API void* onOutOfMemory(arena_id_t arenaId, AllocFunction allocFunc,
                                     size_t nbytes, void* reallocPtr = nullptr);
 
   template <typename T>
   T* onOutOfMemoryTyped(arena_id_t arenaId, AllocFunction allocFunc,
                         size_t numElems, void* reallocPtr = nullptr) {
     size_t bytes;
     if (MOZ_UNLIKELY(!CalculateAllocSize<T>(numElems, &bytes))) {
       return nullptr;
@@ -170,17 +170,17 @@ class TempAllocPolicy : public AllocPoli
     return pod_arena_realloc<T>(js::MallocArena, prior, oldSize, newSize);
   }
 
   template <typename T>
   void free_(T* p, size_t numElems = 0) {
     js_free(p);
   }
 
-  JS_FRIEND_API void reportAllocOverflow() const;
+  JS_PUBLIC_API void reportAllocOverflow() const;
 
   bool checkSimulatedOOM() const {
     if (js::oom::ShouldFailWithOOM()) {
       ReportOutOfMemory(cx_);
       return false;
     }
 
     return true;
--- a/js/public/AllocationRecording.h
+++ b/js/public/AllocationRecording.h
@@ -53,21 +53,21 @@ typedef void (*RecordAllocationsCallback
  * Enable recording JS allocations. This feature hooks into the object creation
  * in the JavaScript engine, and reports back the allocation info through the
  * callback. This allocation tracking is turned on for all encountered realms.
  * The JS Debugger API can also turn on allocation tracking with its own
  * probability. If both allocation tracking mechanisms are turned on at the same
  * time, the Debugger's probability defers to the EnableRecordingAllocations's
  * probability setting.
  */
-JS_FRIEND_API void EnableRecordingAllocations(
+JS_PUBLIC_API void EnableRecordingAllocations(
     JSContext* cx, RecordAllocationsCallback callback, double probability);
 
 /**
  * Turn off JS allocation recording. If any JS Debuggers are also recording
  * allocations, then the probability will be reset to the Debugger's desired
  * setting.
  */
-JS_FRIEND_API void DisableRecordingAllocations(JSContext* cx);
+JS_PUBLIC_API void DisableRecordingAllocations(JSContext* cx);
 
 }  // namespace JS
 
 #endif /* js_AllocationRecording_h */
--- a/js/public/ArrayBufferMaybeShared.h
+++ b/js/public/ArrayBufferMaybeShared.h
@@ -90,13 +90,13 @@ extern JS_PUBLIC_API uint8_t* GetArrayBu
     JSObject* obj, bool* isSharedMemory, const AutoRequireNoGC&);
 
 /**
  * Returns whether the passed array buffer is 'large': its byteLength >= 2 GB.
  * See also SetLargeArrayBuffersEnabled.
  *
  * |obj| must pass a JS::IsArrayBufferObjectMaybeShared test.
  */
-extern JS_FRIEND_API bool IsLargeArrayBufferMaybeShared(JSObject* obj);
+extern JS_PUBLIC_API bool IsLargeArrayBufferMaybeShared(JSObject* obj);
 
 }  // namespace JS
 
 #endif /* js_ArrayBufferMaybeShared_h */
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -30,17 +30,17 @@ struct JSAtomState;
 struct JSFunctionSpec;
 
 namespace js {
 
 class PropertyResult;
 
 // This is equal to JSFunction::class_.  Use it in places where you don't want
 // to #include jsfun.h.
-extern JS_FRIEND_DATA const JSClass* const FunctionClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const FunctionClassPtr;
 
 }  // namespace js
 
 namespace JS {
 
 /**
  * Per ES6, the [[DefineOwnProperty]] internal method has three different
  * possible outcomes:
@@ -340,17 +340,17 @@ typedef bool (*SetPropertyOp)(JSContext*
                               JS::HandleValue receiver,
                               JS::ObjectOpResult& result);
 typedef bool (*GetOwnPropertyOp)(
     JSContext* cx, JS::HandleObject obj, JS::HandleId id,
     JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc);
 typedef bool (*DeletePropertyOp)(JSContext* cx, JS::HandleObject obj,
                                  JS::HandleId id, JS::ObjectOpResult& result);
 
-class JS_FRIEND_API ElementAdder {
+class JS_PUBLIC_API ElementAdder {
  public:
   enum GetBehavior {
     // Check if the element exists before performing the Get and preserve
     // holes.
     CheckHasElemPreserveHoles,
 
     // Perform a Get operation, like obj[index] in JS.
     GetElement
@@ -816,14 +816,14 @@ enum class ESClass {
   /** None of the above. */
   Other
 };
 
 /* Fills |vp| with the unboxed value for boxed types, or undefined otherwise. */
 bool Unbox(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp);
 
 #ifdef DEBUG
-JS_FRIEND_API bool HasObjectMovedOp(JSObject* obj);
+JS_PUBLIC_API bool HasObjectMovedOp(JSObject* obj);
 #endif
 
 } /* namespace js */
 
 #endif /* js_Class_h */
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -1022,17 +1022,17 @@ class JS_PUBLIC_API AutoCheckCannotGC : 
 } JS_HAZ_GC_INVALIDATED;
 #endif
 
 extern JS_PUBLIC_API void SetLowMemoryState(JSContext* cx, bool newState);
 
 /*
  * Internal to Firefox.
  */
-extern JS_FRIEND_API void NotifyGCRootsRemoved(JSContext* cx);
+extern JS_PUBLIC_API void NotifyGCRootsRemoved(JSContext* cx);
 
 } /* namespace JS */
 
 typedef void (*JSGCCallback)(JSContext* cx, JSGCStatus status,
                              JS::GCReason reason, void* data);
 
 /**
  * Register externally maintained GC roots.
--- a/js/public/HeapAPI.h
+++ b/js/public/HeapAPI.h
@@ -20,17 +20,17 @@
 #include "js/TraceKind.h"
 #include "js/TypeDecls.h"
 
 /* These values are private to the JS engine. */
 namespace js {
 
 class NurseryDecommitTask;
 
-JS_FRIEND_API bool CurrentThreadCanAccessZone(JS::Zone* zone);
+JS_PUBLIC_API bool CurrentThreadCanAccessZone(JS::Zone* zone);
 
 namespace gc {
 
 class Arena;
 struct Cell;
 class TenuredChunk;
 class StoreBuffer;
 class TenuredCell;
@@ -261,17 +261,17 @@ const size_t ArenaHeaderSize = ArenaZone
 const size_t CellFlagBitsReservedForGC = 3;
 
 // The first word can be used to store JSClass pointers for some thing kinds, so
 // these must be suitably aligned.
 const size_t JSClassAlignBytes = size_t(1) << CellFlagBitsReservedForGC;
 
 #ifdef JS_DEBUG
 /* When downcasting, ensure we are actually the right type. */
-extern JS_FRIEND_API void AssertGCThingHasType(js::gc::Cell* cell,
+extern JS_PUBLIC_API void AssertGCThingHasType(js::gc::Cell* cell,
                                                JS::TraceKind kind);
 #else
 inline void AssertGCThingHasType(js::gc::Cell* cell, JS::TraceKind kind) {}
 #endif
 
 MOZ_ALWAYS_INLINE bool IsInsideNursery(const js::gc::Cell* cell);
 MOZ_ALWAYS_INLINE bool IsInsideNursery(const js::gc::TenuredCell* cell);
 
@@ -344,17 +344,17 @@ const uint32_t DefaultHeapMaxBytes = 32 
 
 /**
  * A GC pointer, tagged with the trace kind.
  *
  * In general, a GC pointer should be stored with an exact type. This class
  * is for use when that is not possible because a single pointer must point
  * to several kinds of GC thing.
  */
-class JS_FRIEND_API GCCellPtr {
+class JS_PUBLIC_API GCCellPtr {
  public:
   GCCellPtr() : GCCellPtr(nullptr) {}
 
   // Construction from a void* and trace kind.
   GCCellPtr(void* gcthing, JS::TraceKind traceKind)
       : ptr(checkedCast(gcthing, traceKind)) {}
 
   // Automatically construct a null GCCellPtr from nullptr.
@@ -682,17 +682,17 @@ extern JS_PUBLIC_API void IncrementalPre
  */
 extern JS_PUBLIC_API void IncrementalPreWriteBarrier(GCCellPtr thing);
 
 /**
  * Unsets the gray bit for anything reachable from |thing|. |kind| should not be
  * JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
  * if anything was unmarked.
  */
-extern JS_FRIEND_API bool UnmarkGrayGCThingRecursively(GCCellPtr thing);
+extern JS_PUBLIC_API bool UnmarkGrayGCThingRecursively(GCCellPtr thing);
 
 }  // namespace JS
 
 namespace js {
 namespace gc {
 
 extern JS_PUBLIC_API void PerformIncrementalReadBarrier(JS::GCCellPtr thing);
 
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -125,17 +125,17 @@ namespace js {
  * In memory reporting, we have concept of "sundries", line items which are too
  * small to be worth reporting individually.  Under some circumstances, a memory
  * reporter gets tossed into the sundries bucket if it's smaller than
  * MemoryReportingSundriesThreshold() bytes.
  *
  * We need to define this value here, rather than in the code which actually
  * generates the memory reports, because NotableStringInfo uses this value.
  */
-JS_FRIEND_API size_t MemoryReportingSundriesThreshold();
+JS_PUBLIC_API size_t MemoryReportingSundriesThreshold();
 
 /**
  * This hash policy avoids flattening ropes (which perturbs the site being
  * measured and requires a JSContext) at the expense of doing a FULL ROPE COPY
  * on every hash and match! Beware.
  */
 struct InefficientNonFlatteningStringHashPolicy {
   typedef JSString* Lookup;
--- a/js/public/Object.h
+++ b/js/public/Object.h
@@ -85,17 +85,17 @@ extern JS_PUBLIC_API void SetPrivate(JSO
  */
 inline const Value& GetReservedSlot(JSObject* obj, size_t slot) {
   MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetClass(obj)));
   return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
 }
 
 namespace detail {
 
-extern JS_FRIEND_API void SetReservedSlotWithBarrier(JSObject* obj, size_t slot,
+extern JS_PUBLIC_API void SetReservedSlotWithBarrier(JSObject* obj, size_t slot,
                                                      const Value& value);
 
 }  // namespace detail
 
 /**
  * Store a value in an object's reserved slot.
  *
  * This can be used with both native objects and proxies.  However, if |obj| is
--- a/js/public/ProfilingCategory.h
+++ b/js/public/ProfilingCategory.h
@@ -2,17 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_ProfilingCategory_h
 #define js_ProfilingCategory_h
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 // The source lives in mozglue/baseprofiler/public/ProfilingCategoryList.h
 #include "js/ProfilingCategoryList.h"  // MOZ_PROFILING_CATEGORY_LIST
 
 namespace JS {
 
 // clang-format off
 
@@ -52,14 +52,14 @@ enum class ProfilingCategory : uint32_t 
 // clang-format on
 
 struct ProfilingCategoryPairInfo {
   ProfilingCategory mCategory;
   uint32_t mSubcategoryIndex;
   const char* mLabel;
 };
 
-JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
+JS_PUBLIC_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
     ProfilingCategoryPair aCategoryPair);
 
 }  // namespace JS
 
 #endif /* js_ProfilingCategory_h */
--- a/js/public/ProfilingFrameIterator.h
+++ b/js/public/ProfilingFrameIterator.h
@@ -152,27 +152,27 @@ class MOZ_NON_PARAM JS_PUBLIC_API Profil
       js::jit::JitcodeGlobalEntry* entry) const;
 
   void iteratorConstruct(const RegisterState& state);
   void iteratorConstruct();
   void iteratorDestroy();
   bool iteratorDone();
 } JS_HAZ_GC_INVALIDATED;
 
-JS_FRIEND_API bool IsProfilingEnabledForContext(JSContext* cx);
+JS_PUBLIC_API bool IsProfilingEnabledForContext(JSContext* cx);
 
 /**
  * After each sample run, this method should be called with the current buffer
  * position at which the buffer contents start. This will update the
  * corresponding field on the JSRuntime.
  *
  * See the field |profilerSampleBufferRangeStart| on JSRuntime for documentation
  * about what this value is used for.
  */
-JS_FRIEND_API void SetJSContextProfilerSampleBufferRangeStart(
+JS_PUBLIC_API void SetJSContextProfilerSampleBufferRangeStart(
     JSContext* cx, uint64_t rangeStart);
 
 class ProfiledFrameRange;
 
 // A handle to the underlying JitcodeGlobalEntry, so as to avoid repeated
 // lookups on JitcodeGlobalTable.
 class MOZ_STACK_CLASS ProfiledFrameHandle {
   friend class ProfiledFrameRange;
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -12,17 +12,17 @@
 #include <stdint.h>
 
 #include "jstypes.h"
 
 #include "js/ProfilingCategory.h"
 #include "js/TypeDecls.h"
 
 class JS_PUBLIC_API JSTracer;
-class JS_FRIEND_API ProfilingStack;
+class JS_PUBLIC_API ProfilingStack;
 
 // This file defines the classes ProfilingStack and ProfilingStackFrame.
 // The ProfilingStack manages an array of ProfilingStackFrames.
 // It keeps track of the "label stack" and the JS interpreter stack.
 // The two stack types are interleaved.
 //
 // Usage:
 //
@@ -333,50 +333,50 @@ class ProfilingStackFrame {
   // Note that the pointer returned might be invalid.
   JSScript* rawScript() const {
     MOZ_ASSERT(isJsFrame());
     void* script = spOrScript;
     return static_cast<JSScript*>(script);
   }
 
   // We can't know the layout of JSScript, so look in vm/GeckoProfiler.cpp.
-  JS_FRIEND_API jsbytecode* pc() const;
+  JS_PUBLIC_API jsbytecode* pc() const;
   void setPC(jsbytecode* pc);
 
   void trace(JSTracer* trc);
 
   // The offset of a pc into a script's code can actually be 0, so to
   // signify a nullptr pc, use a -1 index. This is checked against in
   // pc() and setPC() to set/get the right pc.
   static const int32_t NullPCOffset = -1;
 };
 
-JS_FRIEND_API void SetContextProfilingStack(JSContext* cx,
+JS_PUBLIC_API void SetContextProfilingStack(JSContext* cx,
                                             ProfilingStack* profilingStack);
 
 // GetContextProfilingStack also exists, but it's defined in RootingAPI.h.
 
-JS_FRIEND_API void EnableContextProfilingStack(JSContext* cx, bool enabled);
+JS_PUBLIC_API void EnableContextProfilingStack(JSContext* cx, bool enabled);
 
-JS_FRIEND_API void RegisterContextProfilingEventMarker(JSContext* cx,
+JS_PUBLIC_API void RegisterContextProfilingEventMarker(JSContext* cx,
                                                        void (*fn)(const char*,
                                                                   const char*));
 
 }  // namespace js
 
 namespace JS {
 
 typedef ProfilingStack* (*RegisterThreadCallback)(const char* threadName,
                                                   void* stackBase);
 
 typedef void (*UnregisterThreadCallback)();
 
 // regiserThread and unregisterThread callbacks are functions which are called
 // by other threads without any locking mechanism.
-JS_FRIEND_API void SetProfilingThreadCallbacks(
+JS_PUBLIC_API void SetProfilingThreadCallbacks(
     RegisterThreadCallback registerThread,
     UnregisterThreadCallback unregisterThread);
 
 }  // namespace JS
 
 // Each thread has its own ProfilingStack. That thread modifies the
 // ProfilingStack, pushing and popping elements as necessary.
 //
@@ -391,17 +391,17 @@ JS_FRIEND_API void SetProfilingThreadCal
 //   frame visible to the sampler thread -- only after the new frame has been
 //   fully written. The stack pointer is Atomic<uint32_t,ReleaseAcquire>, so
 //   the increment is a release-store, which ensures that this store is not
 //   reordered before the writes of the frame.
 //
 // - When popping an old frame, the only operation is the decrementing of the
 //   stack pointer, which is obviously atomic.
 //
-class JS_FRIEND_API ProfilingStack final {
+class JS_PUBLIC_API ProfilingStack final {
  public:
   ProfilingStack() = default;
 
   ~ProfilingStack();
 
   void pushLabelFrame(const char* label, const char* dynamicString, void* sp,
                       JS::ProfilingCategoryPair categoryPair,
                       uint32_t flags = 0) {
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -4,34 +4,34 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_Proxy_h
 #define js_Proxy_h
 
 #include "mozilla/Maybe.h"
 
-#include "jstypes.h"  // for JS_FRIEND_API, JS_FRIEND_DATA
+#include "jstypes.h"  // for JS_PUBLIC_API, JS_PUBLIC_DATA
 
 #include "js/Array.h"  // JS::IsArrayAnswer
 #include "js/CallNonGenericMethod.h"
 #include "js/Class.h"
 #include "js/HeapAPI.h"        // for ObjectIsMarkedBlack
 #include "js/Id.h"             // for jsid
 #include "js/Object.h"         // JS::GetClass
 #include "js/RootingAPI.h"     // for Handle, MutableHandle (ptr only)
 #include "js/shadow/Object.h"  // JS::shadow::Object
 #include "js/TypeDecls.h"  // for HandleObject, HandleId, HandleValue, MutableHandleIdVector, MutableHandleValue, MutableHand...
 #include "js/Value.h"  // for Value, AssertValueIsNotGray, UndefinedValue, ObjectOrNullValue
 
 namespace js {
 
 class RegExpShared;
 
-class JS_FRIEND_API Wrapper;
+class JS_PUBLIC_API Wrapper;
 
 /*
  * [SMDOC] Proxy Objects
  *
  * A proxy is a JSObject with highly customizable behavior. ES6 specifies a
  * single kind of proxy, but the customization mechanisms we use to implement
  * ES6 Proxy objects are also useful wherever an object with weird behavior is
  * wanted. Proxies are used to implement:
@@ -151,17 +151,17 @@ class JS_FRIEND_API Wrapper;
  * methods, like get() and set(), are given default implementations that work by
  * calling the low-level methods, like getOwnPropertyDescriptor().
  *
  * Important: If you add a method here, you should probably also add a
  * Proxy::foo entry point with an AutoEnterPolicy. If you don't, you need an
  * explicit override for the method in SecurityWrapper. See bug 945826 comment
  * 0.
  */
-class JS_FRIEND_API BaseProxyHandler {
+class JS_PUBLIC_API BaseProxyHandler {
   /*
    * Sometimes it's desirable to designate groups of proxy handlers as
    * "similar". For this, we use the notion of a "family": A consumer-provided
    * opaque pointer that designates the larger group to which this proxy
    * belongs.
    *
    * If it will never be important to differentiate this proxy from others as
    * part of a distinct group, nullptr may be used instead.
@@ -368,17 +368,17 @@ class JS_FRIEND_API BaseProxyHandler {
 
   virtual bool getElements(JSContext* cx, JS::HandleObject proxy,
                            uint32_t begin, uint32_t end,
                            ElementAdder* adder) const;
 
   virtual bool isScripted() const { return false; }
 };
 
-extern JS_FRIEND_DATA const JSClass ProxyClass;
+extern JS_PUBLIC_DATA const JSClass ProxyClass;
 
 inline bool IsProxy(const JSObject* obj) {
   return JS::GetClass(obj)->isProxyObject();
 }
 
 namespace detail {
 
 // Proxy slot layout
@@ -482,17 +482,17 @@ inline ProxyDataLayout* GetProxyDataLayo
 }
 
 inline const ProxyDataLayout* GetProxyDataLayout(const JSObject* obj) {
   MOZ_ASSERT(IsProxy(obj));
   return reinterpret_cast<const ProxyDataLayout*>(
       reinterpret_cast<const uint8_t*>(obj) + ProxyDataOffset);
 }
 
-JS_FRIEND_API void SetValueInProxy(JS::Value* slot, const JS::Value& value);
+JS_PUBLIC_API void SetValueInProxy(JS::Value* slot, const JS::Value& value);
 
 inline void SetProxyReservedSlotUnchecked(JSObject* obj, size_t n,
                                           const JS::Value& extra) {
   MOZ_ASSERT(n < JSCLASS_RESERVED_SLOTS(JS::GetClass(obj)));
 
   JS::Value* vp = &GetProxyDataLayout(obj)->reservedSlots->slots[n];
 
   // Trigger a barrier before writing the slot.
@@ -583,24 +583,24 @@ class MOZ_STACK_CLASS ProxyOptions {
     return *this;
   }
 
  private:
   bool lazyProto_;
   const JSClass* clasp_;
 };
 
-JS_FRIEND_API JSObject* NewProxyObject(
+JS_PUBLIC_API JSObject* NewProxyObject(
     JSContext* cx, const BaseProxyHandler* handler, JS::HandleValue priv,
     JSObject* proto, const ProxyOptions& options = ProxyOptions());
 
 JSObject* RenewProxyObject(JSContext* cx, JSObject* obj,
                            BaseProxyHandler* handler, const JS::Value& priv);
 
-class JS_FRIEND_API AutoEnterPolicy {
+class JS_PUBLIC_API AutoEnterPolicy {
  public:
   typedef BaseProxyHandler::Action Action;
   AutoEnterPolicy(JSContext* cx, const BaseProxyHandler* handler,
                   JS::HandleObject wrapper, JS::HandleId id, Action act,
                   bool mayThrow)
 #ifdef JS_DEBUG
       : context(nullptr)
 #endif
@@ -648,17 +648,17 @@ class JS_FRIEND_API AutoEnterPolicy {
   // NB: We explicitly don't track the entered action here, because sometimes
   // set() methods do an implicit get() during their implementation, leading
   // to spurious assertions.
   AutoEnterPolicy* prev;
   void recordEnter(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                    Action act);
   void recordLeave();
 
-  friend JS_FRIEND_API void assertEnteredPolicy(JSContext* cx, JSObject* proxy,
+  friend JS_PUBLIC_API void assertEnteredPolicy(JSContext* cx, JSObject* proxy,
                                                 jsid id, Action act);
 #else
   inline void recordEnter(JSContext* cx, JSObject* proxy, jsid id, Action act) {
   }
   inline void recordLeave() {}
 #endif
 
  private:
@@ -668,44 +668,44 @@ class JS_FRIEND_API AutoEnterPolicy {
   // and consequently instantiation of assign operator of mozilla::Maybe
   // would fail. See bug 1325351 comment 16. Copy constructor is removed at
   // the same time for consistency.
   AutoEnterPolicy(const AutoEnterPolicy&) = delete;
   AutoEnterPolicy& operator=(const AutoEnterPolicy&) = delete;
 };
 
 #ifdef JS_DEBUG
-class JS_FRIEND_API AutoWaivePolicy : public AutoEnterPolicy {
+class JS_PUBLIC_API AutoWaivePolicy : public AutoEnterPolicy {
  public:
   AutoWaivePolicy(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                   BaseProxyHandler::Action act) {
     allow = true;
     recordEnter(cx, proxy, id, act);
   }
 };
 #else
-class JS_FRIEND_API AutoWaivePolicy {
+class JS_PUBLIC_API AutoWaivePolicy {
  public:
   AutoWaivePolicy(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
                   BaseProxyHandler::Action act) {}
 };
 #endif
 
 #ifdef JS_DEBUG
-extern JS_FRIEND_API void assertEnteredPolicy(JSContext* cx, JSObject* obj,
+extern JS_PUBLIC_API void assertEnteredPolicy(JSContext* cx, JSObject* obj,
                                               jsid id,
                                               BaseProxyHandler::Action act);
 #else
 inline void assertEnteredPolicy(JSContext* cx, JSObject* obj, jsid id,
                                 BaseProxyHandler::Action act) {}
 #endif
 
-extern JS_FRIEND_DATA const JSClassOps ProxyClassOps;
-extern JS_FRIEND_DATA const js::ClassExtension ProxyClassExtension;
-extern JS_FRIEND_DATA const js::ObjectOps ProxyObjectOps;
+extern JS_PUBLIC_DATA const JSClassOps ProxyClassOps;
+extern JS_PUBLIC_DATA const js::ClassExtension ProxyClassExtension;
+extern JS_PUBLIC_DATA const js::ObjectOps ProxyObjectOps;
 
 template <unsigned Flags>
 constexpr unsigned CheckProxyFlags() {
   constexpr size_t reservedSlots =
       (Flags >> JSCLASS_RESERVED_SLOTS_SHIFT) & JSCLASS_RESERVED_SLOTS_MASK;
 
   // For now assert each Proxy Class has at least 1 reserved slot. This is
   // not a hard requirement, but helps catch Classes that need an explicit
@@ -740,18 +740,18 @@ constexpr unsigned CheckProxyFlags() {
   }
 
 #define PROXY_CLASS_DEF(name, flags) \
   PROXY_CLASS_DEF_WITH_CLASS_SPEC(name, flags, JS_NULL_CLASS_SPEC)
 
 // Converts a proxy into a DeadObjectProxy that will throw exceptions on all
 // access. This will run the proxy's finalizer to perform clean-up before the
 // conversion happens.
-JS_FRIEND_API void NukeNonCCWProxy(JSContext* cx, JS::HandleObject proxy);
+JS_PUBLIC_API void NukeNonCCWProxy(JSContext* cx, JS::HandleObject proxy);
 
 // This is a variant of js::NukeNonCCWProxy() for CCWs. It should only be called
 // on CCWs that have been removed from CCW tables.
-JS_FRIEND_API void NukeRemovedCrossCompartmentWrapper(JSContext* cx,
+JS_PUBLIC_API void NukeRemovedCrossCompartmentWrapper(JSContext* cx,
                                                       JSObject* wrapper);
 
 } /* namespace js */
 
 #endif /* js_Proxy_h */
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -195,30 +195,30 @@ struct PersistentRootedMarker;
 #define DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr) \
   T* address() { return &(ptr); }                        \
   T& get() { return (ptr); }
 
 } /* namespace js */
 
 namespace JS {
 
-JS_FRIEND_API void HeapObjectPostWriteBarrier(JSObject** objp, JSObject* prev,
+JS_PUBLIC_API void HeapObjectPostWriteBarrier(JSObject** objp, JSObject* prev,
                                               JSObject* next);
-JS_FRIEND_API void HeapStringPostWriteBarrier(JSString** objp, JSString* prev,
+JS_PUBLIC_API void HeapStringPostWriteBarrier(JSString** objp, JSString* prev,
                                               JSString* next);
-JS_FRIEND_API void HeapBigIntPostWriteBarrier(JS::BigInt** bip,
+JS_PUBLIC_API void HeapBigIntPostWriteBarrier(JS::BigInt** bip,
                                               JS::BigInt* prev,
                                               JS::BigInt* next);
-JS_FRIEND_API void HeapObjectWriteBarriers(JSObject** objp, JSObject* prev,
+JS_PUBLIC_API void HeapObjectWriteBarriers(JSObject** objp, JSObject* prev,
                                            JSObject* next);
-JS_FRIEND_API void HeapStringWriteBarriers(JSString** objp, JSString* prev,
+JS_PUBLIC_API void HeapStringWriteBarriers(JSString** objp, JSString* prev,
                                            JSString* next);
-JS_FRIEND_API void HeapBigIntWriteBarriers(JS::BigInt** bip, JS::BigInt* prev,
+JS_PUBLIC_API void HeapBigIntWriteBarriers(JS::BigInt** bip, JS::BigInt* prev,
                                            JS::BigInt* next);
-JS_FRIEND_API void HeapScriptWriteBarriers(JSScript** objp, JSScript* prev,
+JS_PUBLIC_API void HeapScriptWriteBarriers(JSScript** objp, JSScript* prev,
                                            JSScript* next);
 
 /**
  * Create a safely-initialized |T|, suitable for use as a default value in
  * situations requiring a safe but arbitrary |T| value.
  */
 template <typename T>
 inline T SafelyInitialized() {
@@ -249,18 +249,18 @@ inline T SafelyInitialized() {
   return T();
 }
 
 #ifdef JS_DEBUG
 /**
  * For generational GC, assert that an object is in the tenured generation as
  * opposed to being in the nursery.
  */
-extern JS_FRIEND_API void AssertGCThingMustBeTenured(JSObject* obj);
-extern JS_FRIEND_API void AssertGCThingIsNotNurseryAllocable(
+extern JS_PUBLIC_API void AssertGCThingMustBeTenured(JSObject* obj);
+extern JS_PUBLIC_API void AssertGCThingIsNotNurseryAllocable(
     js::gc::Cell* cell);
 #else
 inline void AssertGCThingMustBeTenured(JSObject* obj) {}
 inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {}
 #endif
 
 /**
  * The Heap<T> class is a heap-stored reference to a JS GC thing for use outside
--- a/js/public/SavedFrameAPI.h
+++ b/js/public/SavedFrameAPI.h
@@ -6,17 +6,17 @@
 /*
  * Functions and types related to SavedFrame objects created by the Debugger
  * API.
  */
 
 #ifndef js_SavedFrameAPI_h
 #define js_SavedFrameAPI_h
 
-#include "jstypes.h"  // JS_FRIEND_API, JS_PUBLIC_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/TypeDecls.h"
 
 struct JSPrincipals;
 
 namespace JS {
 
 /*
@@ -143,15 +143,15 @@ namespace js {
 
 /**
  * Get the first SavedFrame object in this SavedFrame stack whose principals are
  * subsumed by the given |principals|. If there is no such frame, return
  * nullptr.
  *
  * Do NOT pass a non-SavedFrame object here.
  */
-extern JS_FRIEND_API JSObject* GetFirstSubsumedSavedFrame(
+extern JS_PUBLIC_API JSObject* GetFirstSubsumedSavedFrame(
     JSContext* cx, JSPrincipals* principals, JS::Handle<JSObject*> savedFrame,
     JS::SavedFrameSelfHosted selfHosted);
 
 }  // namespace js
 
 #endif /* js_SavedFrameAPI_h */
--- a/js/public/StableStringChars.h
+++ b/js/public/StableStringChars.h
@@ -14,17 +14,17 @@
 #include "mozilla/Assertions.h"  // MOZ_ASSERT
 #include "mozilla/Attributes.h"  // MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS
 #include "mozilla/Maybe.h"       // mozilla::Maybe
 #include "mozilla/Range.h"       // mozilla::Range
 
 #include <stddef.h>  // size_t
 #include <stdint.h>  // uint8_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/AllocPolicy.h"
 #include "js/RootingAPI.h"  // JS::Handle, JS::Rooted
 #include "js/String.h"      // JS::GetStringLength
 #include "js/TypeDecls.h"   // JSContext, JS::Latin1Char, JSString
 #include "js/Vector.h"      // js::Vector
 
 class JSLinearString;
@@ -34,17 +34,17 @@ namespace JS {
 /**
  * This class provides safe access to a string's chars across a GC. If we ever
  * nursery allocate strings' out of line chars, this class will have to make a
  * copy, so it's best to avoid using this class unless you really need it. It's
  * usually more efficient to use the latin1Chars/twoByteChars JSString methods
  * and often the code can be rewritten so that only indexes instead of char
  * pointers are used in parts of the code that can GC.
  */
-class MOZ_STACK_CLASS JS_FRIEND_API AutoStableStringChars final {
+class MOZ_STACK_CLASS JS_PUBLIC_API AutoStableStringChars final {
   /*
    * When copying string char, use this many bytes of inline storage.  This is
    * chosen to allow the inline string types to be copied without allocating.
    * This is asserted in AutoStableStringChars::allocOwnChars.
    */
   static const size_t InlineCapacity = 24;
 
   /* Ensure the string is kept alive while we're using its chars. */
--- a/js/public/String.h
+++ b/js/public/String.h
@@ -409,17 +409,17 @@ MOZ_ALWAYS_INLINE bool IsExternalString(
 
   *callbacks = s->externalCallbacks;
   *chars = s->nonInlineCharsTwoByte;
   return true;
 }
 
 namespace detail {
 
-extern JS_FRIEND_API JSLinearString* StringToLinearStringSlow(JSContext* cx,
+extern JS_PUBLIC_API JSLinearString* StringToLinearStringSlow(JSContext* cx,
                                                               JSString* str);
 
 }  // namespace detail
 
 /** Convert a string to a linear string. */
 MOZ_ALWAYS_INLINE JSLinearString* StringToLinearString(JSContext* cx,
                                                        JSString* str) {
   if (MOZ_LIKELY(shadow::AsShadowString(str)->isLinear())) {
--- a/js/public/TracingAPI.h
+++ b/js/public/TracingAPI.h
@@ -16,20 +16,20 @@ class JS_PUBLIC_API JSTracer;
 namespace JS {
 class JS_PUBLIC_API CallbackTracer;
 template <typename T>
 class Heap;
 template <typename T>
 class TenuredHeap;
 
 /** Returns a static string equivalent of |kind|. */
-JS_FRIEND_API const char* GCTraceKindToAscii(JS::TraceKind kind);
+JS_PUBLIC_API const char* GCTraceKindToAscii(JS::TraceKind kind);
 
 /** Returns the base size in bytes of the GC thing of kind |kind|. */
-JS_FRIEND_API size_t GCTraceKindSize(JS::TraceKind kind);
+JS_PUBLIC_API size_t GCTraceKindSize(JS::TraceKind kind);
 
 // Kinds of JSTracer.
 enum class TracerKind {
   // Marking path: a tracer used only for marking liveness of cells, not
   // for moving them.
   Marking,
 
   // Generic tracers: Internal tracers that have a different virtual method
@@ -522,14 +522,14 @@ bool IsAboutToBeFinalizedUnbarriered(T* 
 
 }  // namespace gc
 
 #ifdef DEBUG
 /*
  * Return whether the runtime is currently being destroyed, for use in
  * assertions.
  */
-extern JS_FRIEND_API bool RuntimeIsBeingDestroyed();
+extern JS_PUBLIC_API bool RuntimeIsBeingDestroyed();
 #endif
 
 }  // namespace js
 
 #endif /* js_TracingAPI_h */
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -84,17 +84,17 @@ namespace oom {
 
 // Define the range of threads tested by simulated OOM testing and the
 // like. Testing worker threads is not supported.
 const ThreadType FirstThreadTypeToTest = THREAD_TYPE_MAIN;
 const ThreadType LastThreadTypeToTest = THREAD_TYPE_WASM_GENERATOR_TIER2;
 
 extern bool InitThreadType(void);
 extern void SetThreadType(ThreadType);
-extern JS_FRIEND_API uint32_t GetThreadType(void);
+extern JS_PUBLIC_API uint32_t GetThreadType(void);
 
 #  else
 
 inline bool InitThreadType(void) { return true; }
 inline void SetThreadType(ThreadType t){};
 inline uint32_t GetThreadType(void) { return 0; }
 inline uint32_t GetAllocationThreadType(void) { return 0; }
 inline uint32_t GetStackCheckThreadType(void) { return 0; }
--- a/js/public/Wrapper.h
+++ b/js/public/Wrapper.h
@@ -36,17 +36,17 @@ class MOZ_STACK_CLASS WrapperOptions : p
   }
 
  private:
   mozilla::Maybe<JS::RootedObject> proto_;
 };
 
 // Base class for proxy handlers that want to forward all operations to an
 // object stored in the proxy's private slot.
-class JS_FRIEND_API ForwardingProxyHandler : public BaseProxyHandler {
+class JS_PUBLIC_API ForwardingProxyHandler : public BaseProxyHandler {
  public:
   using BaseProxyHandler::BaseProxyHandler;
 
   /* Standard internal methods. */
   virtual bool getOwnPropertyDescriptor(
       JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
       JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc)
       const override;
@@ -127,17 +127,17 @@ class JS_FRIEND_API ForwardingProxyHandl
  * A wrapper can be "unwrapped" in C++, exposing the underlying object.
  * Callers should be careful to avoid unwrapping security wrappers in the wrong
  * context.
  *
  * Important: If you add a method implementation here, you probably also need
  * to add an override in CrossCompartmentWrapper. If you don't, you risk
  * compartment mismatches. See bug 945826 comment 0.
  */
-class JS_FRIEND_API Wrapper : public ForwardingProxyHandler {
+class JS_PUBLIC_API Wrapper : public ForwardingProxyHandler {
   unsigned mFlags;
 
  public:
   explicit constexpr Wrapper(unsigned aFlags, bool aHasPrototype = false,
                              bool aHasSecurityPolicy = false)
       : ForwardingProxyHandler(&family, aHasPrototype, aHasSecurityPolicy),
         mFlags(aFlags) {}
 
@@ -181,17 +181,17 @@ class JS_FRIEND_API Wrapper : public For
   static JSObject* const defaultProto;
 };
 
 inline JSObject* WrapperOptions::proto() const {
   return proto_ ? *proto_ : Wrapper::defaultProto;
 }
 
 /* Base class for all cross compartment wrapper handlers. */
-class JS_FRIEND_API CrossCompartmentWrapper : public Wrapper {
+class JS_PUBLIC_API CrossCompartmentWrapper : public Wrapper {
  public:
   explicit constexpr CrossCompartmentWrapper(unsigned aFlags,
                                              bool aHasPrototype = false,
                                              bool aHasSecurityPolicy = false)
       : Wrapper(CROSS_COMPARTMENT | aFlags, aHasPrototype, aHasSecurityPolicy) {
   }
 
   /* Standard internal methods. */
@@ -259,17 +259,17 @@ class JS_FRIEND_API CrossCompartmentWrap
 
   // Allocate CrossCompartmentWrappers in the nursery.
   virtual bool canNurseryAllocate() const override { return true; }
 
   static const CrossCompartmentWrapper singleton;
   static const CrossCompartmentWrapper singletonWithPrototype;
 };
 
-class JS_FRIEND_API OpaqueCrossCompartmentWrapper
+class JS_PUBLIC_API OpaqueCrossCompartmentWrapper
     : public CrossCompartmentWrapper {
  public:
   explicit constexpr OpaqueCrossCompartmentWrapper()
       : CrossCompartmentWrapper(0) {}
 
   /* Standard internal methods. */
   virtual bool getOwnPropertyDescriptor(
       JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
@@ -337,17 +337,17 @@ class JS_FRIEND_API OpaqueCrossCompartme
  * all or part of some wrapped object thus SecurityWrapper defaults to denying
  * access to the wrappee. This is the opposite of Wrapper which tries to be
  * completely transparent.
  *
  * NB: Currently, only a few ProxyHandler operations are overridden to deny
  * access, relying on derived SecurityWrapper to block access when necessary.
  */
 template <class Base>
-class JS_FRIEND_API SecurityWrapper : public Base {
+class JS_PUBLIC_API SecurityWrapper : public Base {
  public:
   explicit constexpr SecurityWrapper(unsigned flags, bool hasPrototype = false)
       : Base(flags, hasPrototype, /* hasSecurityPolicy = */ true) {}
 
   virtual bool enter(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
                      Wrapper::Action act, bool mayThrow,
                      bool* bp) const override;
 
@@ -413,17 +413,17 @@ inline bool IsCrossCompartmentWrapper(co
 // Given a JSObject, returns that object stripped of wrappers. If
 // stopAtWindowProxy is true, then this returns the WindowProxy if it was
 // previously wrapped. Otherwise, this returns the first object for which
 // JSObject::isWrapper returns false.
 //
 // ExposeToActiveJS is called on wrapper targets to allow gray marking
 // assertions to work while an incremental GC is in progress, but this means
 // that this cannot be called from the GC or off the main thread.
-JS_FRIEND_API JSObject* UncheckedUnwrap(JSObject* obj,
+JS_PUBLIC_API JSObject* UncheckedUnwrap(JSObject* obj,
                                         bool stopAtWindowProxy = true,
                                         unsigned* flagsp = nullptr);
 
 // Given a JSObject, returns that object stripped of wrappers, except
 // WindowProxy wrappers.  At each stage, the wrapper has the opportunity to veto
 // the unwrap. Null is returned if there are security wrappers that can't be
 // unwrapped.
 //
@@ -433,21 +433,21 @@ JS_FRIEND_API JSObject* UncheckedUnwrap(
 // spec's cross-origin objects (WindowProxy and Location), but is fine to use
 // when failure to unwrap one of those objects wouldn't be a problem.  For
 // example, if you want to test whether your target object is a specific class
 // that's not WindowProxy or Location, you can use this.
 //
 // ExposeToActiveJS is called on wrapper targets to allow gray marking
 // assertions to work while an incremental GC is in progress, but this means
 // that this cannot be called from the GC or off the main thread.
-JS_FRIEND_API JSObject* CheckedUnwrapStatic(JSObject* obj);
+JS_PUBLIC_API JSObject* CheckedUnwrapStatic(JSObject* obj);
 
 // Unwrap only the outermost security wrapper, with the same semantics as
 // above. This is the checked version of Wrapper::wrappedObject.
-JS_FRIEND_API JSObject* UnwrapOneCheckedStatic(JSObject* obj);
+JS_PUBLIC_API JSObject* UnwrapOneCheckedStatic(JSObject* obj);
 
 // Given a JSObject, returns that object stripped of wrappers. At each stage,
 // the security wrapper has the opportunity to veto the unwrap. If
 // stopAtWindowProxy is true, then this returns the WindowProxy if it was
 // previously wrapped.  Null is returned if there are security wrappers that
 // can't be unwrapped.
 //
 // ExposeToActiveJS is called on wrapper targets to allow gray marking
@@ -461,51 +461,51 @@ JS_FRIEND_API JSObject* UnwrapOneChecked
 // This function may be able to GC (and the static analysis definitely thinks it
 // can), but it still takes a JSObject* argument, because some of its callers
 // would actually have a bit of a hard time producing a Rooted.  And it ends up
 // having to root internally anyway, because it wants to use the value in a loop
 // and you can't assign to a HandleObject.  What this means is that callers who
 // plan to use the argument object after they have called this function will
 // need to root it to avoid hazard failures, even though this function doesn't
 // require a Handle.
-JS_FRIEND_API JSObject* CheckedUnwrapDynamic(JSObject* obj, JSContext* cx,
+JS_PUBLIC_API JSObject* CheckedUnwrapDynamic(JSObject* obj, JSContext* cx,
                                              bool stopAtWindowProxy = true);
 
 // Unwrap only the outermost security wrapper, with the same semantics as
 // above. This is the checked version of Wrapper::wrappedObject.
-JS_FRIEND_API JSObject* UnwrapOneCheckedDynamic(JS::HandleObject obj,
+JS_PUBLIC_API JSObject* UnwrapOneCheckedDynamic(JS::HandleObject obj,
                                                 JSContext* cx,
                                                 bool stopAtWindowProxy = true);
 
 // Given a JSObject, returns that object stripped of wrappers. This returns the
 // WindowProxy if it was previously wrapped.
 //
 // ExposeToActiveJS is not called on wrapper targets so this can be called from
 // the GC or off the main thread.
-JS_FRIEND_API JSObject* UncheckedUnwrapWithoutExpose(JSObject* obj);
+JS_PUBLIC_API JSObject* UncheckedUnwrapWithoutExpose(JSObject* obj);
 
 void ReportAccessDenied(JSContext* cx);
 
-JS_FRIEND_API void NukeCrossCompartmentWrapper(JSContext* cx,
+JS_PUBLIC_API void NukeCrossCompartmentWrapper(JSContext* cx,
                                                JSObject* wrapper);
 
 // If a cross-compartment wrapper source => target exists, nuke it.
-JS_FRIEND_API void NukeCrossCompartmentWrapperIfExists(JSContext* cx,
+JS_PUBLIC_API void NukeCrossCompartmentWrapperIfExists(JSContext* cx,
                                                        JS::Compartment* source,
                                                        JSObject* target);
 
 void RemapWrapper(JSContext* cx, JSObject* wobj, JSObject* newTarget);
 void RemapDeadWrapper(JSContext* cx, JS::HandleObject wobj,
                       JS::HandleObject newTarget);
 
-JS_FRIEND_API bool RemapAllWrappersForObject(JSContext* cx,
+JS_PUBLIC_API bool RemapAllWrappersForObject(JSContext* cx,
                                              JS::HandleObject oldTarget,
                                              JS::HandleObject newTarget);
 
 // API to recompute all cross-compartment wrappers whose source and target
 // match the given filters.
-JS_FRIEND_API bool RecomputeWrappers(JSContext* cx,
+JS_PUBLIC_API bool RecomputeWrappers(JSContext* cx,
                                      const CompartmentFilter& sourceFilter,
                                      const CompartmentFilter& targetFilter);
 
 } /* namespace js */
 
 #endif /* js_Wrapper_h */
--- a/js/public/experimental/CTypes.h
+++ b/js/public/experimental/CTypes.h
@@ -6,17 +6,17 @@
 
 #ifndef js_experimental_CTypes_h
 #define js_experimental_CTypes_h
 
 #include "mozilla/Attributes.h"  // MOZ_RAII
 
 #include <stddef.h>  // size_t
 
-#include "jstypes.h"  // JS_PUBLIC_API, JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/TypeDecls.h"
 
 namespace JS {
 
 #ifdef JS_HAS_CTYPES
 
 /**
@@ -43,20 +43,20 @@ enum class CTypesActivityType {
  * activity.
  */
 using CTypesActivityCallback = void (*)(JSContext*, CTypesActivityType);
 
 /**
  * Sets a callback that is run whenever js-ctypes is about to be used when
  * calling into C.
  */
-extern JS_FRIEND_API void SetCTypesActivityCallback(JSContext* cx,
+extern JS_PUBLIC_API void SetCTypesActivityCallback(JSContext* cx,
                                                     CTypesActivityCallback cb);
 
-class MOZ_RAII JS_FRIEND_API AutoCTypesActivityCallback {
+class MOZ_RAII JS_PUBLIC_API AutoCTypesActivityCallback {
  private:
   JSContext* cx;
   CTypesActivityCallback callback;
   CTypesActivityType endType;
 
  public:
   AutoCTypesActivityCallback(JSContext* cx, CTypesActivityType beginType,
                              CTypesActivityType endType);
--- a/js/public/experimental/CodeCoverage.h
+++ b/js/public/experimental/CodeCoverage.h
@@ -2,39 +2,39 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_experimental_CodeCoverage_h
 #define js_experimental_CodeCoverage_h
 
-#include "jstypes.h"     // JS_FRIEND_API
+#include "jstypes.h"     // JS_PUBLIC_API
 #include "js/Utility.h"  // JS::UniqueChars
 
 struct JS_PUBLIC_API JSContext;
 
 namespace js {
 
 /**
  * Enable the collection of lcov code coverage metrics.
  * Must be called before a runtime is created and before any calls to
  * GetCodeCoverageSummary.
  */
-extern JS_FRIEND_API void EnableCodeCoverage();
+extern JS_PUBLIC_API void EnableCodeCoverage();
 
 /**
  * Generate lcov trace file content for the current realm, and allocate a new
  * buffer and return the content in it, the size of the newly allocated content
  * within the buffer would be set to the length out-param. The 'All' variant
  * will collect data for all realms in the runtime.
  *
  * In case of out-of-memory, this function returns nullptr. The length
  * out-param is undefined on failure.
  */
-extern JS_FRIEND_API JS::UniqueChars GetCodeCoverageSummary(JSContext* cx,
+extern JS_PUBLIC_API JS::UniqueChars GetCodeCoverageSummary(JSContext* cx,
                                                             size_t* length);
-extern JS_FRIEND_API JS::UniqueChars GetCodeCoverageSummaryAll(JSContext* cx,
+extern JS_PUBLIC_API JS::UniqueChars GetCodeCoverageSummaryAll(JSContext* cx,
                                                                size_t* length);
 
 }  // namespace js
 
 #endif  // js_experimental_CodeCoverage_h
--- a/js/public/experimental/Intl.h
+++ b/js/public/experimental/Intl.h
@@ -2,17 +2,17 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_experimental_Intl_h
 #define js_experimental_Intl_h
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/TypeDecls.h"
 
 namespace JS {
 
 /**
  * Create and add the Intl.MozDateTimeFormat constructor function to the
  * provided object.
@@ -25,26 +25,26 @@ namespace JS {
  * not shippable on the web, and it *must* be fixed before this functionality
  * can be exposed in the real world.  (There are also some questions about
  * whether the format exposed here is the *right* one to standardize, that will
  * also need to be resolved to ship this.)
  *
  * If JS was built without JS_HAS_INTL_API, this function will throw an
  * exception.
  */
-extern JS_FRIEND_API bool AddMozDateTimeFormatConstructor(
+extern JS_PUBLIC_API bool AddMozDateTimeFormatConstructor(
     JSContext* cx, Handle<JSObject*> intl);
 
 /**
  * Create and add the Intl.MozDisplayNames constructor function to the
  * provided object.  This constructor acts like the standard |Intl.DisplayNames|
  * but accepts certain additional syntax that isn't standardized to the point of
  * being shippable.
  *
  * If JS was built without JS_HAS_INTL_API, this function will throw an
  * exception.
  */
-extern JS_FRIEND_API bool AddMozDisplayNamesConstructor(JSContext* cx,
+extern JS_PUBLIC_API bool AddMozDisplayNamesConstructor(JSContext* cx,
                                                         Handle<JSObject*> intl);
 
 }  // namespace JS
 
 #endif  // js_experimental_Intl_h
--- a/js/public/experimental/JSStencil.h
+++ b/js/public/experimental/JSStencil.h
@@ -15,17 +15,17 @@
  */
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"  // mozilla::UniquePtr
 #include "mozilla/Utf8.h"       // mozilla::Utf8Unit
 
 #include <stddef.h>  // size_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/CompileOptions.h"  // JS::ReadOnlyCompileOptions
 #include "js/SourceText.h"      // JS::SourceText
 #include "js/Transcoding.h"
 
 struct JS_PUBLIC_API JSContext;
 
 // Underlying opaque type.
--- a/js/public/experimental/SourceHook.h
+++ b/js/public/experimental/SourceHook.h
@@ -35,17 +35,17 @@
 
 #ifndef js_experimental_SourceHook_h
 #define js_experimental_SourceHook_h
 
 #include "mozilla/UniquePtr.h"  // mozilla::UniquePtr
 
 #include <stddef.h>  // size_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 struct JS_PUBLIC_API JSContext;
 
 namespace js {
 
 /**
  * A class of objects that return source code on demand.
  *
@@ -82,18 +82,18 @@ class SourceHook {
 };
 
 /**
  * Have |cx| use |hook| to retrieve lazily-retrieved source code. See the
  * comments for SourceHook. The context takes ownership of the hook, and
  * will delete it when the context itself is deleted, or when a new hook is
  * set.
  */
-extern JS_FRIEND_API void SetSourceHook(JSContext* cx,
+extern JS_PUBLIC_API void SetSourceHook(JSContext* cx,
                                         mozilla::UniquePtr<SourceHook> hook);
 
 /** Remove |cx|'s source hook, and return it. The caller now owns the hook. */
-extern JS_FRIEND_API mozilla::UniquePtr<SourceHook> ForgetSourceHook(
+extern JS_PUBLIC_API mozilla::UniquePtr<SourceHook> ForgetSourceHook(
     JSContext* cx);
 
 }  // namespace js
 
 #endif  // js_experimental_SourceHook_h
--- a/js/public/experimental/TypedData.h
+++ b/js/public/experimental/TypedData.h
@@ -13,17 +13,17 @@
 #define js_experimental_TypedData_h
 
 #include "mozilla/Assertions.h"  // MOZ_ASSERT, MOZ_CRASH
 #include "mozilla/Casting.h"     // mozilla::AssertedCast
 
 #include <stddef.h>  // size_t
 #include <stdint.h>  // {,u}int8_t, {,u}int16_t, {,u}int32_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/Object.h"      // JS::GetClass, JS::GetPrivate, JS::GetReservedSlot
 #include "js/RootingAPI.h"  // JS::Handle
 #include "js/ScalarType.h"  // js::Scalar::Type
 
 struct JSClass;
 class JS_PUBLIC_API JSObject;
 
@@ -35,179 +35,179 @@ class JS_PUBLIC_API AutoRequireNoGC;
 
 /*
  * Create a new typed array with nelements elements.
  *
  * These functions (except the WithBuffer variants) fill in the array with
  * zeros.
  */
 
-extern JS_FRIEND_API JSObject* JS_NewInt8Array(JSContext* cx, size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewUint8Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewInt8Array(JSContext* cx, size_t nelements);
+extern JS_PUBLIC_API JSObject* JS_NewUint8Array(JSContext* cx,
                                                 size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArray(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewUint8ClampedArray(JSContext* cx,
                                                        size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewInt16Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewInt16Array(JSContext* cx,
                                                 size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewUint16Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewUint16Array(JSContext* cx,
                                                  size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewInt32Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewInt32Array(JSContext* cx,
                                                 size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewUint32Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewUint32Array(JSContext* cx,
                                                  size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewFloat32Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewFloat32Array(JSContext* cx,
                                                   size_t nelements);
-extern JS_FRIEND_API JSObject* JS_NewFloat64Array(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_NewFloat64Array(JSContext* cx,
                                                   size_t nelements);
 
 /*
  * Create a new typed array and copy in values from the given object. The
  * object is used as if it were an array; that is, the new array (if
  * successfully created) will have length given by array.length, and its
  * elements will be those specified by array[0], array[1], and so on, after
  * conversion to the typed array element type.
  */
 
-extern JS_FRIEND_API JSObject* JS_NewInt8ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewInt8ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewUint8ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewUint8ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewUint8ClampedArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewInt16ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewInt16ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewUint16ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewUint16ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewInt32ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewInt32ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewUint32ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewUint32ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewFloat32ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewFloat32ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
-extern JS_FRIEND_API JSObject* JS_NewFloat64ArrayFromArray(
+extern JS_PUBLIC_API JSObject* JS_NewFloat64ArrayFromArray(
     JSContext* cx, JS::Handle<JSObject*> array);
 
 /*
  * Create a new typed array using the given ArrayBuffer or
  * SharedArrayBuffer for storage.  The length value is optional; if -1
  * is passed, enough elements to use up the remainder of the byte
  * array is used as the default value.
  */
 
-extern JS_FRIEND_API JSObject* JS_NewInt8ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewInt8ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewUint8ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewUint8ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewUint8ClampedArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewUint8ClampedArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewInt16ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewInt16ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewUint16ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewUint16ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewInt32ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewInt32ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewUint32ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewUint32ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewBigInt64ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewBigInt64ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewBigUint64ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewBigUint64ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewFloat32ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewFloat32ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
-extern JS_FRIEND_API JSObject* JS_NewFloat64ArrayWithBuffer(
+extern JS_PUBLIC_API JSObject* JS_NewFloat64ArrayWithBuffer(
     JSContext* cx, JS::Handle<JSObject*> arrayBuffer, size_t byteOffset,
     int64_t length);
 
 /**
  * Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
  * false if a security wrapper is encountered that denies the unwrapping. If
  * this test or one of the JS_Is*Array tests succeeds, then it is safe to call
  * the various accessor JSAPI calls defined below.
  */
-extern JS_FRIEND_API bool JS_IsTypedArrayObject(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsTypedArrayObject(JSObject* obj);
 
 /**
  * Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
  * return false if a security wrapper is encountered that denies the
  * unwrapping. If this test or one of the more specific tests succeeds, then it
  * is safe to call the various ArrayBufferView accessor JSAPI calls defined
  * below.
  */
-extern JS_FRIEND_API bool JS_IsArrayBufferViewObject(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsArrayBufferViewObject(JSObject* obj);
 
 /*
  * Test for specific typed array types (ArrayBufferView subtypes)
  */
 
-extern JS_FRIEND_API bool JS_IsInt8Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsUint8Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsUint8ClampedArray(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsInt16Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsUint16Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsInt32Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsUint32Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsFloat32Array(JSObject* obj);
-extern JS_FRIEND_API bool JS_IsFloat64Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsInt8Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsUint8Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsUint8ClampedArray(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsInt16Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsUint16Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsInt32Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsUint32Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsFloat32Array(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsFloat64Array(JSObject* obj);
 
 /**
  * Return the isShared flag of a typed array, which denotes whether
  * the underlying buffer is a SharedArrayBuffer.
  *
  * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is a typed array or a wrapper of
  * a typed array, and the unwrapping will succeed.
  */
-extern JS_FRIEND_API bool JS_GetTypedArraySharedness(JSObject* obj);
+extern JS_PUBLIC_API bool JS_GetTypedArraySharedness(JSObject* obj);
 
 /*
  * Test for specific typed array types (ArrayBufferView subtypes) and return
  * the unwrapped object if so, else nullptr.  Never throws.
  */
 
 namespace js {
 
-extern JS_FRIEND_API JSObject* UnwrapInt8Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapUint8Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapUint8ClampedArray(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapInt16Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapUint16Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapInt32Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapUint32Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapBigInt64Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapBigUint64Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapFloat32Array(JSObject* obj);
-extern JS_FRIEND_API JSObject* UnwrapFloat64Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapInt8Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapUint8Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapUint8ClampedArray(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapInt16Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapUint16Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapInt32Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapUint32Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapBigInt64Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapBigUint64Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapFloat32Array(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapFloat64Array(JSObject* obj);
 
-extern JS_FRIEND_API JSObject* UnwrapArrayBufferView(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapArrayBufferView(JSObject* obj);
 
-extern JS_FRIEND_API JSObject* UnwrapReadableStream(JSObject* obj);
+extern JS_PUBLIC_API JSObject* UnwrapReadableStream(JSObject* obj);
 
 namespace detail {
 
-extern JS_FRIEND_DATA const JSClass* const Int8ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Uint8ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Uint8ClampedArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Int16ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Uint16ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Int32ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Uint32ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const BigInt64ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const BigUint64ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Float32ArrayClassPtr;
-extern JS_FRIEND_DATA const JSClass* const Float64ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Int8ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Uint8ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Uint8ClampedArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Int16ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Uint16ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Int32ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Uint32ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const BigInt64ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const BigUint64ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Float32ArrayClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const Float64ArrayClassPtr;
 
 const size_t TypedArrayLengthSlot = 1;
 
 }  // namespace detail
 
 #define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type)                    \
   inline void Get##Type##ArrayLengthAndData(                              \
       JSObject* obj, size_t* length, bool* isSharedMemory, type** data) { \
@@ -228,206 +228,206 @@ JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
 JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
 
 #undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
 
 // This one isn't inlined because it's rather tricky (by dint of having to deal
 // with a dozen-plus classes and varying slot layouts.
-extern JS_FRIEND_API void GetArrayBufferViewLengthAndData(JSObject* obj,
+extern JS_PUBLIC_API void GetArrayBufferViewLengthAndData(JSObject* obj,
                                                           size_t* length,
                                                           bool* isSharedMemory,
                                                           uint8_t** data);
 
 }  // namespace js
 
 /*
  * Unwrap Typed arrays all at once. Return nullptr without throwing if the
  * object cannot be viewed as the correct typed array, or the typed array
  * object on success, filling both outparameters.
  */
-extern JS_FRIEND_API JSObject* JS_GetObjectAsInt8Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsInt8Array(JSObject* obj,
                                                        size_t* length,
                                                        bool* isSharedMemory,
                                                        int8_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsUint8Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsUint8Array(JSObject* obj,
                                                         size_t* length,
                                                         bool* isSharedMemory,
                                                         uint8_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsUint8ClampedArray(
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsUint8ClampedArray(
     JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsInt16Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsInt16Array(JSObject* obj,
                                                         size_t* length,
                                                         bool* isSharedMemory,
                                                         int16_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsUint16Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsUint16Array(JSObject* obj,
                                                          size_t* length,
                                                          bool* isSharedMemory,
                                                          uint16_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsInt32Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsInt32Array(JSObject* obj,
                                                         size_t* length,
                                                         bool* isSharedMemory,
                                                         int32_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsUint32Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsUint32Array(JSObject* obj,
                                                          size_t* length,
                                                          bool* isSharedMemory,
                                                          uint32_t** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsFloat32Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsFloat32Array(JSObject* obj,
                                                           size_t* length,
                                                           bool* isSharedMemory,
                                                           float** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsFloat64Array(JSObject* obj,
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsFloat64Array(JSObject* obj,
                                                           size_t* length,
                                                           bool* isSharedMemory,
                                                           double** data);
-extern JS_FRIEND_API JSObject* JS_GetObjectAsArrayBufferView(
+extern JS_PUBLIC_API JSObject* JS_GetObjectAsArrayBufferView(
     JSObject* obj, size_t* length, bool* isSharedMemory, uint8_t** data);
 
 /*
  * Get the type of elements in a typed array, or MaxTypedArrayViewType if a
  * DataView.
  *
  * |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is an ArrayBufferView or a
  * wrapper of an ArrayBufferView, and the unwrapping will succeed.
  */
-extern JS_FRIEND_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj);
+extern JS_PUBLIC_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj);
 
 /**
  * Return the number of elements in a typed array.
  *
  * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is a typed array or a wrapper of
  * a typed array, and the unwrapping will succeed.
  */
-extern JS_FRIEND_API size_t JS_GetTypedArrayLength(JSObject* obj);
+extern JS_PUBLIC_API size_t JS_GetTypedArrayLength(JSObject* obj);
 
 /**
  * Return the byte offset from the start of an ArrayBuffer to the start of a
  * typed array view.
  *
  * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is a typed array or a wrapper of
  * a typed array, and the unwrapping will succeed.
  */
-extern JS_FRIEND_API size_t JS_GetTypedArrayByteOffset(JSObject* obj);
+extern JS_PUBLIC_API size_t JS_GetTypedArrayByteOffset(JSObject* obj);
 
 /**
  * Return the byte length of a typed array.
  *
  * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  * be known that it would pass such a test: it is a typed array or a wrapper of
  * a typed array, and the unwrapping will succeed.
  */
-extern JS_FRIEND_API size_t JS_GetTypedArrayByteLength(JSObject* obj);
+extern JS_PUBLIC_API size_t JS_GetTypedArrayByteLength(JSObject* obj);
 
 /**
  * More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
  */
-extern JS_FRIEND_API size_t JS_GetArrayBufferViewByteLength(JSObject* obj);
+extern JS_PUBLIC_API size_t JS_GetArrayBufferViewByteLength(JSObject* obj);
 
 /**
  * More generic name for JS_GetTypedArrayByteOffset to cover DataViews as well
  */
-extern JS_FRIEND_API size_t JS_GetArrayBufferViewByteOffset(JSObject* obj);
+extern JS_PUBLIC_API size_t JS_GetArrayBufferViewByteOffset(JSObject* obj);
 
 /*
  * Return a pointer to the start of the data referenced by a typed array. The
  * data is still owned by the typed array, and should not be modified on
  * another thread. Furthermore, the pointer can become invalid on GC (if the
  * data is small and fits inside the array's GC header), so callers must take
  * care not to hold on across anything that could GC.
  *
  * |obj| must have passed a JS_Is*Array test, or somehow be known that it would
  * pass such a test: it is a typed array or a wrapper of a typed array, and the
  * unwrapping will succeed.
  *
  * |*isSharedMemory| will be set to true if the typed array maps a
  * SharedArrayBuffer, otherwise to false.
  */
 
-extern JS_FRIEND_API int8_t* JS_GetInt8ArrayData(JSObject* obj,
+extern JS_PUBLIC_API int8_t* JS_GetInt8ArrayData(JSObject* obj,
                                                  bool* isSharedMemory,
                                                  const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API uint8_t* JS_GetUint8ArrayData(JSObject* obj,
+extern JS_PUBLIC_API uint8_t* JS_GetUint8ArrayData(JSObject* obj,
                                                    bool* isSharedMemory,
                                                    const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API uint8_t* JS_GetUint8ClampedArrayData(
+extern JS_PUBLIC_API uint8_t* JS_GetUint8ClampedArrayData(
     JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API int16_t* JS_GetInt16ArrayData(JSObject* obj,
+extern JS_PUBLIC_API int16_t* JS_GetInt16ArrayData(JSObject* obj,
                                                    bool* isSharedMemory,
                                                    const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API uint16_t* JS_GetUint16ArrayData(
+extern JS_PUBLIC_API uint16_t* JS_GetUint16ArrayData(
     JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API int32_t* JS_GetInt32ArrayData(JSObject* obj,
+extern JS_PUBLIC_API int32_t* JS_GetInt32ArrayData(JSObject* obj,
                                                    bool* isSharedMemory,
                                                    const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API uint32_t* JS_GetUint32ArrayData(
+extern JS_PUBLIC_API uint32_t* JS_GetUint32ArrayData(
     JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API float* JS_GetFloat32ArrayData(JSObject* obj,
+extern JS_PUBLIC_API float* JS_GetFloat32ArrayData(JSObject* obj,
                                                    bool* isSharedMemory,
                                                    const JS::AutoRequireNoGC&);
-extern JS_FRIEND_API double* JS_GetFloat64ArrayData(JSObject* obj,
+extern JS_PUBLIC_API double* JS_GetFloat64ArrayData(JSObject* obj,
                                                     bool* isSharedMemory,
                                                     const JS::AutoRequireNoGC&);
 
 /**
  * Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
  * versions when possible.
  */
-extern JS_FRIEND_API void* JS_GetArrayBufferViewData(
+extern JS_PUBLIC_API void* JS_GetArrayBufferViewData(
     JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
 
 /**
  * Return a "fixed" pointer (one that will not move during a GC) to the
  * ArrayBufferView's data. Note that this will not keep the object alive; the
  * holding object should be rooted or traced. If the view is storing the data
  * inline, this will copy the data to the provided buffer, returning nullptr if
  * bufSize is inadequate.
  *
  * Avoid using this unless necessary. JS_GetArrayBufferViewData is simpler and
  * more efficient because it requires the caller to ensure that a GC will not
  * occur and thus does not need to handle movable data.
  */
-extern JS_FRIEND_API uint8_t* JS_GetArrayBufferViewFixedData(JSObject* obj,
+extern JS_PUBLIC_API uint8_t* JS_GetArrayBufferViewFixedData(JSObject* obj,
                                                              uint8_t* buffer,
                                                              size_t bufSize);
 
 /**
  * If the bufSize passed to JS_GetArrayBufferViewFixedData is at least this
  * many bytes, then any copied data is guaranteed to fit into the provided
  * buffer.
  */
-extern JS_FRIEND_API size_t JS_MaxMovableTypedArraySize();
+extern JS_PUBLIC_API size_t JS_MaxMovableTypedArraySize();
 
 /**
  * Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
  * This may return a detached buffer.  |obj| must be an object that would
  * return true for JS_IsArrayBufferViewObject().
  */
-extern JS_FRIEND_API JSObject* JS_GetArrayBufferViewBuffer(
+extern JS_PUBLIC_API JSObject* JS_GetArrayBufferViewBuffer(
     JSContext* cx, JS::Handle<JSObject*> obj, bool* isSharedMemory);
 
 /**
  * Create a new DataView using the given buffer for storage. The given buffer
  * must be an ArrayBuffer or SharedArrayBuffer (or a cross-compartment wrapper
  * of either type), and the offset and length must fit within the bounds of the
  * buffer. Currently, nullptr will be returned and an exception will be thrown
  * if these conditions do not hold, but do not depend on that behavior.
  */
-JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx,
+JS_PUBLIC_API JSObject* JS_NewDataView(JSContext* cx,
                                        JS::Handle<JSObject*> buffer,
                                        size_t byteOffset, size_t byteLength);
 
 namespace JS {
 
 /*
  * Returns whether the passed array buffer view is 'large': its byteLength >= 2
  * GB. See also SetLargeArrayBuffersEnabled.
  *
  * |obj| must pass a JS_IsArrayBufferViewObject test.
  */
-JS_FRIEND_API bool IsLargeArrayBufferView(JSObject* obj);
+JS_PUBLIC_API bool IsLargeArrayBufferView(JSObject* obj);
 
 }  // namespace JS
 
 #endif  // js_experimental_TypedData_h
--- a/js/public/friend/DOMProxy.h
+++ b/js/public/friend/DOMProxy.h
@@ -12,17 +12,17 @@
  */
 
 #ifndef js_friend_DOMProxy_h
 #define js_friend_DOMProxy_h
 
 #include <stddef.h>  // size_t
 #include <stdint.h>  // uint64_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/Id.h"          // JS::PropertyKey
 #include "js/RootingAPI.h"  // JS::Handle, JS::Heap
 #include "js/Value.h"       // JS::UndefinedValue, JS::Value
 
 struct JS_PUBLIC_API JSContext;
 class JS_PUBLIC_API JSObject;
 
@@ -76,16 +76,16 @@ enum class DOMProxyShadowsResult {
   ShadowsViaDirectExpando,
   ShadowsViaIndirectExpando
 };
 
 using DOMProxyShadowsCheck = DOMProxyShadowsResult (*)(JSContext*,
                                                        Handle<JSObject*>,
                                                        Handle<JS::PropertyKey>);
 
-extern JS_FRIEND_API void SetDOMProxyInformation(
+extern JS_PUBLIC_API void SetDOMProxyInformation(
     const void* domProxyHandlerFamily,
     DOMProxyShadowsCheck domProxyShadowsCheck,
     const void* domRemoteProxyHandlerFamily);
 
 }  // namespace JS
 
 #endif  // js_friend_DOMProxy_h
--- a/js/public/friend/DumpFunctions.h
+++ b/js/public/friend/DumpFunctions.h
@@ -9,17 +9,17 @@
 #ifndef js_friend_DumpFunctions_h
 #define js_friend_DumpFunctions_h
 
 #include "mozilla/MemoryReporting.h"  // mozilla::MallocSizeOf
 
 #include <stddef.h>  // size_t
 #include <stdio.h>   // FILE
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/Utility.h"  // JS::UniqueChars
 
 class JS_PUBLIC_API JSAtom;
 struct JS_PUBLIC_API JSContext;
 class JS_PUBLIC_API JSObject;
 class JS_PUBLIC_API JSScript;
 class JS_PUBLIC_API JSString;
@@ -36,17 +36,17 @@ namespace js {
 
 class InterpreterFrame;
 
 }  // namespace js
 
 namespace JS {
 
 /** Exposed for DumpJSStack */
-extern JS_FRIEND_API JS::UniqueChars FormatStackDump(JSContext* cx,
+extern JS_PUBLIC_API JS::UniqueChars FormatStackDump(JSContext* cx,
                                                      bool showArgs,
                                                      bool showLocals,
                                                      bool showThisProps);
 
 }  // namespace JS
 
 namespace js {
 
@@ -54,66 +54,66 @@ namespace js {
  * These functions are FRIEND_API to help the debugger find them and to support
  * temporarily hacking js::Dump* calls into other code.  Note that there are
  * overloads that do not require the FILE* parameter, which will default to
  * stderr.
  *
  * These functions are no-ops unless built with DEBUG or JS_JITSPEW.
  */
 
-extern JS_FRIEND_API void DumpString(JSString* str, FILE* fp);
+extern JS_PUBLIC_API void DumpString(JSString* str, FILE* fp);
 
-extern JS_FRIEND_API void DumpAtom(JSAtom* atom, FILE* fp);
+extern JS_PUBLIC_API void DumpAtom(JSAtom* atom, FILE* fp);
 
-extern JS_FRIEND_API void DumpObject(JSObject* obj, FILE* fp);
+extern JS_PUBLIC_API void DumpObject(JSObject* obj, FILE* fp);
 
-extern JS_FRIEND_API void DumpChars(const char16_t* s, size_t n, FILE* fp);
+extern JS_PUBLIC_API void DumpChars(const char16_t* s, size_t n, FILE* fp);
 
 // DumpBigInt() outputs the value in decimal if it fits within a 64-bit int, and
 // otherwise in hex, prefixed with "0x". In both cases the "n" is appended.
-extern JS_FRIEND_API void DumpBigInt(JS::BigInt* bi, FILE* fp);
+extern JS_PUBLIC_API void DumpBigInt(JS::BigInt* bi, FILE* fp);
 
-extern JS_FRIEND_API void DumpValue(const JS::Value& val, FILE* fp);
+extern JS_PUBLIC_API void DumpValue(const JS::Value& val, FILE* fp);
 
-extern JS_FRIEND_API void DumpId(JS::PropertyKey id, FILE* fp);
+extern JS_PUBLIC_API void DumpId(JS::PropertyKey id, FILE* fp);
 
-extern JS_FRIEND_API bool DumpPC(JSContext* cx, FILE* fp);
+extern JS_PUBLIC_API bool DumpPC(JSContext* cx, FILE* fp);
 
-extern JS_FRIEND_API bool DumpScript(JSContext* cx, JSScript* scriptArg,
+extern JS_PUBLIC_API bool DumpScript(JSContext* cx, JSScript* scriptArg,
                                      FILE* fp);
 
 // Versions for use directly in a debugger (default parameters are not handled
 // well in gdb; built-in handles like stderr are not handled well in lldb.)
-extern JS_FRIEND_API void DumpString(JSString* str);
-extern JS_FRIEND_API void DumpAtom(JSAtom* atom);
-extern JS_FRIEND_API void DumpObject(JSObject* obj);
-extern JS_FRIEND_API void DumpChars(const char16_t* s, size_t n);
-extern JS_FRIEND_API void DumpBigInt(JS::BigInt* bi);
-extern JS_FRIEND_API void DumpValue(const JS::Value& val);
-extern JS_FRIEND_API void DumpId(JS::PropertyKey id);
-extern JS_FRIEND_API void DumpInterpreterFrame(
+extern JS_PUBLIC_API void DumpString(JSString* str);
+extern JS_PUBLIC_API void DumpAtom(JSAtom* atom);
+extern JS_PUBLIC_API void DumpObject(JSObject* obj);
+extern JS_PUBLIC_API void DumpChars(const char16_t* s, size_t n);
+extern JS_PUBLIC_API void DumpBigInt(JS::BigInt* bi);
+extern JS_PUBLIC_API void DumpValue(const JS::Value& val);
+extern JS_PUBLIC_API void DumpId(JS::PropertyKey id);
+extern JS_PUBLIC_API void DumpInterpreterFrame(
     JSContext* cx, InterpreterFrame* start = nullptr);
-extern JS_FRIEND_API bool DumpPC(JSContext* cx);
-extern JS_FRIEND_API bool DumpScript(JSContext* cx, JSScript* scriptArg);
+extern JS_PUBLIC_API bool DumpPC(JSContext* cx);
+extern JS_PUBLIC_API bool DumpScript(JSContext* cx, JSScript* scriptArg);
 
 // DumpBacktrace(), unlike the other dump functions, always dumps a backtrace --
 // regardless of DEBUG or JS_JITSPEW.
 
-extern JS_FRIEND_API void DumpBacktrace(JSContext* cx, FILE* fp);
+extern JS_PUBLIC_API void DumpBacktrace(JSContext* cx, FILE* fp);
 
-extern JS_FRIEND_API void DumpBacktrace(JSContext* cx);
+extern JS_PUBLIC_API void DumpBacktrace(JSContext* cx);
 
 enum DumpHeapNurseryBehaviour {
   CollectNurseryBeforeDump,
   IgnoreNurseryObjects
 };
 
 /**
  * Dump the complete object graph of heap-allocated things.
  * fp is the file for the dump output.
  */
-extern JS_FRIEND_API void DumpHeap(
+extern JS_PUBLIC_API void DumpHeap(
     JSContext* cx, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour,
     mozilla::MallocSizeOf mallocSizeOf = nullptr);
 
 }  // namespace js
 
 #endif  // js_friend_DumpFunctions_h
--- a/js/public/friend/ErrorMessages.h
+++ b/js/public/friend/ErrorMessages.h
@@ -14,17 +14,17 @@
  * However, the set of error numbers is not stable, error number values are not
  * stable, error types are not stable, etc.  Use your own error reporting code
  * if you can.
  */
 
 #ifndef js_friend_ErrorMessages_h
 #define js_friend_ErrorMessages_h
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 struct JSErrorFormatString;
 
 enum JSErrNum {
 #define MSG_DEF(name, count, exception, format) name,
 #include "js/friend/ErrorNumbers.msg"
 #undef MSG_DEF
   JSErr_Limit
@@ -34,14 +34,14 @@ namespace js {
 
 /**
  * A JSErrorCallback suitable for passing to |JS_ReportErrorNumberASCII| and
  * similar functions in concert with one of the |JSErrNum| error numbers.
  *
  * This function is a function only of |errorNumber|: |userRef| and ambient
  * state have no effect on its behavior.
  */
-extern JS_FRIEND_API const JSErrorFormatString* GetErrorMessage(
+extern JS_PUBLIC_API const JSErrorFormatString* GetErrorMessage(
     void* userRef, unsigned errorNumber);
 
 }  // namespace js
 
 #endif  // js_friend_ErrorMessages_h
--- a/js/public/friend/JSMEnvironment.h
+++ b/js/public/friend/JSMEnvironment.h
@@ -10,17 +10,17 @@
  * from SpiderMonkey to do so.
  *
  * Embedders who aren't Gecko can ignore this header.
  */
 
 #ifndef js_friend_JSMEnvironment_h
 #define js_friend_JSMEnvironment_h
 
-#include "jstypes.h"  // JS_FRIEND_API, JS_PUBLIC_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/GCVector.h"  // JS::StackGCVector
 #include "js/TypeDecls.h"
 
 // A 'JSMEnvironment' refers to an environment chain constructed for JSM loading
 // in a shared global. Internally it is a NonSyntacticVariablesObject with a
 // corresponding extensible LexicalEnvironmentObject that is accessible by
 // JS_ExtensibleLexicalEnvironment. The |this| value of that lexical environment
@@ -44,50 +44,50 @@
 //      Object, Math, etc. live here)
 
 namespace JS {
 
 /**
  * Allocate a new environment in the current compartment that is compatible with
  * JSM shared loading.
  */
-extern JS_FRIEND_API JSObject* NewJSMEnvironment(JSContext* cx);
+extern JS_PUBLIC_API JSObject* NewJSMEnvironment(JSContext* cx);
 
 /**
  * Execute the given script (copied into the current compartment if necessary)
  * in the given JSMEnvironment.  The script must have been compiled for
  * hasNonSyntacticScope.  The |jsmEnv| must have been previously allocated by
  * |NewJSMEnvironment|.
  *
  * NOTE: The associated extensible lexical environment is reused.
  */
-extern JS_FRIEND_API bool ExecuteInJSMEnvironment(JSContext* cx,
+extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(JSContext* cx,
                                                   Handle<JSScript*> script,
                                                   Handle<JSObject*> jsmEnv);
 
 // Additionally, target objects may be specified as required by the Gecko
 // subscript loader. These are wrapped in non-syntactic WithEnvironments and
 // temporarily placed on the environment chain.
 //
 // See also: JS::CloneAndExecuteScript(...)
-extern JS_FRIEND_API bool ExecuteInJSMEnvironment(
+extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(
     JSContext* cx, Handle<JSScript*> script, Handle<JSObject*> jsmEnv,
     Handle<StackGCVector<JSObject*>> targetObj);
 
 // Used by native methods to determine the JSMEnvironment of caller if possible
 // by looking at stack frames. Returns nullptr if top frame isn't a scripted
 // caller in a JSM.
 //
 // NOTE: This may find NonSyntacticVariablesObject generated by other embedding
 // such as a Gecko FrameScript. Caller can check the compartment if needed.
-extern JS_FRIEND_API JSObject* GetJSMEnvironmentOfScriptedCaller(JSContext* cx);
+extern JS_PUBLIC_API JSObject* GetJSMEnvironmentOfScriptedCaller(JSContext* cx);
 
 /**
  * Determine if obj is a JSMEnvironment
  *
  * NOTE: This may return true for an NonSyntacticVariablesObject generated by
  * other embedding such as a Gecko FrameScript. Caller can check compartment.
  */
-extern JS_FRIEND_API bool IsJSMEnvironment(JSObject* obj);
+extern JS_PUBLIC_API bool IsJSMEnvironment(JSObject* obj);
 
 }  // namespace JS
 
 #endif  // js_friend_JSMEnvironment_h
--- a/js/public/friend/PerformanceHint.h
+++ b/js/public/friend/PerformanceHint.h
@@ -13,15 +13,15 @@ namespace gc {
 // API to let the DOM tell us whether we're currently in pageload, so we can
 // change the GC triggers to discourage collection of the atoms zone.
 //
 // This is a temporary measure until parsing is changed to not allocate GC
 // things off the main thread.
 
 enum class PerformanceHint { Normal, InPageLoad };
 
-extern JS_FRIEND_API void SetPerformanceHint(JSContext* cx,
+extern JS_PUBLIC_API void SetPerformanceHint(JSContext* cx,
                                              PerformanceHint hint);
 
 } /* namespace gc */
 } /* namespace js */
 
 #endif  // js_friend_PerformanceHint_h
--- a/js/public/friend/StackLimits.h
+++ b/js/public/friend/StackLimits.h
@@ -8,17 +8,17 @@
 #define js_friend_StackLimits_h
 
 #include "mozilla/Attributes.h"  // MOZ_ALWAYS_INLINE, MOZ_COLD
 #include "mozilla/Likely.h"      // MOZ_LIKELY
 
 #include <stddef.h>  // size_t
 #include <stdint.h>  // uintptr_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/HeapAPI.h"  // JS::StackKind, JS::StackForTrustedScript, JS::StackForUntrustedScript
 #include "js/RootingAPI.h"  // JS::RootingContext
 #include "js/Utility.h"     // JS_STACK_OOM_POSSIBLY_FAIL
 
 struct JS_PUBLIC_API JSContext;
 
 #ifndef JS_STACK_GROWTH_DIRECTION
@@ -54,17 +54,17 @@ class MOZ_RAII AutoCheckRecursionLimit {
   [[nodiscard]] MOZ_ALWAYS_INLINE bool checkLimitImpl(uintptr_t limit,
                                                       void* sp) const;
 
   MOZ_ALWAYS_INLINE uintptr_t getStackLimitSlow(JSContext* cx) const;
   MOZ_ALWAYS_INLINE uintptr_t getStackLimitHelper(JSContext* cx,
                                                   JS::StackKind kind,
                                                   int extraAllowance) const;
 
-  JS_FRIEND_API bool runningWithTrustedPrincipals(JSContext* cx) const;
+  JS_PUBLIC_API bool runningWithTrustedPrincipals(JSContext* cx) const;
 
 #ifdef __wasi__
   // The JSContext outlives AutoCheckRecursionLimit so it is safe to use raw
   // pointer here.
   JSContext* cx_;
 #endif  // __wasi__
 
  public:
@@ -96,17 +96,17 @@ class MOZ_RAII AutoCheckRecursionLimit {
   [[nodiscard]] MOZ_ALWAYS_INLINE bool checkConservativeDontReport(
       JSContext* cx) const;
 
   [[nodiscard]] MOZ_ALWAYS_INLINE bool checkSystem(JSContext* cx) const;
   [[nodiscard]] MOZ_ALWAYS_INLINE bool checkSystemDontReport(
       JSContext* cx) const;
 };
 
-extern MOZ_COLD JS_FRIEND_API void ReportOverRecursed(JSContext* maybecx);
+extern MOZ_COLD JS_PUBLIC_API void ReportOverRecursed(JSContext* maybecx);
 
 MOZ_ALWAYS_INLINE bool AutoCheckRecursionLimit::checkLimitImpl(uintptr_t limit,
                                                                void* sp) const {
   JS_STACK_OOM_POSSIBLY_FAIL();
 
 #ifdef __wasi__
   // WASI has two limits:
   // 1) The stack pointer in linear memory that grows to zero. See --stack-first
--- a/js/public/friend/UsageStatistics.h
+++ b/js/public/friend/UsageStatistics.h
@@ -6,17 +6,17 @@
 
 /* Telemetry and use counter functionality. */
 
 #ifndef js_friend_UsageStatistics_h
 #define js_friend_UsageStatistics_h
 
 #include <stdint.h>  // uint32_t
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 struct JS_PUBLIC_API JSContext;
 class JS_PUBLIC_API JSObject;
 
 /*
  * Telemetry reasons passed to the accumulate telemetry callback.
  *
  * It's OK for these enum values to change as they will be mapped to a fixed
@@ -64,26 +64,26 @@ enum {
   MAP_JS_TELEMETRY(ENUM_DEF)
   JS_TELEMETRY_END
 };
 #undef ENUM_DEF
 // clang-format on
 
 using JSAccumulateTelemetryDataCallback = void (*)(int, uint32_t, const char*);
 
-extern JS_FRIEND_API void JS_SetAccumulateTelemetryCallback(
+extern JS_PUBLIC_API void JS_SetAccumulateTelemetryCallback(
     JSContext* cx, JSAccumulateTelemetryDataCallback callback);
 
 /*
  * Use counter names passed to the accumulate use counter callback.
  *
  * It's OK to for these enum values to change as they will be mapped to a
  * fixed member of the mozilla::UseCounter enum by the callback.
  */
 
 enum class JSUseCounter { ASMJS, WASM, WASM_DUPLICATE_IMPORTS };
 
 using JSSetUseCounterCallback = void (*)(JSObject*, JSUseCounter);
 
-extern JS_FRIEND_API void JS_SetSetUseCounterCallback(
+extern JS_PUBLIC_API void JS_SetSetUseCounterCallback(
     JSContext* cx, JSSetUseCounterCallback callback);
 
 #endif  // js_friend_UsageStatistics_h
--- a/js/public/friend/WindowProxy.h
+++ b/js/public/friend/WindowProxy.h
@@ -26,48 +26,48 @@
  *
  * If you're not embedding SpiderMonkey in a web browser, you can almost
  * certainly ignore this header.
  */
 
 #ifndef js_friend_WindowProxy_h
 #define js_friend_WindowProxy_h
 
-#include "jstypes.h"  // JS_FRIEND_API, JS_PUBLIC_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "js/Class.h"       // JSCLASS_IS_GLOBAL
 #include "js/Object.h"      // JS::GetClass
 #include "js/RootingAPI.h"  // JS::Handle
 
 struct JSClass;
 struct JS_PUBLIC_API JSContext;
 class JS_PUBLIC_API JSObject;
 
 namespace js {
 
 /**
  * Tell the JS engine which Class is used for WindowProxy objects. Used by the
  * functions below.
  */
-extern JS_FRIEND_API void SetWindowProxyClass(JSContext* cx,
+extern JS_PUBLIC_API void SetWindowProxyClass(JSContext* cx,
                                               const JSClass* clasp);
 
 /**
  * Associates a WindowProxy with a Window (global object). `windowProxy` must
  * have the Class set by SetWindowProxyClass.
  */
-extern JS_FRIEND_API void SetWindowProxy(JSContext* cx,
+extern JS_PUBLIC_API void SetWindowProxy(JSContext* cx,
                                          JS::Handle<JSObject*> global,
                                          JS::Handle<JSObject*> windowProxy);
 
 namespace detail {
 
-extern JS_FRIEND_API bool IsWindowSlow(JSObject* obj);
+extern JS_PUBLIC_API bool IsWindowSlow(JSObject* obj);
 
-extern JS_FRIEND_API JSObject* ToWindowProxyIfWindowSlow(JSObject* obj);
+extern JS_PUBLIC_API JSObject* ToWindowProxyIfWindowSlow(JSObject* obj);
 
 }  // namespace detail
 
 /**
  * Returns true iff `obj` is a global object with an associated WindowProxy,
  * see SetWindowProxy.
  */
 inline bool IsWindow(JSObject* obj) {
@@ -75,17 +75,17 @@ inline bool IsWindow(JSObject* obj) {
     return detail::IsWindowSlow(obj);
   }
   return false;
 }
 
 /**
  * Returns true iff `obj` has the WindowProxy Class (see SetWindowProxyClass).
  */
-extern JS_FRIEND_API bool IsWindowProxy(JSObject* obj);
+extern JS_PUBLIC_API bool IsWindowProxy(JSObject* obj);
 
 /**
  * If `obj` is a Window, get its associated WindowProxy (or a CCW or dead
  * wrapper if the page was navigated away from), else return `obj`. This
  * function is infallible and never returns nullptr.
  */
 MOZ_ALWAYS_INLINE JSObject* ToWindowProxyIfWindow(JSObject* obj) {
   if (JS::GetClass(obj)->flags & JSCLASS_IS_GLOBAL) {
@@ -94,13 +94,13 @@ MOZ_ALWAYS_INLINE JSObject* ToWindowProx
   return obj;
 }
 
 /**
  * If `obj` is a WindowProxy, get its associated Window (the compartment's
  * global), else return `obj`. This function is infallible and never returns
  * nullptr.
  */
-extern JS_FRIEND_API JSObject* ToWindowIfWindowProxy(JSObject* obj);
+extern JS_PUBLIC_API JSObject* ToWindowIfWindowProxy(JSObject* obj);
 
 }  // namespace js
 
 #endif  // js_friend_WindowProxy_h
--- a/js/public/friend/XrayJitInfo.h
+++ b/js/public/friend/XrayJitInfo.h
@@ -11,23 +11,23 @@
  * This header is completely irrelevant to non-Gecko embedders.
  */
 
 #ifndef js_friend_XrayJitInfo_h
 #define js_friend_XrayJitInfo_h
 
 #include <stddef.h>  // size_t
 
-#include "jstypes.h"  // JS_FRIEND_API, JS_PUBLIC_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 class JS_PUBLIC_API JSObject;
 
 namespace js {
 
-class JS_FRIEND_API BaseProxyHandler;
+class JS_PUBLIC_API BaseProxyHandler;
 
 }  // namespace js
 
 namespace JS {
 
 // Callbacks and other information for use by the JITs when optimizing accesses
 // on xray wrappers.
 struct XrayJitInfo {
@@ -45,13 +45,13 @@ struct XrayJitInfo {
 
   // Reserved slot used by xray holders to store the xray's expando object.
   size_t holderExpandoSlot;
 
   // Reserved slot used by xray expandos to store a custom prototype.
   size_t expandoProtoSlot;
 };
 
-extern JS_FRIEND_API void SetXrayJitInfo(XrayJitInfo* info);
+extern JS_PUBLIC_API void SetXrayJitInfo(XrayJitInfo* info);
 
 }  // namespace JS
 
 #endif  // js_friend_XrayJitInfo_h
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -177,26 +177,26 @@ static MOZ_ALWAYS_INLINE bool GetLengthP
  *
  * In our implementation, it would be sufficient to check for id.isInt32()
  * except that by using signed 31-bit integers we miss the top half of the
  * valid range. This function checks the string representation itself; note
  * that calling a standard conversion routine might allow strings such as
  * "08" or "4.0" as array indices, which they are not.
  *
  */
-JS_FRIEND_API bool js::StringIsArrayIndex(JSLinearString* str,
+JS_PUBLIC_API bool js::StringIsArrayIndex(JSLinearString* str,
                                           uint32_t* indexp) {
   if (!str->isIndex(indexp)) {
     return false;
   }
   MOZ_ASSERT(*indexp <= MAX_ARRAY_INDEX);
   return true;
 }
 
-JS_FRIEND_API bool js::StringIsArrayIndex(const char16_t* str, uint32_t length,
+JS_PUBLIC_API bool js::StringIsArrayIndex(const char16_t* str, uint32_t length,
                                           uint32_t* indexp) {
   if (length == 0 || length > UINT32_CHAR_BUFFER_LENGTH) {
     return false;
   }
   if (!mozilla::IsAsciiDigit(str[0])) {
     return false;
   }
   if (!CheckStringIsIndex(str, length, indexp)) {
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -1014,17 +1014,17 @@ const JSFunctionSpec DataViewObject::met
     JS_FS_END};
 
 const JSPropertySpec DataViewObject::properties[] = {
     JS_PSG("buffer", DataViewObject::bufferGetter, 0),
     JS_PSG("byteLength", DataViewObject::byteLengthGetter, 0),
     JS_PSG("byteOffset", DataViewObject::byteOffsetGetter, 0),
     JS_STRING_SYM_PS(toStringTag, "DataView", JSPROP_READONLY), JS_PS_END};
 
-JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer,
+JS_PUBLIC_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer,
                                        size_t byteOffset, size_t byteLength) {
   JSProtoKey key = JSProto_DataView;
   RootedObject constructor(cx, GlobalObject::getOrCreateConstructor(cx, key));
   if (!constructor) {
     return nullptr;
   }
 
   FixedConstructArgs<3> cargs(cx);
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -405,17 +405,17 @@ static bool ExecuteInExtensibleLexicalEn
     }
   }
 
   RootedValue rval(cx);
   return ExecuteKernel(cx, script, env, UndefinedHandleValue,
                        NullFramePtr() /* evalInFrame */, &rval);
 }
 
-JS_FRIEND_API bool js::ExecuteInFrameScriptEnvironment(
+JS_PUBLIC_API bool js::ExecuteInFrameScriptEnvironment(
     JSContext* cx, HandleObject objArg, HandleScript scriptArg,
     MutableHandleObject envArg) {
   RootedObject varEnv(cx, NonSyntacticVariablesObject::create(cx));
   if (!varEnv) {
     return false;
   }
 
   RootedObjectVector envChain(cx);
@@ -444,40 +444,40 @@ JS_FRIEND_API bool js::ExecuteInFrameScr
   if (!ExecuteInExtensibleLexicalEnvironment(cx, scriptArg, lexicalEnv)) {
     return false;
   }
 
   envArg.set(lexicalEnv);
   return true;
 }
 
-JS_FRIEND_API JSObject* JS::NewJSMEnvironment(JSContext* cx) {
+JS_PUBLIC_API JSObject* JS::NewJSMEnvironment(JSContext* cx) {
   RootedObject varEnv(cx, NonSyntacticVariablesObject::create(cx));
   if (!varEnv) {
     return nullptr;
   }
 
   // Force the NonSyntacticLexicalEnvironmentObject to be created.
   ObjectRealm& realm = ObjectRealm::get(varEnv);
   MOZ_ASSERT(!realm.getNonSyntacticLexicalEnvironment(varEnv));
   if (!realm.getOrCreateNonSyntacticLexicalEnvironment(cx, varEnv)) {
     return nullptr;
   }
 
   return varEnv;
 }
 
-JS_FRIEND_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
+JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
                                                HandleScript scriptArg,
                                                HandleObject varEnv) {
   RootedObjectVector emptyChain(cx);
   return ExecuteInJSMEnvironment(cx, scriptArg, varEnv, emptyChain);
 }
 
-JS_FRIEND_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
+JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
                                                HandleScript scriptArg,
                                                HandleObject varEnv,
                                                HandleObjectVector targetObj) {
   cx->check(varEnv);
   MOZ_ASSERT(
       ObjectRealm::get(varEnv).getNonSyntacticLexicalEnvironment(varEnv));
   MOZ_DIAGNOSTIC_ASSERT(scriptArg->noScriptRval());
 
@@ -514,17 +514,17 @@ JS_FRIEND_API bool JS::ExecuteInJSMEnvir
     if (!env) {
       return false;
     }
   }
 
   return ExecuteInExtensibleLexicalEnvironment(cx, scriptArg, env);
 }
 
-JS_FRIEND_API JSObject* JS::GetJSMEnvironmentOfScriptedCaller(JSContext* cx) {
+JS_PUBLIC_API JSObject* JS::GetJSMEnvironmentOfScriptedCaller(JSContext* cx) {
   FrameIter iter(cx);
   if (iter.done()) {
     return nullptr;
   }
 
   // WASM frames don't always provide their environment, but we also shouldn't
   // expect to see any calling into here.
   MOZ_RELEASE_ASSERT(!iter.isWasm());
@@ -532,13 +532,13 @@ JS_FRIEND_API JSObject* JS::GetJSMEnviro
   RootedObject env(cx, iter.environmentChain(cx));
   while (env && !env->is<NonSyntacticVariablesObject>()) {
     env = env->enclosingEnvironment();
   }
 
   return env;
 }
 
-JS_FRIEND_API bool JS::IsJSMEnvironment(JSObject* obj) {
+JS_PUBLIC_API bool JS::IsJSMEnvironment(JSObject* obj) {
   // NOTE: This also returns true if the NonSyntacticVariablesObject was
   // created for reasons other than the JSM loader.
   return obj->is<NonSyntacticVariablesObject>();
 }
--- a/js/src/builtin/Profilers.cpp
+++ b/js/src/builtin/Profilers.cpp
@@ -402,28 +402,28 @@ JS_PUBLIC_API bool JS_DefineProfilingFun
 
 #  if !defined(JS_SILENCE_UNUSED_VALUE_IN_EXPR)
 #    define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
       JS_BEGIN_MACRO                              \
         expr;                                     \
       JS_END_MACRO
 #  endif
 
-JS_FRIEND_API bool js_StartCallgrind() {
+JS_PUBLIC_API bool js_StartCallgrind() {
   JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_START_INSTRUMENTATION);
   JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_ZERO_STATS);
   return true;
 }
 
-JS_FRIEND_API bool js_StopCallgrind() {
+JS_PUBLIC_API bool js_StopCallgrind() {
   JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_STOP_INSTRUMENTATION);
   return true;
 }
 
-JS_FRIEND_API bool js_DumpCallgrind(const char* outfile) {
+JS_PUBLIC_API bool js_DumpCallgrind(const char* outfile) {
   if (outfile) {
     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS_AT(outfile));
   } else {
     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS);
   }
 
   return true;
 }
--- a/js/src/builtin/Profilers.h
+++ b/js/src/builtin/Profilers.h
@@ -64,25 +64,25 @@ typedef int pid_t;
  * The profiling API calls are not able to report errors, so they use a
  * thread-unsafe global memory buffer to hold the last error encountered. This
  * should only be called after something returns false.
  */
 JS_PUBLIC_API const char* JS_UnsafeGetLastProfilingError();
 
 #ifdef MOZ_CALLGRIND
 
-[[nodiscard]] extern JS_FRIEND_API bool js_StopCallgrind();
+[[nodiscard]] extern JS_PUBLIC_API bool js_StopCallgrind();
 
-[[nodiscard]] extern JS_FRIEND_API bool js_StartCallgrind();
+[[nodiscard]] extern JS_PUBLIC_API bool js_StartCallgrind();
 
-[[nodiscard]] extern JS_FRIEND_API bool js_DumpCallgrind(const char* outfile);
+[[nodiscard]] extern JS_PUBLIC_API bool js_DumpCallgrind(const char* outfile);
 
 #endif /* MOZ_CALLGRIND */
 
 #ifdef __linux__
 
-[[nodiscard]] extern JS_FRIEND_API bool js_StartPerf();
+[[nodiscard]] extern JS_PUBLIC_API bool js_StartPerf();
 
-[[nodiscard]] extern JS_FRIEND_API bool js_StopPerf();
+[[nodiscard]] extern JS_PUBLIC_API bool js_StopPerf();
 
 #endif /* __linux__ */
 
 #endif /* builtin_Profilers_h */
--- a/js/src/builtin/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -160,17 +160,17 @@ bool WeakCollectionObject::nondeterminis
         return false;
       }
     }
   }
   ret.set(arr);
   return true;
 }
 
-JS_FRIEND_API bool JS_NondeterministicGetWeakMapKeys(JSContext* cx,
+JS_PUBLIC_API bool JS_NondeterministicGetWeakMapKeys(JSContext* cx,
                                                      HandleObject objArg,
                                                      MutableHandleObject ret) {
   RootedObject obj(cx, UncheckedUnwrap(objArg));
   if (!obj || !obj->is<WeakMapObject>()) {
     ret.set(nullptr);
     return true;
   }
   return WeakCollectionObject::nondeterministicGetKeys(
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -223,17 +223,17 @@ bool WeakSetObject::construct(JSContext*
       }
     }
   }
 
   args.rval().setObject(*obj);
   return true;
 }
 
-JS_FRIEND_API bool JS_NondeterministicGetWeakSetKeys(JSContext* cx,
+JS_PUBLIC_API bool JS_NondeterministicGetWeakSetKeys(JSContext* cx,
                                                      HandleObject objArg,
                                                      MutableHandleObject ret) {
   RootedObject obj(cx, UncheckedUnwrap(objArg));
   if (!obj || !obj->is<WeakSetObject>()) {
     ret.set(nullptr);
     return true;
   }
   return WeakCollectionObject::nondeterministicGetKeys(
--- a/js/src/builtin/streams/StreamAPI.cpp
+++ b/js/src/builtin/streams/StreamAPI.cpp
@@ -64,17 +64,17 @@ using js::ReadableStreamGetNumReadReques
 using js::ReadableStreamHasDefaultReader;
 using js::ReadableStreamReader;
 using js::ReadableStreamTee;
 using js::SetUpReadableStreamDefaultControllerFromUnderlyingSource;
 using js::StreamController;
 using js::UnwrapAndDowncastObject;
 using js::UnwrapStreamFromReader;
 
-JS_FRIEND_API JSObject* js::UnwrapReadableStream(JSObject* obj) {
+JS_PUBLIC_API JSObject* js::UnwrapReadableStream(JSObject* obj) {
   return obj->maybeUnwrapIf<ReadableStream>();
 }
 
 JS_PUBLIC_API JSObject* JS::NewReadableDefaultStreamObject(
     JSContext* cx, JS::Handle<JSObject*> underlyingSource /* = nullptr */,
     JS::Handle<JSFunction*> size /* = nullptr */,
     double highWaterMark /* = 1 */,
     JS::Handle<JSObject*> proto /* = nullptr */) {
--- a/js/src/debugger/Debugger.h
+++ b/js/src/debugger/Debugger.h
@@ -49,17 +49,17 @@
 #include "vm/SavedFrame.h"          // for SavedFrame
 #include "vm/Stack.h"               // for AbstractFramePtr, FrameIter
 #include "vm/StringType.h"          // for JSAtom
 #include "wasm/WasmJS.h"            // for WasmInstanceObject
 
 class JS_PUBLIC_API JSFunction;
 
 namespace JS {
-class JS_FRIEND_API AutoStableStringChars;
+class JS_PUBLIC_API AutoStableStringChars;
 class JS_PUBLIC_API Compartment;
 class JS_PUBLIC_API Realm;
 class JS_PUBLIC_API Zone;
 } /* namespace JS */
 
 namespace js {
 class AutoRealm;
 class CrossCompartmentKey;
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -2017,28 +2017,28 @@ bool GCRuntime::addRoot(Value* vp, const
   return rootsHash.ref().put(vp, name);
 }
 
 void GCRuntime::removeRoot(Value* vp) {
   rootsHash.ref().remove(vp);
   notifyRootsRemoved();
 }
 
-extern JS_FRIEND_API bool js::AddRawValueRoot(JSContext* cx, Value* vp,
+extern JS_PUBLIC_API bool js::AddRawValueRoot(JSContext* cx, Value* vp,
                                               const char* name) {
   MOZ_ASSERT(vp);
   MOZ_ASSERT(name);
   bool ok = cx->runtime()->gc.addRoot(vp, name);
   if (!ok) {
     JS_ReportOutOfMemory(cx);
   }
   return ok;
 }
 
-extern JS_FRIEND_API void js::RemoveRawValueRoot(JSContext* cx, Value* vp) {
+extern JS_PUBLIC_API void js::RemoveRawValueRoot(JSContext* cx, Value* vp) {
   cx->runtime()->gc.removeRoot(vp);
 }
 
 /* Compacting GC */
 
 bool js::gc::IsCurrentlyAnimating(const TimeStamp& lastAnimationTime,
                                   const TimeStamp& currentTime) {
   // Assume that we're currently animating if js::NotifyAnimationActivity has
@@ -8480,29 +8480,29 @@ AutoSuppressGC::AutoSuppressGC(JSContext
 AutoDisableProxyCheck::AutoDisableProxyCheck() {
   TlsContext.get()->disableStrictProxyChecking();
 }
 
 AutoDisableProxyCheck::~AutoDisableProxyCheck() {
   TlsContext.get()->enableStrictProxyChecking();
 }
 
-JS_FRIEND_API void JS::AssertGCThingMustBeTenured(JSObject* obj) {
+JS_PUBLIC_API void JS::AssertGCThingMustBeTenured(JSObject* obj) {
   MOZ_ASSERT(obj->isTenured() &&
              (!IsNurseryAllocable(obj->asTenured().getAllocKind()) ||
               obj->getClass()->hasFinalize()));
 }
 
-JS_FRIEND_API void JS::AssertGCThingIsNotNurseryAllocable(Cell* cell) {
+JS_PUBLIC_API void JS::AssertGCThingIsNotNurseryAllocable(Cell* cell) {
   MOZ_ASSERT(cell);
   MOZ_ASSERT(!cell->is<JSObject>() && !cell->is<JSString>() &&
              !cell->is<JS::BigInt>());
 }
 
-JS_FRIEND_API void js::gc::AssertGCThingHasType(js::gc::Cell* cell,
+JS_PUBLIC_API void js::gc::AssertGCThingHasType(js::gc::Cell* cell,
                                                 JS::TraceKind kind) {
   if (!cell) {
     MOZ_ASSERT(kind == JS::TraceKind::Null);
     return;
   }
 
   MOZ_ASSERT(IsCellPointerValid(cell));
   MOZ_ASSERT(cell->getTraceKind() == kind);
@@ -8550,29 +8550,29 @@ JS::AutoEnterCycleCollection::~AutoEnter
 }
 
 JS::AutoAssertGCCallback::AutoAssertGCCallback() : AutoSuppressGCAnalysis() {
   MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
 }
 
 #endif  // DEBUG
 
-JS_FRIEND_API const char* JS::GCTraceKindToAscii(JS::TraceKind kind) {
+JS_PUBLIC_API const char* JS::GCTraceKindToAscii(JS::TraceKind kind) {
   switch (kind) {
 #define MAP_NAME(name, _0, _1, _2) \
   case JS::TraceKind::name:        \
     return "JS " #name;
     JS_FOR_EACH_TRACEKIND(MAP_NAME);
 #undef MAP_NAME
     default:
       return "Invalid";
   }
 }
 
-JS_FRIEND_API size_t JS::GCTraceKindSize(JS::TraceKind kind) {
+JS_PUBLIC_API size_t JS::GCTraceKindSize(JS::TraceKind kind) {
   switch (kind) {
 #define MAP_SIZE(name, type, _0, _1) \
   case JS::TraceKind::name:          \
     return sizeof(type);
     JS_FOR_EACH_TRACEKIND(MAP_SIZE);
 #undef MAP_SIZE
     default:
       return 0;
@@ -9110,17 +9110,17 @@ AutoEmptyNursery::AutoEmptyNursery(JSCon
 
 #ifdef DEBUG
 
 namespace js {
 
 // We don't want jsfriendapi.h to depend on GenericPrinter,
 // so these functions are declared directly in the cpp.
 
-extern JS_FRIEND_API void DumpString(JSString* str, js::GenericPrinter& out);
+extern JS_PUBLIC_API void DumpString(JSString* str, js::GenericPrinter& out);
 
 }  // namespace js
 
 void js::gc::Cell::dump(js::GenericPrinter& out) const {
   switch (getTraceKind()) {
     case JS::TraceKind::Object:
       reinterpret_cast<const JSObject*>(this)->dump(out);
       break;
@@ -9303,17 +9303,17 @@ JS_PUBLIC_API void js::gc::FinalizeDeadN
   mozilla::DebugOnly<JSObject*> prior(obj);
   MOZ_ASSERT(IsAboutToBeFinalizedUnbarriered(&prior));
   MOZ_ASSERT(obj == prior);
 
   const JSClass* jsClass = JS::GetClass(obj);
   jsClass->doFinalize(cx->defaultFreeOp(), obj);
 }
 
-JS_FRIEND_API void js::gc::SetPerformanceHint(JSContext* cx,
+JS_PUBLIC_API void js::gc::SetPerformanceHint(JSContext* cx,
                                               PerformanceHint hint) {
   CHECK_THREAD(cx);
   MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
 
   cx->runtime()->gc.setPerformanceHint(hint);
 }
 
 void GCRuntime::setPerformanceHint(PerformanceHint hint) {
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -152,19 +152,19 @@ class FreeSpan {
  *
  * <----------------------------------------------> = ArenaSize bytes
  * +---------------+---------+----+----+-----+----+
  * | header fields | padding | T0 | T1 | ... | Tn |
  * +---------------+---------+----+----+-----+----+
  * <-------------------------> = first thing offset
  */
 class alignas(ArenaSize) Arena {
-  static JS_FRIEND_DATA const uint8_t ThingSizes[];
-  static JS_FRIEND_DATA const uint8_t FirstThingOffsets[];
-  static JS_FRIEND_DATA const uint8_t ThingsPerArena[];
+  static JS_PUBLIC_DATA const uint8_t ThingSizes[];
+  static JS_PUBLIC_DATA const uint8_t FirstThingOffsets[];
+  static JS_PUBLIC_DATA const uint8_t ThingsPerArena[];
   /*
    * The first span of free things in the arena. Most of these spans are
    * stored as offsets in free regions of the data array, and most operations
    * on FreeSpans take an Arena pointer for safety. However, the FreeSpans
    * used for allocation are stored here, at the start of an Arena, and use
    * their own address to grab the next span within the same Arena.
    */
   FreeSpan firstFreeSpan;
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -3963,17 +3963,17 @@ bool js::gc::UnmarkGrayGCThingUnchecked(
       TlsContext.get(), "UnmarkGrayGCThing",
       JS::ProfilingCategoryPair::GCCC_UnmarkGray);
 
   UnmarkGrayTracer unmarker(rt);
   unmarker.unmark(thing);
   return unmarker.unmarkedAny;
 }
 
-JS_FRIEND_API bool JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr thing) {
+JS_PUBLIC_API bool JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr thing) {
   MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
   MOZ_ASSERT(!JS::RuntimeHeapIsCycleCollecting());
 
   JSRuntime* rt = thing.asCell()->runtimeFromMainThread();
   if (thing.asCell()->zone()->isGCPreparing()) {
     // Mark bits are being cleared in preparation for GC.
     return false;
   }
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -988,17 +988,17 @@ void CheckGrayMarkingTracer::checkCell(C
 bool CheckGrayMarkingTracer::check(AutoTraceSession& session) {
   if (!traceHeap(session)) {
     return true;  // Ignore failure.
   }
 
   return failures == 0;
 }
 
-JS_FRIEND_API bool js::CheckGrayMarkingState(JSRuntime* rt) {
+JS_PUBLIC_API bool js::CheckGrayMarkingState(JSRuntime* rt) {
   MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
   MOZ_ASSERT(!rt->gc.isIncrementalGCInProgress());
   if (!rt->gc.areGrayBitsValid()) {
     return true;
   }
 
   gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::TRACE_HEAP);
   AutoTraceSession session(rt);
--- a/js/src/jit/ProcessExecutableMemory.cpp
+++ b/js/src/jit/ProcessExecutableMemory.cpp
@@ -78,17 +78,17 @@ static void* ComputeRandomAllocationAddr
   uint64_t rand = js::GenerateRandomSeed();
   return (void*)(base | (rand & mask));
 }
 
 #  ifdef NEED_JIT_UNWIND_HANDLING
 static js::JitExceptionHandler sJitExceptionHandler;
 #  endif
 
-JS_FRIEND_API void js::SetJitExceptionHandler(JitExceptionHandler handler) {
+JS_PUBLIC_API void js::SetJitExceptionHandler(JitExceptionHandler handler) {
 #  ifdef NEED_JIT_UNWIND_HANDLING
   MOZ_ASSERT(!sJitExceptionHandler);
   sJitExceptionHandler = handler;
 #  else
   // Just do nothing if unwind handling is disabled.
 #  endif
 }
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -744,17 +744,17 @@ JS_PUBLIC_API JSObject* JS_TransplantObj
   }
 
   // The new identity object might be one of several things. Return it to avoid
   // ambiguity.
   JS::AssertCellIsNotGray(newIdentity);
   return newIdentity;
 }
 
-JS_FRIEND_API void js::RemapRemoteWindowProxies(
+JS_PUBLIC_API void js::RemapRemoteWindowProxies(
     JSContext* cx, CompartmentTransplantCallback* callback,
     MutableHandleObject target) {
   AssertHeapIsIdle();
   CheckTransplantObject(target);
   ReleaseAssertObjectHasNoWrappers(cx, target);
 
   // |target| can't be a remote proxy, because we expect it to get a CCW when
   // wrapped across compartments.
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3496,26 +3496,26 @@ JSObject* js::NewDateObjectMsec(JSContex
 }
 
 JS_PUBLIC_API JSObject* JS::NewDateObject(JSContext* cx, ClippedTime time) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   return NewDateObjectMsec(cx, time);
 }
 
-JS_FRIEND_API JSObject* js::NewDateObject(JSContext* cx, int year, int mon,
+JS_PUBLIC_API JSObject* js::NewDateObject(JSContext* cx, int year, int mon,
                                           int mday, int hour, int min,
                                           int sec) {
   MOZ_ASSERT(mon < 12);
   double msec_time =
       MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0.0));
   return NewDateObjectMsec(cx, TimeClip(UTC(msec_time)));
 }
 
-JS_FRIEND_API bool js::DateIsValid(JSContext* cx, HandleObject obj,
+JS_PUBLIC_API bool js::DateIsValid(JSContext* cx, HandleObject obj,
                                    bool* isValid) {
   ESClass cls;
   if (!GetBuiltinClass(cx, obj, &cls)) {
     return false;
   }
 
   if (cls != ESClass::Date) {
     *isValid = false;
@@ -3547,17 +3547,17 @@ JS_PUBLIC_API bool JS::ObjectIsDate(JSCo
   if (!GetBuiltinClass(cx, obj, &cls)) {
     return false;
   }
 
   *isDate = cls == ESClass::Date;
   return true;
 }
 
-JS_FRIEND_API bool js::DateGetMsecSinceEpoch(JSContext* cx, HandleObject obj,
+JS_PUBLIC_API bool js::DateGetMsecSinceEpoch(JSContext* cx, HandleObject obj,
                                              double* msecsSinceEpoch) {
   ESClass cls;
   if (!GetBuiltinClass(cx, obj, &cls)) {
     return false;
   }
 
   if (cls != ESClass::Date) {
     *msecsSinceEpoch = 0;
--- a/js/src/jsdate.h
+++ b/js/src/jsdate.h
@@ -32,17 +32,17 @@ extern JSObject* NewDateObjectMsec(JSCon
 
 /*
  * Construct a new Date Object from an exploded local time value.
  *
  * Assert that mon < 12 to help catch off-by-one user errors, which are common
  * due to the 0-based month numbering copied into JS from Java (java.util.Date
  * in 1995).
  */
-extern JS_FRIEND_API JSObject* NewDateObject(JSContext* cx, int year, int mon,
+extern JS_PUBLIC_API JSObject* NewDateObject(JSContext* cx, int year, int mon,
                                              int mday, int hour, int min,
                                              int sec);
 
 /* Date methods exposed so they can be installed in the self-hosting global. */
 bool date_now(JSContext* cx, unsigned argc, JS::Value* vp);
 
 bool date_valueOf(JSContext* cx, unsigned argc, JS::Value* vp);
 
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -265,17 +265,17 @@ JS_PUBLIC_API JSObject* JS::ExceptionSta
   ErrorObject* obj = objArg->maybeUnwrapIf<ErrorObject>();
   if (!obj) {
     return nullptr;
   }
 
   return obj->stack();
 }
 
-JS_FRIEND_API JSLinearString* js::GetErrorTypeName(JSContext* cx,
+JS_PUBLIC_API JSLinearString* js::GetErrorTypeName(JSContext* cx,
                                                    int16_t exnType) {
   /*
    * JSEXN_INTERNALERR returns null to prevent that "InternalError: "
    * is prepended before "uncaught exception: "
    */
   if (exnType < 0 || exnType >= JSEXN_LIMIT || exnType == JSEXN_INTERNALERR ||
       exnType == JSEXN_WARN || exnType == JSEXN_NOTE) {
     return nullptr;
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -72,22 +72,22 @@ JS::RootingContext::RootingContext() : r
   PodArrayZero(nativeStackLimit);
 #if JS_STACK_GROWTH_DIRECTION > 0
   for (int i = 0; i < StackKindCount; i++) {
     nativeStackLimit[i] = UINTPTR_MAX;
   }
 #endif
 }
 
-JS_FRIEND_API void JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp,
+JS_PUBLIC_API void JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp,
                                            void* data) {
   cx->runtime()->gc.setGrayRootsTracer(traceOp, data);
 }
 
-JS_FRIEND_API JSObject* JS_FindCompilationScope(JSContext* cx,
+JS_PUBLIC_API JSObject* JS_FindCompilationScope(JSContext* cx,
                                                 HandleObject objArg) {
   cx->check(objArg);
 
   RootedObject obj(cx, objArg);
 
   /*
    * We unwrap wrappers here. This is a little weird, but it's what's being
    * asked of us.
@@ -98,39 +98,39 @@ JS_FRIEND_API JSObject* JS_FindCompilati
 
   /*
    * Get the Window if `obj` is a WindowProxy so that we compile in the
    * correct (global) scope.
    */
   return ToWindowIfWindowProxy(obj);
 }
 
-JS_FRIEND_API JSFunction* JS_GetObjectFunction(JSObject* obj) {
+JS_PUBLIC_API JSFunction* JS_GetObjectFunction(JSObject* obj) {
   if (obj->is<JSFunction>()) {
     return &obj->as<JSFunction>();
   }
   return nullptr;
 }
 
-JS_FRIEND_API JSObject* JS_NewObjectWithoutMetadata(
+JS_PUBLIC_API JSObject* JS_NewObjectWithoutMetadata(
     JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto) {
   cx->check(proto);
   AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
   return JS_NewObjectWithGivenProto(cx, clasp, proto);
 }
 
-JS_FRIEND_API bool JS::GetIsSecureContext(JS::Realm* realm) {
+JS_PUBLIC_API bool JS::GetIsSecureContext(JS::Realm* realm) {
   return realm->creationOptions().secureContext();
 }
 
-JS_FRIEND_API JSPrincipals* JS::GetRealmPrincipals(JS::Realm* realm) {
+JS_PUBLIC_API JSPrincipals* JS::GetRealmPrincipals(JS::Realm* realm) {
   return realm->principals();
 }
 
-JS_FRIEND_API void JS::SetRealmPrincipals(JS::Realm* realm,
+JS_PUBLIC_API void JS::SetRealmPrincipals(JS::Realm* realm,
                                           JSPrincipals* principals) {
   // Short circuit if there's no change.
   if (principals == realm->principals()) {
     return;
   }
 
   // We'd like to assert that our new principals is always same-origin
   // with the old one, but JSPrincipals doesn't give us a way to do that.
@@ -149,52 +149,52 @@ JS_FRIEND_API void JS::SetRealmPrincipal
 
   // Set up the new principals.
   if (principals) {
     JS_HoldPrincipals(principals);
     realm->setPrincipals(principals);
   }
 }
 
-JS_FRIEND_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script) {
+JS_PUBLIC_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script) {
   return script->principals();
 }
 
-JS_FRIEND_API bool JS_ScriptHasMutedErrors(JSScript* script) {
+JS_PUBLIC_API bool JS_ScriptHasMutedErrors(JSScript* script) {
   return script->mutedErrors();
 }
 
-JS_FRIEND_API bool JS_WrapPropertyDescriptor(
+JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
     JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc) {
   return cx->compartment()->wrap(cx, desc);
 }
 
-JS_FRIEND_API bool JS_WrapPropertyDescriptor(
+JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
     JSContext* cx,
     JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc) {
   return cx->compartment()->wrap(cx, desc);
 }
 
-JS_FRIEND_API void JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc,
+JS_PUBLIC_API void JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc,
                                                        JS::GCCellPtr shape) {
   MOZ_ASSERT(shape.is<Shape>());
   TraceCycleCollectorChildren(trc, &shape.as<Shape>());
 }
 
 static bool DefineHelpProperty(JSContext* cx, HandleObject obj,
                                const char* prop, const char* value) {
   RootedAtom atom(cx, Atomize(cx, value, strlen(value)));
   if (!atom) {
     return false;
   }
   return JS_DefineProperty(cx, obj, prop, atom,
                            JSPROP_READONLY | JSPROP_PERMANENT);
 }
 
-JS_FRIEND_API bool JS_DefineFunctionsWithHelp(
+JS_PUBLIC_API bool JS_DefineFunctionsWithHelp(
     JSContext* cx, HandleObject obj, const JSFunctionSpecWithHelp* fs) {
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
 
   CHECK_THREAD(cx);
   cx->check(obj);
   for (; fs->name; fs++) {
     JSAtom* atom = Atomize(cx, fs->name, strlen(fs->name));
     if (!atom) {
@@ -223,17 +223,17 @@ JS_FRIEND_API bool JS_DefineFunctionsWit
         return false;
       }
     }
   }
 
   return true;
 }
 
-JS_FRIEND_API bool JS::GetBuiltinClass(JSContext* cx, HandleObject obj,
+JS_PUBLIC_API bool JS::GetBuiltinClass(JSContext* cx, HandleObject obj,
                                        js::ESClass* cls) {
   if (MOZ_UNLIKELY(obj->is<ProxyObject>())) {
     return Proxy::getBuiltinClass(cx, obj, cls);
   }
 
   if (obj->is<PlainObject>()) {
     *cls = ESClass::Object;
   } else if (obj->is<ArrayObject>()) {
@@ -272,100 +272,100 @@ JS_FRIEND_API bool JS::GetBuiltinClass(J
     *cls = ESClass::Function;
   } else {
     *cls = ESClass::Other;
   }
 
   return true;
 }
 
-JS_FRIEND_API bool js::IsArgumentsObject(HandleObject obj) {
+JS_PUBLIC_API bool js::IsArgumentsObject(HandleObject obj) {
   return obj->is<ArgumentsObject>();
 }
 
-JS_FRIEND_API JS::Zone* js::GetRealmZone(JS::Realm* realm) {
+JS_PUBLIC_API JS::Zone* js::GetRealmZone(JS::Realm* realm) {
   return realm->zone();
 }
 
-JS_FRIEND_API bool js::IsSystemCompartment(JS::Compartment* comp) {
+JS_PUBLIC_API bool js::IsSystemCompartment(JS::Compartment* comp) {
   // Realms in the same compartment must either all be system realms or
   // non-system realms. We assert this in NewRealm and SetRealmPrincipals,
   // but do an extra sanity check here.
   MOZ_ASSERT(comp->realms()[0]->isSystem() ==
              comp->realms().back()->isSystem());
   return comp->realms()[0]->isSystem();
 }
 
-JS_FRIEND_API bool js::IsSystemRealm(JS::Realm* realm) {
+JS_PUBLIC_API bool js::IsSystemRealm(JS::Realm* realm) {
   return realm->isSystem();
 }
 
-JS_FRIEND_API bool js::IsSystemZone(Zone* zone) { return zone->isSystemZone(); }
+JS_PUBLIC_API bool js::IsSystemZone(Zone* zone) { return zone->isSystemZone(); }
 
-JS_FRIEND_API bool js::IsFunctionObject(JSObject* obj) {
+JS_PUBLIC_API bool js::IsFunctionObject(JSObject* obj) {
   return obj->is<JSFunction>();
 }
 
-JS_FRIEND_API bool js::IsSavedFrame(JSObject* obj) {
+JS_PUBLIC_API bool js::IsSavedFrame(JSObject* obj) {
   return obj->is<SavedFrame>();
 }
 
-JS_FRIEND_API bool js::UninlinedIsCrossCompartmentWrapper(const JSObject* obj) {
+JS_PUBLIC_API bool js::UninlinedIsCrossCompartmentWrapper(const JSObject* obj) {
   return js::IsCrossCompartmentWrapper(obj);
 }
 
-JS_FRIEND_API void js::AssertSameCompartment(JSContext* cx, JSObject* obj) {
+JS_PUBLIC_API void js::AssertSameCompartment(JSContext* cx, JSObject* obj) {
   cx->check(obj);
 }
 
-JS_FRIEND_API void js::AssertSameCompartment(JSContext* cx, JS::HandleValue v) {
+JS_PUBLIC_API void js::AssertSameCompartment(JSContext* cx, JS::HandleValue v) {
   cx->check(v);
 }
 
 #ifdef DEBUG
-JS_FRIEND_API void js::AssertSameCompartment(JSObject* objA, JSObject* objB) {
+JS_PUBLIC_API void js::AssertSameCompartment(JSObject* objA, JSObject* objB) {
   MOZ_ASSERT(objA->compartment() == objB->compartment());
 }
 #endif
 
-JS_FRIEND_API void js::NotifyAnimationActivity(JSObject* obj) {
+JS_PUBLIC_API void js::NotifyAnimationActivity(JSObject* obj) {
   MOZ_ASSERT(obj->is<GlobalObject>());
 
   auto timeNow = mozilla::TimeStamp::Now();
   obj->as<GlobalObject>().realm()->lastAnimationTime = timeNow;
   obj->runtimeFromMainThread()->lastAnimationTime = timeNow;
 }
 
-JS_FRIEND_API bool js::IsObjectInContextCompartment(JSObject* obj,
+JS_PUBLIC_API bool js::IsObjectInContextCompartment(JSObject* obj,
                                                     const JSContext* cx) {
   return obj->compartment() == cx->compartment();
 }
 
-JS_FRIEND_API bool js::AutoCheckRecursionLimit::runningWithTrustedPrincipals(
+JS_PUBLIC_API bool js::AutoCheckRecursionLimit::runningWithTrustedPrincipals(
     JSContext* cx) const {
   return cx->runningWithTrustedPrincipals();
 }
 
-JS_FRIEND_API JSFunction* js::DefineFunctionWithReserved(
+JS_PUBLIC_API JSFunction* js::DefineFunctionWithReserved(
     JSContext* cx, JSObject* objArg, const char* name, JSNative call,
     unsigned nargs, unsigned attrs) {
   RootedObject obj(cx, objArg);
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
   CHECK_THREAD(cx);
   cx->check(obj);
   JSAtom* atom = Atomize(cx, name, strlen(name));
   if (!atom) {
     return nullptr;
   }
   Rooted<jsid> id(cx, AtomToId(atom));
   return DefineFunction(cx, obj, id, call, nargs, attrs,
                         gc::AllocKind::FUNCTION_EXTENDED);
 }
 
-JS_FRIEND_API JSFunction* js::NewFunctionWithReserved(JSContext* cx,
+JS_PUBLIC_API JSFunction* js::NewFunctionWithReserved(JSContext* cx,
                                                       JSNative native,
                                                       unsigned nargs,
                                                       unsigned flags,
                                                       const char* name) {
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
 
   CHECK_THREAD(cx);
 
@@ -379,68 +379,68 @@ JS_FRIEND_API JSFunction* js::NewFunctio
 
   return (flags & JSFUN_CONSTRUCTOR)
              ? NewNativeConstructor(cx, native, nargs, atom,
                                     gc::AllocKind::FUNCTION_EXTENDED)
              : NewNativeFunction(cx, native, nargs, atom,
                                  gc::AllocKind::FUNCTION_EXTENDED);
 }
 
-JS_FRIEND_API JSFunction* js::NewFunctionByIdWithReserved(
+JS_PUBLIC_API JSFunction* js::NewFunctionByIdWithReserved(
     JSContext* cx, JSNative native, unsigned nargs, unsigned flags, jsid id) {
   MOZ_ASSERT(JSID_IS_STRING(id));
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
   CHECK_THREAD(cx);
   cx->check(id);
 
   RootedAtom atom(cx, JSID_TO_ATOM(id));
   return (flags & JSFUN_CONSTRUCTOR)
              ? NewNativeConstructor(cx, native, nargs, atom,
                                     gc::AllocKind::FUNCTION_EXTENDED)
              : NewNativeFunction(cx, native, nargs, atom,
                                  gc::AllocKind::FUNCTION_EXTENDED);
 }
 
-JS_FRIEND_API const Value& js::GetFunctionNativeReserved(JSObject* fun,
+JS_PUBLIC_API const Value& js::GetFunctionNativeReserved(JSObject* fun,
                                                          size_t which) {
   MOZ_ASSERT(fun->as<JSFunction>().isNativeFun());
   return fun->as<JSFunction>().getExtendedSlot(which);
 }
 
-JS_FRIEND_API void js::SetFunctionNativeReserved(JSObject* fun, size_t which,
+JS_PUBLIC_API void js::SetFunctionNativeReserved(JSObject* fun, size_t which,
                                                  const Value& val) {
   MOZ_ASSERT(fun->as<JSFunction>().isNativeFun());
   MOZ_ASSERT_IF(val.isObject(),
                 val.toObject().compartment() == fun->compartment());
   fun->as<JSFunction>().setExtendedSlot(which, val);
 }
 
-JS_FRIEND_API bool js::FunctionHasNativeReserved(JSObject* fun) {
+JS_PUBLIC_API bool js::FunctionHasNativeReserved(JSObject* fun) {
   MOZ_ASSERT(fun->as<JSFunction>().isNativeFun());
   return fun->as<JSFunction>().isExtended();
 }
 
 bool js::GetObjectProto(JSContext* cx, JS::Handle<JSObject*> obj,
                         JS::MutableHandle<JSObject*> proto) {
   cx->check(obj);
 
   if (obj->is<ProxyObject>()) {
     return JS_GetPrototype(cx, obj, proto);
   }
 
   proto.set(obj->staticPrototype());
   return true;
 }
 
-JS_FRIEND_API JSObject* js::GetStaticPrototype(JSObject* obj) {
+JS_PUBLIC_API JSObject* js::GetStaticPrototype(JSObject* obj) {
   MOZ_ASSERT(obj->hasStaticPrototype());
   return obj->staticPrototype();
 }
 
-JS_FRIEND_API bool js::GetRealmOriginalEval(JSContext* cx,
+JS_PUBLIC_API bool js::GetRealmOriginalEval(JSContext* cx,
                                             MutableHandleObject eval) {
   return GlobalObject::getOrCreateEval(cx, cx->global(), eval);
 }
 
 void JS::detail::SetReservedSlotWithBarrier(JSObject* obj, size_t slot,
                                             const Value& value) {
   if (obj->is<ProxyObject>()) {
     obj->as<ProxyObject>().setReservedSlot(slot, value);
@@ -451,54 +451,54 @@ void JS::detail::SetReservedSlotWithBarr
 
 void js::SetPreserveWrapperCallbacks(
     JSContext* cx, PreserveWrapperCallback preserveWrapper,
     HasReleasedWrapperCallback hasReleasedWrapper) {
   cx->runtime()->preserveWrapperCallback = preserveWrapper;
   cx->runtime()->hasReleasedWrapperCallback = hasReleasedWrapper;
 }
 
-JS_FRIEND_API unsigned JS_PCToLineNumber(JSScript* script, jsbytecode* pc,
+JS_PUBLIC_API unsigned JS_PCToLineNumber(JSScript* script, jsbytecode* pc,
                                          unsigned* columnp) {
   return PCToLineNumber(script, pc, columnp);
 }
 
-JS_FRIEND_API bool JS_IsDeadWrapper(JSObject* obj) {
+JS_PUBLIC_API bool JS_IsDeadWrapper(JSObject* obj) {
   return IsDeadProxyObject(obj);
 }
 
-JS_FRIEND_API JSObject* JS_NewDeadWrapper(JSContext* cx, JSObject* origObj) {
+JS_PUBLIC_API JSObject* JS_NewDeadWrapper(JSContext* cx, JSObject* origObj) {
   return NewDeadProxyObject(cx, origObj);
 }
 
 void js::TraceWeakMaps(WeakMapTracer* trc) {
   WeakMapBase::traceAllMappings(trc);
 }
 
-extern JS_FRIEND_API bool js::AreGCGrayBitsValid(JSRuntime* rt) {
+extern JS_PUBLIC_API bool js::AreGCGrayBitsValid(JSRuntime* rt) {
   return rt->gc.areGrayBitsValid();
 }
 
-JS_FRIEND_API bool js::ZoneGlobalsAreAllGray(JS::Zone* zone) {
+JS_PUBLIC_API bool js::ZoneGlobalsAreAllGray(JS::Zone* zone) {
   for (RealmsInZoneIter realm(zone); !realm.done(); realm.next()) {
     JSObject* obj = realm->unsafeUnbarrieredMaybeGlobal();
     if (!obj || !JS::ObjectIsMarkedGray(obj)) {
       return false;
     }
   }
   return true;
 }
 
-JS_FRIEND_API bool js::IsCompartmentZoneSweepingOrCompacting(
+JS_PUBLIC_API bool js::IsCompartmentZoneSweepingOrCompacting(
     JS::Compartment* comp) {
   MOZ_ASSERT(comp);
   return comp->zone()->isGCSweepingOrCompacting();
 }
 
-JS_FRIEND_API void js::TraceGrayWrapperTargets(JSTracer* trc, Zone* zone) {
+JS_PUBLIC_API void js::TraceGrayWrapperTargets(JSTracer* trc, Zone* zone) {
   JS::AutoSuppressGCAnalysis nogc;
 
   for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
     for (Compartment::ObjectWrapperEnum e(comp); !e.empty(); e.popFront()) {
       JSObject* target = e.front().key();
       if (target->isMarkedGray()) {
         TraceManuallyBarrieredEdge(trc, &target, "gray CCW target");
         MOZ_ASSERT(target == e.front().key());
@@ -536,17 +536,17 @@ static bool CopyProxyObject(JSContext* c
       return false;
     }
     SetProxyReservedSlot(to, n, v);
   }
 
   return true;
 }
 
-JS_FRIEND_API JSObject* JS_CloneObject(JSContext* cx, HandleObject obj,
+JS_PUBLIC_API JSObject* JS_CloneObject(JSContext* cx, HandleObject obj,
                                        HandleObject proto) {
   // |obj| might be in a different compartment.
   cx->check(proto);
 
   if (!obj->is<NativeObject>() && !obj->is<ProxyObject>()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_CANT_CLONE_OBJECT);
     return nullptr;
@@ -592,17 +592,17 @@ JS_FRIEND_API JSObject* JS_CloneObject(J
     if (!CopyProxyObject(cx, obj.as<ProxyObject>(), clone.as<ProxyObject>())) {
       return nullptr;
     }
   }
 
   return clone;
 }
 
-extern JS_FRIEND_API bool JS::ForceLexicalInitialization(JSContext* cx,
+extern JS_PUBLIC_API bool JS::ForceLexicalInitialization(JSContext* cx,
                                                          HandleObject obj) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(obj);
 
   bool initializedAny = false;
   NativeObject* nobj = &obj->as<NativeObject>();
 
@@ -612,39 +612,39 @@ extern JS_FRIEND_API bool JS::ForceLexic
         v.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
       nobj->setSlot(iter->slot(), UndefinedValue());
       initializedAny = true;
     }
   }
   return initializedAny;
 }
 
-extern JS_FRIEND_API int JS::IsGCPoisoning() {
+extern JS_PUBLIC_API int JS::IsGCPoisoning() {
 #ifdef JS_GC_ALLOW_EXTRA_POISONING
   return js::gExtraPoisoningEnabled;
 #else
   return false;
 #endif
 }
 
-JS_FRIEND_API void JS::NotifyGCRootsRemoved(JSContext* cx) {
+JS_PUBLIC_API void JS::NotifyGCRootsRemoved(JSContext* cx) {
   cx->runtime()->gc.notifyRootsRemoved();
 }
 
-JS_FRIEND_API JS::Realm* js::GetAnyRealmInZone(JS::Zone* zone) {
+JS_PUBLIC_API JS::Realm* js::GetAnyRealmInZone(JS::Zone* zone) {
   if (zone->isAtomsZone()) {
     return nullptr;
   }
 
   RealmsInZoneIter realm(zone);
   MOZ_ASSERT(!realm.done());
   return realm.get();
 }
 
-JS_FRIEND_API bool js::IsSharableCompartment(JS::Compartment* comp) {
+JS_PUBLIC_API bool js::IsSharableCompartment(JS::Compartment* comp) {
   // If this compartment has nuked outgoing wrappers (because all its globals
   // got nuked), we won't be able to create any useful CCWs out of it in the
   // future, and so we shouldn't use it for any new globals.
   if (comp->nukedOutgoingWrappers) {
     return false;
   }
 
   // If this compartment has no live globals, it might be in the middle of being
@@ -654,125 +654,125 @@ JS_FRIEND_API bool js::IsSharableCompart
   if (!CompartmentHasLiveGlobal(comp)) {
     return false;
   }
 
   // Good to go.
   return true;
 }
 
-JS_FRIEND_API JSObject* js::GetTestingFunctions(JSContext* cx) {
+JS_PUBLIC_API JSObject* js::GetTestingFunctions(JSContext* cx) {
   RootedObject obj(cx, JS_NewPlainObject(cx));
   if (!obj) {
     return nullptr;
   }
 
   if (!DefineTestingFunctions(cx, obj, false, false)) {
     return nullptr;
   }
 
   return obj;
 }
 
-JS_FRIEND_API void js::SetDOMCallbacks(JSContext* cx,
+JS_PUBLIC_API void js::SetDOMCallbacks(JSContext* cx,
                                        const DOMCallbacks* callbacks) {
   cx->runtime()->DOMcallbacks = callbacks;
 }
 
-JS_FRIEND_API const DOMCallbacks* js::GetDOMCallbacks(JSContext* cx) {
+JS_PUBLIC_API const DOMCallbacks* js::GetDOMCallbacks(JSContext* cx) {
   return cx->runtime()->DOMcallbacks;
 }
 
-JS_FRIEND_API void js::PrepareScriptEnvironmentAndInvoke(
+JS_PUBLIC_API void js::PrepareScriptEnvironmentAndInvoke(
     JSContext* cx, HandleObject global,
     ScriptEnvironmentPreparer::Closure& closure) {
   MOZ_ASSERT(!cx->isExceptionPending());
   MOZ_ASSERT(global->is<GlobalObject>());
 
   MOZ_RELEASE_ASSERT(
       cx->runtime()->scriptEnvironmentPreparer,
       "Embedding needs to set a scriptEnvironmentPreparer callback");
 
   cx->runtime()->scriptEnvironmentPreparer->invoke(global, closure);
 }
 
-JS_FRIEND_API void js::SetScriptEnvironmentPreparer(
+JS_PUBLIC_API void js::SetScriptEnvironmentPreparer(
     JSContext* cx, ScriptEnvironmentPreparer* preparer) {
   cx->runtime()->scriptEnvironmentPreparer = preparer;
 }
 
-JS_FRIEND_API void JS::SetCTypesActivityCallback(JSContext* cx,
+JS_PUBLIC_API void JS::SetCTypesActivityCallback(JSContext* cx,
                                                  CTypesActivityCallback cb) {
   cx->runtime()->ctypesActivityCallback = cb;
 }
 
 JS::AutoCTypesActivityCallback::AutoCTypesActivityCallback(
     JSContext* cx, CTypesActivityType beginType, CTypesActivityType endType)
     : cx(cx),
       callback(cx->runtime()->ctypesActivityCallback),
       endType(endType) {
   if (callback) {
     callback(cx, beginType);
   }
 }
 
-JS_FRIEND_API void js::SetAllocationMetadataBuilder(
+JS_PUBLIC_API void js::SetAllocationMetadataBuilder(
     JSContext* cx, const AllocationMetadataBuilder* callback) {
   cx->realm()->setAllocationMetadataBuilder(callback);
 }
 
-JS_FRIEND_API JSObject* js::GetAllocationMetadata(JSObject* obj) {
+JS_PUBLIC_API JSObject* js::GetAllocationMetadata(JSObject* obj) {
   ObjectWeakMap* map = ObjectRealm::get(obj).objectMetadataTable.get();
   if (map) {
     return map->lookup(obj);
   }
   return nullptr;
 }
 
-JS_FRIEND_API bool js::ReportIsNotFunction(JSContext* cx, HandleValue v) {
+JS_PUBLIC_API bool js::ReportIsNotFunction(JSContext* cx, HandleValue v) {
   cx->check(v);
   return ReportIsNotFunction(cx, v, -1);
 }
 
 #ifdef DEBUG
 bool js::HasObjectMovedOp(JSObject* obj) {
   return !!JS::GetClass(obj)->extObjectMovedOp();
 }
 #endif
 
-JS_FRIEND_API bool js::ForwardToNative(JSContext* cx, JSNative native,
+JS_PUBLIC_API bool js::ForwardToNative(JSContext* cx, JSNative native,
                                        const CallArgs& args) {
   return native(cx, args.length(), args.base());
 }
 
 AutoAssertNoContentJS::AutoAssertNoContentJS(JSContext* cx)
     : context_(cx), prevAllowContentJS_(cx->runtime()->allowContentJS_) {
   cx->runtime()->allowContentJS_ = false;
 }
 
 AutoAssertNoContentJS::~AutoAssertNoContentJS() {
   context_->runtime()->allowContentJS_ = prevAllowContentJS_;
 }
 
-JS_FRIEND_API void js::EnableCodeCoverage() { js::coverage::EnableLCov(); }
+JS_PUBLIC_API void js::EnableCodeCoverage() { js::coverage::EnableLCov(); }
 
-JS_FRIEND_API JS::Value js::MaybeGetScriptPrivate(JSObject* object) {
+JS_PUBLIC_API JS::Value js::MaybeGetScriptPrivate(JSObject* object) {
   if (!object->is<ScriptSourceObject>()) {
     return UndefinedValue();
   }
 
   return object->as<ScriptSourceObject>().canonicalPrivate();
 }
 
-JS_FRIEND_API uint64_t js::GetGCHeapUsageForObjectZone(JSObject* obj) {
+JS_PUBLIC_API uint64_t js::GetGCHeapUsageForObjectZone(JSObject* obj) {
   return obj->zone()->gcHeapSize.bytes();
 }
 
 #ifdef DEBUG
-JS_FRIEND_API bool js::RuntimeIsBeingDestroyed() {
+JS_PUBLIC_API bool js::RuntimeIsBeingDestroyed() {
   JSRuntime* runtime = TlsContext.get()->runtime();
   MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(runtime));
   return runtime->isBeingDestroyed();
 }
 #endif
 
 // No-op implementations of public API that would depend on --with-intl-api
 
@@ -789,11 +789,11 @@ bool JS::AddMozDateTimeFormatConstructor
 }
 
 bool JS::AddMozDisplayNamesConstructor(JSContext* cx, JS::HandleObject intl) {
   return IntlNotEnabled(cx);
 }
 
 #endif  // !JS_HAS_INTL_API
 
-JS_FRIEND_API JS::Zone* js::GetObjectZoneFromAnyThread(const JSObject* obj) {
+JS_PUBLIC_API JS::Zone* js::GetObjectZoneFromAnyThread(const JSObject* obj) {
   return MaybeForwarded(obj)->zoneFromAnyThread();
 }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -30,163 +30,163 @@ class JSJitInfo;
 
 namespace JS {
 template <class T>
 class Heap;
 
 class ExceptionStack;
 } /* namespace JS */
 
-extern JS_FRIEND_API void JS_SetGrayGCRootsTracer(JSContext* cx,
+extern JS_PUBLIC_API void JS_SetGrayGCRootsTracer(JSContext* cx,
                                                   JSTraceDataOp traceOp,
                                                   void* data);
 
-extern JS_FRIEND_API JSObject* JS_FindCompilationScope(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_FindCompilationScope(JSContext* cx,
                                                        JS::HandleObject obj);
 
-extern JS_FRIEND_API JSFunction* JS_GetObjectFunction(JSObject* obj);
+extern JS_PUBLIC_API JSFunction* JS_GetObjectFunction(JSObject* obj);
 
 /**
  * Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
  * without invoking the metadata callback on it.  This allows creation of
  * internal bookkeeping objects that are guaranteed to not have metadata
  * attached to them.
  */
-extern JS_FRIEND_API JSObject* JS_NewObjectWithoutMetadata(
+extern JS_PUBLIC_API JSObject* JS_NewObjectWithoutMetadata(
     JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
 
-extern JS_FRIEND_API bool JS_NondeterministicGetWeakMapKeys(
+extern JS_PUBLIC_API bool JS_NondeterministicGetWeakMapKeys(
     JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
 
-extern JS_FRIEND_API bool JS_NondeterministicGetWeakSetKeys(
+extern JS_PUBLIC_API bool JS_NondeterministicGetWeakSetKeys(
     JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
 
 // Raw JSScript* because this needs to be callable from a signal handler.
-extern JS_FRIEND_API unsigned JS_PCToLineNumber(JSScript* script,
+extern JS_PUBLIC_API unsigned JS_PCToLineNumber(JSScript* script,
                                                 jsbytecode* pc,
                                                 unsigned* columnp = nullptr);
 
 /**
  * Determine whether the given object is backed by a DeadObjectProxy.
  *
  * Such objects hold no other objects (they have no outgoing reference edges)
  * and will throw if you touch them (e.g. by reading/writing a property).
  */
-extern JS_FRIEND_API bool JS_IsDeadWrapper(JSObject* obj);
+extern JS_PUBLIC_API bool JS_IsDeadWrapper(JSObject* obj);
 
 /**
  * Creates a new dead wrapper object in the given scope. To be used when
  * attempting to wrap objects from scopes which are already dead.
  *
  * If origObject is passed, it must be an proxy object, and will be
  * used to determine the characteristics of the new dead wrapper.
  */
-extern JS_FRIEND_API JSObject* JS_NewDeadWrapper(
+extern JS_PUBLIC_API JSObject* JS_NewDeadWrapper(
     JSContext* cx, JSObject* origObject = nullptr);
 
 namespace js {
 
 /**
  * Get the script private value associated with an object, if any.
  *
  * The private value is set with SetScriptPrivate() or SetModulePrivate() and is
  * internally stored on the relevant ScriptSourceObject.
  *
  * This is used by the cycle collector to trace through
  * ScriptSourceObjects. This allows private values to contain an nsISupports
  * pointer and hence support references to cycle collected C++ objects.
  */
-JS_FRIEND_API JS::Value MaybeGetScriptPrivate(JSObject* object);
+JS_PUBLIC_API JS::Value MaybeGetScriptPrivate(JSObject* object);
 
 }  // namespace js
 
 /*
  * Used by the cycle collector to trace through a shape or object group and
  * all cycle-participating data it reaches, using bounded stack space.
  */
-extern JS_FRIEND_API void JS_TraceShapeCycleCollectorChildren(
+extern JS_PUBLIC_API void JS_TraceShapeCycleCollectorChildren(
     JS::CallbackTracer* trc, JS::GCCellPtr shape);
-extern JS_FRIEND_API void JS_TraceObjectGroupCycleCollectorChildren(
+extern JS_PUBLIC_API void JS_TraceObjectGroupCycleCollectorChildren(
     JS::CallbackTracer* trc, JS::GCCellPtr group);
 
-extern JS_FRIEND_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script);
+extern JS_PUBLIC_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script);
 
-extern JS_FRIEND_API bool JS_ScriptHasMutedErrors(JSScript* script);
+extern JS_PUBLIC_API bool JS_ScriptHasMutedErrors(JSScript* script);
 
-extern JS_FRIEND_API JSObject* JS_CloneObject(JSContext* cx,
+extern JS_PUBLIC_API JSObject* JS_CloneObject(JSContext* cx,
                                               JS::HandleObject obj,
                                               JS::HandleObject proto);
 
 /**
  * Copy the own properties of src to dst in a fast way.  src and dst must both
  * be native and must be in the compartment of cx.  They must have the same
  * class, the same parent, and the same prototype.  Class reserved slots will
  * NOT be copied.
  *
  * dst must not have any properties on it before this function is called.
  *
  * src must have been allocated via JS_NewObjectWithoutMetadata so that we can
  * be sure it has no metadata that needs copying to dst.  This also means that
  * dst needs to have the compartment global as its parent.  This function will
  * preserve the existing metadata on dst, if any.
  */
-extern JS_FRIEND_API bool JS_InitializePropertiesFromCompatibleNativeObject(
+extern JS_PUBLIC_API bool JS_InitializePropertiesFromCompatibleNativeObject(
     JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
 
 namespace js {
 
-JS_FRIEND_API bool IsArgumentsObject(JS::HandleObject obj);
+JS_PUBLIC_API bool IsArgumentsObject(JS::HandleObject obj);
 
-JS_FRIEND_API bool AddRawValueRoot(JSContext* cx, JS::Value* vp,
+JS_PUBLIC_API bool AddRawValueRoot(JSContext* cx, JS::Value* vp,
                                    const char* name);
 
-JS_FRIEND_API void RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
+JS_PUBLIC_API void RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
 
 }  // namespace js
 
 namespace JS {
 
 /**
  * Set all of the uninitialized lexicals on an object to undefined. Return
  * true if any lexicals were initialized and false otherwise.
  * */
-extern JS_FRIEND_API bool ForceLexicalInitialization(JSContext* cx,
+extern JS_PUBLIC_API bool ForceLexicalInitialization(JSContext* cx,
                                                      HandleObject obj);
 
 /**
  * Whether we are poisoning unused/released data for error detection. Governed
  * by the JS_GC_ALLOW_EXTRA_POISONING #ifdef as well as the
  * $JSGC_EXTRA_POISONING environment variable.
  */
-extern JS_FRIEND_API int IsGCPoisoning();
+extern JS_PUBLIC_API int IsGCPoisoning();
 
-extern JS_FRIEND_API JSPrincipals* GetRealmPrincipals(JS::Realm* realm);
+extern JS_PUBLIC_API JSPrincipals* GetRealmPrincipals(JS::Realm* realm);
 
-extern JS_FRIEND_API void SetRealmPrincipals(JS::Realm* realm,
+extern JS_PUBLIC_API void SetRealmPrincipals(JS::Realm* realm,
                                              JSPrincipals* principals);
 
-extern JS_FRIEND_API bool GetIsSecureContext(JS::Realm* realm);
+extern JS_PUBLIC_API bool GetIsSecureContext(JS::Realm* realm);
 
 }  // namespace JS
 
 /**
  * Copies all own properties and private fields from |obj| to |target|. Both
  * |obj| and |target| must not be cross-compartment wrappers because we have to
  * enter their realms.
  *
  * This function immediately enters a realm, and does not impose any
  * restrictions on the realm of |cx|.
  */
-extern JS_FRIEND_API bool JS_CopyOwnPropertiesAndPrivateFields(
+extern JS_PUBLIC_API bool JS_CopyOwnPropertiesAndPrivateFields(
     JSContext* cx, JS::HandleObject target, JS::HandleObject obj);
 
-extern JS_FRIEND_API bool JS_WrapPropertyDescriptor(
+extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
     JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
 
-extern JS_FRIEND_API bool JS_WrapPropertyDescriptor(
+extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
     JSContext* cx,
     JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc);
 
 struct JSFunctionSpecWithHelp {
   const char* name;
   JSNative call;
   uint16_t nargs;
   uint16_t flags;
@@ -200,131 +200,131 @@ struct JSFunctionSpecWithHelp {
 #define JS_INLINABLE_FN_HELP(name, call, nargs, flags, native, usage, help)    \
   {                                                                            \
     name, call, nargs, (flags) | JSPROP_ENUMERATE, &js::jit::JitInfo_##native, \
         usage, help                                                            \
   }
 #define JS_FS_HELP_END \
   { nullptr, nullptr, 0, 0, nullptr, nullptr }
 
-extern JS_FRIEND_API bool JS_DefineFunctionsWithHelp(
+extern JS_PUBLIC_API bool JS_DefineFunctionsWithHelp(
     JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs);
 
 namespace js {
 
 /**
  * Use the runtime's internal handling of job queues for Promise jobs.
  *
  * Most embeddings, notably web browsers, will have their own task scheduling
  * systems and need to integrate handling of Promise jobs into that, so they
  * will want to manage job queues themselves. For basic embeddings such as the
  * JS shell that don't have an event loop of their own, it's easier to have
  * SpiderMonkey handle job queues internally.
  *
  * Note that the embedding still has to trigger processing of job queues at
  * right time(s), such as after evaluation of a script has run to completion.
  */
-extern JS_FRIEND_API bool UseInternalJobQueues(JSContext* cx);
+extern JS_PUBLIC_API bool UseInternalJobQueues(JSContext* cx);
 
 /**
  * Enqueue |job| on the internal job queue.
  *
  * This is useful in tests for creating situations where a call occurs with no
  * other JavaScript on the stack.
  */
-extern JS_FRIEND_API bool EnqueueJob(JSContext* cx, JS::HandleObject job);
+extern JS_PUBLIC_API bool EnqueueJob(JSContext* cx, JS::HandleObject job);
 
 /**
  * Instruct the runtime to stop draining the internal job queue.
  *
  * Useful if the embedding is in the process of quitting in reaction to a
  * builtin being called, or if it wants to resume executing jobs later on.
  */
-extern JS_FRIEND_API void StopDrainingJobQueue(JSContext* cx);
+extern JS_PUBLIC_API void StopDrainingJobQueue(JSContext* cx);
 
-extern JS_FRIEND_API void RunJobs(JSContext* cx);
+extern JS_PUBLIC_API void RunJobs(JSContext* cx);
 
-extern JS_FRIEND_API JS::Zone* GetRealmZone(JS::Realm* realm);
+extern JS_PUBLIC_API JS::Zone* GetRealmZone(JS::Realm* realm);
 
 using PreserveWrapperCallback = bool (*)(JSContext*, JS::HandleObject);
 using HasReleasedWrapperCallback = bool (*)(JS::HandleObject);
 
-extern JS_FRIEND_API bool IsSystemRealm(JS::Realm* realm);
+extern JS_PUBLIC_API bool IsSystemRealm(JS::Realm* realm);
 
-extern JS_FRIEND_API bool IsSystemCompartment(JS::Compartment* comp);
+extern JS_PUBLIC_API bool IsSystemCompartment(JS::Compartment* comp);
 
-extern JS_FRIEND_API bool IsSystemZone(JS::Zone* zone);
+extern JS_PUBLIC_API bool IsSystemZone(JS::Zone* zone);
 
 struct WeakMapTracer {
   JSRuntime* runtime;
 
   explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
 
   // Weak map tracer callback, called once for every binding of every
   // weak map that was live at the time of the last garbage collection.
   //
   // m will be nullptr if the weak map is not contained in a JS Object.
   //
   // The callback should not GC (and will assert in a debug build if it does
   // so.)
   virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0;
 };
 
-extern JS_FRIEND_API void TraceWeakMaps(WeakMapTracer* trc);
+extern JS_PUBLIC_API void TraceWeakMaps(WeakMapTracer* trc);
 
-extern JS_FRIEND_API bool AreGCGrayBitsValid(JSRuntime* rt);
+extern JS_PUBLIC_API bool AreGCGrayBitsValid(JSRuntime* rt);
 
-extern JS_FRIEND_API bool ZoneGlobalsAreAllGray(JS::Zone* zone);
+extern JS_PUBLIC_API bool ZoneGlobalsAreAllGray(JS::Zone* zone);
 
-extern JS_FRIEND_API bool IsCompartmentZoneSweepingOrCompacting(
+extern JS_PUBLIC_API bool IsCompartmentZoneSweepingOrCompacting(
     JS::Compartment* comp);
 
 using IterateGCThingCallback = void (*)(void*, JS::GCCellPtr,
                                         const JS::AutoRequireNoGC&);
 
-extern JS_FRIEND_API void TraceGrayWrapperTargets(JSTracer* trc,
+extern JS_PUBLIC_API void TraceGrayWrapperTargets(JSTracer* trc,
                                                   JS::Zone* zone);
 
 /**
  * Invoke cellCallback on every gray JSObject in the given zone.
  */
-extern JS_FRIEND_API void IterateGrayObjects(
+extern JS_PUBLIC_API void IterateGrayObjects(
     JS::Zone* zone, IterateGCThingCallback cellCallback, void* data);
 
 #if defined(JS_GC_ZEAL) || defined(DEBUG)
 // Trace the heap and check there are no black to gray edges. These are
 // not allowed since the cycle collector could throw away the gray thing and
 // leave a dangling pointer.
 //
 // This doesn't trace weak maps as these are handled separately.
-extern JS_FRIEND_API bool CheckGrayMarkingState(JSRuntime* rt);
+extern JS_PUBLIC_API bool CheckGrayMarkingState(JSRuntime* rt);
 #endif
 
 // Note: this returns nullptr iff |zone| is the atoms zone.
-extern JS_FRIEND_API JS::Realm* GetAnyRealmInZone(JS::Zone* zone);
+extern JS_PUBLIC_API JS::Realm* GetAnyRealmInZone(JS::Zone* zone);
 
 // Returns the first realm's global in a compartment. Note: this is not
 // guaranteed to always be the same realm because individual realms can be
 // collected by the GC.
-extern JS_FRIEND_API JSObject* GetFirstGlobalInCompartment(
+extern JS_PUBLIC_API JSObject* GetFirstGlobalInCompartment(
     JS::Compartment* comp);
 
 // Returns true if the compartment contains a global object and this global is
 // not being collected.
-extern JS_FRIEND_API bool CompartmentHasLiveGlobal(JS::Compartment* comp);
+extern JS_PUBLIC_API bool CompartmentHasLiveGlobal(JS::Compartment* comp);
 
 // Returns true if this compartment can be shared across multiple Realms.  Used
 // when we're looking for an existing compartment to place a new Realm in.
-extern JS_FRIEND_API bool IsSharableCompartment(JS::Compartment* comp);
+extern JS_PUBLIC_API bool IsSharableCompartment(JS::Compartment* comp);
 
 // This is equal to |&JSObject::class_|.  Use it in places where you don't want
 // to #include vm/JSObject.h.
-extern JS_FRIEND_DATA const JSClass* const ObjectClassPtr;
+extern JS_PUBLIC_DATA const JSClass* const ObjectClassPtr;
 
-JS_FRIEND_API const JSClass* ProtoKeyToClass(JSProtoKey key);
+JS_PUBLIC_API const JSClass* ProtoKeyToClass(JSProtoKey key);
 
 // Returns the key for the class inherited by a given standard class (that
 // is to say, the prototype of this standard class's prototype).
 //
 // You must be sure that this corresponds to a standard class with a cached
 // JSProtoKey before calling this function. In general |key| will match the
 // cached proto key, except in cases where multiple JSProtoKeys share a
 // JSClass.
@@ -338,70 +338,70 @@ inline JSProtoKey InheritanceProtoKeyFor
   if (ProtoKeyToClass(key)->specDefined()) {
     return ProtoKeyToClass(key)->specInheritanceProtoKey();
   }
 
   // Otherwise, we inherit [Object].
   return JSProto_Object;
 }
 
-JS_FRIEND_API bool ShouldIgnorePropertyDefinition(JSContext* cx, JSProtoKey key,
+JS_PUBLIC_API bool ShouldIgnorePropertyDefinition(JSContext* cx, JSProtoKey key,
                                                   jsid id);
 
-JS_FRIEND_API bool IsFunctionObject(JSObject* obj);
+JS_PUBLIC_API bool IsFunctionObject(JSObject* obj);
 
-JS_FRIEND_API bool UninlinedIsCrossCompartmentWrapper(const JSObject* obj);
+JS_PUBLIC_API bool UninlinedIsCrossCompartmentWrapper(const JSObject* obj);
 
 // CrossCompartmentWrappers are shared by all realms within the compartment, so
 // getting a wrapper's realm usually doesn't make sense.
 static MOZ_ALWAYS_INLINE JS::Realm* GetNonCCWObjectRealm(JSObject* obj) {
   MOZ_ASSERT(!js::UninlinedIsCrossCompartmentWrapper(obj));
   return reinterpret_cast<JS::shadow::Object*>(obj)->shape->base->realm;
 }
 
-JS_FRIEND_API void AssertSameCompartment(JSContext* cx, JSObject* obj);
+JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JSObject* obj);
 
-JS_FRIEND_API void AssertSameCompartment(JSContext* cx, JS::HandleValue v);
+JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JS::HandleValue v);
 
 #ifdef JS_DEBUG
-JS_FRIEND_API void AssertSameCompartment(JSObject* objA, JSObject* objB);
+JS_PUBLIC_API void AssertSameCompartment(JSObject* objA, JSObject* objB);
 #else
 inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
 #endif
 
-JS_FRIEND_API void NotifyAnimationActivity(JSObject* obj);
+JS_PUBLIC_API void NotifyAnimationActivity(JSObject* obj);
 
-JS_FRIEND_API JSFunction* DefineFunctionWithReserved(
+JS_PUBLIC_API JSFunction* DefineFunctionWithReserved(
     JSContext* cx, JSObject* obj, const char* name, JSNative call,
     unsigned nargs, unsigned attrs);
 
-JS_FRIEND_API JSFunction* NewFunctionWithReserved(JSContext* cx, JSNative call,
+JS_PUBLIC_API JSFunction* NewFunctionWithReserved(JSContext* cx, JSNative call,
                                                   unsigned nargs,
                                                   unsigned flags,
                                                   const char* name);
 
-JS_FRIEND_API JSFunction* NewFunctionByIdWithReserved(JSContext* cx,
+JS_PUBLIC_API JSFunction* NewFunctionByIdWithReserved(JSContext* cx,
                                                       JSNative native,
                                                       unsigned nargs,
                                                       unsigned flags, jsid id);
 
-JS_FRIEND_API const JS::Value& GetFunctionNativeReserved(JSObject* fun,
+JS_PUBLIC_API const JS::Value& GetFunctionNativeReserved(JSObject* fun,
                                                          size_t which);
 
-JS_FRIEND_API void SetFunctionNativeReserved(JSObject* fun, size_t which,
+JS_PUBLIC_API void SetFunctionNativeReserved(JSObject* fun, size_t which,
                                              const JS::Value& val);
 
-JS_FRIEND_API bool FunctionHasNativeReserved(JSObject* fun);
+JS_PUBLIC_API bool FunctionHasNativeReserved(JSObject* fun);
 
-JS_FRIEND_API bool GetObjectProto(JSContext* cx, JS::HandleObject obj,
+JS_PUBLIC_API bool GetObjectProto(JSContext* cx, JS::HandleObject obj,
                                   JS::MutableHandleObject proto);
 
-extern JS_FRIEND_API JSObject* GetStaticPrototype(JSObject* obj);
+extern JS_PUBLIC_API JSObject* GetStaticPrototype(JSObject* obj);
 
-JS_FRIEND_API bool GetRealmOriginalEval(JSContext* cx,
+JS_PUBLIC_API bool GetRealmOriginalEval(JSContext* cx,
                                         JS::MutableHandleObject eval);
 
 /**
  * Add some or all property keys of obj to the id vector *props.
  *
  * The flags parameter controls which property keys are added. Pass a
  * combination of the following bits:
  *
@@ -415,92 +415,92 @@ JS_FRIEND_API bool GetRealmOriginalEval(
  *
  *     JSITER_SYMBOLSONLY - Exclude non-symbol property keys.
  *
  * This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or
  * equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass
  * `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get
  * results that match the output of Reflect.ownKeys.
  */
-JS_FRIEND_API bool GetPropertyKeys(JSContext* cx, JS::HandleObject obj,
+JS_PUBLIC_API bool GetPropertyKeys(JSContext* cx, JS::HandleObject obj,
                                    unsigned flags,
                                    JS::MutableHandleIdVector props);
 
-JS_FRIEND_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base,
+JS_PUBLIC_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base,
                                 JS::HandleIdVector others);
 
 /**
  * Determine whether the given string is an array index in the sense of
  * <https://tc39.github.io/ecma262/#array-index>.
  *
  * If it isn't, returns false.
  *
  * If it is, returns true and outputs the index in *indexp.
  */
-JS_FRIEND_API bool StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
+JS_PUBLIC_API bool StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
 
 /**
  * Overload of StringIsArrayIndex taking a (char16_t*,length) pair. Behaves
  * the same as the JSLinearString version.
  */
-JS_FRIEND_API bool StringIsArrayIndex(const char16_t* str, uint32_t length,
+JS_PUBLIC_API bool StringIsArrayIndex(const char16_t* str, uint32_t length,
                                       uint32_t* indexp);
 
-JS_FRIEND_API void SetPreserveWrapperCallbacks(
+JS_PUBLIC_API void SetPreserveWrapperCallbacks(
     JSContext* cx, PreserveWrapperCallback preserveWrapper,
     HasReleasedWrapperCallback hasReleasedWrapper);
 
-JS_FRIEND_API bool IsObjectInContextCompartment(JSObject* obj,
+JS_PUBLIC_API bool IsObjectInContextCompartment(JSObject* obj,
                                                 const JSContext* cx);
 
 /*
  * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
  */
 /* 0x1 is no longer used */
 /* 0x2 is no longer used */
 #define JSITER_PRIVATE 0x4      /* Include private names in iteration */
 #define JSITER_OWNONLY 0x8      /* iterate over obj's own properties only */
 #define JSITER_HIDDEN 0x10      /* also enumerate non-enumerable properties */
 #define JSITER_SYMBOLS 0x20     /* also include symbol property keys */
 #define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
 #define JSITER_FORAWAITOF 0x80  /* for-await-of */
 
-JS_FRIEND_API void StartPCCountProfiling(JSContext* cx);
+JS_PUBLIC_API void StartPCCountProfiling(JSContext* cx);
 
-JS_FRIEND_API void StopPCCountProfiling(JSContext* cx);
+JS_PUBLIC_API void StopPCCountProfiling(JSContext* cx);
 
-JS_FRIEND_API void PurgePCCounts(JSContext* cx);
+JS_PUBLIC_API void PurgePCCounts(JSContext* cx);
 
-JS_FRIEND_API size_t GetPCCountScriptCount(JSContext* cx);
+JS_PUBLIC_API size_t GetPCCountScriptCount(JSContext* cx);
 
-JS_FRIEND_API JSString* GetPCCountScriptSummary(JSContext* cx, size_t script);
+JS_PUBLIC_API JSString* GetPCCountScriptSummary(JSContext* cx, size_t script);
 
-JS_FRIEND_API JSString* GetPCCountScriptContents(JSContext* cx, size_t script);
+JS_PUBLIC_API JSString* GetPCCountScriptContents(JSContext* cx, size_t script);
 
 using DOMInstanceClassHasProtoAtDepth = bool (*)(const JSClass*, uint32_t,
                                                  uint32_t);
 struct JSDOMCallbacks {
   DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto;
 };
 using DOMCallbacks = struct JSDOMCallbacks;
 
-extern JS_FRIEND_API void SetDOMCallbacks(JSContext* cx,
+extern JS_PUBLIC_API void SetDOMCallbacks(JSContext* cx,
                                           const DOMCallbacks* callbacks);
 
-extern JS_FRIEND_API const DOMCallbacks* GetDOMCallbacks(JSContext* cx);
+extern JS_PUBLIC_API const DOMCallbacks* GetDOMCallbacks(JSContext* cx);
 
-extern JS_FRIEND_API JSObject* GetTestingFunctions(JSContext* cx);
+extern JS_PUBLIC_API JSObject* GetTestingFunctions(JSContext* cx);
 
 /* Implemented in jsexn.cpp. */
 
 /**
  * Get an error type name from a JSExnType constant.
  * Returns nullptr for invalid arguments and JSEXN_INTERNALERR
  */
-extern JS_FRIEND_API JSLinearString* GetErrorTypeName(JSContext* cx,
+extern JS_PUBLIC_API JSLinearString* GetErrorTypeName(JSContext* cx,
                                                       int16_t exnType);
 
 /* Implemented in CrossCompartmentWrapper.cpp. */
 typedef enum NukeReferencesToWindow {
   NukeWindowReferences,
   DontNukeWindowReferences
 } NukeReferencesToWindow;
 
@@ -522,42 +522,42 @@ struct AllCompartments : public Compartm
 };
 
 struct SingleCompartment : public CompartmentFilter {
   JS::Compartment* ours;
   explicit SingleCompartment(JS::Compartment* c) : ours(c) {}
   virtual bool match(JS::Compartment* c) const override { return c == ours; }
 };
 
-extern JS_FRIEND_API bool NukeCrossCompartmentWrappers(
+extern JS_PUBLIC_API bool NukeCrossCompartmentWrappers(
     JSContext* cx, const CompartmentFilter& sourceFilter, JS::Realm* target,
     NukeReferencesToWindow nukeReferencesToWindow,
     NukeReferencesFromTarget nukeReferencesFromTarget);
 
-extern JS_FRIEND_API bool AllowNewWrapper(JS::Compartment* target,
+extern JS_PUBLIC_API bool AllowNewWrapper(JS::Compartment* target,
                                           JSObject* obj);
 
-extern JS_FRIEND_API bool NukedObjectRealm(JSObject* obj);
+extern JS_PUBLIC_API bool NukedObjectRealm(JSObject* obj);
 
 /* Implemented in jsdate.cpp. */
 
 /** Detect whether the internal date value is NaN. */
-extern JS_FRIEND_API bool DateIsValid(JSContext* cx, JS::HandleObject obj,
+extern JS_PUBLIC_API bool DateIsValid(JSContext* cx, JS::HandleObject obj,
                                       bool* isValid);
 
-extern JS_FRIEND_API bool DateGetMsecSinceEpoch(JSContext* cx,
+extern JS_PUBLIC_API bool DateGetMsecSinceEpoch(JSContext* cx,
                                                 JS::HandleObject obj,
                                                 double* msecSinceEpoch);
 
 } /* namespace js */
 
 namespace js {
 
 /* Implemented in vm/StructuredClone.cpp. */
-extern JS_FRIEND_API uint64_t GetSCOffset(JSStructuredCloneWriter* writer);
+extern JS_PUBLIC_API uint64_t GetSCOffset(JSStructuredCloneWriter* writer);
 
 }  // namespace js
 
 namespace js {
 
 /* Statically asserted in FunctionFlags.cpp. */
 static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x0060;
 
@@ -625,21 +625,21 @@ static MOZ_ALWAYS_INLINE JS::Value IdToV
 struct ScriptEnvironmentPreparer {
   struct Closure {
     virtual bool operator()(JSContext* cx) = 0;
   };
 
   virtual void invoke(JS::HandleObject global, Closure& closure) = 0;
 };
 
-extern JS_FRIEND_API void PrepareScriptEnvironmentAndInvoke(
+extern JS_PUBLIC_API void PrepareScriptEnvironmentAndInvoke(
     JSContext* cx, JS::HandleObject global,
     ScriptEnvironmentPreparer::Closure& closure);
 
-JS_FRIEND_API void SetScriptEnvironmentPreparer(
+JS_PUBLIC_API void SetScriptEnvironmentPreparer(
     JSContext* cx, ScriptEnvironmentPreparer* preparer);
 
 // Abstract base class for objects that build allocation metadata for JavaScript
 // values.
 struct AllocationMetadataBuilder {
   AllocationMetadataBuilder() = default;
 
   // Return a metadata object for the newly constructed object |obj|, or
@@ -654,28 +654,28 @@ struct AllocationMetadataBuilder {
   }
 };
 
 /**
  * Specify a callback to invoke when creating each JS object in the current
  * compartment, which may return a metadata object to associate with the
  * object.
  */
-JS_FRIEND_API void SetAllocationMetadataBuilder(
+JS_PUBLIC_API void SetAllocationMetadataBuilder(
     JSContext* cx, const AllocationMetadataBuilder* callback);
 
 /** Get the metadata associated with an object. */
-JS_FRIEND_API JSObject* GetAllocationMetadata(JSObject* obj);
+JS_PUBLIC_API JSObject* GetAllocationMetadata(JSObject* obj);
 
-JS_FRIEND_API bool GetElementsWithAdder(JSContext* cx, JS::HandleObject obj,
+JS_PUBLIC_API bool GetElementsWithAdder(JSContext* cx, JS::HandleObject obj,
                                         JS::HandleObject receiver,
                                         uint32_t begin, uint32_t end,
                                         js::ElementAdder* adder);
 
-JS_FRIEND_API bool ForwardToNative(JSContext* cx, JSNative native,
+JS_PUBLIC_API bool ForwardToNative(JSContext* cx, JSNative native,
                                    const JS::CallArgs& args);
 
 /**
  * Helper function for HTMLDocument and HTMLFormElement.
  *
  * These are the only two interfaces that have [OverrideBuiltins], a named
  * getter, and no named setter. They're implemented as proxies with a custom
  * getOwnPropertyDescriptor() method. Unfortunately, overriding
@@ -688,29 +688,29 @@ JS_FRIEND_API bool ForwardToNative(JSCon
  *
  * SetPropertyIgnoringNamedGetter is exposed to make it easier to override
  * set() in this way.  It carries out all the steps of BaseProxyHandler::set()
  * except the initial getOwnPropertyDescriptor() call.  The caller must supply
  * that descriptor as the 'ownDesc' parameter.
  *
  * Implemented in proxy/BaseProxyHandler.cpp.
  */
-JS_FRIEND_API bool SetPropertyIgnoringNamedGetter(
+JS_PUBLIC_API bool SetPropertyIgnoringNamedGetter(
     JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
     JS::HandleValue receiver,
     JS::Handle<mozilla::Maybe<JS::PropertyDescriptor>> ownDesc,
     JS::ObjectOpResult& result);
 
 // This function is for one specific use case, please don't use this for
 // anything else!
-extern JS_FRIEND_API bool ExecuteInFrameScriptEnvironment(
+extern JS_PUBLIC_API bool ExecuteInFrameScriptEnvironment(
     JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
     JS::MutableHandleObject scope);
 
-extern JS_FRIEND_API bool IsSavedFrame(JSObject* obj);
+extern JS_PUBLIC_API bool IsSavedFrame(JSObject* obj);
 
 // Matches the condition in js/src/jit/ProcessExecutableMemory.cpp
 #if defined(XP_WIN)
 // Parameters use void* types to avoid #including windows.h. The return value of
 // this function is returned from the exception handler.
 typedef long (*JitExceptionHandler)(void* exceptionRecord,  // PEXECTION_RECORD
                                     void* context);         // PCONTEXT
 
@@ -728,50 +728,50 @@ typedef long (*JitExceptionHandler)(void
  * a handler for all JIT code that simply calls breakpad's unhandled exception
  * filter (which will perform crash reporting and then terminate the process).
  * This would be wrong if there was an outer __try block that expected to handle
  * the fault, but this is not generally allowed.
  *
  * Gecko must call SetJitExceptionFilter before any JIT code is compiled and
  * only once per process.
  */
-extern JS_FRIEND_API void SetJitExceptionHandler(JitExceptionHandler handler);
+extern JS_PUBLIC_API void SetJitExceptionHandler(JitExceptionHandler handler);
 #endif
 
-extern JS_FRIEND_API bool ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
+extern JS_PUBLIC_API bool ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
 
-class MOZ_STACK_CLASS JS_FRIEND_API AutoAssertNoContentJS {
+class MOZ_STACK_CLASS JS_PUBLIC_API AutoAssertNoContentJS {
  public:
   explicit AutoAssertNoContentJS(JSContext* cx);
   ~AutoAssertNoContentJS();
 
  private:
   JSContext* context_;
   bool prevAllowContentJS_;
 };
 
 /**
  * This function only reports GC heap memory,
  * and not malloc allocated memory associated with GC things.
  */
-extern JS_FRIEND_API uint64_t GetGCHeapUsageForObjectZone(JSObject* obj);
+extern JS_PUBLIC_API uint64_t GetGCHeapUsageForObjectZone(JSObject* obj);
 
-class JS_FRIEND_API CompartmentTransplantCallback {
+class JS_PUBLIC_API CompartmentTransplantCallback {
  public:
   virtual JSObject* getObjectToTransplant(JS::Compartment* compartment) = 0;
 };
 
 // Gather a set of remote window proxies by calling the callback on every
 // compartment, then transform them into cross-compartment wrappers to newTarget
 // via brain transplants. If there's a proxy in newTarget's compartment, it will
 // get swapped with newTarget, and the value of newTarget will be updated. If
 // the callback returns null for a compartment, no cross-compartment wrapper
 // will be created for that compartment. Any non-null values it returns must be
 // DOM remote proxies from the compartment that was passed in.
-extern JS_FRIEND_API void RemapRemoteWindowProxies(
+extern JS_PUBLIC_API void RemapRemoteWindowProxies(
     JSContext* cx, CompartmentTransplantCallback* callback,
     JS::MutableHandleObject newTarget);
 
-extern JS_FRIEND_API JS::Zone* GetObjectZoneFromAnyThread(const JSObject* obj);
+extern JS_PUBLIC_API JS::Zone* GetObjectZoneFromAnyThread(const JSObject* obj);
 
 } /* namespace js */
 
 #endif /* jsfriendapi_h */
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -74,20 +74,20 @@ using JSConstIntegerSpec = JSConstScalar
 namespace js {
 
 inline JS::Realm* GetContextRealm(const JSContext* cx);
 inline JS::Compartment* GetContextCompartment(const JSContext* cx);
 inline JS::Zone* GetContextZone(const JSContext* cx);
 
 // Whether the current thread is permitted access to any part of the specified
 // runtime or zone.
-JS_FRIEND_API bool CurrentThreadCanAccessRuntime(const JSRuntime* rt);
+JS_PUBLIC_API bool CurrentThreadCanAccessRuntime(const JSRuntime* rt);
 
 #ifdef DEBUG
-JS_FRIEND_API bool CurrentThreadIsPerformingGC();
+JS_PUBLIC_API bool CurrentThreadIsPerformingGC();
 #endif
 
 }  // namespace js
 
 namespace JS {
 
 class JS_PUBLIC_API PropertyDescriptor;
 
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -35,28 +35,22 @@
  * The linkage of JS API functions differs depending on whether the file is
  * used within the JS library or not. Any source file within the JS
  * interpreter should define EXPORT_JS_API whereas any client of the library
  * should not. STATIC_JS_API is used to build JS as a static library.
  */
 #if defined(STATIC_JS_API)
 #  define JS_PUBLIC_API
 #  define JS_PUBLIC_DATA
-#  define JS_FRIEND_API
-#  define JS_FRIEND_DATA
 #elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
 #  define JS_PUBLIC_API MOZ_EXPORT
 #  define JS_PUBLIC_DATA MOZ_EXPORT
-#  define JS_FRIEND_API MOZ_EXPORT
-#  define JS_FRIEND_DATA MOZ_EXPORT
 #else
 #  define JS_PUBLIC_API MOZ_IMPORT_API
 #  define JS_PUBLIC_DATA MOZ_IMPORT_DATA
-#  define JS_FRIEND_API MOZ_IMPORT_API
-#  define JS_FRIEND_DATA MOZ_IMPORT_DATA
 #endif
 
 /***********************************************************************
 ** MACROS:      JS_BEGIN_MACRO
 **              JS_END_MACRO
 ** DESCRIPTION:
 **      Macro body brackets so that macros with compound statement definitions
 **      behave syntactically more like functions when called.
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -392,32 +392,32 @@ bool BaseProxyHandler::getElements(JSCon
 
   return js::GetElementsWithAdder(cx, proxy, proxy, begin, end, adder);
 }
 
 bool BaseProxyHandler::isCallable(JSObject* obj) const { return false; }
 
 bool BaseProxyHandler::isConstructor(JSObject* obj) const { return false; }
 
-JS_FRIEND_API void js::NukeNonCCWProxy(JSContext* cx, HandleObject proxy) {
+JS_PUBLIC_API void js::NukeNonCCWProxy(JSContext* cx, HandleObject proxy) {
   MOZ_ASSERT(proxy->is<ProxyObject>());
   MOZ_ASSERT(!proxy->is<CrossCompartmentWrapperObject>());
 
   // (NotifyGCNukeWrapper() only needs to be called on CCWs.)
 
   // The proxy is about to be replaced, so we need to do any necessary
   // cleanup first.
   proxy->as<ProxyObject>().handler()->finalize(cx->defaultFreeOp(), proxy);
 
   proxy->as<ProxyObject>().nuke();
 
   MOZ_ASSERT(IsDeadProxyObject(proxy));
 }
 
-JS_FRIEND_API void js::NukeRemovedCrossCompartmentWrapper(JSContext* cx,
+JS_PUBLIC_API void js::NukeRemovedCrossCompartmentWrapper(JSContext* cx,
                                                           JSObject* wrapper) {
   MOZ_ASSERT(wrapper->is<CrossCompartmentWrapperObject>());
 
   NotifyGCNukeWrapper(wrapper);
 
   // We don't need to call finalize here because the CCW finalizer doesn't do
   // anything. Skipping finalize means that |wrapper| doesn't need to be rooted
   // to pass the hazard analysis, which is needed because this method is called
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -357,27 +357,27 @@ bool CrossCompartmentWrapper::boxedValue
                                                HandleObject wrapper,
                                                MutableHandleValue vp) const {
   PIERCE(cx, wrapper, NOTHING, Wrapper::boxedValue_unbox(cx, wrapper, vp),
          cx->compartment()->wrap(cx, vp));
 }
 
 const CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u);
 
-JS_FRIEND_API void js::NukeCrossCompartmentWrapper(JSContext* cx,
+JS_PUBLIC_API void js::NukeCrossCompartmentWrapper(JSContext* cx,
                                                    JSObject* wrapper) {
   JS::Compartment* comp = wrapper->compartment();
   auto ptr = comp->lookupWrapper(Wrapper::wrappedObject(wrapper));
   if (ptr) {
     comp->removeWrapper(ptr);
   }
   NukeRemovedCrossCompartmentWrapper(cx, wrapper);
 }
 
-JS_FRIEND_API void js::NukeCrossCompartmentWrapperIfExists(
+JS_PUBLIC_API void js::NukeCrossCompartmentWrapperIfExists(
     JSContext* cx, JS::Compartment* source, JSObject* target) {
   MOZ_ASSERT(source != target->compartment());
   MOZ_ASSERT(!target->is<CrossCompartmentWrapperObject>());
   auto ptr = source->lookupWrapper(target);
   if (ptr) {
     JSObject* wrapper = ptr->value().get();
     NukeCrossCompartmentWrapper(cx, wrapper);
   }
@@ -396,17 +396,17 @@ static bool NukedAllRealms(JS::Compartme
 /*
  * NukeChromeCrossCompartmentWrappersForGlobal reaches into chrome and cuts
  * all of the cross-compartment wrappers that point to an object in the |target|
  * realm. The snag here is that we need to avoid cutting wrappers that point to
  * the window object on page navigation (inner window destruction) and only do
  * that on tab close (outer window destruction).  Thus the option of how to
  * handle the global object.
  */
-JS_FRIEND_API bool js::NukeCrossCompartmentWrappers(
+JS_PUBLIC_API bool js::NukeCrossCompartmentWrappers(
     JSContext* cx, const CompartmentFilter& sourceFilter, JS::Realm* target,
     js::NukeReferencesToWindow nukeReferencesToWindow,
     js::NukeReferencesFromTarget nukeReferencesFromTarget) {
   CHECK_THREAD(cx);
   JSRuntime* rt = cx->runtime();
 
   // If we're nuking all wrappers into the target realm, prevent us from
   // creating new wrappers for it in the future.
@@ -469,17 +469,17 @@ JS_FRIEND_API bool js::NukeCrossCompartm
       e->removeFront();
       NukeRemovedCrossCompartmentWrapper(cx, wobj);
     }
   }
 
   return true;
 }
 
-JS_FRIEND_API bool js::AllowNewWrapper(JS::Compartment* target, JSObject* obj) {
+JS_PUBLIC_API bool js::AllowNewWrapper(JS::Compartment* target, JSObject* obj) {
   // Disallow creating new wrappers if we nuked the object realm or target
   // compartment. However, we always need to provide live wrappers for
   // ScriptSourceObjects, since they're used for cross-compartment cloned
   // scripts, and need to remain accessible even after the original realm has
   // been nuked.
 
   MOZ_ASSERT(obj->compartment() != target);
 
@@ -490,17 +490,17 @@ JS_FRIEND_API bool js::AllowNewWrapper(J
   if (target->nukedOutgoingWrappers ||
       obj->nonCCWRealm()->nukedIncomingWrappers) {
     return false;
   }
 
   return true;
 }
 
-JS_FRIEND_API bool js::NukedObjectRealm(JSObject* obj) {
+JS_PUBLIC_API bool js::NukedObjectRealm(JSObject* obj) {
   return obj->nonCCWRealm()->nukedIncomingWrappers;
 }
 
 // Given a cross-compartment wrapper |wobj|, update it to point to
 // |newTarget|. This recomputes the wrapper with JS_WrapValue, and thus can be
 // useful even if wrapper already points to newTarget.
 // This operation crashes on failure rather than leaving the heap in an
 // inconsistent state.
@@ -598,17 +598,17 @@ void js::RemapDeadWrapper(JSContext* cx,
   // wrapper, which has now been updated (via reuse or swap).
   if (!wcompartment->putWrapper(cx, newTarget, wobj)) {
     oomUnsafe.crash("js::RemapWrapper");
   }
 }
 
 // Remap all cross-compartment wrappers pointing to |oldTarget| to point to
 // |newTarget|. All wrappers are recomputed.
-JS_FRIEND_API bool js::RemapAllWrappersForObject(JSContext* cx,
+JS_PUBLIC_API bool js::RemapAllWrappersForObject(JSContext* cx,
                                                  HandleObject oldTarget,
                                                  HandleObject newTarget) {
   MOZ_ASSERT(!IsInsideNursery(oldTarget));
   MOZ_ASSERT(!IsInsideNursery(newTarget));
 
   AutoWrapperVector toTransplant(cx);
 
   for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
@@ -622,17 +622,17 @@ JS_FRIEND_API bool js::RemapAllWrappersF
 
   for (const WrapperValue& v : toTransplant) {
     RemapWrapper(cx, v, newTarget);
   }
 
   return true;
 }
 
-JS_FRIEND_API bool js::RecomputeWrappers(
+JS_PUBLIC_API bool js::RecomputeWrappers(
     JSContext* cx, const CompartmentFilter& sourceFilter,
     const CompartmentFilter& targetFilter) {
   bool evictedNursery = false;
 
   AutoWrapperVector toRecompute(cx);
   for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
     // Filter by source compartment.
     if (!sourceFilter.match(c)) {
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -155,17 +155,17 @@ void js::AutoEnterPolicy::recordEnter(JS
 
 void js::AutoEnterPolicy::recordLeave() {
   if (enteredProxy) {
     MOZ_ASSERT(context->enteredPolicy == this);
     context->enteredPolicy = prev;
   }
 }
 
-JS_FRIEND_API void js::assertEnteredPolicy(JSContext* cx, JSObject* proxy,
+JS_PUBLIC_API void js::assertEnteredPolicy(JSContext* cx, JSObject* proxy,
                                            jsid id,
                                            BaseProxyHandler::Action act) {
   MOZ_ASSERT(proxy->is<ProxyObject>());
   MOZ_ASSERT(cx->enteredPolicy);
   MOZ_ASSERT(cx->enteredPolicy->enteredProxy->get() == proxy);
   MOZ_ASSERT(cx->enteredPolicy->enteredId->get() == id);
   MOZ_ASSERT(cx->enteredPolicy->enteredAction & act);
 }
@@ -254,17 +254,17 @@ bool Proxy::delete_(JSContext* cx, Handl
 
   // Private names shouldn't take this path, as deleting a private name
   // should be a syntax error.
   MOZ_ASSERT_IF(JSID_IS_SYMBOL(id), !JSID_TO_SYMBOL(id)->isPrivateName());
 
   return proxy->as<ProxyObject>().handler()->delete_(cx, proxy, id, result);
 }
 
-JS_FRIEND_API bool js::AppendUnique(JSContext* cx, MutableHandleIdVector base,
+JS_PUBLIC_API bool js::AppendUnique(JSContext* cx, MutableHandleIdVector base,
                                     HandleIdVector others) {
   RootedIdVector uniqueOthers(cx);
   if (!uniqueOthers.reserve(others.length())) {
     return false;
   }
   for (size_t i = 0; i < others.length(); ++i) {
     bool unique = true;
     for (size_t j = 0; j < base.length(); ++j) {
@@ -951,17 +951,17 @@ static const ClassSpec ProxyClassSpec = 
     GenericCreateConstructor<js::proxy, 2, gc::AllocKind::FUNCTION>, nullptr,
     proxy_static_methods, nullptr};
 
 const JSClass js::ProxyClass = PROXY_CLASS_DEF_WITH_CLASS_SPEC(
     "Proxy",
     JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy) | JSCLASS_HAS_RESERVED_SLOTS(2),
     &ProxyClassSpec);
 
-JS_FRIEND_API JSObject* js::NewProxyObject(JSContext* cx,
+JS_PUBLIC_API JSObject* js::NewProxyObject(JSContext* cx,
                                            const BaseProxyHandler* handler,
                                            HandleValue priv, JSObject* proto_,
                                            const ProxyOptions& options) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 
   // This can be called from the compartment wrap hooks while in a realm with a
   // gray global. Trigger the read barrier on the global to ensure this is
--- a/js/src/proxy/Wrapper.cpp
+++ b/js/src/proxy/Wrapper.cpp
@@ -314,33 +314,33 @@ JSObject* Wrapper::wrappedObject(JSObjec
     // Unmark wrapper targets that should be black in case an incremental GC
     // hasn't marked them the correct color yet.
     JS::ExposeObjectToActiveJS(target);
   }
 
   return target;
 }
 
-JS_FRIEND_API JSObject* js::UncheckedUnwrapWithoutExpose(JSObject* wrapped) {
+JS_PUBLIC_API JSObject* js::UncheckedUnwrapWithoutExpose(JSObject* wrapped) {
   while (true) {
     if (!wrapped->is<WrapperObject>() || MOZ_UNLIKELY(IsWindowProxy(wrapped))) {
       break;
     }
     wrapped = wrapped->as<WrapperObject>().target();
 
     // This can be called from when getting a weakmap key delegate() on a
     // wrapper whose referent has been moved while it is still unmarked.
     if (wrapped) {
       wrapped = MaybeForwarded(wrapped);
     }
   }
   return wrapped;
 }
 
-JS_FRIEND_API JSObject* js::UncheckedUnwrap(JSObject* wrapped,
+JS_PUBLIC_API JSObject* js::UncheckedUnwrap(JSObject* wrapped,
                                             bool stopAtWindowProxy,
                                             unsigned* flagsp) {
   MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
   MOZ_ASSERT(CurrentThreadCanAccessRuntime(wrapped->runtimeFromAnyThread()));
 
   unsigned flags = 0;
   while (true) {
     if (!wrapped->is<WrapperObject>() ||
@@ -351,56 +351,56 @@ JS_FRIEND_API JSObject* js::UncheckedUnw
     wrapped = Wrapper::wrappedObject(wrapped);
   }
   if (flagsp) {
     *flagsp = flags;
   }
   return wrapped;
 }
 
-JS_FRIEND_API JSObject* js::CheckedUnwrapStatic(JSObject* obj) {
+JS_PUBLIC_API JSObject* js::CheckedUnwrapStatic(JSObject* obj) {
   while (true) {
     JSObject* wrapper = obj;
     obj = UnwrapOneCheckedStatic(obj);
     if (!obj || obj == wrapper) {
       return obj;
     }
   }
 }
 
-JS_FRIEND_API JSObject* js::UnwrapOneCheckedStatic(JSObject* obj) {
+JS_PUBLIC_API JSObject* js::UnwrapOneCheckedStatic(JSObject* obj) {
   MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
   MOZ_ASSERT(CurrentThreadCanAccessRuntime(obj->runtimeFromAnyThread()));
 
   // Note: callers that care about WindowProxy unwrapping should use
   // CheckedUnwrapDynamic or UnwrapOneCheckedDynamic instead of this. We don't
   // unwrap WindowProxy here to preserve legacy behavior and for consistency
   // with CheckedUnwrapDynamic's default stopAtWindowProxy = true.
   if (!obj->is<WrapperObject>() || MOZ_UNLIKELY(IsWindowProxy(obj))) {
     return obj;
   }
 
   const Wrapper* handler = Wrapper::wrapperHandler(obj);
   return handler->hasSecurityPolicy() ? nullptr : Wrapper::wrappedObject(obj);
 }
 
-JS_FRIEND_API JSObject* js::CheckedUnwrapDynamic(JSObject* obj, JSContext* cx,
+JS_PUBLIC_API JSObject* js::CheckedUnwrapDynamic(JSObject* obj, JSContext* cx,
                                                  bool stopAtWindowProxy) {
   RootedObject wrapper(cx, obj);
   while (true) {
     JSObject* unwrapped =
         UnwrapOneCheckedDynamic(wrapper, cx, stopAtWindowProxy);
     if (!unwrapped || unwrapped == wrapper) {
       return unwrapped;
     }
     wrapper = unwrapped;
   }
 }
 
-JS_FRIEND_API JSObject* js::UnwrapOneCheckedDynamic(HandleObject obj,
+JS_PUBLIC_API JSObject* js::UnwrapOneCheckedDynamic(HandleObject obj,
                                                     JSContext* cx,
                                                     bool stopAtWindowProxy) {
   MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());
   MOZ_ASSERT(CurrentThreadCanAccessRuntime(obj->runtimeFromAnyThread()));
   // We should know who's asking.
   MOZ_ASSERT(cx);
   MOZ_ASSERT(cx->realm());
 
--- a/js/src/util/DumpFunctions.cpp
+++ b/js/src/util/DumpFunctions.cpp
@@ -8,17 +8,17 @@
 
 #include "mozilla/Maybe.h"  // mozilla::Maybe
 
 #include <inttypes.h>  // PRIu64
 #include <stddef.h>    // size_t
 #include <stdio.h>     // fprintf, fflush
 
 #include "jsfriendapi.h"  // js::WeakMapTracer
-#include "jstypes.h"      // JS_FRIEND_API
+#include "jstypes.h"      // JS_PUBLIC_API
 
 #include "gc/Allocator.h"   // js::CanGC
 #include "gc/Cell.h"        // js::gc::Cell, js::gc::TenuredCell
 #include "gc/GC.h"          // js::TraceRuntimeWithoutEviction
 #include "gc/Heap.h"        // js::gc::Arena
 #include "gc/Tracer.h"      // js::TraceChildren
 #include "gc/WeakMap.h"     // js::IterateHeapUnbarriered, js::WeakMapBase
 #include "js/GCAPI.h"       // JS::GCReason
@@ -76,33 +76,33 @@ using js::WeakMapTracer;
 
 // We don't want jsfriendapi.h to depend on GenericPrinter,
 // so these functions are declared directly in the cpp.
 
 namespace js {
 
 class InterpreterFrame;
 
-extern JS_FRIEND_API void DumpString(JSString* str, GenericPrinter& out);
+extern JS_PUBLIC_API void DumpString(JSString* str, GenericPrinter& out);
 
-extern JS_FRIEND_API void DumpAtom(JSAtom* atom, GenericPrinter& out);
+extern JS_PUBLIC_API void DumpAtom(JSAtom* atom, GenericPrinter& out);
 
-extern JS_FRIEND_API void DumpObject(JSObject* obj, GenericPrinter& out);
+extern JS_PUBLIC_API void DumpObject(JSObject* obj, GenericPrinter& out);
 
-extern JS_FRIEND_API void DumpChars(const char16_t* s, size_t n,
+extern JS_PUBLIC_API void DumpChars(const char16_t* s, size_t n,
                                     GenericPrinter& out);
 
-extern JS_FRIEND_API void DumpValue(const JS::Value& val, GenericPrinter& out);
+extern JS_PUBLIC_API void DumpValue(const JS::Value& val, GenericPrinter& out);
 
-extern JS_FRIEND_API void DumpId(PropertyKey id, GenericPrinter& out);
+extern JS_PUBLIC_API void DumpId(PropertyKey id, GenericPrinter& out);
 
-extern JS_FRIEND_API void DumpInterpreterFrame(
+extern JS_PUBLIC_API void DumpInterpreterFrame(
     JSContext* cx, GenericPrinter& out, InterpreterFrame* start = nullptr);
 
-extern JS_FRIEND_API void DumpBigInt(JS::BigInt* bi, GenericPrinter& out);
+extern JS_PUBLIC_API void DumpBigInt(JS::BigInt* bi, GenericPrinter& out);
 
 }  // namespace js
 
 void js::DumpString(JSString* str, GenericPrinter& out) {
 #if defined(DEBUG) || defined(JS_JITSPEW)
   str->dump(out);
 #endif
 }
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -1688,22 +1688,22 @@ size_t InnerViewTable::sizeOfExcludingTh
          nurseryKeys.sizeOfExcludingThis(mallocSizeOf);
 }
 
 template <>
 bool JSObject::is<js::ArrayBufferObjectMaybeShared>() const {
   return is<ArrayBufferObject>() || is<SharedArrayBufferObject>();
 }
 
-JS_FRIEND_API size_t JS::GetArrayBufferByteLength(JSObject* obj) {
+JS_PUBLIC_API size_t JS::GetArrayBufferByteLength(JSObject* obj) {
   ArrayBufferObject* aobj = obj->maybeUnwrapAs<ArrayBufferObject>();
   return aobj ? aobj->byteLength() : 0;
 }
 
-JS_FRIEND_API uint8_t* JS::GetArrayBufferData(JSObject* obj,
+JS_PUBLIC_API uint8_t* JS::GetArrayBufferData(JSObject* obj,
                                               bool* isSharedMemory,
                                               const JS::AutoRequireNoGC&) {
   ArrayBufferObject* aobj = obj->maybeUnwrapIf<ArrayBufferObject>();
   if (!aobj) {
     return nullptr;
   }
   *isSharedMemory = false;
   return aobj->dataPointer();
@@ -1721,17 +1721,17 @@ static ArrayBufferObject* UnwrapArrayBuf
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_ARRAYBUFFER_REQUIRED);
     return nullptr;
   }
 
   return &obj->as<ArrayBufferObject>();
 }
 
-JS_FRIEND_API bool JS::DetachArrayBuffer(JSContext* cx, HandleObject obj) {
+JS_PUBLIC_API bool JS::DetachArrayBuffer(JSContext* cx, HandleObject obj) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(obj);
 
   Rooted<ArrayBufferObject*> unwrappedBuffer(cx, UnwrapArrayBuffer(cx, obj));
   if (!unwrappedBuffer) {
     return false;
   }
@@ -1742,26 +1742,26 @@ JS_FRIEND_API bool JS::DetachArrayBuffer
     return false;
   }
 
   AutoRealm ar(cx, unwrappedBuffer);
   ArrayBufferObject::detach(cx, unwrappedBuffer);
   return true;
 }
 
-JS_FRIEND_API bool JS::IsDetachedArrayBufferObject(JSObject* obj) {
+JS_PUBLIC_API bool JS::IsDetachedArrayBufferObject(JSObject* obj) {
   ArrayBufferObject* aobj = obj->maybeUnwrapIf<ArrayBufferObject>();
   if (!aobj) {
     return false;
   }
 
   return aobj->isDetached();
 }
 
-JS_FRIEND_API JSObject* JS::NewArrayBuffer(JSContext* cx, size_t nbytes) {
+JS_PUBLIC_API JSObject* JS::NewArrayBuffer(JSContext* cx, size_t nbytes) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 
   return ArrayBufferObject::createZeroed(cx, nbytes);
 }
 
 JS_PUBLIC_API JSObject* JS::NewArrayBufferWithContents(JSContext* cx,
                                                        size_t nbytes,
@@ -1822,29 +1822,29 @@ JS_PUBLIC_API JSObject* JS::NewArrayBuff
   MOZ_ASSERT(data);
 
   using BufferContents = ArrayBufferObject::BufferContents;
 
   BufferContents contents = BufferContents::createUserOwned(data);
   return ArrayBufferObject::createForContents(cx, nbytes, contents);
 }
 
-JS_FRIEND_API bool JS::IsArrayBufferObject(JSObject* obj) {
+JS_PUBLIC_API bool JS::IsArrayBufferObject(JSObject* obj) {
   return obj->canUnwrapAs<ArrayBufferObject>();
 }
 
-JS_FRIEND_API bool JS::ArrayBufferHasData(JSObject* obj) {
+JS_PUBLIC_API bool JS::ArrayBufferHasData(JSObject* obj) {
   return !obj->unwrapAs<ArrayBufferObject>().isDetached();
 }
 
-JS_FRIEND_API JSObject* JS::UnwrapArrayBuffer(JSObject* obj) {
+JS_PUBLIC_API JSObject* JS::UnwrapArrayBuffer(JSObject* obj) {
   return obj->maybeUnwrapIf<ArrayBufferObject>();
 }
 
-JS_FRIEND_API JSObject* JS::UnwrapSharedArrayBuffer(JSObject* obj) {
+JS_PUBLIC_API JSObject* JS::UnwrapSharedArrayBuffer(JSObject* obj) {
   return obj->maybeUnwrapIf<SharedArrayBufferObject>();
 }
 
 JS_PUBLIC_API void* JS::StealArrayBufferContents(JSContext* cx,
                                                  HandleObject obj) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(obj);
@@ -1893,40 +1893,40 @@ JS_PUBLIC_API void* JS::CreateMappedArra
   return ArrayBufferObject::createMappedContents(fd, offset, length).data();
 }
 
 JS_PUBLIC_API void JS::ReleaseMappedArrayBufferContents(void* contents,
                                                         size_t length) {
   gc::DeallocateMappedContent(contents, length);
 }
 
-JS_FRIEND_API bool JS::IsMappedArrayBufferObject(JSObject* obj) {
+JS_PUBLIC_API bool JS::IsMappedArrayBufferObject(JSObject* obj) {
   ArrayBufferObject* aobj = obj->maybeUnwrapIf<ArrayBufferObject>();
   if (!aobj) {
     return false;
   }
 
   return aobj->isMapped();
 }
 
-JS_FRIEND_API JSObject* JS::GetObjectAsArrayBuffer(JSObject* obj,
+JS_PUBLIC_API JSObject* JS::GetObjectAsArrayBuffer(JSObject* obj,
                                                    size_t* length,
                                                    uint8_t** data) {
   ArrayBufferObject* aobj = obj->maybeUnwrapIf<ArrayBufferObject>();
   if (!aobj) {
     return nullptr;
   }
 
   *length = aobj->byteLength();
   *data = aobj->dataPointer();
 
   return aobj;
 }
 
-JS_FRIEND_API void JS::GetArrayBufferLengthAndData(JSObject* obj,
+JS_PUBLIC_API void JS::GetArrayBufferLengthAndData(JSObject* obj,
                                                    size_t* length,
                                                    bool* isSharedMemory,
                                                    uint8_t** data) {
   auto& aobj = obj->as<ArrayBufferObject>();
   *length = aobj.byteLength();
   *data = aobj.dataPointer();
   *isSharedMemory = false;
 }
--- a/js/src/vm/ArrayBufferViewObject.cpp
+++ b/js/src/vm/ArrayBufferViewObject.cpp
@@ -145,40 +145,40 @@ bool ArrayBufferViewObject::init(JSConte
     if (!buffer->as<ArrayBufferObject>().addView(cx, this)) {
       return false;
     }
   }
 
   return true;
 }
 
-/* JS Friend API */
+/* JS Public API */
 
-JS_FRIEND_API bool JS_IsArrayBufferViewObject(JSObject* obj) {
+JS_PUBLIC_API bool JS_IsArrayBufferViewObject(JSObject* obj) {
   return obj->canUnwrapAs<ArrayBufferViewObject>();
 }
 
-JS_FRIEND_API JSObject* js::UnwrapArrayBufferView(JSObject* obj) {
+JS_PUBLIC_API JSObject* js::UnwrapArrayBufferView(JSObject* obj) {
   return obj->maybeUnwrapIf<ArrayBufferViewObject>();
 }
 
-JS_FRIEND_API void* JS_GetArrayBufferViewData(JSObject* obj,
+JS_PUBLIC_API void* JS_GetArrayBufferViewData(JSObject* obj,
                                               bool* isSharedMemory,
                                               const JS::AutoRequireNoGC&) {
   ArrayBufferViewObject* view = obj->maybeUnwrapAs<ArrayBufferViewObject>();
   if (!view) {
     return nullptr;
   }
 
   *isSharedMemory = view->isSharedMemory();
   return view->dataPointerEither().unwrap(
       /*safe - caller sees isSharedMemory flag*/);
 }
 
-JS_FRIEND_API uint8_t* JS_GetArrayBufferViewFixedData(JSObject* obj,
+JS_PUBLIC_API uint8_t* JS_GetArrayBufferViewFixedData(JSObject* obj,
                                                       uint8_t* buffer,
                                                       size_t bufSize) {
   ArrayBufferViewObject* view = obj->maybeUnwrapAs<ArrayBufferViewObject>();
   if (!view) {
     return nullptr;
   }
 
   // Disallow shared memory until it is needed.
@@ -198,17 +198,17 @@ JS_FRIEND_API uint8_t* JS_GetArrayBuffer
       memcpy(buffer, view->dataPointerUnshared(), bytes);
       return buffer;
     }
   }
 
   return static_cast<uint8_t*>(view->dataPointerUnshared());
 }
 
-JS_FRIEND_API JSObject* JS_GetArrayBufferViewBuffer(JSContext* cx,
+JS_PUBLIC_API JSObject* JS_GetArrayBufferViewBuffer(JSContext* cx,
                                                     HandleObject obj,
                                                     bool* isSharedMemory) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
   cx->check(obj);
 
   Rooted<ArrayBufferViewObject*> unwrappedView(
       cx, obj->maybeUnwrapAs<ArrayBufferViewObject>());
@@ -230,52 +230,52 @@ JS_FRIEND_API JSObject* JS_GetArrayBuffe
   RootedObject buffer(cx, unwrappedBuffer);
   if (!cx->compartment()->wrap(cx, &buffer)) {
     return nullptr;
   }
 
   return buffer;
 }
 
-JS_FRIEND_API size_t JS_GetArrayBufferViewByteLength(JSObject* obj) {
+JS_PUBLIC_API size_t JS_GetArrayBufferViewByteLength(JSObject* obj) {
   obj = obj->maybeUnwrapAs<ArrayBufferViewObject>();
   if (!obj) {
     return 0;
   }
   size_t length = obj->is<DataViewObject>()
                       ? obj->as<DataViewObject>().byteLength()
                       : obj->as<TypedArrayObject>().byteLength();
   return length;
 }
 
-JS_FRIEND_API size_t JS_GetArrayBufferViewByteOffset(JSObject* obj) {
+JS_PUBLIC_API size_t JS_GetArrayBufferViewByteOffset(JSObject* obj) {
   obj = obj->maybeUnwrapAs<ArrayBufferViewObject>();
   if (!obj) {
     return 0;
   }
   size_t offset = obj->is<DataViewObject>()
                       ? obj->as<DataViewObject>().byteOffset()
                       : obj->as<TypedArrayObject>().byteOffset();
   return offset;
 }
 
-JS_FRIEND_API JSObject* JS_GetObjectAsArrayBufferView(JSObject* obj,
+JS_PUBLIC_API JSObject* JS_GetObjectAsArrayBufferView(JSObject* obj,
                                                       size_t* length,
                                                       bool* isSharedMemory,
                                                       uint8_t** data) {
   obj = obj->maybeUnwrapIf<ArrayBufferViewObject>();
   if (!obj) {
     return nullptr;
   }
 
   js::GetArrayBufferViewLengthAndData(obj, length, isSharedMemory, data);
   return obj;
 }
 
-JS_FRIEND_API void js::GetArrayBufferViewLengthAndData(JSObject* obj,
+JS_PUBLIC_API void js::GetArrayBufferViewLengthAndData(JSObject* obj,
                                                        size_t* length,
                                                        bool* isSharedMemory,
                                                        uint8_t** data) {
   MOZ_ASSERT(obj->is<ArrayBufferViewObject>());
 
   size_t byteLength = obj->is<DataViewObject>()
                           ? obj->as<DataViewObject>().byteLength()
                           : obj->as<TypedArrayObject>().byteLength();
@@ -290,17 +290,17 @@ JS_FRIEND_API void js::GetArrayBufferVie
 JS_PUBLIC_API bool JS::IsArrayBufferViewShared(JSObject* obj) {
   ArrayBufferViewObject* view = obj->maybeUnwrapAs<ArrayBufferViewObject>();
   if (!view) {
     return false;
   }
   return view->isSharedMemory();
 }
 
-JS_FRIEND_API bool JS::IsLargeArrayBufferView(JSObject* obj) {
+JS_PUBLIC_API bool JS::IsLargeArrayBufferView(JSObject* obj) {
 #ifdef JS_64BIT
   obj = &obj->unwrapAs<ArrayBufferViewObject>();
   size_t len = obj->is<DataViewObject>()
                    ? obj->as<DataViewObject>().byteLength()
                    : obj->as<TypedArrayObject>().byteLength();
   return len > ArrayBufferObject::MaxByteLengthForSmallBuffer;
 #else
   // Large ArrayBuffers are not supported on 32-bit.
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -1120,34 +1120,34 @@ static unsigned Disassemble1(JSContext* 
   return true;
 }
 
 bool js::Disassemble(JSContext* cx, HandleScript script, bool lines,
                      Sprinter* sp, DisassembleSkeptically skeptically) {
   return DisassembleAtPC(cx, script, lines, nullptr, false, sp, skeptically);
 }
 
-JS_FRIEND_API bool js::DumpPC(JSContext* cx, FILE* fp) {
+JS_PUBLIC_API bool js::DumpPC(JSContext* cx, FILE* fp) {
   gc::AutoSuppressGC suppressGC(cx);
   Sprinter sprinter(cx);
   if (!sprinter.init()) {
     return false;
   }
   ScriptFrameIter iter(cx);
   if (iter.done()) {
     fprintf(fp, "Empty stack.\n");
     return true;
   }
   RootedScript script(cx, iter.script());
   bool ok = DisassembleAtPC(cx, script, true, iter.pc(), false, &sprinter);
   fprintf(fp, "%s", sprinter.string());
   return ok;
 }
 
-JS_FRIEND_API bool js::DumpScript(JSContext* cx, JSScript* scriptArg,
+JS_PUBLIC_API bool js::DumpScript(JSContext* cx, JSScript* scriptArg,
                                   FILE* fp) {
   gc::AutoSuppressGC suppressGC(cx);
   Sprinter sprinter(cx);
   if (!sprinter.init()) {
     return false;
   }
   RootedScript script(cx, scriptArg);
   bool ok = Disassemble(cx, script, true, &sprinter);
@@ -2550,33 +2550,33 @@ extern bool js::IsValidBytecodeOffset(JS
 
 static void ReleaseScriptCounts(JSRuntime* rt) {
   MOZ_ASSERT(rt->scriptAndCountsVector);
 
   js_delete(rt->scriptAndCountsVector.ref());
   rt->scriptAndCountsVector = nullptr;
 }
 
-JS_FRIEND_API void js::StartPCCountProfiling(JSContext* cx) {
+JS_PUBLIC_API void js::StartPCCountProfiling(JSContext* cx) {
   JSRuntime* rt = cx->runtime();
 
   if (rt->profilingScripts) {
     return;
   }
 
   if (rt->scriptAndCountsVector) {
     ReleaseScriptCounts(rt);
   }
 
   ReleaseAllJITCode(rt->defaultFreeOp());
 
   rt->profilingScripts = true;
 }
 
-JS_FRIEND_API void js::StopPCCountProfiling(JSContext* cx) {
+JS_PUBLIC_API void js::StopPCCountProfiling(JSContext* cx) {
   JSRuntime* rt = cx->runtime();
 
   if (!rt->profilingScripts) {
     return;
   }
   MOZ_ASSERT(!rt->scriptAndCountsVector);
 
   ReleaseAllJITCode(rt->defaultFreeOp());
@@ -2596,28 +2596,28 @@ JS_FRIEND_API void js::StopPCCountProfil
       }
     }
   }
 
   rt->profilingScripts = false;
   rt->scriptAndCountsVector = vec;
 }
 
-JS_FRIEND_API void js::PurgePCCounts(JSContext* cx) {
+JS_PUBLIC_API void js::PurgePCCounts(JSContext* cx) {
   JSRuntime* rt = cx->runtime();
 
   if (!rt->scriptAndCountsVector) {
     return;
   }
   MOZ_ASSERT(!rt->profilingScripts);
 
   ReleaseScriptCounts(rt);
 }
 
-JS_FRIEND_API size_t js::GetPCCountScriptCount(JSContext* cx) {
+JS_PUBLIC_API size_t js::GetPCCountScriptCount(JSContext* cx) {
   JSRuntime* rt = cx->runtime();
 
   if (!rt->scriptAndCountsVector) {
     return 0;
   }
 
   return rt->scriptAndCountsVector->length();
 }
@@ -2627,17 +2627,17 @@ JS_FRIEND_API size_t js::GetPCCountScrip
   json.beginStringProperty(name);
   if (!JSONQuoteString(&sp, str)) {
     return false;
   }
   json.endStringProperty();
   return true;
 }
 
-JS_FRIEND_API JSString* js::GetPCCountScriptSummary(JSContext* cx,
+JS_PUBLIC_API JSString* js::GetPCCountScriptSummary(JSContext* cx,
                                                     size_t index) {
   JSRuntime* rt = cx->runtime();
 
   if (!rt->scriptAndCountsVector ||
       index >= rt->scriptAndCountsVector->length()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_BUFFER_TOO_SMALL);
     return nullptr;
@@ -2835,17 +2835,17 @@ static bool GetPCCountJSON(JSContext* cx
     json.endList();
   }
 
   json.endObject();
 
   return true;
 }
 
-JS_FRIEND_API JSString* js::GetPCCountScriptContents(JSContext* cx,
+JS_PUBLIC_API JSString* js::GetPCCountScriptContents(JSContext* cx,
                                                      size_t index) {
   JSRuntime* rt = cx->runtime();
 
   if (!rt->scriptAndCountsVector ||
       index >= rt->scriptAndCountsVector->length()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_BUFFER_TOO_SMALL);
     return nullptr;
@@ -2985,17 +2985,17 @@ static bool GenerateLcovInfo(JSContext* 
   lcovRealm->exportInto(out, &isEmpty);
   if (out.hadOutOfMemory()) {
     return false;
   }
 
   return true;
 }
 
-JS_FRIEND_API UniqueChars js::GetCodeCoverageSummaryAll(JSContext* cx,
+JS_PUBLIC_API UniqueChars js::GetCodeCoverageSummaryAll(JSContext* cx,
                                                         size_t* length) {
   Sprinter out(cx);
   if (!out.init()) {
     return nullptr;
   }
 
   for (RealmsIter realm(cx->runtime()); !realm.done(); realm.next()) {
     if (!GenerateLcovInfo(cx, realm, out)) {
@@ -3003,17 +3003,17 @@ JS_FRIEND_API UniqueChars js::GetCodeCov
       return nullptr;
     }
   }
 
   *length = out.getOffset();
   return js::DuplicateString(cx, out.string(), *length);
 }
 
-JS_FRIEND_API UniqueChars js::GetCodeCoverageSummary(JSContext* cx,
+JS_PUBLIC_API UniqueChars js::GetCodeCoverageSummary(JSContext* cx,
                                                      size_t* length) {
   Sprinter out(cx);
   if (!out.init()) {
     return nullptr;
   }
 
   if (!GenerateLcovInfo(cx, cx->realm(), out)) {
     JS_ReportOutOfMemory(cx);
--- a/js/src/vm/Compartment.cpp
+++ b/js/src/vm/Compartment.cpp
@@ -564,21 +564,21 @@ GlobalObject& Compartment::firstGlobal()
     }
     GlobalObject* global = realm->maybeGlobal();
     ExposeObjectToActiveJS(global);
     return *global;
   }
   MOZ_CRASH("If all our globals are dead, why is someone expecting a global?");
 }
 
-JS_FRIEND_API JSObject* js::GetFirstGlobalInCompartment(JS::Compartment* comp) {
+JS_PUBLIC_API JSObject* js::GetFirstGlobalInCompartment(JS::Compartment* comp) {
   return &comp->firstGlobal();
 }
 
-JS_FRIEND_API bool js::CompartmentHasLiveGlobal(JS::Compartment* comp) {
+JS_PUBLIC_API bool js::CompartmentHasLiveGlobal(JS::Compartment* comp) {
   MOZ_ASSERT(comp);
   for (Realm* r : comp->realms()) {
     if (r->hasLiveGlobal()) {
       return true;
     }
   }
   return false;
 }
--- a/js/src/vm/GeckoProfiler.cpp
+++ b/js/src/vm/GeckoProfiler.cpp
@@ -460,17 +460,17 @@ JS_PUBLIC_API JSScript* ProfilingStackFr
   return script;
 }
 
 JS_PUBLIC_API JSFunction* ProfilingStackFrame::function() const {
   JSScript* script = this->script();
   return script ? script->function() : nullptr;
 }
 
-JS_FRIEND_API jsbytecode* ProfilingStackFrame::pc() const {
+JS_PUBLIC_API jsbytecode* ProfilingStackFrame::pc() const {
   MOZ_ASSERT(isJsFrame());
   if (pcOffsetIfJS_ == NullPCOffset) {
     return nullptr;
   }
 
   JSScript* script = this->script();
   return script ? script->offsetToPC(pcOffsetIfJS_) : nullptr;
 }
@@ -483,29 +483,29 @@ int32_t ProfilingStackFrame::pcToOffset(
 void ProfilingStackFrame::setPC(jsbytecode* pc) {
   MOZ_ASSERT(isJsFrame());
   JSScript* script = this->script();
   MOZ_ASSERT(
       script);  // This should not be called while profiling is suppressed.
   pcOffsetIfJS_ = pcToOffset(script, pc);
 }
 
-JS_FRIEND_API void js::SetContextProfilingStack(
+JS_PUBLIC_API void js::SetContextProfilingStack(
     JSContext* cx, ProfilingStack* profilingStack) {
   cx->geckoProfiler().setProfilingStack(
       profilingStack, cx->runtime()->geckoProfiler().enabled());
 }
 
-JS_FRIEND_API void js::EnableContextProfilingStack(JSContext* cx,
+JS_PUBLIC_API void js::EnableContextProfilingStack(JSContext* cx,
                                                    bool enabled) {
   cx->geckoProfiler().enable(enabled);
   cx->runtime()->geckoProfiler().enable(enabled);
 }
 
-JS_FRIEND_API void js::RegisterContextProfilingEventMarker(
+JS_PUBLIC_API void js::RegisterContextProfilingEventMarker(
     JSContext* cx, void (*fn)(const char*, const char*)) {
   MOZ_ASSERT(cx->runtime()->geckoProfiler().enabled());
   cx->runtime()->geckoProfiler().setEventMarker(fn);
 }
 
 AutoSuppressProfilerSampling::AutoSuppressProfilerSampling(JSContext* cx)
     : cx_(cx), previouslyEnabled_(cx->isProfilerSamplingEnabled()) {
   if (previouslyEnabled_) {
@@ -555,17 +555,17 @@ const ProfilingCategoryPairInfo sProfili
                               CATEGORY_INFO_END_CATEGORY)
 };
 #undef CATEGORY_INFO_BEGIN_CATEGORY
 #undef CATEGORY_INFO_SUBCATEGORY
 #undef CATEGORY_INFO_END_CATEGORY
 
 // clang-format on
 
-JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
+JS_PUBLIC_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
     ProfilingCategoryPair aCategoryPair) {
   static_assert(
       MOZ_ARRAY_LENGTH(sProfilingCategoryPairInfo) ==
           uint32_t(ProfilingCategoryPair::COUNT),
       "sProfilingCategoryPairInfo and ProfilingCategory need to have the "
       "same order and the same length");
 
   uint32_t categoryPairIndex = uint32_t(aCategoryPair);
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -83,17 +83,17 @@ extern const JSClass ReflectClass;
 static const JSClass* const protoTable[JSProto_LIMIT] = {
 #define INIT_FUNC(name, clasp) clasp,
 #define INIT_FUNC_DUMMY(name, clasp) nullptr,
     JS_FOR_PROTOTYPES(INIT_FUNC, INIT_FUNC_DUMMY)
 #undef INIT_FUNC_DUMMY
 #undef INIT_FUNC
 };
 
-JS_FRIEND_API const JSClass* js::ProtoKeyToClass(JSProtoKey key) {
+JS_PUBLIC_API const JSClass* js::ProtoKeyToClass(JSProtoKey key) {
   MOZ_ASSERT(key < JSProto_LIMIT);
   return protoTable[key];
 }
 
 /* static */
 bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
   switch (key) {
     case JSProto_Null:
--- a/js/src/vm/Iteration.cpp
+++ b/js/src/vm/Iteration.cpp
@@ -554,17 +554,17 @@ static bool Snapshot(JSContext* cx, Hand
       return false;
     }
   }
 #endif
 
   return true;
 }
 
-JS_FRIEND_API bool js::GetPropertyKeys(JSContext* cx, HandleObject obj,
+JS_PUBLIC_API bool js::GetPropertyKeys(JSContext* cx, HandleObject obj,
                                        unsigned flags,
                                        MutableHandleIdVector props) {
   return Snapshot(cx, obj,
                   flags & (JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS |
                            JSITER_SYMBOLSONLY | JSITER_PRIVATE),
                   props);
 }
 
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -242,17 +242,17 @@ bool AutoResolving::alreadyStartedSlow()
  * Since memory has been exhausted, avoid the normal error-handling path which
  * allocates an error object, report and callstack. If code is running, simply
  * throw the static atom "out of memory". If code is not running, call the
  * error reporter directly.
  *
  * Furthermore, callers of ReportOutOfMemory (viz., malloc) assume a GC does
  * not occur, so GC must be avoided or suppressed.
  */
-JS_FRIEND_API void js::ReportOutOfMemory(JSContext* cx) {
+JS_PUBLIC_API void js::ReportOutOfMemory(JSContext* cx) {
   /*
    * OOMs are non-deterministic, especially across different execution modes
    * (e.g. interpreter vs JIT). When doing differential testing, print to stderr
    * so that the fuzzers can detect this.
    */
   if (js::SupportDifferentialTesting()) {
     fprintf(stderr, "ReportOutOfMemory called\n");
   }
@@ -305,17 +305,17 @@ void js::ReportOverRecursed(JSContext* m
       maybecx->addPendingOverRecursed();
     }
 #ifdef DEBUG
     maybecx->hadOverRecursed_ = true;
 #endif
   }
 }
 
-JS_FRIEND_API void js::ReportOverRecursed(JSContext* maybecx) {
+JS_PUBLIC_API void js::ReportOverRecursed(JSContext* maybecx) {
   ReportOverRecursed(maybecx, JSMSG_OVER_RECURSED);
 }
 
 void js::ReportAllocationOverflow(JSContext* cx) {
   if (!cx) {
     return;
   }
 
@@ -672,17 +672,17 @@ void JSContext::recoverFromOutOfMemory()
   } else {
     if (isExceptionPending()) {
       MOZ_ASSERT(isThrowingOutOfMemory());
       clearPendingException();
     }
   }
 }
 
-JS_FRIEND_API bool js::UseInternalJobQueues(JSContext* cx) {
+JS_PUBLIC_API bool js::UseInternalJobQueues(JSContext* cx) {
   // Internal job queue handling must be set up very early. Self-hosting
   // initialization is as good a marker for that as any.
   MOZ_RELEASE_ASSERT(
       !cx->runtime()->hasInitializedSelfHosting(),
       "js::UseInternalJobQueues must be called early during runtime startup.");
   MOZ_ASSERT(!cx->jobQueue);
   auto queue = MakeUnique<InternalJobQueue>(cx);
   if (!queue) {
@@ -693,27 +693,27 @@ JS_FRIEND_API bool js::UseInternalJobQue
   cx->jobQueue = cx->internalJobQueue.ref().get();
 
   cx->runtime()->offThreadPromiseState.ref().initInternalDispatchQueue();
   MOZ_ASSERT(cx->runtime()->offThreadPromiseState.ref().initialized());
 
   return true;
 }
 
-JS_FRIEND_API bool js::EnqueueJob(JSContext* cx, JS::HandleObject job) {
+JS_PUBLIC_API bool js::EnqueueJob(JSContext* cx, JS::HandleObject job) {
   MOZ_ASSERT(cx->jobQueue);
   return cx->jobQueue->enqueuePromiseJob(cx, nullptr, job, nullptr, nullptr);
 }
 
-JS_FRIEND_API void js::StopDrainingJobQueue(JSContext* cx) {
+JS_PUBLIC_API void js::StopDrainingJobQueue(JSContext* cx) {
   MOZ_ASSERT(cx->internalJobQueue.ref());
   cx->internalJobQueue->interrupt();
 }
 
-JS_FRIEND_API void js::RunJobs(JSContext* cx) {
+JS_PUBLIC_API void js::RunJobs(JSContext* cx) {
   MOZ_ASSERT(cx->jobQueue);
   cx->jobQueue->runJobs(cx);
   JS::ClearKeptObjects(cx);
 }
 
 JSObject* InternalJobQueue::getIncumbentGlobal(JSContext* cx) {
   if (!cx->compartment()) {
     return nullptr;
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -1047,17 +1047,17 @@ static bool CopyPropertyFrom(JSContext* 
   if (!cx->compartment()->wrap(cx, &desc)) {
     return false;
   }
 
   Rooted<PropertyDescriptor> desc_(cx, *desc);
   return DefineProperty(cx, target, wrappedId, desc_);
 }
 
-JS_FRIEND_API bool JS_CopyOwnPropertiesAndPrivateFields(JSContext* cx,
+JS_PUBLIC_API bool JS_CopyOwnPropertiesAndPrivateFields(JSContext* cx,
                                                         HandleObject target,
                                                         HandleObject obj) {
   // Both |obj| and |target| must not be CCWs because we need to enter their
   // realms below and CCWs are not associated with a single realm.
   MOZ_ASSERT(!IsCrossCompartmentWrapper(obj));
   MOZ_ASSERT(!IsCrossCompartmentWrapper(target));
 
   JSAutoRealm ar(cx, obj);
@@ -1237,17 +1237,17 @@ static bool InitializePropertiesFromComp
   }
   for (size_t i = JSCLASS_RESERVED_SLOTS(src->getClass()); i < span; i++) {
     dst->setSlot(i, src->getSlot(i));
   }
 
   return true;
 }
 
-JS_FRIEND_API bool JS_InitializePropertiesFromCompatibleNativeObject(
+JS_PUBLIC_API bool JS_InitializePropertiesFromCompatibleNativeObject(
     JSContext* cx, HandleObject dst, HandleObject src) {
   return InitializePropertiesFromCompatibleNativeObject(
       cx, dst.as<NativeObject>(), src.as<NativeObject>());
 }
 
 template <XDRMode mode>
 XDRResult js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj) {
   /* NB: Keep this in sync with DeepCloneObjectLiteral. */
@@ -2535,17 +2535,17 @@ bool js::GetPropertyDescriptor(
 
 extern bool PropertySpecNameToId(JSContext* cx, JSPropertySpec::Name name,
                                  MutableHandleId id,
                                  js::PinningBehavior pin = js::DoNotPinAtom);
 
 // If a property or method is part of an experimental feature that can be
 // disabled at run-time by a preference, we keep it in the JSFunctionSpec /
 // JSPropertySpec list, but omit the definition if the preference is off.
-JS_FRIEND_API bool js::ShouldIgnorePropertyDefinition(JSContext* cx,
+JS_PUBLIC_API bool js::ShouldIgnorePropertyDefinition(JSContext* cx,
                                                       JSProtoKey key, jsid id) {
   if (!cx->realm()->creationOptions().getToSourceEnabled() &&
       (id == NameToId(cx->names().toSource) ||
        id == NameToId(cx->names().uneval))) {
     return true;
   }
 
   if (key == JSProto_FinalizationRegistry &&
@@ -3122,31 +3122,31 @@ static void dumpValue(const Value& v, js
   }
 }
 
 namespace js {
 
 // We don't want jsfriendapi.h to depend on GenericPrinter,
 // so these functions are declared directly in the cpp.
 
-JS_FRIEND_API void DumpValue(const JS::Value& val, js::GenericPrinter& out);
-
-JS_FRIEND_API void DumpId(jsid id, js::GenericPrinter& out);
-
-JS_FRIEND_API void DumpInterpreterFrame(JSContext* cx, js::GenericPrinter& out,
+JS_PUBLIC_API void DumpValue(const JS::Value& val, js::GenericPrinter& out);
+
+JS_PUBLIC_API void DumpId(jsid id, js::GenericPrinter& out);
+
+JS_PUBLIC_API void DumpInterpreterFrame(JSContext* cx, js::GenericPrinter& out,
                                         InterpreterFrame* start = nullptr);
 
 }  // namespace js
 
-JS_FRIEND_API void js::DumpValue(const Value& val, js::GenericPrinter& out) {
+JS_PUBLIC_API void js::DumpValue(const Value& val, js::GenericPrinter& out) {
   dumpValue(val, out);
   out.putChar('\n');
 }
 
-JS_FRIEND_API void js::DumpId(jsid id, js::GenericPrinter& out) {
+JS_PUBLIC_API void js::DumpId(jsid id, js::GenericPrinter& out) {
   out.printf("jsid %p = ", (void*)JSID_BITS(id));
   dumpValue(IdToValue(id), out);
   out.putChar('\n');
 }
 
 static void DumpProperty(const NativeObject* obj, Shape& shape,
                          js::GenericPrinter& out) {
   PropertyInfoWithKey prop = shape.propertyInfoWithKey();
@@ -3386,17 +3386,17 @@ static void MaybeDumpValue(const char* n
                            js::GenericPrinter& out) {
   if (!v.isNull()) {
     out.printf("  %s: ", name);
     dumpValue(v, out);
     out.putChar('\n');
   }
 }
 
-JS_FRIEND_API void js::DumpInterpreterFrame(JSContext* cx,
+JS_PUBLIC_API void js::DumpInterpreterFrame(JSContext* cx,
                                             js::GenericPrinter& out,
                                             InterpreterFrame* start) {
   /* This should only called during live debugging. */
   ScriptFrameIter i(cx);
   if (!start) {
     if (i.done()) {
       out.printf("no stack for cx = %p\n", (void*)cx);
       return;
@@ -3467,26 +3467,26 @@ JS_FRIEND_API void js::DumpInterpreterFr
 
 #endif /* defined(DEBUG) || defined(JS_JITSPEW) */
 
 namespace js {
 
 // We don't want jsfriendapi.h to depend on GenericPrinter,
 // so these functions are declared directly in the cpp.
 
-JS_FRIEND_API void DumpBacktrace(JSContext* cx, js::GenericPrinter& out);
+JS_PUBLIC_API void DumpBacktrace(JSContext* cx, js::GenericPrinter& out);
 
 }  // namespace js
 
-JS_FRIEND_API void js::DumpBacktrace(JSContext* cx, FILE* fp) {
+JS_PUBLIC_API void js::DumpBacktrace(JSContext* cx, FILE* fp) {
   Fprinter out(fp);
   js::DumpBacktrace(cx, out);
 }
 
-JS_FRIEND_API void js::DumpBacktrace(JSContext* cx, js::GenericPrinter& out) {
+JS_PUBLIC_API void js::DumpBacktrace(JSContext* cx, js::GenericPrinter& out) {
   size_t depth = 0;
   for (AllFramesIter i(cx); !i.done(); ++i, ++depth) {
     const char* filename;
     unsigned line;
     if (i.hasScript()) {
       filename = JS_GetScriptFilename(i.script());
       line = PCToLineNumber(i.script(), i.pc());
     } else {
@@ -3505,17 +3505,17 @@ JS_FRIEND_API void js::DumpBacktrace(JSC
     if (i.hasScript()) {
       out.printf(" (%p @ %zu)\n", i.script(), i.script()->pcToOffset(i.pc()));
     } else {
       out.printf(" (%p)\n", i.pc());
     }
   }
 }
 
-JS_FRIEND_API void js::DumpBacktrace(JSContext* cx) {
+JS_PUBLIC_API void js::DumpBacktrace(JSContext* cx) {
   DumpBacktrace(cx, stdout);
 }
 
 /* * */
 
 js::gc::AllocKind JSObject::allocKindForTenure(
     const js::Nursery& nursery) const {
   using namespace js::gc;
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -4052,17 +4052,17 @@ jsbytecode* js::LineNumberToPC(JSScript*
   }
   if (best >= 0) {
     offset = best;
   }
 out:
   return script->offsetToPC(offset);
 }
 
-JS_FRIEND_API unsigned js::GetScriptLineExtent(JSScript* script) {
+JS_PUBLIC_API unsigned js::GetScriptLineExtent(JSScript* script) {
   unsigned lineno = script->lineno();
   unsigned maxLineNo = lineno;
   for (SrcNoteIterator iter(script->notes()); !iter.atEnd(); ++iter) {
     auto sn = *iter;
     SrcNoteType type = sn->type();
     if (type == SrcNoteType::SetLine) {
       lineno = SrcNote::SetLine::getLine(sn, script->lineno());
     } else if (type == SrcNoteType::NewLine) {
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2363,17 +2363,17 @@ struct GSNCache;
 const js::SrcNote* GetSrcNote(GSNCache& cache, JSScript* script,
                               jsbytecode* pc);
 
 extern const js::SrcNote* GetSrcNote(JSContext* cx, JSScript* script,
                                      jsbytecode* pc);
 
 extern jsbytecode* LineNumberToPC(JSScript* script, unsigned lineno);
 
-extern JS_FRIEND_API unsigned GetScriptLineExtent(JSScript* script);
+extern JS_PUBLIC_API unsigned GetScriptLineExtent(JSScript* script);
 
 #ifdef JS_CACHEIR_SPEW
 void maybeUpdateWarmUpCount(JSScript* script);
 void maybeSpewScriptFinalWarmUpCount(JSScript* script);
 #endif
 
 } /* namespace js */
 
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -40,17 +40,17 @@ using namespace js;
 
 using JS::ObjectPrivateVisitor;
 using JS::RealmStats;
 using JS::RuntimeStats;
 using JS::ZoneStats;
 
 namespace js {
 
-JS_FRIEND_API size_t MemoryReportingSundriesThreshold() { return 8 * 1024; }
+JS_PUBLIC_API size_t MemoryReportingSundriesThreshold() { return 8 * 1024; }
 
 /* static */
 HashNumber InefficientNonFlatteningStringHashPolicy::hash(const Lookup& l) {
   if (l->isLinear()) {
     return HashStringChars(&l->asLinear());
   }
 
   // Use rope's non-copying hash function.
--- a/js/src/vm/ProxyObject.cpp
+++ b/js/src/vm/ProxyObject.cpp
@@ -193,14 +193,14 @@ void ProxyObject::nuke() {
   // The proxy's reserved slots are not cleared and will continue to be
   // traced. This avoids the possibility of triggering write barriers while
   // nuking proxies in dead compartments which could otherwise cause those
   // compartments to be kept alive. Note that these are slots cannot hold
   // cross compartment pointers, so this cannot cause the target compartment
   // to leak.
 }
 
-JS_FRIEND_API void js::detail::SetValueInProxy(Value* slot,
+JS_PUBLIC_API void js::detail::SetValueInProxy(Value* slot,
                                                const Value& value) {
   // Slots in proxies are not GCPtrValues, so do a cast whenever assigning
   // values to them which might trigger a barrier.
   *reinterpret_cast<GCPtrValue*>(slot) = value;
 }
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -679,17 +679,17 @@ js::HashNumber JSRuntime::randomHashCode
     mozilla::Array<uint64_t, 2> seed;
     GenerateXorShift128PlusSeed(seed);
     randomHashCodeGenerator_.emplace(seed[0], seed[1]);
   }
 
   return HashNumber(randomHashCodeGenerator_->next());
 }
 
-JS_FRIEND_API void* JSRuntime::onOutOfMemory(AllocFunction allocFunc,
+JS_PUBLIC_API void* JSRuntime::onOutOfMemory(AllocFunction allocFunc,
                                              arena_id_t arena, size_t nbytes,
                                              void* reallocPtr,
                                              JSContext* maybecx) {
   MOZ_ASSERT_IF(allocFunc != AllocFunction::Realloc, !reallocPtr);
 
   if (JS::RuntimeHeapIsBusy()) {
     return nullptr;
   }
@@ -825,34 +825,34 @@ bool js::CurrentThreadCanAccessZone(Zone
 
 #ifdef DEBUG
 bool js::CurrentThreadIsPerformingGC() {
   JSContext* cx = TlsContext.get();
   return cx->defaultFreeOp()->isCollecting();
 }
 #endif
 
-JS_FRIEND_API void JS::SetJSContextProfilerSampleBufferRangeStart(
+JS_PUBLIC_API void JS::SetJSContextProfilerSampleBufferRangeStart(
     JSContext* cx, uint64_t rangeStart) {
   cx->runtime()->setProfilerSampleBufferRangeStart(rangeStart);
 }
 
-JS_FRIEND_API bool JS::IsProfilingEnabledForContext(JSContext* cx) {
+JS_PUBLIC_API bool JS::IsProfilingEnabledForContext(JSContext* cx) {
   MOZ_ASSERT(cx);
   return cx->runtime()->geckoProfiler().enabled();
 }
 
-JS_FRIEND_API void JS::EnableRecordingAllocations(
+JS_PUBLIC_API void JS::EnableRecordingAllocations(
     JSContext* cx, JS::RecordAllocationsCallback callback, double probability) {
   MOZ_ASSERT(cx);
   MOZ_ASSERT(cx->isMainThreadContext());
   cx->runtime()->startRecordingAllocations(probability, callback);
 }
 
-JS_FRIEND_API void JS::DisableRecordingAllocations(JSContext* cx) {
+JS_PUBLIC_API void JS::DisableRecordingAllocations(JSContext* cx) {
   MOZ_ASSERT(cx);
   MOZ_ASSERT(cx->isMainThreadContext());
   cx->runtime()->stopRecordingAllocations();
 }
 
 JS_PUBLIC_API void JS::shadow::RegisterWeakCache(
     JSRuntime* rt, detail::WeakCacheBase* cachep) {
   rt->registerWeakCache(cachep);
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -919,23 +919,23 @@ struct JSRuntime {
 
   /*
    * This should be called after system malloc/calloc/realloc returns nullptr
    * to try to recove some memory or to report an error.  For realloc, the
    * original pointer must be passed as reallocPtr.
    *
    * The function must be called outside the GC lock.
    */
-  JS_FRIEND_API void* onOutOfMemory(js::AllocFunction allocator,
+  JS_PUBLIC_API void* onOutOfMemory(js::AllocFunction allocator,
                                     arena_id_t arena, size_t nbytes,
                                     void* reallocPtr = nullptr,
                                     JSContext* maybecx = nullptr);
 
   /*  onOutOfMemory but can call OnLargeAllocationFailure. */
-  JS_FRIEND_API void* onOutOfMemoryCanGC(js::AllocFunction allocator,
+  JS_PUBLIC_API void* onOutOfMemoryCanGC(js::AllocFunction allocator,
                                          arena_id_t arena, size_t nbytes,
                                          void* reallocPtr = nullptr);
 
   static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
 
   void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
                               JS::RuntimeSizes* rtSizes);
 
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -656,17 +656,17 @@ static SavedFrame* GetFirstSubsumedFrame
                                          JSPrincipals* principals,
                                          HandleSavedFrame frame,
                                          JS::SavedFrameSelfHosted selfHosted,
                                          bool& skippedAsync) {
   return GetFirstMatchedFrame(cx, principals, SavedFrameSubsumedByPrincipals,
                               frame, selfHosted, skippedAsync);
 }
 
-JS_FRIEND_API JSObject* GetFirstSubsumedSavedFrame(
+JS_PUBLIC_API JSObject* GetFirstSubsumedSavedFrame(
     JSContext* cx, JSPrincipals* principals, HandleObject savedFrame,
     JS::SavedFrameSelfHosted selfHosted) {
   if (!savedFrame) {
     return nullptr;
   }
 
   auto subsumes = cx->runtime()->securityCallbacks->subsumes;
   if (!subsumes) {
--- a/js/src/vm/SharedArrayObject.cpp
+++ b/js/src/vm/SharedArrayObject.cpp
@@ -429,50 +429,50 @@ const JSClass SharedArrayBufferObject::c
     &SharedArrayBufferObjectClassOps, &SharedArrayBufferObjectClassSpec,
     JS_NULL_CLASS_EXT};
 
 const JSClass SharedArrayBufferObject::protoClass_ = {
     "SharedArrayBuffer.prototype",
     JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer), JS_NULL_CLASS_OPS,
     &SharedArrayBufferObjectClassSpec};
 
-JS_FRIEND_API size_t JS::GetSharedArrayBufferByteLength(JSObject* obj) {
+JS_PUBLIC_API size_t JS::GetSharedArrayBufferByteLength(JSObject* obj) {
   auto* aobj = obj->maybeUnwrapAs<SharedArrayBufferObject>();
   return aobj ? aobj->byteLength() : 0;
 }
 
-JS_FRIEND_API void JS::GetSharedArrayBufferLengthAndData(JSObject* obj,
+JS_PUBLIC_API void JS::GetSharedArrayBufferLengthAndData(JSObject* obj,
                                                          size_t* length,
                                                          bool* isSharedMemory,
                                                          uint8_t** data) {
   MOZ_ASSERT(obj->is<SharedArrayBufferObject>());
   *length = obj->as<SharedArrayBufferObject>().byteLength();
   *data = obj->as<SharedArrayBufferObject>().dataPointerShared().unwrap(
       /*safe - caller knows*/);
   *isSharedMemory = true;
 }
 
-JS_FRIEND_API JSObject* JS::NewSharedArrayBuffer(JSContext* cx, size_t nbytes) {
+JS_PUBLIC_API JSObject* JS::NewSharedArrayBuffer(JSContext* cx, size_t nbytes) {
   MOZ_ASSERT(cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled());
 
   if (nbytes > ArrayBufferObject::maxBufferByteLength()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_SHARED_ARRAY_BAD_LENGTH);
     return nullptr;
   }
 
   return SharedArrayBufferObject::New(cx, nbytes,
                                       /* proto = */ nullptr);
 }
 
-JS_FRIEND_API bool JS::IsSharedArrayBufferObject(JSObject* obj) {
+JS_PUBLIC_API bool JS::IsSharedArrayBufferObject(JSObject* obj) {
   return obj->canUnwrapAs<SharedArrayBufferObject>();
 }
 
-JS_FRIEND_API uint8_t* JS::GetSharedArrayBufferData(
+JS_PUBLIC_API uint8_t* JS::GetSharedArrayBufferData(
     JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&) {
   auto* aobj = obj->maybeUnwrapAs<SharedArrayBufferObject>();
   if (!aobj) {
     return nullptr;
   }
   *isSharedMemory = true;
   return aobj->dataPointerShared().unwrap(/*safe - caller knows*/);
 }
--- a/js/src/vm/SourceHook.cpp
+++ b/js/src/vm/SourceHook.cpp
@@ -5,22 +5,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "js/experimental/SourceHook.h"
 
 #include "mozilla/UniquePtr.h"  // mozilla::UniquePtr
 
 #include <utility>  // std::move
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "jstypes.h"  // JS_PUBLIC_API
 
 #include "vm/JSContext.h"  // JSContext
 #include "vm/Runtime.h"    // JSRuntime
 
-JS_FRIEND_API void js::SetSourceHook(JSContext* cx,
+JS_PUBLIC_API void js::SetSourceHook(JSContext* cx,
                                      mozilla::UniquePtr<SourceHook> hook) {
   cx->runtime()->sourceHook.ref() = std::move(hook);
 }
 
-JS_FRIEND_API mozilla::UniquePtr<js::SourceHook> js::ForgetSourceHook(
+JS_PUBLIC_API mozilla::UniquePtr<js::SourceHook> js::ForgetSourceHook(
     JSContext* cx) {
   return std::move(cx->runtime()->sourceHook.ref());
 }
--- a/js/src/vm/StringType.h
+++ b/js/src/vm/StringType.h
@@ -35,17 +35,17 @@
 class JSDependentString;
 class JSExtensibleString;
 class JSExternalString;
 class JSInlineString;
 class JSRope;
 
 namespace JS {
 
-class JS_FRIEND_API AutoStableStringChars;
+class JS_PUBLIC_API AutoStableStringChars;
 
 }  // namespace JS
 
 namespace js {
 
 namespace frontend {
 
 class ParserAtomsTable;
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -593,17 +593,17 @@ struct JSStructuredCloneWriter {
 
   const JS::CloneDataPolicy cloneDataPolicy;
 
   friend bool JS_WriteString(JSStructuredCloneWriter* w, HandleString str);
   friend bool JS_WriteTypedArray(JSStructuredCloneWriter* w, HandleValue v);
   friend bool JS_ObjectNotWritten(JSStructuredCloneWriter* w, HandleObject obj);
 };
 
-JS_FRIEND_API uint64_t js::GetSCOffset(JSStructuredCloneWriter* writer) {
+JS_PUBLIC_API uint64_t js::GetSCOffset(JSStructuredCloneWriter* writer) {
   MOZ_ASSERT(writer);
   return writer->output().count() * sizeof(uint64_t);
 }
 
 static_assert(SCTAG_END_OF_BUILTIN_TYPES <= JS_SCTAG_USER_MIN);
 static_assert(JS_SCTAG_USER_MIN <= JS_SCTAG_USER_MAX);
 static_assert(Scalar::Int8 == 0);
 
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -2621,130 +2621,130 @@ struct ExternalTypeOf {
 };
 
 template <>
 struct ExternalTypeOf<uint8_clamped> {
   using Type = uint8_t;
 };
 
 #define IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(NativeType, Name)                \
-  JS_FRIEND_API JSObject* JS_New##Name##Array(JSContext* cx,                 \
+  JS_PUBLIC_API JSObject* JS_New##Name##Array(JSContext* cx,                 \
                                               size_t nelements) {            \
     return TypedArrayObjectTemplate<NativeType>::fromLength(cx, nelements);  \
   }                                                                          \
                                                                              \
-  JS_FRIEND_API JSObject* JS_New##Name##ArrayFromArray(JSContext* cx,        \
+  JS_PUBLIC_API JSObject* JS_New##Name##ArrayFromArray(JSContext* cx,        \
                                                        HandleObject other) { \
     return TypedArrayObjectTemplate<NativeType>::fromArray(cx, other);       \
   }                                                                          \
                                                                              \
-  JS_FRIEND_API JSObject* JS_New##Name##ArrayWithBuffer(                     \
+  JS_PUBLIC_API JSObject* JS_New##Name##ArrayWithBuffer(                     \
       JSContext* cx, HandleObject arrayBuffer, size_t byteOffset,            \
       int64_t length) {                                                      \
     return TypedArrayObjectTemplate<NativeType>::fromBuffer(                 \
         cx, arrayBuffer, byteOffset, length);                                \
   }                                                                          \
                                                                              \
-  JS_FRIEND_API JSObject* js::Unwrap##Name##Array(JSObject* obj) {           \
+  JS_PUBLIC_API JSObject* js::Unwrap##Name##Array(JSObject* obj) {           \
     obj = obj->maybeUnwrapIf<TypedArrayObject>();                            \
     if (!obj) {                                                              \
       return nullptr;                                                        \
     }                                                                        \
     const JSClass* clasp = obj->getClass();                                  \
     if (clasp != TypedArrayObjectTemplate<NativeType>::instanceClass()) {    \
       return nullptr;                                                        \
     }                                                                        \
     return obj;                                                              \
   }                                                                          \
                                                                              \
-  JS_FRIEND_API bool JS_Is##Name##Array(JSObject* obj) {                     \
+  JS_PUBLIC_API bool JS_Is##Name##Array(JSObject* obj) {                     \
     return js::Unwrap##Name##Array(obj) != nullptr;                          \
   }                                                                          \
                                                                              \
   const JSClass* const js::detail::Name##ArrayClassPtr =                     \
       &js::TypedArrayObject::classes                                         \
           [TypedArrayObjectTemplate<NativeType>::ArrayTypeID()];             \
                                                                              \
-  JS_FRIEND_API JSObject* JS_GetObjectAs##Name##Array(                       \
+  JS_PUBLIC_API JSObject* JS_GetObjectAs##Name##Array(                       \
       JSObject* obj, size_t* length, bool* isShared,                         \
       ExternalTypeOf<NativeType>::Type** data) {                             \
     obj = js::Unwrap##Name##Array(obj);                                      \
     if (!obj) {                                                              \
       return nullptr;                                                        \
     }                                                                        \
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();                   \
     *length = tarr->length();                                                \
     *isShared = tarr->isSharedMemory();                                      \
     *data = static_cast<ExternalTypeOf<NativeType>::Type*>(                  \
         tarr->dataPointerEither().unwrap(                                    \
             /*safe - caller sees isShared flag*/));                          \
     return obj;                                                              \
   }                                                                          \
                                                                              \
-  JS_FRIEND_API ExternalTypeOf<NativeType>::Type* JS_Get##Name##ArrayData(   \
+  JS_PUBLIC_API ExternalTypeOf<NativeType>::Type* JS_Get##Name##ArrayData(   \
       JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&) {     \
     TypedArrayObject* tarr = obj->maybeUnwrapAs<TypedArrayObject>();         \
     if (!tarr) {                                                             \
       return nullptr;                                                        \
     }                                                                        \
     MOZ_ASSERT(tarr->type() == TypeIDOfType<NativeType>::id);                \
     *isSharedMemory = tarr->isSharedMemory();                                \
     return static_cast<ExternalTypeOf<NativeType>::Type*>(                   \
         tarr->dataPointerEither().unwrap(/*safe - caller sees isShared*/));  \
   }
 
 JS_FOR_EACH_TYPED_ARRAY(IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS)
 #undef IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS
 
-JS_FRIEND_API bool JS_IsTypedArrayObject(JSObject* obj) {
+JS_PUBLIC_API bool JS_IsTypedArrayObject(JSObject* obj) {
   return obj->canUnwrapAs<TypedArrayObject>();
 }
 
-JS_FRIEND_API size_t JS_GetTypedArrayLength(JSObject* obj) {
+JS_PUBLIC_API size_t JS_GetTypedArrayLength(JSObject* obj) {
   TypedArrayObject* tarr = obj->maybeUnwrapAs<TypedArrayObject>();
   if (!tarr) {
     return 0;
   }
   return tarr->length();
 }
 
-JS_FRIEND_API size_t JS_GetTypedArrayByteOffset(JSObject* obj) {
+JS_PUBLIC_API size_t JS_GetTypedArrayByteOffset(JSObject* obj) {
   TypedArrayObject* tarr = obj->maybeUnwrapAs<TypedArrayObject>();
   if (!tarr) {
     return 0;
   }
   return tarr->byteOffset();
 }
 
-JS_FRIEND_API size_t JS_GetTypedArrayByteLength(JSObject* obj) {
+JS_PUBLIC_API size_t JS_GetTypedArrayByteLength(JSObject* obj) {
   TypedArrayObject* tarr = obj->maybeUnwrapAs<TypedArrayObject>();
   if (!tarr) {
     return 0;
   }
   return tarr->byteLength();
 }
 
-JS_FRIEND_API bool JS_GetTypedArraySharedness(JSObject* obj) {
+JS_PUBLIC_API bool JS_GetTypedArraySharedness(JSObject* obj) {
   TypedArrayObject* tarr = obj->maybeUnwrapAs<TypedArrayObject>();
   if (!tarr) {
     return false;
   }
   return tarr->isSharedMemory();
 }
 
-JS_FRIEND_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj) {
+JS_PUBLIC_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj) {
   ArrayBufferViewObject* view = obj->maybeUnwrapAs<ArrayBufferViewObject>();
   if (!view) {
     return Scalar::MaxTypedArrayViewType;
   }
 
   if (view->is<TypedArrayObject>()) {
     return view->as<TypedArrayObject>().type();
   }
   if (view->is<DataViewObject>()) {
     return Scalar::MaxTypedArrayViewType;
   }
   MOZ_CRASH("invalid ArrayBufferView type");
 }
 
-JS_FRIEND_API size_t JS_MaxMovableTypedArraySize() {
+JS_PUBLIC_API size_t JS_MaxMovableTypedArraySize() {
   return TypedArrayObject::INLINE_BUFFER_LIMIT;
 }