Bug 1602882 - Move array operations to a new js/Array.h header. r=sfink,bzbarsky
authorJeff Walden <jwalden@mit.edu>
Wed, 11 Dec 2019 06:17:44 +0000
changeset 506368 f83f2771414cf5938a46f44e1b11cdcd5181ea0f
parent 506367 2d7d6f9a04a47be448eba7f68e71067346ba5297
child 506369 8c086b8b46df392416b80553fa804a1503fc6b9c
push id36903
push userncsoregi@mozilla.com
push dateWed, 11 Dec 2019 09:46:40 +0000
treeherdermozilla-central@f83f2771414c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, bzbarsky
bugs1602882
milestone73.0a1
first release with
nightly linux32
f83f2771414c / 73.0a1 / 20191211094640 / files
nightly linux64
f83f2771414c / 73.0a1 / 20191211094640 / files
nightly mac
f83f2771414c / 73.0a1 / 20191211094640 / files
nightly win32
f83f2771414c / 73.0a1 / 20191211094640 / files
nightly win64
f83f2771414c / 73.0a1 / 20191211094640 / 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 1602882 - Move array operations to a new js/Array.h header. r=sfink,bzbarsky Differential Revision: https://phabricator.services.mozilla.com/D56595
devtools/shared/heapsnapshot/HeapSnapshot.cpp
dom/base/nsContentUtils.cpp
dom/base/nsJSEnvironment.cpp
dom/bindings/Codegen.py
dom/bindings/ToJSValue.h
dom/cache/Cache.cpp
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasUtils.h
dom/canvas/WebGL2ContextUniforms.cpp
dom/console/Console.cpp
dom/filesystem/compat/FileSystemDirectoryReader.cpp
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/Key.cpp
dom/indexedDB/Key.h
dom/indexedDB/KeyPath.cpp
dom/indexedDB/test/gtest/TestKey.cpp
dom/media/webaudio/AudioWorkletGlobalScope.cpp
dom/media/webaudio/AudioWorkletNode.cpp
dom/reporting/ReportingHeader.cpp
dom/script/ScriptLoader.cpp
dom/security/nsContentSecurityUtils.cpp
dom/serviceworkers/ServiceWorkerScriptCache.cpp
js/public/Array.h
js/public/Class.h
js/public/Modules.h
js/public/Proxy.h
js/rust/build.rs
js/rust/etc/wrapper.hpp
js/rust/src/conversions.rs
js/rust/tests/vec_conversion.rs
js/src/builtin/Array.cpp
js/src/builtin/TestingFunctions.cpp
js/src/ctypes/CTypes.cpp
js/src/gdb/tests/test-Root.cpp
js/src/jsapi-tests/testAddPropertyPropcache.cpp
js/src/jsapi-tests/testArrayBuffer.cpp
js/src/jsapi-tests/testInformalValueTypeName.cpp
js/src/jsapi-tests/testMappedArrayBuffer.cpp
js/src/jsapi-tests/testNewObject.cpp
js/src/jsapi-tests/testParseJSON.cpp
js/src/jsapi-tests/testWeakMap.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/moz.build
js/src/proxy/Proxy.h
js/src/shell/js.cpp
js/src/vm/IsGivenTypeObject-inl.h
js/src/vm/StructuredClone.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/XPCVariant.cpp
js/xpconnect/src/XPCWrappedNative.cpp
layout/style/FontFaceSetIterator.cpp
mobile/android/components/geckoview/GeckoViewHistory.cpp
netwerk/base/LoadInfo.cpp
storage/mozStorageStatementRow.cpp
toolkit/components/backgroundhangmonitor/HangDetails.cpp
toolkit/components/places/History.cpp
toolkit/components/places/PlaceInfo.cpp
toolkit/components/sessionstore/SessionStoreUtils.cpp
toolkit/components/telemetry/core/Telemetry.cpp
toolkit/components/telemetry/core/TelemetryEvent.cpp
toolkit/components/telemetry/core/TelemetryHistogram.cpp
toolkit/components/telemetry/core/TelemetryOrigin.cpp
toolkit/components/telemetry/core/TelemetryScalar.cpp
toolkit/components/telemetry/other/CombinedStacks.cpp
toolkit/components/telemetry/other/KeyedStackCapturer.cpp
toolkit/components/telemetry/other/TelemetryIOInterposeObserver.cpp
toolkit/components/telemetry/other/UntrustedModules.cpp
toolkit/components/telemetry/tests/gtest/TelemetryTestHelpers.cpp
toolkit/components/telemetry/tests/gtest/TestEvents.cpp
toolkit/mozapps/extensions/AddonManagerStartup-inlines.h
toolkit/mozapps/extensions/AddonManagerStartup.cpp
toolkit/recordreplay/ipc/JSControl.cpp
tools/profiler/gecko/nsProfiler.cpp
widget/GfxInfoBase.cpp
widget/android/EventDispatcher.cpp
widget/cocoa/nsMacSharingService.mm
--- a/devtools/shared/heapsnapshot/HeapSnapshot.cpp
+++ b/devtools/shared/heapsnapshot/HeapSnapshot.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "HeapSnapshot.h"
 
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/gzip_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/Debug.h"
 #include "js/TypeDecls.h"
 #include "js/UbiNodeBreadthFirst.h"
 #include "js/UbiNodeCensus.h"
 #include "js/UbiNodeDominatorTree.h"
 #include "js/UbiNodeShortestPaths.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CycleCollectedJSContext.h"
@@ -626,26 +627,26 @@ void HeapSnapshot::ComputeShortestPaths(
           return false;
         }
 
         if (!pathValues.append(ObjectValue(*pathPart))) {
           return false;
         }
       }
 
-      RootedObject pathObj(cx, JS_NewArrayObject(cx, pathValues));
+      RootedObject pathObj(cx, JS::NewArrayObject(cx, pathValues));
       return pathObj && paths.append(ObjectValue(*pathObj));
     });
 
     if (NS_WARN_IF(!ok)) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
 
-    JS::RootedObject pathsArray(cx, JS_NewArrayObject(cx, paths));
+    JS::RootedObject pathsArray(cx, JS::NewArrayObject(cx, paths));
     if (NS_WARN_IF(!pathsArray)) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
 
     JS::RootedValue pathsVal(cx, ObjectValue(*pathsArray));
     if (NS_WARN_IF(!JS::MapSet(cx, resultsMap, key, pathsVal))) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -15,16 +15,17 @@
 #include "harfbuzz/hb.h"
 #include "imgICache.h"
 #include "imgIContainer.h"
 #include "imgINotificationObserver.h"
 #include "imgLoader.h"
 #include "imgRequestProxy.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"        // JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{GetArrayBufferData,IsArrayBufferObject,NewArrayBuffer}
 #include "js/JSON.h"
 #include "js/RegExp.h"  // JS::ExecuteRegExpNoStatics, JS::NewUCRegExpObject, JS::RegExpFlags
 #include "js/Value.h"
 #include "Layers.h"
 #include "nsAppRunner.h"
 // nsNPAPIPluginInstance must be included before mozilla/dom/Document.h, which
 // is included in mozAutoDocUpdate.h.
@@ -9556,17 +9557,17 @@ void nsContentUtils::GetContentPolicyTyp
 /* static */
 nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
     JSContext* aCx, const Sequence<JSObject*>& aTransfer,
     JS::MutableHandle<JS::Value> aValue) {
   if (aTransfer.IsEmpty()) {
     return NS_OK;
   }
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aTransfer.Length()));
+  JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
     JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
     if (!object) {
       continue;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -35,16 +35,17 @@
 #  include <process.h>
 #  define getpid _getpid
 #else
 #  include <unistd.h>  // for getpid()
 #endif
 #include "xpcpublic.h"
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/PropertySpec.h"
 #include "js/SliceBudget.h"
 #include "js/Wrapper.h"
 #include "nsIArray.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/MainThreadIdlePeriod.h"
@@ -723,17 +724,17 @@ nsresult nsJSContext::SetProperty(JS::Ha
   // got the arguments, now attach them.
 
   for (uint32_t i = 0; i < args.length(); ++i) {
     if (!JS_WrapValue(cx, args[i])) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  JS::Rooted<JSObject*> array(cx, ::JS_NewArrayObject(cx, args));
+  JS::Rooted<JSObject*> array(cx, JS::NewArrayObject(cx, args));
   if (!array) {
     return NS_ERROR_FAILURE;
   }
 
   return JS_DefineProperty(cx, aTarget, aPropName, array, 0) ? NS_OK
                                                              : NS_ERROR_FAILURE;
 }
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1130,24 +1130,27 @@ class CGHeaders(CGWrapper):
             """
             t, dictionary = typeAndPossibleDictionary
             # Dictionaries have members that need to be actually
             # declared, not just forward-declared.
             if dictionary:
                 headerSet = declareIncludes
             else:
                 headerSet = bindingHeaders
-            # Strip off outer layers and add headers they might (conservatively:
-            # only nullable non-pointer types need Nullable.h, and only
-            # sequences outside unions require ForOfIterator.h) require.
+            # Strip off outer layers and add headers they might require.  (This
+            # is conservative: only nullable non-pointer types need Nullable.h;
+            # only sequences outside unions need ForOfIterator.h; only functions
+            # that return, and attributes that are, sequences in interfaces need
+            # Array.h, &c.)
             unrolled = t
             while True:
                 if unrolled.nullable():
                     headerSet.add("mozilla/dom/Nullable.h")
                 elif unrolled.isSequence():
+                    bindingHeaders.add("js/Array.h")
                     bindingHeaders.add("js/ForOfIterator.h")
                 else:
                     break
                 unrolled = unrolled.inner
             if unrolled.isUnion():
                 headerSet.add(self.getUnionDeclarationFilename(config, unrolled))
                 bindingHeaders.add("mozilla/dom/UnionConversions.h")
             elif unrolled.isDate():
@@ -6856,17 +6859,17 @@ def getWrapTemplateForType(type, descrip
                 'obj': "returnArray",
                 'spiderMonkeyInterfacesAreStructs': spiderMonkeyInterfacesAreStructs
             })
         sequenceWrapLevel -= 1
         code = fill(
             """
 
             uint32_t length = ${result}.Length();
-            JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
+            JS::Rooted<JSObject*> returnArray(cx, JS::NewArrayObject(cx, length));
             if (!returnArray) {
               $*{exceptionCode}
             }
             // Scope for 'tmp'
             {
               JS::Rooted<JS::Value> tmp(cx);
               for (uint32_t ${index} = 0; ${index} < length; ++${index}) {
                 // Control block to let us common up the JS_DefineElement calls when there
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -9,16 +9,17 @@
 
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/NonRefcountedDOMObject.h"
 #include "mozilla/dom/TypedArray.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "nsISupports.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -357,17 +358,17 @@ MOZ_MUST_USE bool ToJSValue(JSContext* a
   if (!v.resize(aLength)) {
     return false;
   }
   for (size_t i = 0; i < aLength; ++i) {
     if (!ToJSValue(aCx, aArguments[i], v[i])) {
       return false;
     }
   }
-  JSObject* arrayObj = JS_NewArrayObject(aCx, v);
+  JSObject* arrayObj = JS::NewArrayObject(aCx, v);
   if (!arrayObj) {
     return false;
   }
   aValue.setObject(*arrayObj);
   return true;
 }
 
 }  // namespace dom
--- a/dom/cache/Cache.cpp
+++ b/dom/cache/Cache.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "mozilla/dom/cache/Cache.h"
 
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/InternalResponse.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/CacheBinding.h"
 #include "mozilla/dom/cache/AutoUtils.h"
@@ -123,25 +124,25 @@ class Cache::FetchHandler final : public
     // Promise::All() passed an array of fetch() Promises should give us
     // an Array of Response objects.  The following code unwraps these
     // JS values back to an nsTArray<RefPtr<Response>>.
 
     AutoTArray<RefPtr<Response>, 256> responseList;
     responseList.SetCapacity(mRequestList.Length());
 
     bool isArray;
-    if (NS_WARN_IF(!JS_IsArrayObject(aCx, aValue, &isArray) || !isArray)) {
+    if (NS_WARN_IF(!JS::IsArrayObject(aCx, aValue, &isArray) || !isArray)) {
       Fail();
       return;
     }
 
     JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
 
     uint32_t length;
-    if (NS_WARN_IF(!JS_GetArrayLength(aCx, obj, &length))) {
+    if (NS_WARN_IF(!JS::GetArrayLength(aCx, obj, &length))) {
       Fail();
       return;
     }
 
     for (uint32_t i = 0; i < length; ++i) {
       JS::Rooted<JS::Value> value(aCx);
 
       if (NS_WARN_IF(!JS_GetElement(aCx, obj, i, &value))) {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -60,16 +60,17 @@
 #include "nsIMemoryReporter.h"
 #include "nsStyleUtil.h"
 #include "CanvasImageCache.h"
 
 #include <algorithm>
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::GetArrayLength
 #include "js/Conversions.h"
 #include "js/HeapAPI.h"
 #include "js/Warnings.h"  // JS::WarnASCII
 
 #include "mozilla/Alignment.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DebugOnly.h"
@@ -1894,17 +1895,17 @@ static void MatrixToJSObject(JSContext* 
   } else {
     aResult.set(&val.toObject());
   }
 }
 
 static bool ObjectToMatrix(JSContext* aCx, JS::Handle<JSObject*> aObj,
                            Matrix& aMatrix, ErrorResult& aError) {
   uint32_t length;
-  if (!JS_GetArrayLength(aCx, aObj, &length) || length != 6) {
+  if (!JS::GetArrayLength(aCx, aObj, &length) || length != 6) {
     // Not an array-like thing or wrong size
     aError.Throw(NS_ERROR_INVALID_ARG);
     return false;
   }
 
   Float* elts[] = {&aMatrix._11, &aMatrix._12, &aMatrix._21,
                    &aMatrix._22, &aMatrix._31, &aMatrix._32};
   for (uint32_t i = 0; i < 6; ++i) {
--- a/dom/canvas/CanvasUtils.h
+++ b/dom/canvas/CanvasUtils.h
@@ -5,16 +5,17 @@
 
 #ifndef _CANVASUTILS_H_
 #define _CANVASUTILS_H_
 
 #include "CanvasRenderingContextHelper.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength
 #include "mozilla/FloatingPoint.h"
 #include "nsLayoutUtils.h"
 
 class nsIPrincipal;
 
 namespace mozilla {
 
 namespace dom {
@@ -116,17 +117,17 @@ nsresult JSValToDashArray(JSContext* cx,
                           nsTArray<T>& dashes) {
   // The cap is pretty arbitrary.  16k should be enough for
   // anybody...
   static const uint32_t MAX_NUM_DASHES = 1 << 14;
 
   if (!patternArray.isPrimitive()) {
     JS::Rooted<JSObject*> obj(cx, patternArray.toObjectOrNull());
     uint32_t length;
-    if (!JS_GetArrayLength(cx, obj, &length)) {
+    if (!JS::GetArrayLength(cx, obj, &length)) {
       // Not an array-like thing
       return NS_ERROR_INVALID_ARG;
     } else if (length > MAX_NUM_DASHES) {
       // Too many dashes in the pattern
       return NS_ERROR_ILLEGAL_VALUE;
     }
 
     bool haveNonzeroElement = false;
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "WebGL2Context.h"
 
 #include "GLContext.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "mozilla/RefPtr.h"
 #include "WebGLBuffer.h"
 #include "WebGLContext.h"
 #include "WebGLProgram.h"
 #include "WebGLUniformLocation.h"
 #include "WebGLVertexArray.h"
 #include "WebGLVertexAttribData.h"
@@ -160,17 +161,17 @@ void WebGL2Context::GetActiveUniforms(
     if (curIndex >= numActiveUniforms) {
       ErrorInvalidValue("Too-large active uniform index queried.");
       return;
     }
   }
 
   const auto& count = uniformIndices.Length();
 
-  JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
+  JS::Rooted<JSObject*> array(cx, JS::NewArrayObject(cx, count));
   UniquePtr<GLint[]> samples(new GLint[count]);
   if (!array || !samples) {
     ErrorOutOfMemory("Failed to allocate buffers.");
     return;
   }
   retval.setObject(*array);
 
   gl->fGetActiveUniformsiv(program.mGLName, count, uniformIndices.Elements(),
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/ConsoleInstance.h"
 #include "mozilla/dom/ConsoleBinding.h"
 #include "ConsoleCommon.h"
 
+#include "js/Array.h"  // JS::GetArrayLength, JS::NewArrayObject
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -337,17 +338,17 @@ class ConsoleRunnable : public Structure
     return true;
   }
 
   // Helper methods for CallData
   bool StoreConsoleData(JSContext* aCx, ConsoleCallData* aCallData) {
     ConsoleCommon::ClearException ce(aCx);
 
     JS::Rooted<JSObject*> arguments(
-        aCx, JS_NewArrayObject(aCx, aCallData->mCopiedArguments.Length()));
+        aCx, JS::NewArrayObject(aCx, aCallData->mCopiedArguments.Length()));
     if (NS_WARN_IF(!arguments)) {
       return false;
     }
 
     JS::Rooted<JS::Value> arg(aCx);
     for (uint32_t i = 0; i < aCallData->mCopiedArguments.Length(); ++i) {
       arg = aCallData->mCopiedArguments[i];
       if (NS_WARN_IF(
@@ -376,17 +377,17 @@ class ConsoleRunnable : public Structure
       return;
     }
 
     MOZ_ASSERT(argumentsValue.isObject());
 
     JS::Rooted<JSObject*> argumentsObj(aCx, &argumentsValue.toObject());
 
     uint32_t length;
-    if (!JS_GetArrayLength(aCx, argumentsObj, &length)) {
+    if (!JS::GetArrayLength(aCx, argumentsObj, &length)) {
       return;
     }
 
     Sequence<JS::Value> values;
     SequenceRooter<JS::Value> arguments(aCx, &values);
 
     for (uint32_t i = 0; i < length; ++i) {
       JS::Rooted<JS::Value> value(aCx);
@@ -416,17 +417,17 @@ class ConsoleRunnable : public Structure
     }
   }
 
   // Helper methods for Profile calls
   bool StoreProfileData(JSContext* aCx, const Sequence<JS::Value>& aArguments) {
     ConsoleCommon::ClearException ce(aCx);
 
     JS::Rooted<JSObject*> arguments(
-        aCx, JS_NewArrayObject(aCx, aArguments.Length()));
+        aCx, JS::NewArrayObject(aCx, aArguments.Length()));
     if (NS_WARN_IF(!arguments)) {
       return false;
     }
 
     JS::Rooted<JS::Value> arg(aCx);
     for (uint32_t i = 0; i < aArguments.Length(); ++i) {
       arg = aArguments[i];
       if (NS_WARN_IF(
@@ -460,17 +461,17 @@ class ConsoleRunnable : public Structure
 
     MOZ_ASSERT(argumentsValue.isObject());
     JS::Rooted<JSObject*> argumentsObj(aCx, &argumentsValue.toObject());
     if (NS_WARN_IF(!argumentsObj)) {
       return;
     }
 
     uint32_t length;
-    if (!JS_GetArrayLength(aCx, argumentsObj, &length)) {
+    if (!JS::GetArrayLength(aCx, argumentsObj, &length)) {
       return;
     }
 
     Sequence<JS::Value> arguments;
 
     for (uint32_t i = 0; i < length; ++i) {
       JS::Rooted<JS::Value> value(aCx);
 
--- a/dom/filesystem/compat/FileSystemDirectoryReader.cpp
+++ b/dom/filesystem/compat/FileSystemDirectoryReader.cpp
@@ -2,16 +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/. */
 
 #include "FileSystemDirectoryReader.h"
 #include "CallbackRunnables.h"
 #include "FileSystemFileEntry.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/dom/FileBinding.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/DirectoryBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 
 namespace mozilla {
@@ -41,17 +42,17 @@ class PromiseHandler final : public Prom
                                 JS::Handle<JS::Value> aValue) override {
     if (NS_WARN_IF(!aValue.isObject())) {
       return;
     }
 
     JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
 
     uint32_t length;
-    if (NS_WARN_IF(!JS_GetArrayLength(aCx, obj, &length))) {
+    if (NS_WARN_IF(!JS::GetArrayLength(aCx, obj, &length))) {
       return;
     }
 
     Sequence<OwningNonNull<FileSystemEntry>> sequence;
     if (NS_WARN_IF(!sequence.SetLength(length, fallible))) {
       return;
     }
 
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -14,16 +14,17 @@
 #include "IDBFileHandle.h"
 #include "IDBIndex.h"
 #include "IDBMutableFile.h"
 #include "IDBObjectStore.h"
 #include "IDBRequest.h"
 #include "IDBTransaction.h"
 #include "IndexedDatabase.h"
 #include "IndexedDatabaseInlines.h"
+#include "js/Array.h"  // JS::NewArrayObject, JS::SetArrayLength
 #include <mozIIPCBlobInputStream.h>
 #include "mozilla/BasicEvents.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/SnappyUncompressInputStream.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
@@ -396,26 +397,26 @@ class MOZ_STACK_CLASS ResultHelper final
     }
 
     return NS_OK;
   }
 
   nsresult GetResult(JSContext* aCx,
                      const nsTArray<StructuredCloneReadInfo>* aCloneInfos,
                      JS::MutableHandle<JS::Value> aResult) {
-    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
+    JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
     if (NS_WARN_IF(!array)) {
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     if (!aCloneInfos->IsEmpty()) {
       const uint32_t count = aCloneInfos->Length();
 
-      if (NS_WARN_IF(!JS_SetArrayLength(aCx, array, count))) {
+      if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
         IDB_REPORT_INTERNAL_ERR();
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
 
       for (uint32_t index = 0; index < count; index++) {
         auto& cloneInfo =
             const_cast<StructuredCloneReadInfo&>(aCloneInfos->ElementAt(index));
 
@@ -444,26 +445,26 @@ class MOZ_STACK_CLASS ResultHelper final
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   nsresult GetResult(JSContext* aCx, const nsTArray<Key>* aKeys,
                      JS::MutableHandle<JS::Value> aResult) {
-    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
+    JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
     if (NS_WARN_IF(!array)) {
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     if (!aKeys->IsEmpty()) {
       const uint32_t count = aKeys->Length();
 
-      if (NS_WARN_IF(!JS_SetArrayLength(aCx, array, count))) {
+      if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
         IDB_REPORT_INTERNAL_ERR();
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
 
       for (uint32_t index = 0; index < count; index++) {
         const Key& key = aKeys->ElementAt(index);
         MOZ_ASSERT(!key.IsUnset());
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -14,16 +14,17 @@
 #include "IDBIndex.h"
 #include "IDBKeyRange.h"
 #include "IDBMutableFile.h"
 #include "IDBRequest.h"
 #include "IDBTransaction.h"
 #include "IndexedDatabase.h"
 #include "IndexedDatabaseInlines.h"
 #include "IndexedDatabaseManager.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/Class.h"
 #include "js/Date.h"
 #include "js/StructuredClone.h"
 #include "KeyPath.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EndianUtils.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/JSObjectHolder.h"
@@ -958,25 +959,25 @@ void IDBObjectStore::AppendIndexUpdateIn
   }
 
   JS::Rooted<JS::Value> val(aCx);
   if (NS_FAILED(aKeyPath.ExtractKeyAsJSVal(aCx, aVal, val.address()))) {
     return;
   }
 
   bool isArray;
-  if (NS_WARN_IF(!JS_IsArrayObject(aCx, val, &isArray))) {
+  if (NS_WARN_IF(!JS::IsArrayObject(aCx, val, &isArray))) {
     IDB_REPORT_INTERNAL_ERR();
     aRv->Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     return;
   }
   if (isArray) {
     JS::Rooted<JSObject*> array(aCx, &val.toObject());
     uint32_t arrayLength;
-    if (NS_WARN_IF(!JS_GetArrayLength(aCx, array, &arrayLength))) {
+    if (NS_WARN_IF(!JS::GetArrayLength(aCx, array, &arrayLength))) {
       IDB_REPORT_INTERNAL_ERR();
       aRv->Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
       return;
     }
 
     for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
       JS::RootedId indexId(aCx);
       if (NS_WARN_IF(!JS_IndexToId(aCx, arrayIndex, &indexId))) {
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "Key.h"
 
 #include <algorithm>
 #include <stdint.h>  // for UINT32_MAX, uintptr_t
 #include "IndexedDatabaseManager.h"
+#include "js/Array.h"        // JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{IsArrayBufferObject,NewArrayBuffer{,WithContents},GetArrayBufferLengthAndData}
 #include "js/Date.h"
 #include "js/MemoryFunctions.h"
 #include "js/Value.h"
 #include "jsfriendapi.h"
 #include "mozilla/Casting.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/EndianUtils.h"
@@ -387,17 +388,17 @@ nsresult Key::DecodeJSValInternal(const 
                                   uint8_t aTypeOffset,
                                   JS::MutableHandle<JS::Value> aVal,
                                   uint16_t aRecursionDepth) {
   if (NS_WARN_IF(aRecursionDepth == kMaxRecursionDepth)) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
 
   if (*aPos - aTypeOffset >= eArray) {
-    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
+    JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
     if (!array) {
       NS_WARNING("Failed to make array!");
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     aTypeOffset += eMaxType;
 
--- a/dom/indexedDB/Key.h
+++ b/dom/indexedDB/Key.h
@@ -4,16 +4,17 @@
  * 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 mozilla_dom_indexeddb_key_h__
 #define mozilla_dom_indexeddb_key_h__
 
 #include "mozilla/dom/indexedDB/IDBResult.h"
 
+#include "js/Array.h"  // JS::GetArrayLength
 #include "js/RootingAPI.h"
 #include "jsapi.h"
 #include "mozilla/ErrorResult.h"
 #include "nsString.h"
 
 class mozIStorageStatement;
 class mozIStorageValueArray;
 
@@ -190,17 +191,17 @@ class Key {
   // Implementation of the array branch of step 3 of
   // https://w3c.github.io/IndexedDB/#convert-value-to-key
   template <typename ArrayConversionPolicy>
   static IDBResult<void, IDBSpecialValue::Invalid> ConvertArrayValueToKey(
       JSContext* const aCx, JS::HandleObject aObject,
       ArrayConversionPolicy&& aPolicy, ErrorResult& aRv) {
     // 1. Let `len` be ? ToLength( ? Get(`input`, "length")).
     uint32_t len;
-    if (!JS_GetArrayLength(aCx, aObject, &len)) {
+    if (!JS::GetArrayLength(aCx, aObject, &len)) {
       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
       return Exception;
     }
 
     // 2. Add `input` to `seen`.
     aPolicy.AddToSeenSet(aCx, aObject);
 
     // 3. Let `keys` be a new empty list.
--- a/dom/indexedDB/KeyPath.cpp
+++ b/dom/indexedDB/KeyPath.cpp
@@ -9,16 +9,17 @@
 #include "Key.h"
 #include "ReportInternalError.h"
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsJSUtils.h"
 #include "nsPrintfCString.h"
 #include "xpcpublic.h"
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Blob.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/IDBObjectStoreBinding.h"
 
 namespace mozilla {
 namespace dom {
@@ -368,17 +369,17 @@ nsresult KeyPath::ExtractKeyAsJSVal(JSCo
   NS_ASSERTION(IsValid(), "This doesn't make sense!");
 
   if (IsString()) {
     return GetJSValFromKeyPathString(aCx, aValue, mStrings[0], aOutVal,
                                      DoNotCreateProperties, nullptr, nullptr);
   }
 
   const uint32_t len = mStrings.Length();
-  JS::Rooted<JSObject*> arrayObj(aCx, JS_NewArrayObject(aCx, len));
+  JS::Rooted<JSObject*> arrayObj(aCx, JS::NewArrayObject(aCx, len));
   if (!arrayObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JS::Value> value(aCx);
   for (uint32_t i = 0; i < len; ++i) {
     nsresult rv =
         GetJSValFromKeyPathString(aCx, aValue, mStrings[i], value.address(),
@@ -483,17 +484,17 @@ KeyPath KeyPath::DeserializeFromString(c
 
   return keyPath;
 }
 
 nsresult KeyPath::ToJSVal(JSContext* aCx,
                           JS::MutableHandle<JS::Value> aValue) const {
   if (IsArray()) {
     uint32_t len = mStrings.Length();
-    JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, len));
+    JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, len));
     if (!array) {
       IDB_WARNING("Failed to make array!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     for (uint32_t i = 0; i < len; ++i) {
       JS::Rooted<JS::Value> val(aCx);
       nsString tmp(mStrings[i]);
--- a/dom/indexedDB/test/gtest/TestKey.cpp
+++ b/dom/indexedDB/test/gtest/TestKey.cpp
@@ -6,16 +6,17 @@
 
 #include "gtest/gtest.h"
 
 #include "mozilla/dom/SimpleGlobalObject.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/indexedDB/Key.h"
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "js/ArrayBuffer.h"
 
 // TODO: This PrintTo overload is defined in dom/media/gtest/TestGroupId.cpp.
 // However, it is not used, probably because of
 // https://stackoverflow.com/a/36941270
 void PrintTo(const nsString& value, std::ostream* os);
 
 using namespace mozilla;
@@ -103,17 +104,17 @@ static JSObject& ExpectArrayBufferObject
   return object;
 }
 
 static JSObject& ExpectArrayObject(JSContext* const aContext,
                                    const JS::Heap<JS::Value>& aValue) {
   EXPECT_TRUE(aValue.get().isObject());
   auto&& value = JS::RootedValue(aContext, aValue.get());
   bool rv;
-  EXPECT_TRUE(JS_IsArrayObject(aContext, value, &rv));
+  EXPECT_TRUE(JS::IsArrayObject(aContext, value, &rv));
   EXPECT_TRUE(rv);
   return value.toObject();
 }
 
 static void CheckArrayBuffer(const nsCString& aExpected,
                              const JS::Value& aActual) {
   auto& obj = ExpectArrayBufferObject(aActual);
   uint32_t length;
@@ -289,29 +290,29 @@ template <typename CheckElement>
 static void CheckArray(JSContext* const context,
                        const JS::Heap<JS::Value>& arrayValue,
                        const size_t expectedLength,
                        const CheckElement& checkElement) {
   auto&& actualArray =
       JS::RootedObject(context, &ExpectArrayObject(context, arrayValue));
 
   uint32_t actualLength;
-  EXPECT_TRUE(JS_GetArrayLength(context, actualArray, &actualLength));
+  EXPECT_TRUE(JS::GetArrayLength(context, actualArray, &actualLength));
   EXPECT_EQ(expectedLength, actualLength);
   for (size_t i = 0; i < expectedLength; ++i) {
     JS::RootedValue element(static_cast<JSContext*>(context));
     EXPECT_TRUE(JS_GetElement(context, actualArray, i, &element));
 
     checkElement(i, element);
   }
 }
 
 static JS::RootedValue CreateArrayBufferArray(
     JSContext* const context, const std::vector<nsCString>& elements) {
-  auto* const array = JS_NewArrayObject(context, elements.size());
+  auto* const array = JS::NewArrayObject(context, elements.size());
   auto&& arrayObject = JS::RootedObject{context, array};
 
   for (size_t i = 0; i < elements.size(); ++i) {
     // TODO strdup only works if the element is actually 0-terminated
     auto&& arrayBuffer = CreateArrayBufferValue(
         context, elements[i].Length(),
         elements[i].Length() ? strdup(elements[i].get()) : nullptr);
     EXPECT_TRUE(JS_SetElement(context, arrayObject, i, arrayBuffer));
@@ -353,17 +354,17 @@ INSTANTIATE_TEST_CASE_P(
 
 static JS::RootedValue CreateStringValue(JSContext* const context,
                                          const nsString& string) {
   return {context, JS::StringValue(JS_NewUCStringCopyZ(context, string.get()))};
 }
 
 static JS::RootedValue CreateStringArray(
     JSContext* const context, const std::vector<nsString>& elements) {
-  auto* const array = JS_NewArrayObject(context, elements.size());
+  auto* const array = JS::NewArrayObject(context, elements.size());
   auto&& arrayObject = JS::RootedObject{context, array};
 
   for (size_t i = 0; i < elements.size(); ++i) {
     auto&& string = CreateStringValue(context, elements[i]);
     EXPECT_TRUE(JS_SetElement(context, arrayObject, i, string));
   }
 
   return {context, JS::ObjectValue(*array)};
--- a/dom/media/webaudio/AudioWorkletGlobalScope.cpp
+++ b/dom/media/webaudio/AudioWorkletGlobalScope.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AudioWorkletGlobalScope.h"
 
 #include "AudioNodeEngine.h"
 #include "AudioNodeTrack.h"
 #include "AudioWorkletImpl.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "mozilla/dom/AudioWorkletGlobalScopeBinding.h"
 #include "mozilla/dom/AudioWorkletProcessor.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/StructuredCloneHolder.h"
 #include "mozilla/dom/WorkletPrincipals.h"
 #include "mozilla/dom/AudioParamDescriptorBinding.h"
 #include "nsPrintfCString.h"
 #include "nsTHashtable.h"
@@ -148,18 +149,18 @@ void AudioWorkletGlobalScope::RegisterPr
     return;
   }
 
   /**
    * 8. If descriptors is neither an array nor undefined, throw a
    *    TypeError and abort these steps.
    */
   bool isArray = false;
-  if (!JS_IsArrayObject(aCx, descriptors, &isArray)) {
-    // I would assume isArray won't be set to true if JS_IsArrayObject
+  if (!JS::IsArrayObject(aCx, descriptors, &isArray)) {
+    // I would assume isArray won't be set to true if JS::IsArrayObject
     // failed, but just in case, force it to false
     isArray = false;
     JS_ClearPendingException(aCx);
   }
 
   if (!descriptors.isUndefined() && !isArray) {
     aRv.ThrowTypeError<MSG_NOT_ARRAY_NOR_UNDEFINED>(NS_LITERAL_STRING(
         "Argument 2 of AudioWorkletGlobalScope.registerProcessor "
@@ -228,17 +229,17 @@ AudioParamDescriptorMap AudioWorkletGlob
   MOZ_ASSERT(aDescriptors.isObject());
 
   AudioParamDescriptorMap res;
   // To check for duplicates
   nsTHashtable<nsStringHashKey> namesSet;
 
   JS::Rooted<JSObject*> aDescriptorsArray(aCx, &aDescriptors.toObject());
   uint32_t length = 0;
-  if (!JS_GetArrayLength(aCx, aDescriptorsArray, &length)) {
+  if (!JS::GetArrayLength(aCx, aDescriptorsArray, &length)) {
     aRv.NoteJSContextException(aCx);
     return AudioParamDescriptorMap();
   }
 
   for (uint32_t i = 0; i < length; ++i) {
     JS::Rooted<JS::Value> descriptorElement(aCx);
     if (!JS_GetElement(aCx, aDescriptorsArray, i, &descriptorElement)) {
       aRv.NoteJSContextException(aCx);
--- a/dom/media/webaudio/AudioWorkletNode.cpp
+++ b/dom/media/webaudio/AudioWorkletNode.cpp
@@ -2,16 +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 https://mozilla.org/MPL/2.0/. */
 
 #include "AudioWorkletNode.h"
 
 #include "AudioParamMap.h"
+#include "js/Array.h"  // JS::{Get,Set}ArrayLength, JS::NewArrayLength
 #include "mozilla/dom/AudioWorkletNodeBinding.h"
 #include "mozilla/dom/MessageChannel.h"
 #include "mozilla/dom/MessagePort.h"
 #include "PlayingRefChangeHandler.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -179,25 +180,25 @@ static bool SetArrayElements(JSContext* 
 
 template <typename T>
 static bool PrepareArray(JSContext* aCx, const T& aElements,
                          JS::MutableHandle<JSObject*> aArray) {
   size_t length = aElements.length();
   if (aArray) {
     // Attempt to reuse.
     uint32_t oldLength;
-    if (JS_GetArrayLength(aCx, aArray, &oldLength) &&
-        (oldLength == length || JS_SetArrayLength(aCx, aArray, length)) &&
+    if (JS::GetArrayLength(aCx, aArray, &oldLength) &&
+        (oldLength == length || JS::SetArrayLength(aCx, aArray, length)) &&
         SetArrayElements(aCx, aElements, aArray)) {
       return true;
     }
     // Script may have frozen the array.  Try again with a new Array.
     JS_ClearPendingException(aCx);
   }
-  JSObject* array = JS_NewArrayObject(aCx, length);
+  JSObject* array = JS::NewArrayObject(aCx, length);
   if (NS_WARN_IF(!array)) {
     return false;
   }
   aArray.set(array);
   return SetArrayElements(aCx, aElements, aArray);
 }
 
 enum class ArrayElementInit { None, Zero };
--- a/dom/reporting/ReportingHeader.cpp
+++ b/dom/reporting/ReportingHeader.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "mozilla/dom/ReportingHeader.h"
 
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/JSON.h"
 #include "mozilla/dom/ReportingBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/SimpleGlobalObject.h"
 #include "mozilla/OriginAttributes.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/StaticPtr.h"
@@ -267,23 +268,23 @@ void ReportingHeader::ReportingFromChann
       LogToConsoleIncompleteItem(aChannel, aURI, groupName);
       continue;
     }
 
     JS::Rooted<JSObject*> endpoints(cx, &item.mEndpoints.toObject());
     MOZ_ASSERT(endpoints);
 
     bool isArray = false;
-    if (!JS_IsArrayObject(cx, endpoints, &isArray) || !isArray) {
+    if (!JS::IsArrayObject(cx, endpoints, &isArray) || !isArray) {
       LogToConsoleIncompleteItem(aChannel, aURI, groupName);
       continue;
     }
 
     uint32_t endpointsLength;
-    if (!JS_GetArrayLength(cx, endpoints, &endpointsLength) ||
+    if (!JS::GetArrayLength(cx, endpoints, &endpointsLength) ||
         endpointsLength == 0) {
       LogToConsoleIncompleteItem(aChannel, aURI, groupName);
       continue;
     }
 
     bool found = false;
     nsTObserverArray<Group>::ForwardIterator iter(client->mGroups);
     while (iter.HasMore()) {
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -9,16 +9,17 @@
 #include "ScriptLoadRequest.h"
 #include "ScriptTrace.h"
 #include "LoadedScript.h"
 #include "ModuleLoadRequest.h"
 
 #include "prsystem.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::GetArrayLength
 #include "js/CompilationAndEvaluation.h"
 #include "js/MemoryFunctions.h"
 #include "js/Modules.h"  // JS::FinishDynamicModuleImport, JS::{G,S}etModuleResolveHook, JS::Get{ModulePrivate,ModuleScript,RequestedModule{s,Specifier,SourcePos}}, JS::SetModule{DynamicImport,Metadata}Hook
 #include "js/OffThreadScriptCompilation.h"
 #include "js/Realm.h"
 #include "js/SourceText.h"
 #include "js/Utility.h"
 #include "xpcpublic.h"
@@ -665,17 +666,17 @@ static nsresult ResolveRequestedModules(
 
   JSContext* cx = jsapi.cx();
   JS::Rooted<JSObject*> moduleRecord(cx, ms->ModuleRecord());
   JS::Rooted<JSObject*> requestedModules(cx);
   requestedModules = JS::GetRequestedModules(cx, moduleRecord);
   MOZ_ASSERT(requestedModules);
 
   uint32_t length;
-  if (!JS_GetArrayLength(cx, requestedModules, &length)) {
+  if (!JS::GetArrayLength(cx, requestedModules, &length)) {
     return NS_ERROR_FAILURE;
   }
 
   JS::Rooted<JS::Value> element(cx);
   for (uint32_t i = 0; i < length; i++) {
     if (!JS_GetElement(cx, requestedModules, i, &element)) {
       return NS_ERROR_FAILURE;
     }
--- a/dom/security/nsContentSecurityUtils.cpp
+++ b/dom/security/nsContentSecurityUtils.cpp
@@ -13,16 +13,17 @@
 #include "nsIHttpChannel.h"
 #include "nsIMultiPartChannel.h"
 #include "nsIURI.h"
 #if defined(XP_WIN)
 #  include "WinUtils.h"
 #  include <wininet.h>
 #endif
 
+#include "js/Array.h"  // JS::GetArrayLength
 #include "mozilla/Logging.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/StaticPrefs_extensions.h"
 
 /*
  * Performs a Regular Expression match, optionally returning the results.
  * This function is not safe to use OMT.
  *
@@ -77,17 +78,17 @@ nsresult RegexEval(const nsAString& aPat
   }
   if (aRegexResults == nullptr) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Now we know we have a result, and we need to extract it so we can read it.
   uint32_t length;
   JS::RootedObject regexResultObj(cx, &regexResult.toObject());
-  if (!JS_GetArrayLength(cx, regexResultObj, &length)) {
+  if (!JS::GetArrayLength(cx, regexResultObj, &length)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   MOZ_LOG(sCSMLog, LogLevel::Verbose, ("Regex Matched %i strings", length));
 
   for (uint32_t i = 0; i < length; i++) {
     JS::RootedValue element(cx);
     if (!JS_GetElement(cx, regexResultObj, i, &element)) {
       return NS_ERROR_NO_CONTENT;
@@ -787,9 +788,9 @@ bool nsContentSecurityUtils::ValidateScr
   }
   Telemetry::RecordEvent(eventType,
                          mozilla::Some(fileNameTypeAndDetails.first()), extra);
 
   // Presently we are not enforcing any restrictions for the script filename,
   // we're only reporting Telemetry. In the future we will assert in debug
   // builds and return false to prevent execution in non-debug builds.
   return true;
-}
\ No newline at end of file
+}
--- a/dom/serviceworkers/ServiceWorkerScriptCache.cpp
+++ b/dom/serviceworkers/ServiceWorkerScriptCache.cpp
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "ServiceWorkerScriptCache.h"
+
+#include "js/Array.h"  // JS::GetArrayLength
 #include "mozilla/SystemGroup.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/CacheBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/cache/Cache.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseWorkerProxy.h"
 #include "mozilla/dom/ScriptLoader.h"
@@ -385,17 +387,17 @@ class CompareManager final : public Prom
     }
 
     JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
     if (NS_WARN_IF(!obj)) {
       return;
     }
 
     uint32_t len = 0;
-    if (!JS_GetArrayLength(aCx, obj, &len)) {
+    if (!JS::GetArrayLength(aCx, obj, &len)) {
       return;
     }
 
     // Fetch and compare the source scripts.
     MOZ_ASSERT(mPendingCount == 0);
 
     mState = WaitingForScriptOrComparisonResult;
 
new file mode 100644
--- /dev/null
+++ b/js/public/Array.h
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/* Array-related operations. */
+
+#ifndef js_Array_h
+#define js_Array_h
+
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint32_t
+
+#include "jstypes.h"  // JS_PUBLIC_API
+
+#include "js/RootingAPI.h"  // JS::Handle
+#include "js/Value.h"       // JS::Value
+
+struct JS_PUBLIC_API JSContext;
+class JS_PUBLIC_API JSObject;
+
+namespace JS {
+
+class HandleValueArray;
+
+/**
+ * Create an Array from the current realm with the given contents.
+ */
+extern JS_PUBLIC_API JSObject* NewArrayObject(JSContext* cx,
+                                              const HandleValueArray& contents);
+
+/**
+ * Create an Array from the current realm with the given length and allocate
+ * memory for all its elements.  (The elements nonetheless will not exist as
+ * properties on the returned array until values have been assigned to them.)
+ */
+extern JS_PUBLIC_API JSObject* NewArrayObject(JSContext* cx, size_t length);
+
+/**
+ * Determine whether |value| is an Array object or a wrapper around one.  (An
+ * ES6 proxy whose target is an Array object, e.g.
+ * |var target = [], handler = {}; Proxy.revocable(target, handler).proxy|, is
+ * not considered to be an Array.)
+ *
+ * On success set |*isArray| accordingly and return true; on failure return
+ * false.
+ */
+extern JS_PUBLIC_API bool IsArrayObject(JSContext* cx, Handle<Value> value,
+                                        bool* isArray);
+
+/**
+ * Determine whether |obj| is an Array object or a wrapper around one.  (An
+ * ES6 proxy whose target is an Array object, e.g.
+ * |var target = [], handler = {}; Proxy.revocable(target, handler).proxy|, is
+ * not considered to be an Array.)
+ *
+ * On success set |*isArray| accordingly and return true; on failure return
+ * false.
+ */
+extern JS_PUBLIC_API bool IsArrayObject(JSContext* cx, Handle<JSObject*> obj,
+                                        bool* isArray);
+
+/**
+ * Store |*lengthp = ToLength(obj.length)| and return true on success, else
+ * return false.
+ *
+ * |ToLength| converts its input to an integer usable to index an
+ * array-like object.
+ *
+ * If |obj| is an Array, this overall operation is the same as getting
+ * |obj.length|.
+ */
+extern JS_PUBLIC_API bool GetArrayLength(JSContext* cx, Handle<JSObject*> obj,
+                                         uint32_t* lengthp);
+
+/**
+ * Perform |obj.length = length| as if in strict mode code, with a fast path for
+ * the case where |obj| is an Array.
+ *
+ * This operation is exactly and only assigning to a "length" property.  In
+ * general, it can invoke an existing "length" setter, throw if the property is
+ * non-writable, or do anything else a property-set operation might do.
+ */
+extern JS_PUBLIC_API bool SetArrayLength(JSContext* cx, Handle<JSObject*> obj,
+                                         uint32_t length);
+
+/**
+ * The answer to a successful query as to whether an object is an Array per
+ * ES6's internal |IsArray| operation (as exposed by |Array.isArray|).
+ */
+enum class IsArrayAnswer { Array, NotArray, RevokedProxy };
+
+/**
+ * ES6 7.2.2.
+ *
+ * Returns false on failure, otherwise returns true and sets |*isArray|
+ * indicating whether the object passes ECMAScript's IsArray test.  This is the
+ * same test performed by |Array.isArray|.
+ *
+ * This is NOT the same as asking whether |obj| is an Array or a wrapper around
+ * one.  If |obj| is a proxy created by |Proxy.revocable()| and has been
+ * revoked, or if |obj| is a proxy whose target (at any number of hops) is a
+ * revoked proxy, this method throws a TypeError and returns false.
+ */
+extern JS_PUBLIC_API bool IsArray(JSContext* cx, Handle<JSObject*> obj,
+                                  bool* isArray);
+
+/**
+ * Identical to IsArray above, but the nature of the object (if successfully
+ * determined) is communicated via |*answer|.  In particular this method
+ * returns true and sets |*answer = IsArrayAnswer::RevokedProxy| when called on
+ * a revoked proxy.
+ *
+ * Most users will want the overload above, not this one.
+ */
+extern JS_PUBLIC_API bool IsArray(JSContext* cx, Handle<JSObject*> obj,
+                                  IsArrayAnswer* answer);
+
+}  // namespace JS
+
+#endif  // js_Array_h
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -35,48 +35,16 @@ class Shape;
 // to #include jsfun.h.
 extern JS_FRIEND_DATA const JSClass* const FunctionClassPtr;
 
 }  // namespace js
 
 namespace JS {
 
 /**
- * The answer to a successful query as to whether an object is an Array per
- * ES6's internal |IsArray| operation (as exposed by |Array.isArray|).
- */
-enum class IsArrayAnswer { Array, NotArray, RevokedProxy };
-
-/**
- * ES6 7.2.2.
- *
- * Returns false on failure, otherwise returns true and sets |*isArray|
- * indicating whether the object passes ECMAScript's IsArray test.  This is the
- * same test performed by |Array.isArray|.
- *
- * This is NOT the same as asking whether |obj| is an Array or a wrapper around
- * one.  If |obj| is a proxy created by |Proxy.revocable()| and has been
- * revoked, or if |obj| is a proxy whose target (at any number of hops) is a
- * revoked proxy, this method throws a TypeError and returns false.
- */
-extern JS_PUBLIC_API bool IsArray(JSContext* cx, HandleObject obj,
-                                  bool* isArray);
-
-/**
- * Identical to IsArray above, but the nature of the object (if successfully
- * determined) is communicated via |*answer|.  In particular this method
- * returns true and sets |*answer = IsArrayAnswer::RevokedProxy| when called on
- * a revoked proxy.
- *
- * Most users will want the overload above, not this one.
- */
-extern JS_PUBLIC_API bool IsArray(JSContext* cx, HandleObject obj,
-                                  IsArrayAnswer* answer);
-
-/**
  * Per ES6, the [[DefineOwnProperty]] internal method has three different
  * possible outcomes:
  *
  * -   It can throw an exception (which we indicate by returning false).
  *
  * -   It can return true, indicating unvarnished success.
  *
  * -   It can return false, indicating "strict failure". The property could
--- a/js/public/Modules.h
+++ b/js/public/Modules.h
@@ -144,17 +144,17 @@ extern JS_PUBLIC_API bool ModuleInstanti
 extern JS_PUBLIC_API bool ModuleEvaluate(JSContext* cx,
                                          Handle<JSObject*> moduleRecord);
 
 /*
  * Get a list of the module specifiers used by a source text module
  * record to request importation of modules.
  *
  * The result is a JavaScript array of object values.  To extract the individual
- * values use only JS_GetArrayLength and JS_GetElement with indices 0 to length
+ * values use only JS::GetArrayLength and JS_GetElement with indices 0 to length
  * - 1.
  *
  * The element values are objects with the following properties:
  *  - moduleSpecifier: the module specifier string
  *  - lineNumber: the line number of the import in the source text
  *  - columnNumber: the column number of the import in the source text
  *
  * These property values can be extracted with GetRequestedModuleSpecifier() and
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -6,16 +6,17 @@
 
 #ifndef js_Proxy_h
 #define js_Proxy_h
 
 #include "mozilla/Maybe.h"
 
 #include "jsfriendapi.h"
 
+#include "js/Array.h"  // JS::IsArrayAnswer
 #include "js/CallNonGenericMethod.h"
 #include "js/Class.h"
 
 namespace js {
 
 using JS::CallArgs;
 using JS::Handle;
 using JS::HandleId;
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -354,25 +354,25 @@ const WHITELIST_FUNCTIONS: &'static [&'s
     "JS_GetUint16ArrayData",
     "JS_GetUint32ArrayData",
     "JS_GetUint8ArrayData",
     "JS_GetUint8ClampedArrayData",
     "JS::GetWellKnownSymbol",
     "JS_GlobalObjectTraceHook",
     "JS::HideScriptedCaller",
     "JS::InitRealmStandardClasses",
-    "JS_IsArrayObject",
+    "JS::IsArrayObject",
     "JS_IsExceptionPending",
     "JS_IsGlobalObject",
     "JS::IsCallable",
     "JS::LeaveRealm",
     "JS_LinkConstructorAndPrototype",
     "JS_MayResolveStandardClass",
     "JS::NewArrayBuffer",
-    "JS_NewArrayObject",
+    "JS::NewArrayObject",
     "JS_NewContext",
     "JS_NewFloat32Array",
     "JS_NewFloat64Array",
     "JS_NewFunction",
     "js::NewFunctionWithReserved",
     "JS_NewGlobalObject",
     "JS_NewInt16Array",
     "JS_NewInt32Array",
--- a/js/rust/etc/wrapper.hpp
+++ b/js/rust/etc/wrapper.hpp
@@ -8,16 +8,17 @@
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
 
 typedef uint32_t HashNumber;
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"
 #include "js/ArrayBuffer.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/CompileOptions.h"
 #include "js/ContextOptions.h"
 #include "js/Conversions.h"
 #include "js/Date.h"
 #include "js/ForOfIterator.h"
 #include "js/Initialization.h"
--- a/js/rust/src/conversions.rs
+++ b/js/rust/src/conversions.rs
@@ -609,17 +609,17 @@ impl<T: FromJSValConvertible> FromJSValC
         }
     }
 }
 
 // https://heycam.github.io/webidl/#es-sequence
 impl<T: ToJSValConvertible> ToJSValConvertible for Vec<T> {
     #[inline]
     unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
-        rooted!(in(cx) let js_array = JS_NewArrayObject1(cx, self.len() as libc::size_t));
+        rooted!(in(cx) let js_array = JS::NewArrayObject1(cx, self.len() as libc::size_t));
         assert!(!js_array.handle().is_null());
 
         rooted!(in(cx) let mut val = UndefinedValue());
         for (index, obj) in self.iter().enumerate() {
             obj.to_jsval(cx, val.handle_mut());
 
             assert!(JS_DefineElement(
                 cx,
--- a/js/rust/tests/vec_conversion.rs
+++ b/js/rust/tests/vec_conversion.rs
@@ -18,17 +18,17 @@ use js::jsval::UndefinedValue;
 use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
 
 use std::ptr;
 
 fn assert_is_array(cx: *mut js::jsapi::root::JSContext,
                    val: js::jsapi::root::JS::HandleValue) {
     let mut is_array = false;
     assert!(unsafe {
-        js::jsapi::root::JS_IsArrayObject(cx, val, &mut is_array as *mut _)
+        js::jsapi::root::JS::IsArrayObject(cx, val, &mut is_array as *mut _)
     });
     assert!(is_array);
 }
 
 #[test]
 fn vec_conversion() {
     let rt = Runtime::new(false).unwrap();
     let cx = rt.cx();
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -41,16 +41,17 @@
 #include "vm/TypedArrayObject.h"
 #include "vm/WrapperObject.h"
 
 #include "vm/ArgumentsObject-inl.h"
 #include "vm/ArrayObject-inl.h"
 #include "vm/Caches-inl.h"
 #include "vm/GeckoProfiler-inl.h"
 #include "vm/Interpreter-inl.h"
+#include "vm/IsGivenTypeObject-inl.h"
 #include "vm/JSAtom-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
 using mozilla::Abs;
 using mozilla::ArrayLength;
 using mozilla::CeilingLog2;
@@ -4514,8 +4515,60 @@ bool js::ArraySpeciesLookup::tryOptimize
   Shape* shape = array->shape();
   if (shape->previous() && !shape->previous()->isEmptyShape()) {
     return false;
   }
 
   MOZ_ASSERT(JSID_IS_ATOM(shape->propidRaw(), cx->names().length));
   return true;
 }
+
+JS_PUBLIC_API JSObject* JS::NewArrayObject(JSContext* cx,
+                                           const HandleValueArray& contents) {
+  MOZ_ASSERT(!cx->zone()->isAtomsZone());
+  AssertHeapIsIdle();
+  CHECK_THREAD(cx);
+  cx->check(contents);
+
+  return NewDenseCopiedArray(cx, contents.length(), contents.begin());
+}
+
+JS_PUBLIC_API JSObject* JS::NewArrayObject(JSContext* cx, size_t length) {
+  MOZ_ASSERT(!cx->zone()->isAtomsZone());
+  AssertHeapIsIdle();
+  CHECK_THREAD(cx);
+
+  return NewDenseFullyAllocatedArray(cx, length);
+}
+
+JS_PUBLIC_API bool JS::IsArrayObject(JSContext* cx, Handle<JSObject*> obj,
+                                     bool* isArray) {
+  return IsGivenTypeObject(cx, obj, ESClass::Array, isArray);
+}
+
+JS_PUBLIC_API bool JS::IsArrayObject(JSContext* cx, Handle<Value> value,
+                                     bool* isArray) {
+  if (!value.isObject()) {
+    *isArray = false;
+    return true;
+  }
+
+  Rooted<JSObject*> obj(cx, &value.toObject());
+  return IsArrayObject(cx, obj, isArray);
+}
+
+JS_PUBLIC_API bool JS::GetArrayLength(JSContext* cx, Handle<JSObject*> obj,
+                                      uint32_t* lengthp) {
+  AssertHeapIsIdle();
+  CHECK_THREAD(cx);
+  cx->check(obj);
+
+  return GetLengthProperty(cx, obj, lengthp);
+}
+
+JS_PUBLIC_API bool JS::SetArrayLength(JSContext* cx, Handle<JSObject*> obj,
+                                      uint32_t length) {
+  AssertHeapIsIdle();
+  CHECK_THREAD(cx);
+  cx->check(obj);
+
+  return SetLengthProperty(cx, obj, length);
+}
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -40,16 +40,17 @@
 #  include "irregexp/RegExpEngine.h"
 #  include "irregexp/RegExpParser.h"
 #endif
 #include "gc/Heap.h"
 #include "gc/Zone.h"
 #include "jit/BaselineJIT.h"
 #include "jit/InlinableNatives.h"
 #include "jit/JitRealm.h"
+#include "js/Array.h"        // JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{DetachArrayBuffer,GetArrayBufferLengthAndData,NewArrayBufferWithContents}
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/CompileOptions.h"
 #include "js/Date.h"
 #include "js/Debug.h"
 #include "js/HashTable.h"
 #include "js/LocaleSensitive.h"
@@ -899,17 +900,17 @@ static bool WasmTextToBinary(JSContext* 
     return false;
   }
 
   constexpr unsigned propAttrs = JSPROP_ENUMERATE;
   if (!JS_DefineProperty(cx, obj, "binary", binary, propAttrs)) {
     return false;
   }
 
-  RootedObject jsOffsets(cx, JS_NewArrayObject(cx, offsets.length()));
+  RootedObject jsOffsets(cx, JS::NewArrayObject(cx, offsets.length()));
   if (!jsOffsets) {
     return false;
   }
   for (size_t i = 0; i < offsets.length(); i++) {
     uint32_t offset = offsets[i];
     RootedValue offsetVal(cx, NumberValue(offset));
     if (!JS_SetElement(cx, jsOffsets, i, offsetVal)) {
       return false;
@@ -1997,17 +1998,17 @@ static bool EnsureLinearString(JSContext
 
   args.rval().setString(linear);
   return true;
 }
 
 static bool RepresentativeStringArray(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  RootedObject array(cx, JS_NewArrayObject(cx, 0));
+  RootedObject array(cx, JS::NewArrayObject(cx, 0));
   if (!array) {
     return false;
   }
 
   if (!JSString::fillWithRepresentatives(cx, array.as<ArrayObject>())) {
     return false;
   }
 
@@ -4741,17 +4742,17 @@ static bool EnqueueMark(JSContext* cx, u
   return true;
 }
 
 static bool GetMarkQueue(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   auto& queue = cx->runtime()->gc.marker.markQueue.get();
 
-  RootedObject result(cx, JS_NewArrayObject(cx, queue.length()));
+  RootedObject result(cx, JS::NewArrayObject(cx, queue.length()));
   if (!result) {
     return false;
   }
   for (size_t i = 0; i < queue.length(); i++) {
     RootedValue val(cx, queue[i]);
     if (!JS_WrapValue(cx, &val)) {
       return false;
     }
@@ -5024,17 +5025,17 @@ static JSObject* ConvertRegExpTreeToObje
     }
     return ObjectProp(cx, obj, name, treeObj);
   };
 
   auto TreeVectorProp = [&ObjectProp, &alloc](
                             JSContext* cx, HandleObject obj, const char* name,
                             const irregexp::RegExpTreeVector& nodes) {
     size_t len = nodes.length();
-    RootedObject array(cx, JS_NewArrayObject(cx, len));
+    RootedObject array(cx, JS::NewArrayObject(cx, len));
     if (!array) {
       return false;
     }
 
     for (size_t i = 0; i < len; i++) {
       RootedObject child(cx, ConvertRegExpTreeToObject(cx, alloc, nodes[i]));
       if (!child) {
         return false;
@@ -5047,17 +5048,17 @@ static JSObject* ConvertRegExpTreeToObje
     }
     return ObjectProp(cx, obj, name, array);
   };
 
   auto CharRangesProp = [&ObjectProp](
                             JSContext* cx, HandleObject obj, const char* name,
                             const irregexp::CharacterRangeVector& ranges) {
     size_t len = ranges.length();
-    RootedObject array(cx, JS_NewArrayObject(cx, len));
+    RootedObject array(cx, JS::NewArrayObject(cx, len));
     if (!array) {
       return false;
     }
 
     for (size_t i = 0; i < len; i++) {
       const irregexp::CharacterRange& range = ranges[i];
       RootedObject rangeObj(cx, JS_NewPlainObject(cx));
       if (!rangeObj) {
@@ -5088,17 +5089,17 @@ static JSObject* ConvertRegExpTreeToObje
     }
     return ObjectProp(cx, obj, name, array);
   };
 
   auto ElemProp = [&ObjectProp, &alloc](
                       JSContext* cx, HandleObject obj, const char* name,
                       const irregexp::TextElementVector& elements) {
     size_t len = elements.length();
-    RootedObject array(cx, JS_NewArrayObject(cx, len));
+    RootedObject array(cx, JS::NewArrayObject(cx, len));
     if (!array) {
       return false;
     }
 
     for (size_t i = 0; i < len; i++) {
       const irregexp::TextElement& element = elements[i];
       RootedObject elemTree(
           cx, ConvertRegExpTreeToObject(cx, alloc, element.tree()));
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -34,16 +34,17 @@
 #include "jsexn.h"
 #include "jsnum.h"
 
 #include "builtin/TypedObject.h"
 #include "ctypes/Library.h"
 #include "gc/FreeOp.h"
 #include "gc/Policy.h"
 #include "jit/AtomicOperations.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{IsArrayBufferObject,GetArrayBufferData,GetArrayBuffer{ByteLength,Data}}
 #include "js/CharacterEncoding.h"
 #include "js/PropertySpec.h"
 #include "js/SharedArrayBuffer.h"  // JS::{GetSharedArrayBuffer{ByteLength,Data},IsSharedArrayBufferObject}
 #include "js/StableStringChars.h"
 #include "js/UniquePtr.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
@@ -3499,17 +3500,17 @@ static bool ImplicitConvert(JSContext* c
         ESClass cls;
         if (!GetClassOfValue(cx, val, &cls)) {
           return false;
         }
 
         if (cls == ESClass::Array) {
           // Convert each element of the array by calling ImplicitConvert.
           uint32_t sourceLength;
-          if (!JS_GetArrayLength(cx, valObj, &sourceLength) ||
+          if (!JS::GetArrayLength(cx, valObj, &sourceLength) ||
               targetLength != size_t(sourceLength)) {
             MOZ_ASSERT(!funObj);
             return ArrayLengthMismatch(cx, targetLength, targetType,
                                        size_t(sourceLength), val, convType);
           }
 
           // Convert into an intermediate, in case of failure.
           size_t elementSize = CType::GetSize(baseType);
@@ -5786,17 +5787,17 @@ bool StructType::Create(JSContext* cx, u
   }
 
   if (args.length() == 2) {
     RootedObject arr(cx, args[1].isObject() ? &args[1].toObject() : nullptr);
     bool isArray;
     if (!arr) {
       isArray = false;
     } else {
-      if (!JS_IsArrayObject(cx, arr, &isArray)) {
+      if (!JS::IsArrayObject(cx, arr, &isArray)) {
         return false;
       }
     }
     if (!isArray) {
       return ArgumentTypeMismatch(cx, "second ", "StructType", "an array");
     }
 
     // Define the struct fields.
@@ -5810,17 +5811,17 @@ bool StructType::Create(JSContext* cx, u
 }
 
 bool StructType::DefineInternal(JSContext* cx, JSObject* typeObj_,
                                 JSObject* fieldsObj_) {
   RootedObject typeObj(cx, typeObj_);
   RootedObject fieldsObj(cx, fieldsObj_);
 
   uint32_t len;
-  MOZ_ALWAYS_TRUE(JS_GetArrayLength(cx, fieldsObj, &len));
+  MOZ_ALWAYS_TRUE(JS::GetArrayLength(cx, fieldsObj, &len));
 
   // Get the common prototype for CData objects of this type from
   // ctypes.CType.prototype.
   RootedObject dataProto(
       cx, CType::GetProtoFromType(cx, typeObj, SLOT_STRUCTDATAPROTO));
   if (!dataProto) {
     return false;
   }
@@ -6065,17 +6066,17 @@ bool StructType::Define(JSContext* cx, u
     return ArgumentTypeMismatch(cx, "", "StructType.prototype.define",
                                 "an array");
   }
 
   bool isArray;
   if (!arg.isObject()) {
     isArray = false;
   } else {
-    if (!JS_IsArrayObject(cx, arg, &isArray)) {
+    if (!JS::IsArrayObject(cx, arg, &isArray)) {
       return false;
     }
   }
 
   if (!isArray) {
     return ArgumentTypeMismatch(cx, "", "StructType.prototype.define",
                                 "an array");
   }
@@ -6206,17 +6207,17 @@ JSObject* StructType::BuildFieldsArray(J
   for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
     const FieldInfoHash::Entry& entry = r.front();
     // Add the field descriptor to the array.
     if (!AddFieldToArray(cx, fieldsVec[entry.value().mIndex], entry.key(),
                          entry.value().mType))
       return nullptr;
   }
 
-  RootedObject fieldsProp(cx, JS_NewArrayObject(cx, fieldsVec));
+  RootedObject fieldsProp(cx, JS::NewArrayObject(cx, fieldsVec));
   if (!fieldsProp) {
     return nullptr;
   }
 
   // Seal the fields array.
   if (!JS_FreezeObject(cx, fieldsProp)) {
     return nullptr;
   }
@@ -6724,29 +6725,29 @@ bool FunctionType::Create(JSContext* cx,
   RootedObject arrayObj(cx, nullptr);
 
   if (args.length() == 3) {
     // Prepare an array of Values for the arguments.
     bool isArray;
     if (!args[2].isObject()) {
       isArray = false;
     } else {
-      if (!JS_IsArrayObject(cx, args[2], &isArray)) {
+      if (!JS::IsArrayObject(cx, args[2], &isArray)) {
         return false;
       }
     }
 
     if (!isArray) {
       return ArgumentTypeMismatch(cx, "third ", "FunctionType", "an array");
     }
 
     arrayObj = &args[2].toObject();
 
     uint32_t len;
-    MOZ_ALWAYS_TRUE(JS_GetArrayLength(cx, arrayObj, &len));
+    MOZ_ALWAYS_TRUE(JS::GetArrayLength(cx, arrayObj, &len));
 
     if (!argTypes.resize(len)) {
       JS_ReportOutOfMemory(cx);
       return false;
     }
   }
 
   // Pull out the argument types from the array, if any.
@@ -7087,17 +7088,17 @@ bool FunctionType::ArgTypesGetter(JSCont
     if (!vec.resize(len)) {
       return false;
     }
 
     for (size_t i = 0; i < len; ++i) {
       vec[i].setObject(*fninfo->mArgTypes[i]);
     }
 
-    argTypes = JS_NewArrayObject(cx, vec);
+    argTypes = JS::NewArrayObject(cx, vec);
     if (!argTypes) {
       return false;
     }
   }
 
   // Seal and cache it.
   if (!JS_FreezeObject(cx, argTypes)) {
     return false;
--- a/js/src/gdb/tests/test-Root.cpp
+++ b/js/src/gdb/tests/test-Root.cpp
@@ -1,13 +1,14 @@
 #include "gdb-tests.h"
 
 #include "jsapi.h"
 
 #include "gc/Barrier.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "vm/JSFunction.h"
 
 FRAGMENT(Root, null) {
   JS::Rooted<JSObject*> null(cx, nullptr);
 
   breakpoint();
 
   use(null);
@@ -26,17 +27,17 @@ FRAGMENT(Root, handle) {
   callee(global, &global);
   use(global);
 }
 
 FRAGMENT(Root, HeapSlot) {
   JS::Rooted<JS::Value> plinth(
       cx, JS::StringValue(JS_NewStringCopyZ(cx, "plinth")));
   JS::Rooted<JSObject*> array(
-      cx, JS_NewArrayObject(cx, JS::HandleValueArray(plinth)));
+      cx, JS::NewArrayObject(cx, JS::HandleValueArray(plinth)));
 
   breakpoint();
 
   use(plinth);
   use(array);
 }
 
 FRAGMENT(Root, barriers) {
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "jsapi-tests/tests.h"
 
 static int callCount = 0;
 
 static bool AddProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
                         JS::HandleValue v) {
   callCount++;
   return true;
@@ -28,17 +29,17 @@ BEGIN_TEST(testAddPropertyHook) {
   static const int ExpectedCount = 100;
 
   JS::RootedObject obj(cx, JS_NewPlainObject(cx));
   CHECK(obj);
   JS::RootedValue proto(cx, JS::ObjectValue(*obj));
   JS_InitClass(cx, global, obj, &AddPropertyClass, nullptr, 0, nullptr, nullptr,
                nullptr, nullptr);
 
-  obj = JS_NewArrayObject(cx, 0);
+  obj = JS::NewArrayObject(cx, 0);
   CHECK(obj);
   JS::RootedValue arr(cx, JS::ObjectValue(*obj));
 
   CHECK(JS_DefineProperty(cx, global, "arr", arr, JSPROP_ENUMERATE));
 
   JS::RootedObject arrObj(cx, &arr.toObject());
   for (int i = 0; i < ExpectedCount; ++i) {
     obj = JS_NewObject(cx, &AddPropertyClass);
--- a/js/src/jsapi-tests/testArrayBuffer.cpp
+++ b/js/src/jsapi-tests/testArrayBuffer.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  */
 
 #include "jsfriendapi.h"
 
 #include "builtin/TestingFunctions.h"
+#include "js/Array.h"        // JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{GetArrayBuffer{ByteLength,Data},IsArrayBufferObject,NewArrayBuffer{,WithContents},StealArrayBufferContents}
 #include "js/MemoryFunctions.h"
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testArrayBuffer_bug720949_steal) {
   static const unsigned NUM_TEST_BUFFERS = 2;
   static const unsigned MAGIC_VALUE_1 = 3;
   static const unsigned MAGIC_VALUE_2 = 17;
@@ -255,17 +256,17 @@ BEGIN_TEST(testArrayBuffer_serializeExte
   JS::RootedObject externalBuffer(
       cx, JS::NewExternalArrayBuffer(cx, data.len(), data.contents(),
                                      &ExternalData::freeCallback, &data));
   CHECK(externalBuffer);
   CHECK(!data.wasFreed());
 
   JS::RootedValue v(cx, JS::ObjectValue(*externalBuffer));
   JS::RootedObject transferMap(cx,
-                               JS_NewArrayObject(cx, JS::HandleValueArray(v)));
+                               JS::NewArrayObject(cx, JS::HandleValueArray(v)));
   CHECK(transferMap);
 
   JS::AutoValueArray<2> args(cx);
   args[0].setObject(*externalBuffer);
   args[1].setObject(*transferMap);
 
   // serialize(externalBuffer, [externalBuffer]) should throw for an unhandled
   // BufferContents kind.
--- a/js/src/jsapi-tests/testInformalValueTypeName.cpp
+++ b/js/src/jsapi-tests/testInformalValueTypeName.cpp
@@ -1,23 +1,24 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/Symbol.h"
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testInformalValueTypeName) {
   JS::RootedValue v1(cx, JS::ObjectOrNullValue(JS_NewPlainObject(cx)));
   CHECK(strcmp(JS::InformalValueTypeName(v1), "Object") == 0);
 
-  JS::RootedValue v2(cx, JS::ObjectOrNullValue(JS_NewArrayObject(cx, 0)));
+  JS::RootedValue v2(cx, JS::ObjectOrNullValue(JS::NewArrayObject(cx, 0)));
   CHECK(strcmp(JS::InformalValueTypeName(v2), "Array") == 0);
 
   JS::RootedValue v3(cx, JS::StringValue(JS_GetEmptyString(cx)));
   CHECK(strcmp(JS::InformalValueTypeName(v3), "string") == 0);
 
   JS::RootedValue v4(cx, JS::SymbolValue(JS::NewSymbol(cx, nullptr)));
   CHECK(strcmp(JS::InformalValueTypeName(v4), "symbol") == 0);
 
--- a/js/src/jsapi-tests/testMappedArrayBuffer.cpp
+++ b/js/src/jsapi-tests/testMappedArrayBuffer.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  */
 
 #include <fcntl.h>
 #include <stdio.h>
 
 #include "jsfriendapi.h"
+#include "js/Array.h"        // JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{{Create,Release}MappedArrayBufferContents,DetachArrayBuffer,GetArrayBuffer{ByteLength,Data},Is{,Detached,Mapped}ArrayBufferObject,NewMappedArrayBufferWithContents,StealArrayBufferContents}
 #include "js/StructuredClone.h"
 #include "jsapi-tests/tests.h"
 #include "vm/ArrayBufferObject.h"
 
 #ifdef XP_WIN
 #  include <io.h>
 #  define GET_OS_FD(a) int(_get_osfhandle(a))
@@ -162,17 +163,17 @@ bool TestTransferObject() {
 
   // Create an Array of transferable values.
   JS::RootedValueVector argv(cx);
   if (!argv.append(v1)) {
     return false;
   }
 
   JS::RootedObject obj(
-      cx, JS_NewArrayObject(cx, JS::HandleValueArray::subarray(argv, 0, 1)));
+      cx, JS::NewArrayObject(cx, JS::HandleValueArray::subarray(argv, 0, 1)));
   CHECK(obj);
   JS::RootedValue transferable(cx, JS::ObjectValue(*obj));
 
   JSAutoStructuredCloneBuffer cloned_buffer(
       JS::StructuredCloneScope::SameProcessSameThread, nullptr, nullptr);
   JS::CloneDataPolicy policy;
   CHECK(cloned_buffer.write(cx, v1, transferable, policy, nullptr, nullptr));
   JS::RootedValue v2(cx);
--- a/js/src/jsapi-tests/testNewObject.cpp
+++ b/js/src/jsapi-tests/testNewObject.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "jsapi-tests/tests.h"
 
 static bool constructHook(JSContext* cx, unsigned argc, JS::Value* vp) {
   JS::CallArgs args = CallArgsFromVp(argc, vp);
 
   // Check that arguments were passed properly from JS_New.
 
   JS::RootedObject obj(cx, JS_NewPlainObject(cx));
@@ -61,42 +62,42 @@ BEGIN_TEST(testNewObject_1) {
   JS::RootedObject Array(cx, v.toObjectOrNull());
 
   bool isArray;
 
   // With no arguments.
   JS::RootedObject obj(cx, JS_New(cx, Array, JS::HandleValueArray::empty()));
   CHECK(obj);
   JS::RootedValue rt(cx, JS::ObjectValue(*obj));
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(isArray);
   uint32_t len;
-  CHECK(JS_GetArrayLength(cx, obj, &len));
+  CHECK(JS::GetArrayLength(cx, obj, &len));
   CHECK_EQUAL(len, 0u);
 
   // With one argument.
   argv[0].setInt32(4);
   obj = JS_New(cx, Array, JS::HandleValueArray::subarray(argv, 0, 1));
   CHECK(obj);
   rt = JS::ObjectValue(*obj);
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(isArray);
-  CHECK(JS_GetArrayLength(cx, obj, &len));
+  CHECK(JS::GetArrayLength(cx, obj, &len));
   CHECK_EQUAL(len, 4u);
 
   // With N arguments.
   for (size_t i = 0; i < N; i++) {
     argv[i].setInt32(i);
   }
   obj = JS_New(cx, Array, JS::HandleValueArray::subarray(argv, 0, N));
   CHECK(obj);
   rt = JS::ObjectValue(*obj);
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(isArray);
-  CHECK(JS_GetArrayLength(cx, obj, &len));
+  CHECK(JS::GetArrayLength(cx, obj, &len));
   CHECK_EQUAL(len, N);
   CHECK(JS_GetElement(cx, obj, N - 1, &v));
   CHECK(v.isInt32(N - 1));
 
   // With JSClass.construct.
   static const JSClassOps clsOps = {nullptr, nullptr,      nullptr, nullptr,
                                     nullptr, nullptr,      nullptr, nullptr,
                                     nullptr, constructHook};
--- a/js/src/jsapi-tests/testParseJSON.cpp
+++ b/js/src/jsapi-tests/testParseJSON.cpp
@@ -3,16 +3,17 @@
  */
 /* 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/. */
 
 #include <limits>
 #include <string.h>
 
+#include "js/Array.h"  // JS::IsArrayObject
 #include "js/JSON.h"
 #include "js/MemoryFunctions.h"
 #include "js/Printf.h"
 #include "jsapi-tests/tests.h"
 
 using namespace js;
 
 class AutoInflatedString {
@@ -113,42 +114,42 @@ BEGIN_TEST(testParseJSON_success) {
   JS::RootedValue v(cx), v2(cx);
   JS::RootedObject obj(cx);
 
   bool isArray;
 
   CHECK(Parse(cx, "[]", &v));
   CHECK(v.isObject());
   obj = &v.toObject();
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(isArray);
   CHECK(JS_GetProperty(cx, obj, "length", &v2));
   CHECK(v2.isInt32(0));
 
   CHECK(Parse(cx, "[1]", &v));
   CHECK(v.isObject());
   obj = &v.toObject();
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(isArray);
   CHECK(JS_GetProperty(cx, obj, "0", &v2));
   CHECK(v2.isInt32(1));
   CHECK(JS_GetProperty(cx, obj, "length", &v2));
   CHECK(v2.isInt32(1));
 
   // Objects
   CHECK(Parse(cx, "{}", &v));
   CHECK(v.isObject());
   obj = &v.toObject();
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(!isArray);
 
   CHECK(Parse(cx, "{ \"f\": 17 }", &v));
   CHECK(v.isObject());
   obj = &v.toObject();
-  CHECK(JS_IsArrayObject(cx, obj, &isArray));
+  CHECK(JS::IsArrayObject(cx, obj, &isArray));
   CHECK(!isArray);
   CHECK(JS_GetProperty(cx, obj, "f", &v2));
   CHECK(v2.isInt32(17));
 
   return true;
 }
 
 template <size_t N>
--- a/js/src/jsapi-tests/testWeakMap.cpp
+++ b/js/src/jsapi-tests/testWeakMap.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
 #include "gc/Zone.h"
+#include "js/Array.h"  // JS::GetArrayLength
 #include "jsapi-tests/tests.h"
 #include "vm/Realm.h"
 
 JSObject* keyDelegate = nullptr;
 
 BEGIN_TEST(testWeakMap_basicOperations) {
   JS::RootedObject map(cx, JS::NewWeakMapObject(cx));
   CHECK(IsWeakMapObject(map));
@@ -48,17 +49,17 @@ BEGIN_TEST(testWeakMap_basicOperations) 
 
 JSObject* newKey() { return JS_NewPlainObject(cx); }
 
 bool checkSize(JS::HandleObject map, uint32_t expected) {
   JS::RootedObject keys(cx);
   CHECK(JS_NondeterministicGetWeakMapKeys(cx, map, &keys));
 
   uint32_t length;
-  CHECK(JS_GetArrayLength(cx, keys, &length));
+  CHECK(JS::GetArrayLength(cx, keys, &length));
   CHECK(length == expected);
 
   return true;
 }
 END_TEST(testWeakMap_basicOperations)
 
 BEGIN_TEST(testWeakMap_keyDelegates) {
 #ifdef JS_GC_ZEAL
@@ -230,14 +231,14 @@ JSObject* newDelegate() {
   return global;
 }
 
 bool checkSize(JS::HandleObject map, uint32_t expected) {
   JS::RootedObject keys(cx);
   CHECK(JS_NondeterministicGetWeakMapKeys(cx, map, &keys));
 
   uint32_t length;
-  CHECK(JS_GetArrayLength(cx, keys, &length));
+  CHECK(JS::GetArrayLength(cx, keys, &length));
   CHECK(length == expected);
 
   return true;
 }
 END_TEST(testWeakMap_keyDelegates)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -95,16 +95,17 @@
 #include "vm/WrapperObject.h"
 #include "vm/Xdr.h"
 #include "wasm/WasmModule.h"
 #include "wasm/WasmProcess.h"
 
 #include "debugger/DebugAPI-inl.h"
 #include "vm/Compartment-inl.h"
 #include "vm/Interpreter-inl.h"
+#include "vm/IsGivenTypeObject-inl.h"  // js::IsGivenTypeObject
 #include "vm/JSAtom-inl.h"
 #include "vm/JSFunction-inl.h"
 #include "vm/JSScript-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/SavedStacks-inl.h"
 #include "vm/StringType-inl.h"
 
 using namespace js;
@@ -3125,79 +3126,16 @@ JS_PUBLIC_API void JS_InitReservedSlot(J
                    js::MemoryUse(use));
 }
 
 JS_PUBLIC_API void JS_InitPrivate(JSObject* obj, void* data, size_t nbytes,
                                   JS::MemoryUse use) {
   InitObjectPrivate(&obj->as<NativeObject>(), data, nbytes, js::MemoryUse(use));
 }
 
-JS_PUBLIC_API JSObject* JS_NewArrayObject(
-    JSContext* cx, const JS::HandleValueArray& contents) {
-  MOZ_ASSERT(!cx->zone()->isAtomsZone());
-  AssertHeapIsIdle();
-  CHECK_THREAD(cx);
-
-  cx->check(contents);
-  return NewDenseCopiedArray(cx, contents.length(), contents.begin());
-}
-
-JS_PUBLIC_API JSObject* JS_NewArrayObject(JSContext* cx, size_t length) {
-  MOZ_ASSERT(!cx->zone()->isAtomsZone());
-  AssertHeapIsIdle();
-  CHECK_THREAD(cx);
-
-  return NewDenseFullyAllocatedArray(cx, length);
-}
-
-inline bool IsGivenTypeObject(JSContext* cx, JS::HandleObject obj,
-                              const ESClass& typeClass, bool* isType) {
-  cx->check(obj);
-
-  ESClass cls;
-  if (!GetBuiltinClass(cx, obj, &cls)) {
-    return false;
-  }
-
-  *isType = cls == typeClass;
-  return true;
-}
-
-JS_PUBLIC_API bool JS_IsArrayObject(JSContext* cx, JS::HandleObject obj,
-                                    bool* isArray) {
-  return IsGivenTypeObject(cx, obj, ESClass::Array, isArray);
-}
-
-JS_PUBLIC_API bool JS_IsArrayObject(JSContext* cx, JS::HandleValue value,
-                                    bool* isArray) {
-  if (!value.isObject()) {
-    *isArray = false;
-    return true;
-  }
-
-  RootedObject obj(cx, &value.toObject());
-  return JS_IsArrayObject(cx, obj, isArray);
-}
-
-JS_PUBLIC_API bool JS_GetArrayLength(JSContext* cx, HandleObject obj,
-                                     uint32_t* lengthp) {
-  AssertHeapIsIdle();
-  CHECK_THREAD(cx);
-  cx->check(obj);
-  return GetLengthProperty(cx, obj, lengthp);
-}
-
-JS_PUBLIC_API bool JS_SetArrayLength(JSContext* cx, HandleObject obj,
-                                     uint32_t length) {
-  AssertHeapIsIdle();
-  CHECK_THREAD(cx);
-  cx->check(obj);
-  return SetLengthProperty(cx, obj, length);
-}
-
 JS_PUBLIC_API bool JS::IsMapObject(JSContext* cx, JS::HandleObject obj,
                                    bool* isMap) {
   return IsGivenTypeObject(cx, obj, ESClass::Map, isMap);
 }
 
 JS_PUBLIC_API bool JS::IsSetObject(JSContext* cx, JS::HandleObject obj,
                                    bool* isSet) {
   return IsGivenTypeObject(cx, obj, ESClass::Set, isSet);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1600,51 +1600,16 @@ extern JS_PUBLIC_API bool JS_AlreadyHasO
                                                      const char16_t* name,
                                                      size_t namelen,
                                                      bool* foundp);
 
 extern JS_PUBLIC_API bool JS_AlreadyHasOwnElement(JSContext* cx,
                                                   JS::HandleObject obj,
                                                   uint32_t index, bool* foundp);
 
-extern JS_PUBLIC_API JSObject* JS_NewArrayObject(
-    JSContext* cx, const JS::HandleValueArray& contents);
-
-extern JS_PUBLIC_API JSObject* JS_NewArrayObject(JSContext* cx, size_t length);
-
-/**
- * On success, returns true, setting |*isArray| to true if |value| is an Array
- * object or a wrapper around one, or to false if not.  Returns false on
- * failure.
- *
- * This method returns true with |*isArray == false| when passed an ES6 proxy
- * whose target is an Array, or when passed a revoked proxy.
- */
-extern JS_PUBLIC_API bool JS_IsArrayObject(JSContext* cx, JS::HandleValue value,
-                                           bool* isArray);
-
-/**
- * On success, returns true, setting |*isArray| to true if |obj| is an Array
- * object or a wrapper around one, or to false if not.  Returns false on
- * failure.
- *
- * This method returns true with |*isArray == false| when passed an ES6 proxy
- * whose target is an Array, or when passed a revoked proxy.
- */
-extern JS_PUBLIC_API bool JS_IsArrayObject(JSContext* cx, JS::HandleObject obj,
-                                           bool* isArray);
-
-extern JS_PUBLIC_API bool JS_GetArrayLength(JSContext* cx,
-                                            JS::Handle<JSObject*> obj,
-                                            uint32_t* lengthp);
-
-extern JS_PUBLIC_API bool JS_SetArrayLength(JSContext* cx,
-                                            JS::Handle<JSObject*> obj,
-                                            uint32_t length);
-
 namespace JS {
 
 /**
  * On success, returns true, setting |*isMap| to true if |obj| is a Map object
  * or a wrapper around one, or to false if not.  Returns false on failure.
  *
  * This method returns true with |*isMap == false| when passed an ES6 proxy
  * whose target is a Map, or when passed a revoked proxy.
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -118,16 +118,17 @@ EXPORTS += [
     'jsfriendapi.h',
     'jspubtd.h',
     'jstypes.h',
 ]
 
 EXPORTS.js += [
     '../public/AllocationRecording.h',
     '../public/AllocPolicy.h',
+    '../public/Array.h',
     '../public/ArrayBuffer.h',
     '../public/BinASTFormat.h',
     '../public/BuildId.h',
     '../public/CallArgs.h',
     '../public/CallNonGenericMethod.h',
     '../public/CharacterEncoding.h',
     '../public/Class.h',
     '../public/CompilationAndEvaluation.h',
--- a/js/src/proxy/Proxy.h
+++ b/js/src/proxy/Proxy.h
@@ -4,16 +4,17 @@
  * 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 proxy_Proxy_h
 #define proxy_Proxy_h
 
 #include "NamespaceImports.h"
 
+#include "js/Array.h"  // JS::IsArrayAnswer
 #include "js/Class.h"
 
 namespace js {
 
 /*
  * Dispatch point for handlers that executes the appropriate C++ or scripted
  * traps.
  *
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -81,16 +81,17 @@
 #include "frontend/Parser.h"
 #include "gc/PublicIterators.h"
 #include "jit/arm/Simulator-arm.h"
 #include "jit/InlinableNatives.h"
 #include "jit/Ion.h"
 #include "jit/JitcodeMap.h"
 #include "jit/JitRealm.h"
 #include "jit/shared/CodeGenerator-shared.h"
+#include "js/Array.h"        // JS::NewArrayObject
 #include "js/ArrayBuffer.h"  // JS::{CreateMappedArrayBufferContents,NewMappedArrayBufferWithContents,IsArrayBufferObject,GetArrayBufferLengthAndData}
 #include "js/BuildId.h"      // JS::BuildIdCharVector, JS::SetProcessBuildIdOp
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/CompileOptions.h"
 #include "js/ContextOptions.h"  // JS::ContextOptions{,Ref}
 #include "js/Debug.h"
 #include "js/Equality.h"                 // JS::SameValue
@@ -6693,17 +6694,17 @@ static bool DisableSingleStepProfiling(J
     if (!stack) {
       return false;
     }
     if (!elems.append(StringValue(stack))) {
       return false;
     }
   }
 
-  JSObject* array = JS_NewArrayObject(cx, elems);
+  JSObject* array = JS::NewArrayObject(cx, elems);
   if (!array) {
     return false;
   }
 
   sc->stacks.clear();
   args.rval().setObject(*array);
   return true;
 #else
@@ -7950,17 +7951,17 @@ class ShellAutoEntryMonitor : JS::dbg::A
   }
 
   bool buildResult(JSContext* cx, MutableHandleValue resultValue) {
     if (oom) {
       JS_ReportOutOfMemory(cx);
       return false;
     }
 
-    RootedObject result(cx, JS_NewArrayObject(cx, log.length()));
+    RootedObject result(cx, JS::NewArrayObject(cx, log.length()));
     if (!result) {
       return false;
     }
 
     for (size_t i = 0; i < log.length(); i++) {
       char* name = log[i].get();
       RootedString string(cx, Atomize(cx, name, strlen(name)));
       if (!string) {
@@ -10092,17 +10093,17 @@ static JSObject* NewGlobalObject(JSConte
   return glob;
 }
 
 static bool BindScriptArgs(JSContext* cx, OptionParser* op) {
   AutoReportException are(cx);
 
   MultiStringRange msr = op->getMultiStringArg("scriptArgs");
   RootedObject scriptArgs(cx);
-  scriptArgs = JS_NewArrayObject(cx, 0);
+  scriptArgs = JS::NewArrayObject(cx, 0);
   if (!scriptArgs) {
     return false;
   }
 
   if (!JS_DefineProperty(cx, cx->global(), "scriptArgs", scriptArgs, 0)) {
     return false;
   }
 
new file mode 100644
--- /dev/null
+++ b/js/src/vm/IsGivenTypeObject-inl.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 vm_IsGivenTypeObject_inl_h
+#define vm_IsGivenTypeObject_inl_h
+
+#include "js/Class.h"       // js::ESClass
+#include "js/RootingAPI.h"  // JS::Handle
+
+#include "vm/JSContext-inl.h"  // JSContext::check
+
+namespace js {
+
+inline bool IsGivenTypeObject(JSContext* cx, JS::Handle<JSObject*> obj,
+                              const ESClass& typeClass, bool* isType) {
+  cx->check(obj);
+
+  ESClass cls;
+  if (!GetBuiltinClass(cx, obj, &cls)) {
+    return false;
+  }
+
+  *isType = cls == typeClass;
+  return true;
+}
+
+}  // namespace js
+
+#endif  // vm_IsGivenTypeObject_inl_h
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -39,16 +39,17 @@
 #include <memory>
 #include <utility>
 
 #include "jsapi.h"
 #include "jsdate.h"
 
 #include "builtin/DataViewObject.h"
 #include "builtin/MapObject.h"
+#include "js/Array.h"        // JS::GetArrayLength, JS::IsArrayObject
 #include "js/ArrayBuffer.h"  // JS::{ArrayBufferHasData,DetachArrayBuffer,IsArrayBufferObject,New{,Mapped}ArrayBufferWithContents,ReleaseMappedArrayBufferContents}
 #include "js/Date.h"
 #include "js/GCHashTable.h"
 #include "js/RegExpFlags.h"        // JS::RegExpFlag, JS::RegExpFlags
 #include "js/SharedArrayBuffer.h"  // JS::IsSharedArrayBufferObject
 #include "js/Wrapper.h"
 #include "vm/BigIntType.h"
 #include "vm/JSContext.h"
@@ -1022,25 +1023,25 @@ bool JSStructuredCloneWriter::parseTrans
 
   if (!transferable.isObject()) {
     return reportDataCloneError(JS_SCERR_TRANSFERABLE);
   }
 
   JSContext* cx = context();
   RootedObject array(cx, &transferable.toObject());
   bool isArray;
-  if (!JS_IsArrayObject(cx, array, &isArray)) {
+  if (!JS::IsArrayObject(cx, array, &isArray)) {
     return false;
   }
   if (!isArray) {
     return reportDataCloneError(JS_SCERR_TRANSFERABLE);
   }
 
   uint32_t length;
-  if (!JS_GetArrayLength(cx, array, &length)) {
+  if (!JS::GetArrayLength(cx, array, &length)) {
     return false;
   }
 
   // Initialize the set for the provided array's length.
   if (!transferableObjects.reserve(length)) {
     return false;
   }
 
@@ -1433,17 +1434,17 @@ bool JSStructuredCloneWriter::traverseOb
     return false;
   }
   MOZ_ASSERT(cls2 == cls);
 #endif
 
   // Write the header for obj.
   if (cls == ESClass::Array) {
     uint32_t length = 0;
-    if (!JS_GetArrayLength(context(), obj, &length)) {
+    if (!JS::GetArrayLength(context(), obj, &length)) {
       return false;
     }
 
     return out.writePair(SCTAG_ARRAY_OBJECT,
                          NativeEndian::swapToLittleEndian(length));
   }
 
   return out.writePair(SCTAG_OBJECT_OBJECT, 0);
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -13,16 +13,17 @@
 #ifdef ANDROID
 #  include <android/log.h>
 #endif
 #ifdef XP_WIN
 #  include <windows.h>
 #endif
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/Printf.h"
 #include "js/PropertySpec.h"
 #include "js/SourceText.h"  // JS::SourceText
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsExceptionHandler.h"
@@ -1173,29 +1174,29 @@ nsresult mozJSComponentLoader::ExtractEx
     RootedObject obj(
         cx, ResolveModuleObjectProperty(cx, aMod->obj, "EXPORTED_SYMBOLS"));
     if (!obj || !JS_GetProperty(cx, obj, "EXPORTED_SYMBOLS", &symbols)) {
       return ReportOnCallerUTF8(cxhelper, ERROR_NOT_PRESENT, aInfo);
     }
   }
 
   bool isArray;
-  if (!JS_IsArrayObject(cx, symbols, &isArray)) {
+  if (!JS::IsArrayObject(cx, symbols, &isArray)) {
     return NS_ERROR_FAILURE;
   }
   if (!isArray) {
     return ReportOnCallerUTF8(cxhelper, ERROR_NOT_AN_ARRAY, aInfo);
   }
 
   RootedObject symbolsObj(cx, &symbols.toObject());
 
   // Iterate over symbols array, installing symbols on targetObj:
 
   uint32_t symbolCount = 0;
-  if (!JS_GetArrayLength(cx, symbolsObj, &symbolCount)) {
+  if (!JS::GetArrayLength(cx, symbolsObj, &symbolCount)) {
     return ReportOnCallerUTF8(cxhelper, ERROR_GETTING_ARRAY_LENGTH, aInfo);
   }
 
 #ifdef DEBUG
   nsAutoCString logBuffer;
 #endif
 
   aExports.set(JS_NewPlainObject(cx));
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * The Components.Sandbox object.
  */
 
 #include "AccessCheck.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/PropertySpec.h"
 #include "js/Proxy.h"
 #include "js/SourceText.h"
 #include "js/StructuredClone.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
@@ -805,17 +806,17 @@ bool SandboxProxyHandler::getOwnEnumerab
 
 bool SandboxProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
                                     JS::MutableHandleIdVector props) const {
   return BaseProxyHandler::enumerate(cx, proxy, props);
 }
 
 bool xpc::GlobalProperties::Parse(JSContext* cx, JS::HandleObject obj) {
   uint32_t length;
-  bool ok = JS_GetArrayLength(cx, obj, &length);
+  bool ok = JS::GetArrayLength(cx, obj, &length);
   NS_ENSURE_TRUE(ok, false);
   for (uint32_t i = 0; i < length; i++) {
     RootedValue nameValue(cx);
     ok = JS_GetElement(cx, obj, i, &nameValue);
     NS_ENSURE_TRUE(ok, false);
     if (!nameValue.isString()) {
       JS_ReportErrorASCII(cx, "Property names must be strings");
       return false;
@@ -1366,17 +1367,17 @@ static bool GetPrincipalOrSOP(JSContext*
  * principals, either in string format or actual objects (see GetPrincipalOrSOP)
  */
 static bool GetExpandedPrincipal(JSContext* cx, HandleObject arrayObj,
                                  const SandboxOptions& options,
                                  nsIExpandedPrincipal** out) {
   MOZ_ASSERT(out);
   uint32_t length;
 
-  if (!JS_GetArrayLength(cx, arrayObj, &length)) {
+  if (!JS::GetArrayLength(cx, arrayObj, &length)) {
     return false;
   }
   if (!length) {
     // We need a whitelist of principals or uri strings to create an
     // expanded principal, if we got an empty array or something else
     // report error.
     JS_ReportErrorASCII(cx, "Expected an array of URI strings");
     return false;
@@ -1697,17 +1698,17 @@ bool SandboxOptions::ParseGlobalProperti
   if (!value.isObject()) {
     JS_ReportErrorASCII(mCx,
                         "Expected an array value for wantGlobalProperties");
     return false;
   }
 
   RootedObject ctors(mCx, &value.toObject());
   bool isArray;
-  if (!JS_IsArrayObject(mCx, ctors, &isArray)) {
+  if (!JS::IsArrayObject(mCx, ctors, &isArray)) {
     return false;
   }
   if (!isArray) {
     JS_ReportErrorASCII(mCx,
                         "Expected an array value for wantGlobalProperties");
     return false;
   }
 
@@ -1824,17 +1825,17 @@ nsresult nsXPCComponents_utils_Sandbox::
       }
     }
     attrs.mUserContextId = options.userContextId;
     ok = ParsePrincipal(cx, str, attrs, getter_AddRefs(principal));
     prinOrSop = principal;
   } else if (args[0].isObject()) {
     RootedObject obj(cx, &args[0].toObject());
     bool isArray;
-    if (!JS_IsArrayObject(cx, obj, &isArray)) {
+    if (!JS::IsArrayObject(cx, obj, &isArray)) {
       ok = false;
     } else if (isArray) {
       if (options.userContextId != 0) {
         // We don't support passing a userContextId with an array.
         ok = false;
       } else {
         ok = GetExpandedPrincipal(cx, obj, options, getter_AddRefs(expanded));
         prinOrSop = expanded;
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -10,16 +10,17 @@
 #include "xpc_make_class.h"
 #include "XPCJSWeakReference.h"
 #include "WrapperFactory.h"
 #include "nsJSUtils.h"
 #include "mozJSComponentLoader.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollector.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::IsArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/ContextOptions.h"
 #include "js/SavedFrameAPI.h"
 #include "js/StructuredClone.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/Preferences.h"
@@ -1577,17 +1578,17 @@ nsXPCComponents_Utils::ImportGlobalPrope
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   GlobalProperties options;
   NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
 
   RootedObject propertyList(cx, &aPropertyList.toObject());
   bool isArray;
-  if (NS_WARN_IF(!JS_IsArrayObject(cx, propertyList, &isArray))) {
+  if (NS_WARN_IF(!JS::IsArrayObject(cx, propertyList, &isArray))) {
     return NS_ERROR_FAILURE;
   }
   if (NS_WARN_IF(!isArray)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (!options.Parse(cx, propertyList) ||
       !options.DefineInXPCComponents(cx, global)) {
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -17,16 +17,17 @@
 #include "nsQueryObject.h"
 #include "nsScriptError.h"
 #include "WrapperFactory.h"
 
 #include "nsWrapperCacheInlines.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/MemoryFunctions.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
@@ -1375,17 +1376,17 @@ nsresult XPCConvert::JSValToXPCException
 
 // static
 bool XPCConvert::NativeArray2JS(JSContext* cx, MutableHandleValue d,
                                 const void* buf, const nsXPTType& type,
                                 const nsID* iid, uint32_t count,
                                 nsresult* pErr) {
   MOZ_ASSERT(buf || count == 0, "Must have buf or 0 elements");
 
-  RootedObject array(cx, JS_NewArrayObject(cx, count));
+  RootedObject array(cx, JS::NewArrayObject(cx, count));
   if (!array) {
     return false;
   }
 
   if (pErr) {
     *pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
   }
 
@@ -1506,18 +1507,18 @@ bool XPCConvert::JSArray2Native(JSContex
     // Directly copy data into the allocated target buffer.
     memcpy(buf, data, length * aEltType.Stride());
     return true;
   }
 
   // If jsarray is not a TypedArrayObject, check for an Array object.
   uint32_t length = 0;
   bool isArray = false;
-  if (!JS_IsArrayObject(cx, jsarray, &isArray) || !isArray ||
-      !JS_GetArrayLength(cx, jsarray, &length)) {
+  if (!JS::IsArrayObject(cx, jsarray, &isArray) || !isArray ||
+      !JS::GetArrayLength(cx, jsarray, &length)) {
     if (pErr) {
       *pErr = NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY;
     }
     return false;
   }
 
   void* buf = allocFixupLen(&length);
   if (!buf) {
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -2,16 +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/. */
 
 #include "nsXULAppAPI.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"  // JS::Evaluate
 #include "js/ContextOptions.h"
 #include "js/Printf.h"
 #include "js/PropertySpec.h"
 #include "js/SourceText.h"  // JS::SourceText
 #include "mozilla/ChaosMode.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -926,17 +927,17 @@ static bool ProcessArgs(AutoJSAPI& jsapi
                        // |-e foo|.
     }
   }
 
   /*
    * Create arguments early and define it to root it, so it's safe from any
    * GC calls nested below, and so it is available to -f <file> arguments.
    */
-  argsObj = JS_NewArrayObject(cx, 0);
+  argsObj = JS::NewArrayObject(cx, 0);
   if (!argsObj) {
     return 1;
   }
   if (!JS_DefineProperty(cx, global, "arguments", argsObj, 0)) {
     return 1;
   }
 
   for (int j = 0, length = argc - rootPosition; j < length; j++) {
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -6,16 +6,17 @@
 
 /* nsIVariant implementation for xpconnect. */
 
 #include "mozilla/Range.h"
 
 #include "xpcprivate.h"
 
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "js/Wrapper.h"
 
 using namespace JS;
 using namespace mozilla;
 
 NS_IMPL_CLASSINFO(XPCVariant, nullptr, 0, XPCVARIANT_CID)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCVariant)
   NS_INTERFACE_MAP_ENTRY(XPCVariant)
@@ -183,17 +184,17 @@ bool XPCArrayHomogenizer::GetTypeForArra
       type = tNull;
     } else if (val.isString()) {
       type = tStr;
     } else {
       MOZ_ASSERT(val.isObject(), "invalid type of jsval!");
       jsobj = &val.toObject();
 
       bool isArray;
-      if (!JS_IsArrayObject(cx, jsobj, &isArray)) {
+      if (!JS::IsArrayObject(cx, jsobj, &isArray)) {
         return false;
       }
 
       if (isArray) {
         type = tArr;
       } else if (xpc::JSValue2ID(cx, val)) {
         type = tID;
       } else {
@@ -313,18 +314,18 @@ bool XPCVariant::InitializeData(JSContex
 
   RootedObject jsobj(cx, &val.toObject());
 
   // Let's see if it is a js array object.
 
   uint32_t len;
 
   bool isArray;
-  if (!JS_IsArrayObject(cx, jsobj, &isArray) ||
-      (isArray && !JS_GetArrayLength(cx, jsobj, &len))) {
+  if (!JS::IsArrayObject(cx, jsobj, &isArray) ||
+      (isArray && !JS::GetArrayLength(cx, jsobj, &len))) {
     return false;
   }
 
   if (isArray) {
     if (!len) {
       // Zero length array
       mData.SetToEmptyArray();
       return true;
@@ -645,17 +646,17 @@ bool XPCVariant::VariantDataToJS(JSConte
 
       bool success = XPCConvert::NativeData2JS(
           cx, pJSVal, (const void*)&du.u.array.mArrayValue,
           nsXPTType::MkArrayType(xptIndex), pid, du.u.array.mArrayCount, pErr);
 
       return success;
     }
     case nsIDataType::VTYPE_EMPTY_ARRAY: {
-      JSObject* array = JS_NewArrayObject(cx, 0);
+      JSObject* array = JS::NewArrayObject(cx, 0);
       if (!array) {
         return false;
       }
       pJSVal.setObject(*array);
       return true;
     }
     case nsIDataType::VTYPE_VOID:
       pJSVal.setUndefined();
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Wrapper object for reflecting native xpcom objects into JavaScript. */
 
 #include "xpcprivate.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsWrapperCacheInlines.h"
 #include "XPCLog.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/MemoryFunctions.h"
 #include "js/Printf.h"
 #include "jsfriendapi.h"
 #include "AccessCheck.h"
 #include "WrapperFactory.h"
 #include "XrayWrapper.h"
 
 #include "nsContentUtils.h"
@@ -1226,18 +1227,18 @@ bool CallMethodHelper::GetArraySizeFromP
   // have it, we stick it in the right slot so that we can find it again when
   // cleaning up the params. from the array.
   if (argnum >= mArgc && maybeArray.isObject()) {
     MOZ_ASSERT(mMethodInfo->Param(argnum).IsOptional());
     RootedObject arrayOrNull(mCallContext, &maybeArray.toObject());
 
     bool isArray;
     bool ok = false;
-    if (JS_IsArrayObject(mCallContext, maybeArray, &isArray) && isArray) {
-      ok = JS_GetArrayLength(mCallContext, arrayOrNull, lengthp);
+    if (JS::IsArrayObject(mCallContext, maybeArray, &isArray) && isArray) {
+      ok = JS::GetArrayLength(mCallContext, arrayOrNull, lengthp);
     } else if (JS_IsTypedArrayObject(&maybeArray.toObject())) {
       *lengthp = JS_GetTypedArrayLength(&maybeArray.toObject());
       ok = true;
     }
 
     if (!ok) {
       return Throw(NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY, mCallContext);
     }
--- a/layout/style/FontFaceSetIterator.cpp
+++ b/layout/style/FontFaceSetIterator.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "mozilla/dom/FontFaceSetIterator.h"
 
+#include "js/Array.h"  // JS::NewArrayObject
+
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION(FontFaceSetIterator, mFontFaceSet)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(FontFaceSetIterator, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(FontFaceSetIterator, Release)
 
@@ -56,17 +58,17 @@ void FontFaceSetIterator::Next(JSContext
   }
 
   if (mIsKeyAndValue) {
     JS::AutoValueArray<2> values(aCx);
     values[0].set(value);
     values[1].set(value);
 
     JS::Rooted<JSObject*> array(aCx);
-    array = JS_NewArrayObject(aCx, values);
+    array = JS::NewArrayObject(aCx, values);
     if (array) {
       aResult.mValue.setObject(*array);
     }
   } else {
     aResult.mValue = value;
   }
 
   aResult.mDone = false;
--- a/mobile/android/components/geckoview/GeckoViewHistory.cpp
+++ b/mobile/android/components/geckoview/GeckoViewHistory.cpp
@@ -1,16 +1,17 @@
 /* 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/. */
 
 #include "GeckoViewHistory.h"
 
 #include "JavaBuiltins.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "nsIURI.h"
 #include "nsXULAppAPI.h"
 
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/StaticPrefs_layout.h"
 
 #include "mozilla/dom/ContentParent.h"
@@ -390,25 +391,25 @@ class GetVisitedCallback final : public 
    * TODO (bug 1503482): Remove this unboxing.
    */
   bool ExtractVisitedURIs(JSContext* aCx, JS::HandleValue aData,
                           nsTArray<VisitedURI>& aVisitedURIs) {
     if (aData.isNull()) {
       return true;
     }
     bool isArray = false;
-    if (NS_WARN_IF(!JS_IsArrayObject(aCx, aData, &isArray))) {
+    if (NS_WARN_IF(!JS::IsArrayObject(aCx, aData, &isArray))) {
       return false;
     }
     if (NS_WARN_IF(!isArray)) {
       return false;
     }
     JS::Rooted<JSObject*> visited(aCx, &aData.toObject());
     uint32_t length = 0;
-    if (NS_WARN_IF(!JS_GetArrayLength(aCx, visited, &length))) {
+    if (NS_WARN_IF(!JS::GetArrayLength(aCx, visited, &length))) {
       return false;
     }
     if (NS_WARN_IF(length != mURIs.Length())) {
       return false;
     }
     if (!aVisitedURIs.SetCapacity(length, mozilla::fallible)) {
       return false;
     }
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "mozilla/LoadInfo.h"
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/Assertions.h"
 #include "mozilla/ExpandedPrincipal.h"
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/dom/ClientSource.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/PerformanceStorage.h"
 #include "mozilla/dom/BrowserChild.h"
 #include "mozilla/dom/ToJSValue.h"
@@ -1144,17 +1145,18 @@ LoadInfo::AppendRedirectHistoryEntry(nsI
     mRedirectChain.AppendElement(aEntry);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 LoadInfo::GetRedirects(JSContext* aCx, JS::MutableHandle<JS::Value> aRedirects,
                        const RedirectHistoryArray& aArray) {
-  JS::Rooted<JSObject*> redirects(aCx, JS_NewArrayObject(aCx, aArray.Length()));
+  JS::Rooted<JSObject*> redirects(aCx,
+                                  JS::NewArrayObject(aCx, aArray.Length()));
   NS_ENSURE_TRUE(redirects, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
 
   for (size_t idx = 0; idx < aArray.Length(); idx++) {
--- a/storage/mozStorageStatementRow.cpp
+++ b/storage/mozStorageStatementRow.cpp
@@ -7,16 +7,17 @@
 #include "nsMemory.h"
 #include "nsString.h"
 
 #include "mozilla/dom/MozStorageStatementRowBinding.h"
 #include "mozStorageStatementRow.h"
 #include "mozStorageStatement.h"
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 
 #include "xpc_make_class.h"
 
 namespace mozilla {
 namespace storage {
 
 ////////////////////////////////////////////////////////////////////////////////
 //// StatementRow
@@ -93,17 +94,17 @@ void StatementRow::NamedGetter(JSContext
       }
       aResult.setString(str);
       break;
     }
     case mozIStorageValueArray::VALUE_TYPE_BLOB: {
       uint32_t length;
       const uint8_t* blob = static_cast<mozIStorageStatement*>(mStatement)
                                 ->AsSharedBlob(idx, &length);
-      JS::Rooted<JSObject*> obj(aCx, ::JS_NewArrayObject(aCx, length));
+      JS::Rooted<JSObject*> obj(aCx, JS::NewArrayObject(aCx, length));
       if (!obj) {
         aRv.Throw(NS_ERROR_UNEXPECTED);
         return;
       }
       aResult.setObject(*obj);
 
       // Copy the blob over to the JS array.
       for (uint32_t i = 0; i < length; i++) {
--- a/toolkit/components/backgroundhangmonitor/HangDetails.cpp
+++ b/toolkit/components/backgroundhangmonitor/HangDetails.cpp
@@ -2,16 +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/. */
 
 #include "HangDetails.h"
 #include "nsIHangDetails.h"
 #include "nsPrintfCString.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/gfx/GPUParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"  // For RemoteTypePrefix
 #include "mozilla/Unused.h"
 #include "mozilla/GfxMessageUtils.h"  // For ParamTraits<GeckoProcessType>
 #include "mozilla/ResultExtensions.h"
 
 #ifdef MOZ_GECKO_PROFILER
@@ -105,17 +106,17 @@ nsresult StringFrame(JSContext* aCx, JS:
 }
 
 }  // anonymous namespace
 
 NS_IMETHODIMP
 nsHangDetails::GetStack(JSContext* aCx, JS::MutableHandleValue aStack) {
   auto& stack = mDetails.stack();
   uint32_t length = stack.stack().Length();
-  JS::RootedObject ret(aCx, JS_NewArrayObject(aCx, length));
+  JS::RootedObject ret(aCx, JS::NewArrayObject(aCx, length));
   if (!ret) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (uint32_t i = 0; i < length; ++i) {
     auto& entry = stack.stack()[i];
     switch (entry.type()) {
       case HangEntry::TnsCString: {
@@ -148,17 +149,17 @@ nsHangDetails::GetStack(JSContext* aCx, 
         nsresult rv =
             StringFrame(aCx, ret, i, reinterpret_cast<const char*>(start));
         NS_ENSURE_SUCCESS(rv, rv);
         break;
       }
       case HangEntry::THangEntryModOffset: {
         const HangEntryModOffset& mo = entry.get_HangEntryModOffset();
 
-        JS::RootedObject jsFrame(aCx, JS_NewArrayObject(aCx, 2));
+        JS::RootedObject jsFrame(aCx, JS::NewArrayObject(aCx, 2));
         if (!jsFrame) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
         if (!JS_DefineElement(aCx, jsFrame, 0, mo.module(), JSPROP_ENUMERATE)) {
           return NS_ERROR_OUT_OF_MEMORY;
         }
 
@@ -212,24 +213,24 @@ nsHangDetails::GetStack(JSContext* aCx, 
   aStack.setObject(*ret);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHangDetails::GetModules(JSContext* aCx, JS::MutableHandleValue aVal) {
   auto& modules = mDetails.stack().modules();
   size_t length = modules.Length();
-  JS::RootedObject retObj(aCx, JS_NewArrayObject(aCx, length));
+  JS::RootedObject retObj(aCx, JS::NewArrayObject(aCx, length));
   if (!retObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (size_t i = 0; i < length; ++i) {
     const HangModule& module = modules[i];
-    JS::RootedObject jsModule(aCx, JS_NewArrayObject(aCx, 2));
+    JS::RootedObject jsModule(aCx, JS::NewArrayObject(aCx, 2));
     if (!jsModule) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     JS::RootedString name(aCx,
                           JS_NewUCStringCopyN(aCx, module.name().BeginReading(),
                                               module.name().Length()));
     if (!JS_DefineElement(aCx, jsModule, 0, name, JSPROP_ENUMERATE)) {
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -32,16 +32,17 @@
 #include "nsIXULRuntime.h"
 #include "mozilla/Unused.h"
 #include "nsContentUtils.h"  // for nsAutoScriptBlocker
 #include "nsJSUtils.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "nsPrintfCString.h"
 #include "nsTHashtable.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "mozilla/StaticPrefs_layout.h"
 #include "mozilla/dom/ContentProcessMessageManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/PlacesObservers.h"
 #include "mozilla/dom/PlacesVisit.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla::dom;
@@ -182,31 +183,31 @@ namespace {
  *        _array's length.
  */
 nsresult GetJSArrayFromJSValue(JS::Handle<JS::Value> aValue, JSContext* aCtx,
                                JS::MutableHandle<JSObject*> _array,
                                uint32_t* _arrayLength) {
   if (aValue.isObjectOrNull()) {
     JS::Rooted<JSObject*> val(aCtx, aValue.toObjectOrNull());
     bool isArray;
-    if (!JS_IsArrayObject(aCtx, val, &isArray)) {
+    if (!JS::IsArrayObject(aCtx, val, &isArray)) {
       return NS_ERROR_UNEXPECTED;
     }
     if (isArray) {
       _array.set(val);
-      (void)JS_GetArrayLength(aCtx, _array, _arrayLength);
+      (void)JS::GetArrayLength(aCtx, _array, _arrayLength);
       NS_ENSURE_ARG(*_arrayLength > 0);
       return NS_OK;
     }
   }
 
   // Build a temporary array to store this one item so the code below can
   // just loop.
   *_arrayLength = 1;
-  _array.set(JS_NewArrayObject(aCtx, 0));
+  _array.set(JS::NewArrayObject(aCtx, 0));
   NS_ENSURE_TRUE(_array, NS_ERROR_OUT_OF_MEMORY);
 
   bool rc = JS_DefineElement(aCtx, _array, 0, aValue, 0);
   NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   return NS_OK;
 }
 
 /**
@@ -2087,29 +2088,29 @@ History::UpdatePlaces(JS::Handle<JS::Val
     JS::Rooted<JSObject*> visits(aCtx, nullptr);
     {
       JS::Rooted<JS::Value> visitsVal(aCtx);
       bool rc = JS_GetProperty(aCtx, info, "visits", &visitsVal);
       NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
       if (!visitsVal.isPrimitive()) {
         visits = visitsVal.toObjectOrNull();
         bool isArray;
-        if (!JS_IsArrayObject(aCtx, visits, &isArray)) {
+        if (!JS::IsArrayObject(aCtx, visits, &isArray)) {
           return NS_ERROR_UNEXPECTED;
         }
         if (!isArray) {
           return NS_ERROR_INVALID_ARG;
         }
       }
     }
     NS_ENSURE_ARG(visits);
 
     uint32_t visitsLength = 0;
     if (visits) {
-      (void)JS_GetArrayLength(aCtx, visits, &visitsLength);
+      (void)JS::GetArrayLength(aCtx, visits, &visitsLength);
     }
     NS_ENSURE_ARG(visitsLength > 0);
 
     // Check each visit, and build our array of VisitData objects.
     visitData.SetCapacity(visitData.Length() + visitsLength);
     for (uint32_t j = 0; j < visitsLength; j++) {
       JS::Rooted<JSObject*> visit(aCtx);
       rv = GetJSObjectFromArray(aCtx, visits, j, &visit);
--- a/toolkit/components/places/PlaceInfo.cpp
+++ b/toolkit/components/places/PlaceInfo.cpp
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PlaceInfo.h"
 #include "VisitInfo.h"
 #include "nsIURI.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 
 namespace mozilla {
 namespace places {
 
 ////////////////////////////////////////////////////////////////////////////////
 //// PlaceInfo
 
 PlaceInfo::PlaceInfo(int64_t aId, const nsCString& aGUID,
@@ -81,17 +82,17 @@ PlaceInfo::GetVisits(JSContext* aContext
   // of a place without any visit.
   if (!mVisitsAvailable) {
     _visits.setNull();
     return NS_OK;
   }
 
   // TODO bug 625913 when we use this in situations that have more than one
   // visit here, we will likely want to make this cache the value.
-  JS::Rooted<JSObject*> visits(aContext, JS_NewArrayObject(aContext, 0));
+  JS::Rooted<JSObject*> visits(aContext, JS::NewArrayObject(aContext, 0));
   NS_ENSURE_TRUE(visits, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSObject*> global(aContext, JS::CurrentGlobalOrNull(aContext));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
 
   for (VisitsArray::size_type idx = 0; idx < mVisits.Length(); idx++) {
--- a/toolkit/components/sessionstore/SessionStoreUtils.cpp
+++ b/toolkit/components/sessionstore/SessionStoreUtils.cpp
@@ -1,12 +1,13 @@
 /* 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/. */
 
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/JSON.h"
 #include "jsapi.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLSelectElement.h"
 #include "mozilla/dom/HTMLTextAreaElement.h"
@@ -898,23 +899,23 @@ static void SetElementAsObject(JSContext
       } else {
         JS_ClearPendingException(aCx);
       }
       return;
     }
 
     // For Multiple Selects Element
     bool isArray = false;
-    JS_IsArrayObject(aCx, aObject, &isArray);
+    JS::IsArrayObject(aCx, aObject, &isArray);
     if (!isArray) {
       return;
     }
     JS::Rooted<JSObject*> arrayObj(aCx, &aObject.toObject());
     uint32_t arrayLength = 0;
-    if (!JS_GetArrayLength(aCx, arrayObj, &arrayLength)) {
+    if (!JS::GetArrayLength(aCx, arrayObj, &arrayLength)) {
       JS_ClearPendingException(aCx);
       return;
     }
     nsTArray<nsString> array(arrayLength);
     for (uint32_t arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
       JS::Rooted<JS::Value> element(aCx);
       if (!JS_GetElement(aCx, arrayObj, arrayIdx, &element)) {
         JS_ClearPendingException(aCx);
--- a/toolkit/components/telemetry/core/Telemetry.cpp
+++ b/toolkit/components/telemetry/core/Telemetry.cpp
@@ -16,16 +16,17 @@
 #endif
 #include "base/pickle.h"
 #if defined(MOZ_TELEMETRY_GECKOVIEW)
 #  include "geckoview/TelemetryGeckoViewPersistence.h"
 #endif
 #include "ipc/TelemetryIPCAccumulator.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/GCAPI.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/BackgroundHangMonitor.h"
 #include "mozilla/Components.h"
 #include "mozilla/DataMutex.h"
@@ -539,17 +540,17 @@ TelemetryImpl::~TelemetryImpl() {
 void TelemetryImpl::InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
 
 bool TelemetryImpl::ReflectSQL(const SlowSQLEntryType* entry, const Stat* stat,
                                JSContext* cx, JS::Handle<JSObject*> obj) {
   if (stat->hitCount == 0) return true;
 
   const nsACString& sql = entry->GetKey();
 
-  JS::Rooted<JSObject*> arrayObj(cx, JS_NewArrayObject(cx, 0));
+  JS::Rooted<JSObject*> arrayObj(cx, JS::NewArrayObject(cx, 0));
   if (!arrayObj) {
     return false;
   }
   return (
       JS_DefineElement(cx, arrayObj, 0, stat->hitCount, JSPROP_ENUMERATE) &&
       JS_DefineElement(cx, arrayObj, 1, stat->totalTime, JSPROP_ENUMERATE) &&
       JS_DefineProperty(cx, obj, sql.BeginReading(), arrayObj,
                         JSPROP_ENUMERATE));
@@ -736,17 +737,17 @@ class GetLoadedModulesResultRunnable fin
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(mPromise->GetGlobalObject()))) {
       mPromise->MaybeReject(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
     JSContext* cx = jsapi.cx();
 
-    JS::RootedObject moduleArray(cx, JS_NewArrayObject(cx, 0));
+    JS::RootedObject moduleArray(cx, JS::NewArrayObject(cx, 0));
     if (!moduleArray) {
       mPromise->MaybeReject(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
     for (unsigned int i = 0, n = mRawModules.GetSize(); i != n; i++) {
       const SharedLibrary& info = mRawModules.GetEntry(i);
 
@@ -1823,17 +1824,17 @@ TelemetryImpl::GetAllStores(JSContext* a
     JS::RootedValue store(aCx);
 
     store.setString(ToJSString(aCx, value));
     if (!allStores.append(store)) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  JS::Rooted<JSObject*> rarray(aCx, JS_NewArrayObject(aCx, allStores));
+  JS::Rooted<JSObject*> rarray(aCx, JS::NewArrayObject(aCx, allStores));
   if (rarray == nullptr) {
     return NS_ERROR_FAILURE;
   }
   aResult.setObject(*rarray);
 
   return NS_OK;
 }
 
--- a/toolkit/components/telemetry/core/TelemetryEvent.cpp
+++ b/toolkit/components/telemetry/core/TelemetryEvent.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Telemetry.h"
 #include "TelemetryEvent.h"
 #include <prtime.h>
 #include <limits>
 #include "ipc/TelemetryIPCAccumulator.h"
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "mozilla/Maybe.h"
 #include "mozilla/Pair.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Unused.h"
 #include "nsClassHashtable.h"
@@ -569,17 +570,17 @@ void RegisterEvents(const StaticMutexAut
 // PRIVATE: thread-unsafe helpers for event handling.
 
 namespace {
 
 nsresult SerializeEventsArray(const EventRecordArray& events, JSContext* cx,
                               JS::MutableHandleObject result,
                               unsigned int dataset) {
   // We serialize the events to a JS array.
-  JS::RootedObject eventsArray(cx, JS_NewArrayObject(cx, events.Length()));
+  JS::RootedObject eventsArray(cx, JS::NewArrayObject(cx, events.Length()));
   if (!eventsArray) {
     return NS_ERROR_FAILURE;
   }
 
   for (uint32_t i = 0; i < events.Length(); ++i) {
     const EventRecord& record = events[i];
 
     // Each entry is an array of one of the forms:
@@ -655,17 +656,17 @@ nsresult SerializeEventsArray(const Even
       val.setObject(*obj);
 
       if (!items.append(val)) {
         return NS_ERROR_FAILURE;
       }
     }
 
     // Add the record to the events array.
-    JS::RootedObject itemsArray(cx, JS_NewArrayObject(cx, items));
+    JS::RootedObject itemsArray(cx, JS::NewArrayObject(cx, items));
     if (!JS_DefineElement(cx, eventsArray, i, itemsArray, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   result.set(eventsArray);
   return NS_OK;
 }
@@ -1002,25 +1003,25 @@ static bool GetArrayPropertyValues(JSCon
   JS::RootedValue value(cx);
   if (!JS_GetProperty(cx, obj, property, &value)) {
     JS_ReportErrorASCII(cx, R"(Missing required property "%s" for event)",
                         property);
     return false;
   }
 
   bool isArray = false;
-  if (!JS_IsArrayObject(cx, value, &isArray) || !isArray) {
+  if (!JS::IsArrayObject(cx, value, &isArray) || !isArray) {
     JS_ReportErrorASCII(cx, R"(Property "%s" for event should be an array)",
                         property);
     return false;
   }
 
   JS::RootedObject arrayObj(cx, &value.toObject());
   uint32_t arrayLength;
-  if (!JS_GetArrayLength(cx, arrayObj, &arrayLength)) {
+  if (!JS::GetArrayLength(cx, arrayObj, &arrayLength)) {
     return false;
   }
 
   for (uint32_t arrayIdx = 0; arrayIdx < arrayLength; ++arrayIdx) {
     JS::Rooted<JS::Value> element(cx);
     if (!JS_GetElement(cx, arrayObj, arrayIdx, &element)) {
       return false;
     }
--- a/toolkit/components/telemetry/core/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/core/TelemetryHistogram.cpp
@@ -7,16 +7,17 @@
 #include "TelemetryHistogram.h"
 
 #include <limits>
 #include "base/histogram.h"
 #include "geckoview/streaming/GeckoViewStreamingTelemetry.h"
 #include "ipc/TelemetryIPCAccumulator.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "js/GCAPI.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/JSONWriter.h"
 #include "mozilla/StartupTimeline.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/Unused.h"
@@ -795,17 +796,17 @@ nsresult internal_ReflectHistogramAndSam
   // Don't rely on the bucket counts from "aHistogramInfo": it may
   // differ from the length of aSnapshot.mBucketCounts due to expired
   // histograms.
   const size_t count = aSnapshot.mBucketCounts.Length();
   MOZ_ASSERT(count == aSnapshot.mBucketRanges.Length(),
              "The number of buckets and the number of counts must match.");
 
   // Create the "range" property and add it to the final object.
-  JS::Rooted<JSObject*> rarray(cx, JS_NewArrayObject(cx, 2));
+  JS::Rooted<JSObject*> rarray(cx, JS::NewArrayObject(cx, 2));
   if (rarray == nullptr ||
       !JS_DefineProperty(cx, obj, "range", rarray, JSPROP_ENUMERATE)) {
     return NS_ERROR_FAILURE;
   }
   // Add [min, max] into the range array
   if (!JS_DefineElement(cx, rarray, 0, aHistogramInfo.min, JSPROP_ENUMERATE)) {
     return NS_ERROR_FAILURE;
   }
@@ -1739,28 +1740,28 @@ bool internal_JSHistogram_GetValueArray(
     aArray.AppendElement(1);
     return true;
   }
 
   if (args[firstArgIndex].isObject() && !args[firstArgIndex].isString()) {
     JS::Rooted<JSObject*> arrayObj(aCx, &args[firstArgIndex].toObject());
 
     bool isArray = false;
-    JS_IsArrayObject(aCx, arrayObj, &isArray);
+    JS::IsArrayObject(aCx, arrayObj, &isArray);
 
     if (!isArray) {
       LogToBrowserConsole(
           nsIScriptError::errorFlag,
           NS_LITERAL_STRING(
               "The argument to accumulate can't be a non-array object"));
       return false;
     }
 
     uint32_t arrayLength = 0;
-    if (!JS_GetArrayLength(aCx, arrayObj, &arrayLength)) {
+    if (!JS::GetArrayLength(aCx, arrayObj, &arrayLength)) {
       LogToBrowserConsole(
           nsIScriptError::errorFlag,
           NS_LITERAL_STRING("Failed while trying to get array length"));
       return false;
     }
 
     for (uint32_t arrayIdx = 0; arrayIdx < arrayLength; arrayIdx++) {
       JS::Rooted<JS::Value> element(aCx);
@@ -2277,17 +2278,17 @@ bool internal_JSKeyedHistogram_Keys(JSCo
   for (const auto& key : keys) {
     JS::RootedValue jsKey(cx);
     jsKey.setString(ToJSString(cx, key));
     if (!autoKeys.append(jsKey)) {
       return false;
     }
   }
 
-  JS::RootedObject jsKeys(cx, JS_NewArrayObject(cx, autoKeys));
+  JS::RootedObject jsKeys(cx, JS::NewArrayObject(cx, autoKeys));
   if (!jsKeys) {
     return false;
   }
 
   args.rval().setObject(*jsKeys);
   return true;
 }
 
@@ -3093,31 +3094,31 @@ nsresult internal_ParseHistogramData(
     JS_ClearPendingException(aCx);
     return NS_ERROR_FAILURE;
   }
 
   // Get the "counts" array.
   JS::RootedValue countsArray(aCx);
   bool countsIsArray = false;
   if (!JS_GetProperty(aCx, histogramObj, "counts", &countsArray) ||
-      !JS_IsArrayObject(aCx, countsArray, &countsIsArray)) {
+      !JS::IsArrayObject(aCx, countsArray, &countsIsArray)) {
     JS_ClearPendingException(aCx);
     return NS_ERROR_FAILURE;
   }
 
   if (!countsIsArray) {
     // The "counts" property needs to be an array. If this is not the case,
     // skip this histogram.
     return NS_ERROR_FAILURE;
   }
 
   // Get the length of the array.
   uint32_t countsLen = 0;
   JS::RootedObject countsArrayObj(aCx, &countsArray.toObject());
-  if (!JS_GetArrayLength(aCx, countsArrayObj, &countsLen)) {
+  if (!JS::GetArrayLength(aCx, countsArrayObj, &countsLen)) {
     JS_ClearPendingException(aCx);
     return NS_ERROR_FAILURE;
   }
 
   // Parse the "counts" in the array.
   for (uint32_t arrayIdx = 0; arrayIdx < countsLen; arrayIdx++) {
     JS::RootedValue elementValue(aCx);
     int countAsInt = 0;
--- a/toolkit/components/telemetry/core/TelemetryOrigin.cpp
+++ b/toolkit/components/telemetry/core/TelemetryOrigin.cpp
@@ -9,16 +9,17 @@
 
 #include "nsDataHashtable.h"
 #include "nsIObserverService.h"
 #include "nsPrintfCString.h"
 #include "nsTArray.h"
 #include "TelemetryCommon.h"
 #include "TelemetryOriginEnums.h"
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/Atomics.h"
 #include "mozilla/Base64.h"
 #include "mozilla/dom/PrioEncoder.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Pair.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/Tuple.h"
@@ -536,17 +537,17 @@ nsresult TelemetryOrigin::GetEncodedOrig
   //   encoding: <encoding name>,
   //   prio: {
   //     a: <base64 string>,
   //     b: <base64 string>,
   //   },
   // }, ...]
 
   JS::RootedObject prioDataArray(aCx,
-                                 JS_NewArrayObject(aCx, prioData.Length()));
+                                 JS::NewArrayObject(aCx, prioData.Length()));
   if (NS_WARN_IF(!prioDataArray)) {
     return NS_ERROR_FAILURE;
   }
   uint32_t i = 0;
   for (auto& prioDatum : prioData) {
     JS::RootedObject prioDatumObj(aCx, JS_NewPlainObject(aCx));
     if (NS_WARN_IF(!prioDatumObj)) {
       return NS_ERROR_FAILURE;
--- a/toolkit/components/telemetry/core/TelemetryScalar.cpp
+++ b/toolkit/components/telemetry/core/TelemetryScalar.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "TelemetryScalar.h"
 
 #include "geckoview/streaming/GeckoViewStreamingTelemetry.h"
 #include "ipc/TelemetryComms.h"
 #include "ipc/TelemetryIPCAccumulator.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PContent.h"
 #include "mozilla/JSONWriter.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Unused.h"
 #include "nsBaseHashtable.h"
@@ -3418,25 +3419,25 @@ nsresult TelemetryScalar::RegisterScalar
       expired = static_cast<bool>(value.toBoolean());
     }
 
     // Get the scalar's optional stores list (default to ["main"]).
     nsTArray<nsCString> stores;
     if (JS_HasProperty(cx, scalarDef, "stores", &hasProperty) && hasProperty) {
       bool isArray = false;
       if (!JS_GetProperty(cx, scalarDef, "stores", &value) ||
-          !JS_IsArrayObject(cx, value, &isArray) || !isArray) {
+          !JS::IsArrayObject(cx, value, &isArray) || !isArray) {
         JS_ReportErrorASCII(cx, "Invalid 'stores' for scalar %s.",
                             PromiseFlatCString(fullName).get());
         return NS_ERROR_FAILURE;
       }
 
       JS::RootedObject arrayObj(cx, &value.toObject());
       uint32_t storesLength = 0;
-      if (!JS_GetArrayLength(cx, arrayObj, &storesLength)) {
+      if (!JS::GetArrayLength(cx, arrayObj, &storesLength)) {
         JS_ReportErrorASCII(cx,
                             "Can't get 'stores' array length for scalar %s.",
                             PromiseFlatCString(fullName).get());
         return NS_ERROR_FAILURE;
       }
 
       for (uint32_t i = 0; i < storesLength; ++i) {
         JS::Rooted<JS::Value> elt(cx);
--- a/toolkit/components/telemetry/other/CombinedStacks.cpp
+++ b/toolkit/components/telemetry/other/CombinedStacks.cpp
@@ -2,16 +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/. */
 
 #include "CombinedStacks.h"
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/HangAnnotations.h"
 
 namespace mozilla {
 namespace Telemetry {
 
 // The maximum number of chrome hangs stacks that we're keeping.
 const size_t kMaxChromeStacksKept = 50;
 
@@ -126,33 +127,33 @@ void CombinedStacks::Clear() {
 #endif
 
 JSObject* CreateJSStackObject(JSContext* cx, const CombinedStacks& stacks) {
   JS::Rooted<JSObject*> ret(cx, JS_NewPlainObject(cx));
   if (!ret) {
     return nullptr;
   }
 
-  JS::Rooted<JSObject*> moduleArray(cx, JS_NewArrayObject(cx, 0));
+  JS::Rooted<JSObject*> moduleArray(cx, JS::NewArrayObject(cx, 0));
   if (!moduleArray) {
     return nullptr;
   }
   bool ok =
       JS_DefineProperty(cx, ret, "memoryMap", moduleArray, JSPROP_ENUMERATE);
   if (!ok) {
     return nullptr;
   }
 
   const size_t moduleCount = stacks.GetModuleCount();
   for (size_t moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) {
     // Current module
     const Telemetry::ProcessedStack::Module& module =
         stacks.GetModule(moduleIndex);
 
-    JS::Rooted<JSObject*> moduleInfoArray(cx, JS_NewArrayObject(cx, 0));
+    JS::Rooted<JSObject*> moduleInfoArray(cx, JS::NewArrayObject(cx, 0));
     if (!moduleInfoArray) {
       return nullptr;
     }
     if (!JS_DefineElement(cx, moduleArray, moduleIndex, moduleInfoArray,
                           JSPROP_ENUMERATE)) {
       return nullptr;
     }
 
@@ -169,42 +170,42 @@ JSObject* CreateJSStackObject(JSContext*
     JS::Rooted<JSString*> id(cx,
                              JS_NewStringCopyZ(cx, module.mBreakpadId.get()));
     if (!id ||
         !JS_DefineElement(cx, moduleInfoArray, index, id, JSPROP_ENUMERATE)) {
       return nullptr;
     }
   }
 
-  JS::Rooted<JSObject*> reportArray(cx, JS_NewArrayObject(cx, 0));
+  JS::Rooted<JSObject*> reportArray(cx, JS::NewArrayObject(cx, 0));
   if (!reportArray) {
     return nullptr;
   }
   ok = JS_DefineProperty(cx, ret, "stacks", reportArray, JSPROP_ENUMERATE);
   if (!ok) {
     return nullptr;
   }
 
   const size_t length = stacks.GetStackCount();
   for (size_t i = 0; i < length; ++i) {
     // Represent call stack PCs as (module index, offset) pairs.
-    JS::Rooted<JSObject*> pcArray(cx, JS_NewArrayObject(cx, 0));
+    JS::Rooted<JSObject*> pcArray(cx, JS::NewArrayObject(cx, 0));
     if (!pcArray) {
       return nullptr;
     }
 
     if (!JS_DefineElement(cx, reportArray, i, pcArray, JSPROP_ENUMERATE)) {
       return nullptr;
     }
 
     const CombinedStacks::Stack& stack = stacks.GetStack(i);
     const uint32_t pcCount = stack.size();
     for (size_t pcIndex = 0; pcIndex < pcCount; ++pcIndex) {
       const Telemetry::ProcessedStack::Frame& frame = stack[pcIndex];
-      JS::Rooted<JSObject*> framePair(cx, JS_NewArrayObject(cx, 0));
+      JS::Rooted<JSObject*> framePair(cx, JS::NewArrayObject(cx, 0));
       if (!framePair) {
         return nullptr;
       }
       int modIndex = (std::numeric_limits<uint16_t>::max() == frame.mModIndex)
                          ? -1
                          : frame.mModIndex;
       if (!JS_DefineElement(cx, framePair, 0, modIndex, JSPROP_ENUMERATE)) {
         return nullptr;
--- a/toolkit/components/telemetry/other/KeyedStackCapturer.cpp
+++ b/toolkit/components/telemetry/other/KeyedStackCapturer.cpp
@@ -2,16 +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/. */
 
 #include "KeyedStackCapturer.h"
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/StackWalk.h"
 #include "nsPrintfCString.h"
 #include "ProcessedStack.h"
 
 namespace {
 
 /** Defines the size of the keyed stack dictionary. */
 const uint8_t kMaxKeyLength = 50;
@@ -107,33 +108,33 @@ KeyedStackCapturer::ReflectCapturedStack
   MutexAutoLock capturedStackMutex(mStackCapturerMutex);
 
   // this adds the memoryMap and stacks properties.
   JS::RootedObject fullReportObj(cx, CreateJSStackObject(cx, mStacks));
   if (!fullReportObj) {
     return NS_ERROR_FAILURE;
   }
 
-  JS::RootedObject keysArray(cx, JS_NewArrayObject(cx, 0));
+  JS::RootedObject keysArray(cx, JS::NewArrayObject(cx, 0));
   if (!keysArray) {
     return NS_ERROR_FAILURE;
   }
 
   bool ok = JS_DefineProperty(cx, fullReportObj, "captures", keysArray,
                               JSPROP_ENUMERATE);
   if (!ok) {
     return NS_ERROR_FAILURE;
   }
 
   size_t keyIndex = 0;
   for (auto iter = mStackInfos.ConstIter(); !iter.Done();
        iter.Next(), ++keyIndex) {
     const StackFrequencyInfo* info = iter.Data();
 
-    JS::RootedObject infoArray(cx, JS_NewArrayObject(cx, 0));
+    JS::RootedObject infoArray(cx, JS::NewArrayObject(cx, 0));
     if (!keysArray) {
       return NS_ERROR_FAILURE;
     }
     JS::RootedString str(
         cx, JS_NewStringCopyZ(cx, PromiseFlatCString(iter.Key()).get()));
     if (!str || !JS_DefineElement(cx, infoArray, 0, str, JSPROP_ENUMERATE) ||
         !JS_DefineElement(cx, infoArray, 1, info->mIndex, JSPROP_ENUMERATE) ||
         !JS_DefineElement(cx, infoArray, 2, info->mCount, JSPROP_ENUMERATE) ||
--- a/toolkit/components/telemetry/other/TelemetryIOInterposeObserver.cpp
+++ b/toolkit/components/telemetry/other/TelemetryIOInterposeObserver.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "TelemetryIOInterposeObserver.h"
 #include "core/TelemetryCommon.h"
+#include "js/Array.h"  // JS::NewArrayObject
 
 namespace mozilla {
 namespace Telemetry {
 
 TelemetryIOInterposeObserver::TelemetryIOInterposeObserver(nsIFile* aXreDir)
     : mCurStage(STAGE_STARTUP) {
   nsAutoString xreDirPath;
   nsresult rv = aXreDir->GetPath(xreDirPath);
@@ -122,25 +123,25 @@ bool TelemetryIOInterposeObserver::Refle
     stats[0].setNumber(fileStats.totalTime);
     stats[1].setNumber(fileStats.creates);
     stats[2].setNumber(fileStats.reads);
     stats[3].setNumber(fileStats.writes);
     stats[4].setNumber(fileStats.fsyncs);
     stats[5].setNumber(fileStats.stats);
 
     // Create jsStats as array of elements above
-    JS::RootedObject jsStats(cx, JS_NewArrayObject(cx, stats));
+    JS::RootedObject jsStats(cx, JS::NewArrayObject(cx, stats));
     if (!jsStats) {
       continue;
     }
 
     stages[s].setObject(*jsStats);
   }
 
-  JS::Rooted<JSObject*> jsEntry(cx, JS_NewArrayObject(cx, stages));
+  JS::Rooted<JSObject*> jsEntry(cx, JS::NewArrayObject(cx, stages));
   if (!jsEntry) {
     return false;
   }
 
   // Add jsEntry to top-level dictionary
   const nsAString& key = entry->GetKey();
   return JS_DefineUCProperty(cx, obj, key.Data(), key.Length(), jsEntry,
                              JSPROP_ENUMERATE | JSPROP_READONLY);
--- a/toolkit/components/telemetry/other/UntrustedModules.cpp
+++ b/toolkit/components/telemetry/other/UntrustedModules.cpp
@@ -2,16 +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/. */
 
 #include "UntrustedModules.h"
 
 #include "core/TelemetryCommon.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/RDDChild.h"
 #include "mozilla/RDDProcessManager.h"
 #include "mozilla/UntrustedModulesProcessor.h"
 #include "mozilla/WinDllServices.h"
 #include "nsCOMPtr.h"
 #include "nsDataHashtable.h"
@@ -117,17 +118,17 @@ static JSString* ModuleVersionToJSString
  *                                const ArrayElementT& aElement)
  * @return true if aRet was successfully assigned to the new array object.
  */
 template <typename T, size_t N, typename AllocPolicy, typename Converter,
           typename... Args>
 static bool VectorToJSArray(JSContext* cx, JS::MutableHandleObject aRet,
                             const Vector<T, N, AllocPolicy>& aContainer,
                             Converter&& aElementConverter, Args&&... aArgs) {
-  JS::RootedObject arr(cx, JS_NewArrayObject(cx, 0));
+  JS::RootedObject arr(cx, JS::NewArrayObject(cx, 0));
   if (!arr) {
     return false;
   }
 
   for (size_t i = 0, l = aContainer.length(); i < l; ++i) {
     JS::RootedValue jsel(cx);
     if (!aElementConverter(cx, &jsel, aContainer[i],
                            std::forward<Args>(aArgs)...)) {
@@ -388,17 +389,17 @@ static nsresult GetUntrustedModuleLoadEv
   if (!JS_DefineProperty(aCx, mainObj, "structVersion", jsVersion,
                          JSPROP_ENUMERATE)) {
     return NS_ERROR_FAILURE;
   }
 
   IndexMap indexMap;
   uint32_t curModulesArrayIdx = 0;
 
-  JS::RootedObject modulesArray(aCx, JS_NewArrayObject(aCx, 0));
+  JS::RootedObject modulesArray(aCx, JS::NewArrayObject(aCx, 0));
   if (!modulesArray) {
     return NS_ERROR_FAILURE;
   }
 
   JS::RootedObject perProcObjContainer(aCx, JS_NewPlainObject(aCx));
   if (!perProcObjContainer) {
     return NS_ERROR_FAILURE;
   }
--- a/toolkit/components/telemetry/tests/gtest/TelemetryTestHelpers.cpp
+++ b/toolkit/components/telemetry/tests/gtest/TelemetryTestHelpers.cpp
@@ -2,16 +2,17 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 #include "TelemetryTestHelpers.h"
 
 #include "core/TelemetryCommon.h"
 #include "core/TelemetryOrigin.h"
 #include "gtest/gtest.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/Unused.h"
 #include "nsPrintfCString.h"
 
 using namespace mozilla;
 
 // Helper methods provided to simplify writing tests and meant to be used in C++
 // Gtests.
@@ -106,33 +107,33 @@ void CheckNumberOfProperties(const char*
 }
 
 bool EventPresent(JSContext* aCx, const JS::RootedValue& aSnapshot,
                   const nsACString& aCategory, const nsACString& aMethod,
                   const nsACString& aObject) {
   EXPECT_FALSE(aSnapshot.isNullOrUndefined())
       << "Event snapshot must not be null/undefined.";
   bool isArray = false;
-  EXPECT_TRUE(JS_IsArrayObject(aCx, aSnapshot, &isArray) && isArray)
+  EXPECT_TRUE(JS::IsArrayObject(aCx, aSnapshot, &isArray) && isArray)
       << "The snapshot must be an array.";
   JS::RootedObject arrayObj(aCx, &aSnapshot.toObject());
   uint32_t arrayLength = 0;
-  EXPECT_TRUE(JS_GetArrayLength(aCx, arrayObj, &arrayLength))
+  EXPECT_TRUE(JS::GetArrayLength(aCx, arrayObj, &arrayLength))
       << "Array must have a length.";
   EXPECT_TRUE(arrayLength > 0) << "Array must have at least one element.";
 
   for (uint32_t arrayIdx = 0; arrayIdx < arrayLength; ++arrayIdx) {
     JS::Rooted<JS::Value> element(aCx);
     EXPECT_TRUE(JS_GetElement(aCx, arrayObj, arrayIdx, &element))
         << "Must be able to get element.";
-    EXPECT_TRUE(JS_IsArrayObject(aCx, element, &isArray) && isArray)
+    EXPECT_TRUE(JS::IsArrayObject(aCx, element, &isArray) && isArray)
         << "Element must be an array.";
     JS::RootedObject eventArray(aCx, &element.toObject());
     uint32_t eventLength;
-    EXPECT_TRUE(JS_GetArrayLength(aCx, eventArray, &eventLength))
+    EXPECT_TRUE(JS::GetArrayLength(aCx, eventArray, &eventLength))
         << "Event array must have a length.";
     EXPECT_TRUE(eventLength >= 4)
         << "Event array must have at least 4 elements (timestamp, category, "
            "method, object).";
 
     JS::Rooted<JS::Value> str(aCx);
     nsAutoJSString jsStr;
     EXPECT_TRUE(JS_GetElement(aCx, eventArray, 1, &str))
@@ -206,21 +207,21 @@ void GetEncodedOriginStrings(
                                                  &snapshot);
 
   ASSERT_FALSE(NS_FAILED(rv));
   ASSERT_FALSE(snapshot.isNullOrUndefined())
   << "Encoded snapshot must not be null/undefined.";
 
   JS::RootedObject prioDataObj(aCx, &snapshot.toObject());
   bool isArray = false;
-  ASSERT_TRUE(JS_IsArrayObject(aCx, prioDataObj, &isArray) && isArray)
+  ASSERT_TRUE(JS::IsArrayObject(aCx, prioDataObj, &isArray) && isArray)
   << "The metric's origins must be in an array.";
 
   uint32_t length = 0;
-  ASSERT_TRUE(JS_GetArrayLength(aCx, prioDataObj, &length));
+  ASSERT_TRUE(JS::GetArrayLength(aCx, prioDataObj, &length));
   ASSERT_TRUE(length > 0)
   << "Length of returned array must greater than 0";
 
   for (auto i = 0u; i < length; ++i) {
     JS::RootedValue arrayItem(aCx);
     ASSERT_TRUE(JS_GetElement(aCx, prioDataObj, i, &arrayItem));
     ASSERT_TRUE(arrayItem.isObject());
     ASSERT_FALSE(arrayItem.isNullOrUndefined());
--- a/toolkit/components/telemetry/tests/gtest/TestEvents.cpp
+++ b/toolkit/components/telemetry/tests/gtest/TestEvents.cpp
@@ -1,15 +1,16 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 #include "core/TelemetryEvent.h"
 #include "gtest/gtest.h"
+#include "js/Array.h"  // JS::GetArrayLength
 #include "mozilla/Maybe.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "TelemetryFixture.h"
 #include "TelemetryTestHelpers.h"
 
 using namespace mozilla;
 using namespace TelemetryTestHelpers;
@@ -88,17 +89,17 @@ TEST_F(TelemetryTestFixture, RecordEvent
   // Ensure that the truncations happened appropriately.
   JSContext* aCx = cx.GetJSContext();
   JS::RootedObject arrayObj(aCx, &eventsSnapshot.toObject());
   JS::Rooted<JS::Value> eventRecord(aCx);
   ASSERT_TRUE(JS_GetElement(aCx, arrayObj, 2, &eventRecord))
   << "Must be able to get record.";
   JS::RootedObject recordArray(aCx, &eventRecord.toObject());
   uint32_t recordLength;
-  ASSERT_TRUE(JS_GetArrayLength(aCx, recordArray, &recordLength))
+  ASSERT_TRUE(JS::GetArrayLength(aCx, recordArray, &recordLength))
   << "Event record array must have length.";
   ASSERT_TRUE(recordLength == 6)
   << "Event record must have 6 elements.";
 
   JS::Rooted<JS::Value> str(aCx);
   nsAutoJSString jsStr;
   // The value string is at index 4
   ASSERT_TRUE(JS_GetElement(aCx, recordArray, 4, &str))
--- a/toolkit/mozapps/extensions/AddonManagerStartup-inlines.h
+++ b/toolkit/mozapps/extensions/AddonManagerStartup-inlines.h
@@ -2,16 +2,17 @@
 /* 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 AddonManagerStartup_inlines_h
 #define AddonManagerStartup_inlines_h
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "nsJSUtils.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/Move.h"
 
 namespace mozilla {
 
 class ArrayIterElem;
@@ -185,22 +186,22 @@ class MOZ_STACK_CLASS PropertyIterElem
 class MOZ_STACK_CLASS ArrayIter : public BaseIter<ArrayIter, ArrayIterElem> {
   friend class ArrayIterElem;
   friend class BaseIterElem<ArrayIterElem, ArrayIter>;
 
  public:
   ArrayIter(JSContext* cx, JS::HandleObject object)
       : BaseIter(cx, object), mLength(0) {
     bool isArray;
-    if (!JS_IsArrayObject(cx, object, &isArray) || !isArray) {
+    if (!JS::IsArrayObject(cx, object, &isArray) || !isArray) {
       JS_ClearPendingException(cx);
       return;
     }
 
-    if (!JS_GetArrayLength(cx, object, &mLength)) {
+    if (!JS::GetArrayLength(cx, object, &mLength)) {
       JS_ClearPendingException(cx);
     }
   }
 
   uint32_t Length() const { return mLength; }
 
  private:
   uint32_t mLength;
--- a/toolkit/mozapps/extensions/AddonManagerStartup.cpp
+++ b/toolkit/mozapps/extensions/AddonManagerStartup.cpp
@@ -3,16 +3,17 @@
  * 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/. */
 
 #include "AddonManagerStartup.h"
 #include "AddonManagerStartup-inlines.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
+#include "js/Array.h"  // JS::IsArrayObject
 #include "js/ArrayBuffer.h"
 #include "js/JSON.h"
 #include "js/TracingAPI.h"
 #include "xpcpublic.h"
 
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EndianUtils.h"
 #include "mozilla/Components.h"
@@ -774,17 +775,17 @@ static LinkedList<RegistryEntries>& GetR
 };  // anonymous namespace
 
 NS_IMETHODIMP
 AddonManagerStartup::RegisterChrome(nsIURI* manifestURI,
                                     JS::HandleValue locations, JSContext* cx,
                                     nsIJSRAIIHelper** result) {
   auto IsArray = [cx](JS::HandleValue val) -> bool {
     bool isArray;
-    return JS_IsArrayObject(cx, val, &isArray) && isArray;
+    return JS::IsArrayObject(cx, val, &isArray) && isArray;
   };
 
   NS_ENSURE_ARG_POINTER(manifestURI);
   NS_ENSURE_TRUE(IsArray(locations), NS_ERROR_INVALID_ARG);
 
   FileLocation location;
   MOZ_TRY_VAR(location, GetFileLocation(manifestURI));
 
--- a/toolkit/recordreplay/ipc/JSControl.cpp
+++ b/toolkit/recordreplay/ipc/JSControl.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "JSControl.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/Conversions.h"
 #include "js/JSON.h"
 #include "js/PropertySpec.h"
 #include "ChildInternal.h"
 #include "MemorySnapshot.h"
 #include "ParentInternal.h"
 #include "nsImportModule.h"
@@ -1268,17 +1269,17 @@ static bool RecordReplay_FindScriptHits(
             !values.append(ObjectValue(*hitObject))) {
           return false;
         }
       }
     }
     chunk = chunk->mPrevious;
   }
 
-  JSObject* array = JS_NewArrayObject(aCx, values);
+  JSObject* array = JS::NewArrayObject(aCx, values);
   if (!array) {
     return false;
   }
 
   args.rval().setObject(*array);
   return true;
 }
 
@@ -1348,17 +1349,17 @@ static bool RecordReplay_FindChangeFrame
           !JS_DefineProperty(aCx, hitObject, "frameIndex", hit.mFrameIndex,
                              JSPROP_ENUMERATE) ||
           !values.append(ObjectValue(*hitObject))) {
         return false;
       }
     }
   }
 
-  JSObject* array = JS_NewArrayObject(aCx, values);
+  JSObject* array = JS::NewArrayObject(aCx, values);
   if (!array) {
     return false;
   }
 
   args.rval().setObject(*array);
   return true;
 }
 
--- a/tools/profiler/gecko/nsProfiler.cpp
+++ b/tools/profiler/gecko/nsProfiler.cpp
@@ -6,16 +6,17 @@
 
 #include "nsProfiler.h"
 
 #include "GeckoProfiler.h"
 #include "nsProfilerStartParams.h"
 #include "platform.h"
 #include "ProfilerParent.h"
 
+#include "js/Array.h"  // JS::NewArrayObject
 #include "js/JSON.h"
 #include "js/Value.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Move.h"
 #include "mozilla/Services.h"
 #include "mozilla/SystemGroup.h"
@@ -657,17 +658,17 @@ nsProfiler::GetSymbolTable(const nsACStr
             JS::RootedObject indexArray(
                 cx, dom::Uint32Array::Create(cx, aSymbolTable.mIndex.Length(),
                                              aSymbolTable.mIndex.Elements()));
             JS::RootedObject bufferArray(
                 cx, dom::Uint8Array::Create(cx, aSymbolTable.mBuffer.Length(),
                                             aSymbolTable.mBuffer.Elements()));
 
             if (addrsArray && indexArray && bufferArray) {
-              JS::RootedObject tuple(cx, JS_NewArrayObject(cx, 3));
+              JS::RootedObject tuple(cx, JS::NewArrayObject(cx, 3));
               JS_SetElement(cx, tuple, 0, addrsArray);
               JS_SetElement(cx, tuple, 1, indexArray);
               JS_SetElement(cx, tuple, 2, bufferArray);
               promise->MaybeResolve(tuple);
             } else {
               promise->MaybeReject(NS_ERROR_FAILURE);
             }
           },
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -5,16 +5,17 @@
  * 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/. */
 
 #include "mozilla/ArrayUtils.h"
 
 #include "GfxInfoBase.h"
 
 #include "GfxDriverInfo.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::NewArrayObject
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsVersionComparator.h"
 #include "mozilla/Services.h"
 #include "mozilla/Observer.h"
 #include "nsIObserver.h"
@@ -1235,17 +1236,17 @@ nsresult GfxInfoBase::FindMonitors(JSCon
   JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
   JS_SetElement(aCx, aOutArray, 0, element);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfoBase::GetMonitors(JSContext* aCx, JS::MutableHandleValue aResult) {
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
+  JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
 
   nsresult rv = FindMonitors(aCx, array);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   aResult.setObject(*array);
   return NS_OK;
@@ -1262,17 +1263,17 @@ static inline bool SetJSPropertyString(J
   JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
   return JS_SetProperty(aCx, aObj, aProp, val);
 }
 
 template <typename T>
 static inline bool AppendJSElement(JSContext* aCx, JS::Handle<JSObject*> aObj,
                                    const T& aValue) {
   uint32_t index;
-  if (!JS_GetArrayLength(aCx, aObj, &index)) {
+  if (!JS::GetArrayLength(aCx, aObj, &index)) {
     return false;
   }
   return JS_SetElement(aCx, aObj, index, aValue);
 }
 
 nsresult GfxInfoBase::GetFeatures(JSContext* aCx,
                                   JS::MutableHandle<JS::Value> aOut) {
   JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
@@ -1300,17 +1301,17 @@ nsresult GfxInfoBase::GetFeatures(JSCont
 nsresult GfxInfoBase::GetFeatureLog(JSContext* aCx,
                                     JS::MutableHandle<JS::Value> aOut) {
   JS::Rooted<JSObject*> containerObj(aCx, JS_NewPlainObject(aCx));
   if (!containerObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   aOut.setObject(*containerObj);
 
-  JS::Rooted<JSObject*> featureArray(aCx, JS_NewArrayObject(aCx, 0));
+  JS::Rooted<JSObject*> featureArray(aCx, JS::NewArrayObject(aCx, 0));
   if (!featureArray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Collect features.
   gfxConfig::ForEachFeature([&](const char* aName, const char* aDescription,
                                 FeatureState& aFeature) -> void {
     JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
@@ -1332,17 +1333,17 @@ nsresult GfxInfoBase::GetFeatureLog(JSCo
       return;
     }
 
     if (!AppendJSElement(aCx, featureArray, obj)) {
       return;
     }
   });
 
-  JS::Rooted<JSObject*> fallbackArray(aCx, JS_NewArrayObject(aCx, 0));
+  JS::Rooted<JSObject*> fallbackArray(aCx, JS::NewArrayObject(aCx, 0));
   if (!fallbackArray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Collect fallbacks.
   gfxConfig::ForEachFallback(
       [&](const char* aName, const char* aMessage) -> void {
         JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
@@ -1369,17 +1370,17 @@ nsresult GfxInfoBase::GetFeatureLog(JSCo
   JS_SetProperty(aCx, containerObj, "fallbacks", val);
 
   return NS_OK;
 }
 
 bool GfxInfoBase::BuildFeatureStateLog(JSContext* aCx,
                                        const FeatureState& aFeature,
                                        JS::MutableHandle<JS::Value> aOut) {
-  JS::Rooted<JSObject*> log(aCx, JS_NewArrayObject(aCx, 0));
+  JS::Rooted<JSObject*> log(aCx, JS::NewArrayObject(aCx, 0));
   if (!log) {
     return false;
   }
   aOut.setObject(*log);
 
   aFeature.ForEachStatusChange([&](const char* aType, FeatureStatus aStatus,
                                    const char* aMessage) -> void {
     JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
@@ -1453,17 +1454,17 @@ bool GfxInfoBase::InitFeatureObject(JSCo
   }
 
   aOutObj.set(obj);
   return true;
 }
 
 nsresult GfxInfoBase::GetActiveCrashGuards(JSContext* aCx,
                                            JS::MutableHandle<JS::Value> aOut) {
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
+  JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   aOut.setObject(*array);
 
   DriverCrashGuard::ForEachActiveCrashGuard(
       [&](const char* aName, const char* aPrefName) -> void {
         JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
--- a/widget/android/EventDispatcher.cpp
+++ b/widget/android/EventDispatcher.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 #include "EventDispatcher.h"
 
 #include "JavaBuiltins.h"
 #include "nsAppShell.h"
 #include "nsJSUtils.h"
+#include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject, JS::NewArrayObject
 #include "js/Warnings.h"  // JS::WarnUTF8
 #include "xpcpublic.h"
 
 #include "mozilla/ScopeExit.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 // Disable the C++ 2a warning. See bug #1509926
 #if defined(__clang__)
@@ -122,17 +123,17 @@ nsresult BoxArrayObject(JSContext* aCx, 
   }
   aOut = out;
   return NS_OK;
 }
 
 nsresult BoxArray(JSContext* aCx, JS::HandleObject aData,
                   jni::Object::LocalRef& aOut) {
   uint32_t length = 0;
-  NS_ENSURE_TRUE(CheckJS(aCx, JS_GetArrayLength(aCx, aData, &length)),
+  NS_ENSURE_TRUE(CheckJS(aCx, JS::GetArrayLength(aCx, aData, &length)),
                  NS_ERROR_FAILURE);
 
   if (!length) {
     // Always represent empty arrays as an empty boolean array.
     aOut = java::GeckoBundle::EMPTY_BOOLEAN_ARRAY();
     return NS_OK;
   }
 
@@ -179,17 +180,17 @@ nsresult BoxArray(JSContext* aCx, JS::Ha
 
   const auto isObject = [aCx](JS::HandleValue val) -> bool {
     if (!val.isObject()) {
       return false;
     }
     bool array = false;
     JS::RootedObject obj(aCx, &val.toObject());
     // We don't support array of arrays.
-    return CheckJS(aCx, JS_IsArrayObject(aCx, obj, &array)) && !array;
+    return CheckJS(aCx, JS::IsArrayObject(aCx, obj, &array)) && !array;
   };
 
   if (element.isNullOrUndefined() || isObject(element)) {
     return BoxArrayObject<java::GeckoBundle, &BoxObject>(
         aCx, aData, aOut, length, element, isObject);
   }
 
   NS_WARNING("Unknown type");
@@ -207,17 +208,17 @@ nsresult BoxObject(JSContext* aCx, JS::H
   }
 
   MOZ_ASSERT(aData.isObject());
 
   JS::Rooted<JS::IdVector> ids(aCx, JS::IdVector(aCx));
   JS::RootedObject obj(aCx, &aData.toObject());
 
   bool isArray = false;
-  if (CheckJS(aCx, JS_IsArrayObject(aCx, obj, &isArray)) && isArray) {
+  if (CheckJS(aCx, JS::IsArrayObject(aCx, obj, &isArray)) && isArray) {
     return BoxArray(aCx, obj, aOut);
   }
 
   NS_ENSURE_TRUE(CheckJS(aCx, JS_Enumerate(aCx, obj, &ids)), NS_ERROR_FAILURE);
 
   const size_t length = ids.length();
   auto keys = jni::ObjectArray::New<jni::String>(length);
   auto values = jni::ObjectArray::New<jni::Object>(length);
@@ -419,17 +420,17 @@ nsresult UnboxArrayPrimitive(JSContext* 
   NS_ENSURE_TRUE(elements.initCapacity(len), NS_ERROR_FAILURE);
 
   for (size_t i = 0; i < len; i++) {
     NS_ENSURE_TRUE(elements.append((*ToValue)(Type(array[i]))),
                    NS_ERROR_FAILURE);
   }
 
   JS::RootedObject obj(aCx,
-                       JS_NewArrayObject(aCx, JS::HandleValueArray(elements)));
+                       JS::NewArrayObject(aCx, JS::HandleValueArray(elements)));
   NS_ENSURE_TRUE(CheckJS(aCx, !!obj), NS_ERROR_FAILURE);
 
   aOut.setObject(*obj);
   return NS_OK;
 }
 
 struct StringArray : jni::ObjectBase<StringArray> {
   static const char name[];
@@ -444,17 +445,17 @@ const char GeckoBundleArray::name[] = "[
 
 template <nsresult (*Unbox)(JSContext*, const jni::Object::LocalRef&,
                             JS::MutableHandleValue)>
 nsresult UnboxArrayObject(JSContext* aCx, const jni::Object::LocalRef& aData,
                           JS::MutableHandleValue aOut) {
   jni::ObjectArray::LocalRef array(aData.Env(),
                                    jni::ObjectArray::Ref::From(aData));
   const size_t len = array->Length();
-  JS::RootedObject obj(aCx, JS_NewArrayObject(aCx, len));
+  JS::RootedObject obj(aCx, JS::NewArrayObject(aCx, len));
   NS_ENSURE_TRUE(CheckJS(aCx, !!obj), NS_ERROR_FAILURE);
 
   for (size_t i = 0; i < len; i++) {
     jni::Object::LocalRef element = array->GetElement(i);
     JS::RootedValue value(aCx);
     nsresult rv = (*Unbox)(aCx, element, &value);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -836,23 +837,23 @@ nsresult EventDispatcher::IterateEvents(
   };
 
   if (aEvents.isString()) {
     return processEvent(aEvents);
   }
 
   bool isArray = false;
   NS_ENSURE_TRUE(aEvents.isObject(), NS_ERROR_INVALID_ARG);
-  NS_ENSURE_TRUE(CheckJS(aCx, JS_IsArrayObject(aCx, aEvents, &isArray)),
+  NS_ENSURE_TRUE(CheckJS(aCx, JS::IsArrayObject(aCx, aEvents, &isArray)),
                  NS_ERROR_INVALID_ARG);
   NS_ENSURE_TRUE(isArray, NS_ERROR_INVALID_ARG);
 
   JS::RootedObject events(aCx, &aEvents.toObject());
   uint32_t length = 0;
-  NS_ENSURE_TRUE(CheckJS(aCx, JS_GetArrayLength(aCx, events, &length)),
+  NS_ENSURE_TRUE(CheckJS(aCx, JS::GetArrayLength(aCx, events, &length)),
                  NS_ERROR_INVALID_ARG);
   NS_ENSURE_TRUE(length, NS_ERROR_INVALID_ARG);
 
   for (size_t i = 0; i < length; i++) {
     JS::RootedValue event(aCx);
     NS_ENSURE_TRUE(CheckJS(aCx, JS_GetElement(aCx, events, i, &event)),
                    NS_ERROR_INVALID_ARG);
     NS_ENSURE_TRUE(event.isString(), NS_ERROR_INVALID_ARG);
--- a/widget/cocoa/nsMacSharingService.mm
+++ b/widget/cocoa/nsMacSharingService.mm
@@ -3,16 +3,17 @@
  * 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/. */
 
 #import <Cocoa/Cocoa.h>
 
 #include "nsMacSharingService.h"
 
 #include "jsapi.h"
+#include "js/Array.h"  // JS::NewArrayObject
 #include "nsCocoaUtils.h"
 #include "mozilla/MacStringHelpers.h"
 
 NS_IMPL_ISUPPORTS(nsMacSharingService, nsIMacSharingService)
 
 // List of sharingProviders that we do not want to expose to
 // the user, because they are duplicates or do not work correctly
 // within the context
@@ -94,17 +95,17 @@ static void SetStrAttribute(JSContext* a
   JS::Rooted<JS::Value> attVal(aCx, JS::StringValue(title));
   JS_SetProperty(aCx, aObj, aKey, attVal);
 }
 
 nsresult nsMacSharingService::GetSharingProviders(const nsAString& aPageUrl, JSContext* aCx,
                                                   JS::MutableHandleValue aResult) {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
+  JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
   NSURL* url = [NSURL URLWithString:nsCocoaUtils::ToNSString(aPageUrl)];
 
   NSArray* sharingService =
       [NSSharingService sharingServicesForItems:[NSArray arrayWithObject:url]];
   int32_t serviceCount = 0;
 
   for (NSSharingService* currentService in sharingService) {
     if ([filteredProviderNames containsObject:[currentService name]]) {