Bug 1333073 - Move DataViewObject to its own file. r=arai
authorTom Schuster <evilpies@gmail.com>
Sat, 28 Jan 2017 21:33:29 +0100
changeset 331576 d2ce4dbbc26d0937c42fe06d95cd71e2a914f637
parent 331575 34aa0752cd03e7c062d67ccbff83712482ce1447
child 331577 9ff0f1a35a9cdfd0b86c2962709b1414a2dce9d7
push id36615
push userphilringnalda@gmail.com
push dateSun, 29 Jan 2017 17:04:18 +0000
treeherderautoland@77af15f468e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1333073
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1333073 - Move DataViewObject to its own file. r=arai
js/src/builtin/DataViewObject.cpp
js/src/builtin/DataViewObject.h
js/src/moz.build
js/src/vm/ArrayBufferObject.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/StructuredClone.cpp
js/src/vm/TypedArrayObject.cpp
js/src/vm/TypedArrayObject.h
copy from js/src/vm/TypedArrayObject.cpp
copy to js/src/builtin/DataViewObject.cpp
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -1,1690 +1,50 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "vm/TypedArrayObject.h"
+#include "builtin/DataViewObject.h"
 
 #include "mozilla/Alignment.h"
-#include "mozilla/Casting.h"
-#include "mozilla/FloatingPoint.h"
-#include "mozilla/PodOperations.h"
 
 #include <string.h>
-#ifndef XP_WIN
-# include <sys/mman.h>
-#endif
 
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jscntxt.h"
-#include "jscpucfg.h"
 #include "jsnum.h"
 #include "jsobj.h"
-#include "jstypes.h"
-#include "jsutil.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
 #include "jswrapper.h"
 
-#include "builtin/TypedObjectConstants.h"
-#include "gc/Barrier.h"
-#include "gc/Marking.h"
-#include "jit/InlinableNatives.h"
 #include "js/Conversions.h"
 #include "vm/ArrayBufferObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
-#include "vm/PIC.h"
-#include "vm/SelfHosting.h"
 #include "vm/SharedMem.h"
 #include "vm/TypedArrayCommon.h"
 #include "vm/WrapperObject.h"
 
-#include "jsatominlines.h"
-
 #include "gc/Nursery-inl.h"
 #include "gc/StoreBuffer-inl.h"
 #include "vm/ArrayBufferObject-inl.h"
 #include "vm/NativeObject-inl.h"
-#include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
-using mozilla::AssertedCast;
 using JS::CanonicalizeNaN;
 using JS::ToInt32;
 using JS::ToUint32;
 
-/*
- * TypedArrayObject
- *
- * The non-templated base class for the specific typed implementations.
- * This class holds all the member variables that are used by
- * the subclasses.
- */
-
-/* static */ int
-TypedArrayObject::lengthOffset()
-{
-    return NativeObject::getFixedSlotOffset(LENGTH_SLOT);
-}
-
-/* static */ int
-TypedArrayObject::dataOffset()
-{
-    return NativeObject::getPrivateDataOffset(DATA_SLOT);
-}
-
-void
-TypedArrayObject::notifyBufferDetached(JSContext* cx, void* newData)
-{
-    MOZ_ASSERT(!isSharedMemory());
-    setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(0));
-    setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(0));
-
-    // If the object is in the nursery, the buffer will be freed by the next
-    // nursery GC. Free the data slot pointer if the object has no inline data.
-    Nursery& nursery = cx->runtime()->gc.nursery;
-    if (isTenured() && !hasBuffer() && !hasInlineElements() &&
-        !nursery.isInside(elements()))
-    {
-        js_free(elements());
-    }
-
-    setPrivate(newData);
-}
-
-/* static */ bool
-TypedArrayObject::is(HandleValue v)
-{
-    return v.isObject() && v.toObject().is<TypedArrayObject>();
-}
-
-/* static */ bool
-TypedArrayObject::ensureHasBuffer(JSContext* cx, Handle<TypedArrayObject*> tarray)
-{
-    if (tarray->hasBuffer())
-        return true;
-
-    Rooted<ArrayBufferObject*> buffer(cx, ArrayBufferObject::create(cx, tarray->byteLength()));
-    if (!buffer)
-        return false;
-
-    if (!buffer->addView(cx, tarray))
-        return false;
-
-    // tarray is not shared, because if it were it would have a buffer.
-    memcpy(buffer->dataPointer(), tarray->viewDataUnshared(), tarray->byteLength());
-
-    // If the object is in the nursery, the buffer will be freed by the next
-    // nursery GC. Free the data slot pointer if the object has no inline data.
-    Nursery& nursery = cx->runtime()->gc.nursery;
-    if (tarray->isTenured() && !tarray->hasInlineElements() &&
-        !nursery.isInside(tarray->elements()))
-    {
-        js_free(tarray->elements());
-    }
-
-    tarray->setPrivate(buffer->dataPointer());
-
-    tarray->setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectValue(*buffer));
-
-    // Notify compiled jit code that the base pointer has moved.
-    MarkObjectStateChange(cx, tarray);
-
-    return true;
-}
-
-#ifdef DEBUG
-void
-TypedArrayObject::assertZeroLengthArrayData() const
-{
-    if (length() == 0 && !hasBuffer()) {
-        uint8_t* end = fixedData(TypedArrayObject::FIXED_DATA_START);
-        MOZ_ASSERT(end[0] == ZeroLengthArrayData);
-    }
-}
-#endif
-
-/* static */ void
-TypedArrayObject::trace(JSTracer* trc, JSObject* objArg)
-{
-    // Handle all tracing required when the object has a buffer.
-    ArrayBufferViewObject::trace(trc, objArg);
-}
-
-void
-TypedArrayObject::finalize(FreeOp* fop, JSObject* obj)
-{
-    MOZ_ASSERT(!IsInsideNursery(obj));
-    TypedArrayObject* curObj = &obj->as<TypedArrayObject>();
-
-    // Template objects or discarded objects (which didn't have enough room
-    // for inner elements). Don't have anything to free.
-    if (!curObj->elementsRaw())
-        return;
-
-    curObj->assertZeroLengthArrayData();
-
-    // Typed arrays with a buffer object do not need to be free'd
-    if (curObj->hasBuffer())
-        return;
-
-    // Free the data slot pointer if it does not point into the old JSObject.
-    if (!curObj->hasInlineElements())
-        js_free(curObj->elements());
-}
-
-/* static */ void
-TypedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
-{
-    TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
-    const TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
-
-    // Typed arrays with a buffer object do not need an update.
-    if (oldObj->hasBuffer())
-        return;
-
-    // Update the data slot pointer if it points to the old JSObject.
-    if (oldObj->hasInlineElements())
-        newObj->setInlineElements();
-}
-
-/* static */ size_t
-TypedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* obj, const JSObject* old,
-                                           gc::AllocKind newAllocKind)
-{
-    TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
-    const TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
-    MOZ_ASSERT(newObj->elementsRaw() == oldObj->elementsRaw());
-    MOZ_ASSERT(obj->isTenured());
-
-    // Typed arrays with a buffer object do not need an update.
-    if (oldObj->hasBuffer())
-        return 0;
-
-    Nursery& nursery = trc->runtime()->gc.nursery;
-    void* buf = oldObj->elements();
-
-    if (!nursery.isInside(buf)) {
-        nursery.removeMallocedBuffer(buf);
-        return 0;
-    }
-
-    // Determine if we can use inline data for the target array. If this is
-    // possible, the nursery will have picked an allocation size that is large
-    // enough.
-    size_t nbytes = 0;
-    switch (oldObj->type()) {
-#define OBJECT_MOVED_TYPED_ARRAY(T, N) \
-      case Scalar::N: \
-        nbytes = oldObj->length() * sizeof(T); \
-        break;
-JS_FOR_EACH_TYPED_ARRAY(OBJECT_MOVED_TYPED_ARRAY)
-#undef OBJECT_MOVED_TYPED_ARRAY
-      default:
-        MOZ_CRASH("Unsupported TypedArray type");
-    }
-
-    size_t headerSize = dataOffset() + sizeof(HeapSlot);
-
-    // See AllocKindForLazyBuffer.
-    MOZ_ASSERT_IF(nbytes == 0, headerSize + sizeof(uint8_t) <= GetGCKindBytes(newAllocKind));
-
-    if (headerSize + nbytes <= GetGCKindBytes(newAllocKind)) {
-        MOZ_ASSERT(oldObj->hasInlineElements());
-#ifdef DEBUG
-        if (nbytes == 0) {
-            uint8_t* output = newObj->fixedData(TypedArrayObject::FIXED_DATA_START);
-            output[0] = ZeroLengthArrayData;
-        }
-#endif
-        newObj->setInlineElements();
-    } else {
-        MOZ_ASSERT(!oldObj->hasInlineElements());
-        AutoEnterOOMUnsafeRegion oomUnsafe;
-        nbytes = JS_ROUNDUP(nbytes, sizeof(Value));
-        void* data = newObj->zone()->pod_malloc<uint8_t>(nbytes);
-        if (!data)
-            oomUnsafe.crash("Failed to allocate typed array elements while tenuring.");
-        MOZ_ASSERT(!nursery.isInside(data));
-        newObj->initPrivate(data);
-    }
-
-    mozilla::PodCopy(newObj->elements(), oldObj->elements(), nbytes);
-
-    // Set a forwarding pointer for the element buffers in case they were
-    // preserved on the stack by Ion.
-    nursery.maybeSetForwardingPointer(trc, oldObj->elements(), newObj->elements(),
-                                      /* direct = */nbytes >= sizeof(uintptr_t));
-
-    return newObj->hasInlineElements() ? 0 : nbytes;
-}
-
-bool
-TypedArrayObject::hasInlineElements() const
-{
-    return elements() == this->fixedData(TypedArrayObject::FIXED_DATA_START) &&
-        byteLength() <= TypedArrayObject::INLINE_BUFFER_LIMIT;
-}
-
-void
-TypedArrayObject::setInlineElements()
-{
-    char* dataSlot = reinterpret_cast<char*>(this) + this->dataOffset();
-    *reinterpret_cast<void**>(dataSlot) = this->fixedData(TypedArrayObject::FIXED_DATA_START);
-}
-
-/* Helper clamped uint8_t type */
-
-uint32_t JS_FASTCALL
-js::ClampDoubleToUint8(const double x)
-{
-    // Not < so that NaN coerces to 0
-    if (!(x >= 0))
-        return 0;
-
-    if (x > 255)
-        return 255;
-
-    double toTruncate = x + 0.5;
-    uint8_t y = uint8_t(toTruncate);
-
-    /*
-     * now val is rounded to nearest, ties rounded up.  We want
-     * rounded to nearest ties to even, so check whether we had a
-     * tie.
-     */
-    if (y == toTruncate) {
-        /*
-         * It was a tie (since adding 0.5 gave us the exact integer
-         * we want).  Since we rounded up, we either already have an
-         * even number or we have an odd number but the number we
-         * want is one less.  So just unconditionally masking out the
-         * ones bit should do the trick to get us the value we
-         * want.
-         */
-        return y & ~1;
-    }
-
-    return y;
-}
-
-template<typename ElementType>
-static inline JSObject*
-NewArray(JSContext* cx, uint32_t nelements);
-
-namespace {
-
-// We allow nullptr for newTarget for all the creation methods, to allow for
-// JSFriendAPI functions that don't care about subclassing
-static bool
-GetPrototypeForInstance(JSContext* cx, HandleObject newTarget, MutableHandleObject proto)
-{
-    if (newTarget) {
-        if (!GetPrototypeFromConstructor(cx, newTarget, proto))
-            return false;
-    } else {
-        proto.set(nullptr);
-    }
-    return true;
-}
-
-enum class SpeciesConstructorOverride {
-    None,
-    ArrayBuffer
-};
-
-template<typename NativeType>
-class TypedArrayObjectTemplate : public TypedArrayObject
-{
-    friend class TypedArrayObject;
-
-  public:
-    typedef NativeType ElementType;
-
-    static constexpr Scalar::Type ArrayTypeID() { return TypeIDOfType<NativeType>::id; }
-    static bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
-    static bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
-
-    static const size_t BYTES_PER_ELEMENT = sizeof(NativeType);
-
-    static JSObject*
-    createPrototype(JSContext* cx, JSProtoKey key)
-    {
-        Handle<GlobalObject*> global = cx->global();
-        RootedObject typedArrayProto(cx, GlobalObject::getOrCreateTypedArrayPrototype(cx, global));
-        if (!typedArrayProto)
-            return nullptr;
-
-        const Class* clasp = TypedArrayObject::protoClassForType(ArrayTypeID());
-        return GlobalObject::createBlankPrototypeInheriting(cx, global, clasp, typedArrayProto);
-    }
-
-    static JSObject*
-    createConstructor(JSContext* cx, JSProtoKey key)
-    {
-        Handle<GlobalObject*> global = cx->global();
-        RootedFunction ctorProto(cx, GlobalObject::getOrCreateTypedArrayConstructor(cx, global));
-        if (!ctorProto)
-            return nullptr;
-
-        JSFunction* fun = NewFunctionWithProto(cx, class_constructor, 3,
-                                               JSFunction::NATIVE_CTOR, nullptr,
-                                               ClassName(key, cx),
-                                               ctorProto, gc::AllocKind::FUNCTION,
-                                               SingletonObject);
-
-        if (fun)
-            fun->setJitInfo(&jit::JitInfo_TypedArrayConstructor);
-
-        return fun;
-    }
-
-    static bool
-    getOrCreateCreateArrayFromBufferFunction(JSContext* cx, MutableHandleValue fval)
-    {
-        RootedValue cache(cx, cx->global()->createArrayFromBuffer<NativeType>());
-        if (cache.isObject()) {
-            MOZ_ASSERT(cache.toObject().is<JSFunction>());
-            fval.set(cache);
-            return true;
-        }
-
-        RootedFunction fun(cx);
-        fun = NewNativeFunction(cx, ArrayBufferObject::createTypedArrayFromBuffer<NativeType>,
-                                0, nullptr);
-        if (!fun)
-            return false;
-
-        cx->global()->setCreateArrayFromBuffer<NativeType>(fun);
-
-        fval.setObject(*fun);
-        return true;
-    }
-
-    static inline const Class* instanceClass()
-    {
-        return TypedArrayObject::classForType(ArrayTypeID());
-    }
-
-    static bool is(HandleValue v) {
-        return v.isObject() && v.toObject().hasClass(instanceClass());
-    }
-
-    static void
-    setIndexValue(TypedArrayObject& tarray, uint32_t index, double d)
-    {
-        // If the array is an integer array, we only handle up to
-        // 32-bit ints from this point on.  if we want to handle
-        // 64-bit ints, we'll need some changes.
-
-        // Assign based on characteristics of the destination type
-        if (ArrayTypeIsFloatingPoint()) {
-            setIndex(tarray, index, NativeType(d));
-        } else if (ArrayTypeIsUnsigned()) {
-            MOZ_ASSERT(sizeof(NativeType) <= 4);
-            uint32_t n = ToUint32(d);
-            setIndex(tarray, index, NativeType(n));
-        } else if (ArrayTypeID() == Scalar::Uint8Clamped) {
-            // The uint8_clamped type has a special rounding converter
-            // for doubles.
-            setIndex(tarray, index, NativeType(d));
-        } else {
-            MOZ_ASSERT(sizeof(NativeType) <= 4);
-            int32_t n = ToInt32(d);
-            setIndex(tarray, index, NativeType(n));
-        }
-    }
-
-    static TypedArrayObject*
-    makeProtoInstance(JSContext* cx, HandleObject proto, AllocKind allocKind)
-    {
-        MOZ_ASSERT(proto);
-
-        JSObject* obj = NewObjectWithClassProto(cx, instanceClass(), proto, allocKind);
-        return obj ? &obj->as<TypedArrayObject>() : nullptr;
-    }
-
-    static TypedArrayObject*
-    makeTypedInstance(JSContext* cx, uint32_t len, gc::AllocKind allocKind)
-    {
-        const Class* clasp = instanceClass();
-        if (len * sizeof(NativeType) >= TypedArrayObject::SINGLETON_BYTE_LENGTH) {
-            JSObject* obj = NewBuiltinClassInstance(cx, clasp, allocKind, SingletonObject);
-            if (!obj)
-                return nullptr;
-            return &obj->as<TypedArrayObject>();
-        }
-
-        jsbytecode* pc;
-        RootedScript script(cx, cx->currentScript(&pc));
-        NewObjectKind newKind = GenericObject;
-        if (script && ObjectGroup::useSingletonForAllocationSite(script, pc, clasp))
-            newKind = SingletonObject;
-        RootedObject obj(cx, NewBuiltinClassInstance(cx, clasp, allocKind, newKind));
-        if (!obj)
-            return nullptr;
-
-        if (script && !ObjectGroup::setAllocationSiteObjectGroup(cx, script, pc, obj,
-                                                                 newKind == SingletonObject))
-        {
-            return nullptr;
-        }
-
-        return &obj->as<TypedArrayObject>();
-    }
-
-    static TypedArrayObject*
-    makeInstance(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> buffer, uint32_t byteOffset, uint32_t len,
-                 HandleObject proto)
-    {
-        MOZ_ASSERT_IF(!buffer, byteOffset == 0);
-
-        gc::AllocKind allocKind = buffer
-                                  ? GetGCObjectKind(instanceClass())
-                                  : AllocKindForLazyBuffer(len * sizeof(NativeType));
-
-        // Subclassing mandates that we hand in the proto every time. Most of
-        // the time, though, that [[Prototype]] will not be interesting. If
-        // it isn't, we can do some more TI optimizations.
-        RootedObject checkProto(cx);
-        if (!GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()), &checkProto))
-            return nullptr;
-
-        AutoSetNewObjectMetadata metadata(cx);
-        Rooted<TypedArrayObject*> obj(cx);
-        if (proto && proto != checkProto)
-            obj = makeProtoInstance(cx, proto, allocKind);
-        else
-            obj = makeTypedInstance(cx, len, allocKind);
-        if (!obj)
-            return nullptr;
-
-        bool isSharedMemory = buffer && IsSharedArrayBuffer(buffer.get());
-
-        obj->setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectOrNullValue(buffer));
-        // This is invariant.  Self-hosting code that sets BUFFER_SLOT
-        // (if it does) must maintain it, should it need to.
-        if (isSharedMemory)
-            obj->setIsSharedMemory();
-
-        if (buffer) {
-            obj->initViewData(buffer->dataPointerEither() + byteOffset);
-
-            // If the buffer is for an inline typed object, the data pointer
-            // may be in the nursery, so include a barrier to make sure this
-            // object is updated if that typed object moves.
-            auto ptr = buffer->dataPointerEither();
-            if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(ptr)) {
-                // Shared buffer data should never be nursery-allocated, so we
-                // need to fail here if isSharedMemory.  However, mmap() can
-                // place a SharedArrayRawBuffer up against the bottom end of a
-                // nursery chunk, and a zero-length buffer will erroneously be
-                // perceived as being inside the nursery; sidestep that.
-                if (isSharedMemory) {
-                    MOZ_ASSERT(buffer->byteLength() == 0 &&
-                               (uintptr_t(ptr.unwrapValue()) & gc::ChunkMask) == 0);
-                } else {
-                    cx->runtime()->gc.storeBuffer.putWholeCell(obj);
-                }
-            }
-        } else {
-            void* data = obj->fixedData(FIXED_DATA_START);
-            obj->initPrivate(data);
-            memset(data, 0, len * sizeof(NativeType));
-#ifdef DEBUG
-            if (len == 0) {
-                uint8_t* elements = static_cast<uint8_t*>(data);
-                elements[0] = ZeroLengthArrayData;
-            }
-#endif
-        }
-
-        obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(len));
-        obj->setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(byteOffset));
-
-#ifdef DEBUG
-        if (buffer) {
-            uint32_t arrayByteLength = obj->byteLength();
-            uint32_t arrayByteOffset = obj->byteOffset();
-            uint32_t bufferByteLength = buffer->byteLength();
-            // Unwraps are safe: both are for the pointer value.
-            if (IsArrayBuffer(buffer.get())) {
-                MOZ_ASSERT_IF(!AsArrayBuffer(buffer.get()).isDetached(),
-                              buffer->dataPointerEither().unwrap(/*safe*/) <= obj->viewDataEither().unwrap(/*safe*/));
-            }
-            MOZ_ASSERT(bufferByteLength - arrayByteOffset >= arrayByteLength);
-            MOZ_ASSERT(arrayByteOffset <= bufferByteLength);
-        }
-
-        // Verify that the private slot is at the expected place
-        MOZ_ASSERT(obj->numFixedSlots() == TypedArrayObject::DATA_SLOT);
-#endif
-
-        // ArrayBufferObjects track their views to support detaching.
-        if (buffer && buffer->is<ArrayBufferObject>()) {
-            if (!buffer->as<ArrayBufferObject>().addView(cx, obj))
-                return nullptr;
-        }
-
-        return obj;
-    }
-
-    static TypedArrayObject*
-    makeInstance(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> buffer,
-                 uint32_t byteOffset, uint32_t len)
-    {
-        RootedObject proto(cx, nullptr);
-        return makeInstance(cx, buffer, byteOffset, len, proto);
-    }
-
-    static TypedArrayObject*
-    makeTemplateObject(JSContext* cx, int32_t len)
-    {
-        MOZ_ASSERT(len >= 0);
-        size_t nbytes;
-        MOZ_ALWAYS_TRUE(CalculateAllocSize<NativeType>(len, &nbytes));
-        MOZ_ASSERT(nbytes < TypedArrayObject::SINGLETON_BYTE_LENGTH);
-        NewObjectKind newKind = TenuredObject;
-        bool fitsInline = nbytes <= INLINE_BUFFER_LIMIT;
-        const Class* clasp = instanceClass();
-        gc::AllocKind allocKind = !fitsInline
-                                  ? GetGCObjectKind(clasp)
-                                  : AllocKindForLazyBuffer(nbytes);
-        MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, clasp));
-        allocKind = GetBackgroundAllocKind(allocKind);
-
-        AutoSetNewObjectMetadata metadata(cx);
-        jsbytecode* pc;
-        RootedScript script(cx, cx->currentScript(&pc));
-        if (script && ObjectGroup::useSingletonForAllocationSite(script, pc, clasp))
-            newKind = SingletonObject;
-        RootedObject tmp(cx, NewBuiltinClassInstance(cx, clasp, allocKind, newKind));
-        if (!tmp)
-            return nullptr;
-        if (script && !ObjectGroup::setAllocationSiteObjectGroup(cx, script, pc, tmp,
-                                                                 newKind == SingletonObject))
-        {
-            return nullptr;
-        }
-
-        TypedArrayObject* tarray = &tmp->as<TypedArrayObject>();
-        initTypedArraySlots(cx, tarray, len);
-
-        // Template objects do not need memory for its elements, since there
-        // won't be any elements to store. Therefore, we set the pointer to
-        // nullptr and avoid allocating memory that will never be used.
-        tarray->initPrivate(nullptr);
-
-        return tarray;
-    }
-
-    static void
-    initTypedArraySlots(JSContext* cx, TypedArrayObject* tarray, int32_t len)
-    {
-        MOZ_ASSERT(len >= 0);
-        tarray->setFixedSlot(TypedArrayObject::BUFFER_SLOT, NullValue());
-        tarray->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(AssertedCast<int32_t>(len)));
-        tarray->setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(0));
-
-        // Verify that the private slot is at the expected place.
-        MOZ_ASSERT(tarray->numFixedSlots() == TypedArrayObject::DATA_SLOT);
-
-#ifdef DEBUG
-        if (len == 0) {
-            uint8_t* output = tarray->fixedData(TypedArrayObject::FIXED_DATA_START);
-            output[0] = TypedArrayObject::ZeroLengthArrayData;
-        }
-#endif
-    }
-
-    static void
-    initTypedArrayData(JSContext* cx, TypedArrayObject* tarray, int32_t len,
-                       void* buf, AllocKind allocKind)
-    {
-        if (buf) {
-#ifdef DEBUG
-            Nursery& nursery = cx->runtime()->gc.nursery;
-            MOZ_ASSERT_IF(!nursery.isInside(buf) && !tarray->hasInlineElements(),
-                          tarray->isTenured());
-#endif
-            tarray->initPrivate(buf);
-        } else {
-            size_t nbytes = len * sizeof(NativeType);
-#ifdef DEBUG
-            size_t dataOffset = TypedArrayObject::dataOffset();
-            size_t offset = dataOffset + sizeof(HeapSlot);
-            MOZ_ASSERT(offset + nbytes <= GetGCKindBytes(allocKind));
-#endif
-
-            void* data = tarray->fixedData(FIXED_DATA_START);
-            tarray->initPrivate(data);
-            memset(data, 0, nbytes);
-        }
-    }
-
-    static TypedArrayObject*
-    makeTypedArrayWithTemplate(JSContext* cx, TypedArrayObject* templateObj, int32_t len)
-    {
-        size_t nbytes;
-        if (len < 0 || !js::CalculateAllocSize<NativeType>(len, &nbytes)) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
-            return nullptr;
-        }
-
-        bool fitsInline = nbytes <= INLINE_BUFFER_LIMIT;
-
-        AutoSetNewObjectMetadata metadata(cx);
-
-        const Class* clasp = templateObj->group()->clasp();
-        gc::AllocKind allocKind = !fitsInline
-                                  ? GetGCObjectKind(clasp)
-                                  : AllocKindForLazyBuffer(nbytes);
-        MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, clasp));
-        allocKind = GetBackgroundAllocKind(allocKind);
-        RootedObjectGroup group(cx, templateObj->group());
-
-        NewObjectKind newKind = TenuredObject;
-
-        ScopedJSFreePtr<void> buf;
-        if (!fitsInline && len > 0) {
-            buf = cx->zone()->pod_malloc<uint8_t>(nbytes);
-            if (!buf) {
-                ReportOutOfMemory(cx);
-                return nullptr;
-            }
-
-            memset(buf, 0, nbytes);
-         }
-
-        RootedObject tmp(cx, NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind, newKind));
-        if (!tmp)
-            return nullptr;
-
-        TypedArrayObject* obj = &tmp->as<TypedArrayObject>();
-        initTypedArraySlots(cx, obj, len);
-        initTypedArrayData(cx, obj, len, buf.forget(), allocKind);
-
-        return obj;
-    }
-
-    /*
-     * new [Type]Array(length)
-     * new [Type]Array(otherTypedArray)
-     * new [Type]Array(JSArray)
-     * new [Type]Array(ArrayBuffer, [optional] byteOffset, [optional] length)
-     */
-    static bool
-    class_constructor(JSContext* cx, unsigned argc, Value* vp)
-    {
-        CallArgs args = CallArgsFromVp(argc, vp);
-
-        if (!ThrowIfNotConstructing(cx, args, "typed array"))
-            return false;
-
-        JSObject* obj = create(cx, args);
-        if (!obj)
-            return false;
-        args.rval().setObject(*obj);
-        return true;
-    }
-
-    static JSObject*
-    create(JSContext* cx, const CallArgs& args)
-    {
-        MOZ_ASSERT(args.isConstructing());
-        RootedObject newTarget(cx, &args.newTarget().toObject());
-
-        /* () or (number) */
-        uint32_t len = 0;
-        if (args.length() == 0 || ValueIsLength(args[0], &len))
-            return fromLength(cx, len, newTarget);
-
-        /* (not an object) */
-        if (!args[0].isObject()) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
-            return nullptr;
-        }
-
-        RootedObject dataObj(cx, &args.get(0).toObject());
-
-        /*
-         * (typedArray)
-         * (sharedTypedArray)
-         * (type[] array)
-         *
-         * Otherwise create a new typed array and copy elements 0..len-1
-         * properties from the object, treating it as some sort of array.
-         * Note that offset and length will be ignored.  Note that a
-         * shared array's values are copied here.
-         */
-        if (!UncheckedUnwrap(dataObj)->is<ArrayBufferObjectMaybeShared>())
-            return fromArray(cx, dataObj, newTarget);
-
-        /* (ArrayBuffer, [byteOffset, [length]]) */
-        RootedObject proto(cx);
-        if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
-            return nullptr;
-
-        int32_t byteOffset = 0;
-        if (args.hasDefined(1)) {
-            if (!ToInt32(cx, args[1], &byteOffset))
-                return nullptr;
-            if (byteOffset < 0) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                          JSMSG_TYPED_ARRAY_NEGATIVE_ARG,
-                                          "1");
-                return nullptr;
-            }
-        }
-
-        int32_t length = -1;
-        if (args.hasDefined(2)) {
-            if (!ToInt32(cx, args[2], &length))
-                return nullptr;
-            if (length < 0) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                          JSMSG_TYPED_ARRAY_NEGATIVE_ARG,
-                                          "2");
-                return nullptr;
-            }
-        }
-
-        return fromBufferWithProto(cx, dataObj, byteOffset, length, proto);
-    }
-
-  public:
-    static JSObject*
-    fromBuffer(JSContext* cx, HandleObject bufobj, uint32_t byteOffset, int32_t lengthInt) {
-        return fromBufferWithProto(cx, bufobj, byteOffset, lengthInt, nullptr);
-    }
-
-    static JSObject*
-    fromBufferWithProto(JSContext* cx, HandleObject bufobj, uint32_t byteOffset, int32_t lengthInt,
-                        HandleObject proto)
-    {
-        if (bufobj->is<ProxyObject>()) {
-            /*
-             * Normally, NonGenericMethodGuard handles the case of transparent
-             * wrappers. However, we have a peculiar situation: we want to
-             * construct the new typed array in the compartment of the buffer,
-             * so that the typed array can point directly at their buffer's
-             * data without crossing compartment boundaries. So we use the
-             * machinery underlying NonGenericMethodGuard directly to proxy the
-             * native call. We will end up with a wrapper in the origin
-             * compartment for a view in the target compartment referencing the
-             * ArrayBufferObject in that same compartment.
-             */
-            JSObject* wrapped = CheckedUnwrap(bufobj);
-            if (!wrapped) {
-                ReportAccessDenied(cx);
-                return nullptr;
-            }
-
-            if (!IsAnyArrayBuffer(wrapped)) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
-                return nullptr; // must be arrayBuffer
-            }
-
-            /*
-             * And for even more fun, the new view's prototype should be
-             * set to the origin compartment's prototype object, not the
-             * target's (specifically, the actual view in the target
-             * compartment will use as its prototype a wrapper around the
-             * origin compartment's view.prototype object).
-             *
-             * Rather than hack some crazy solution together, implement
-             * this all using a private helper function, created when
-             * ArrayBufferObject was initialized and cached in the global.
-             * This reuses all the existing cross-compartment crazy so we
-             * don't have to do anything *uniquely* crazy here.
-             */
-
-            RootedObject protoRoot(cx, proto);
-            if (!protoRoot) {
-                if (!GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()), &protoRoot))
-                    return nullptr;
-            }
-
-            FixedInvokeArgs<3> args(cx);
-
-            args[0].setNumber(byteOffset);
-            args[1].setInt32(lengthInt);
-            args[2].setObject(*protoRoot);
-
-            RootedValue fval(cx);
-            if (!getOrCreateCreateArrayFromBufferFunction(cx, &fval))
-                return nullptr;
-
-            RootedValue thisv(cx, ObjectValue(*bufobj));
-            RootedValue rval(cx);
-            if (!js::Call(cx, fval, thisv, args, &rval))
-                return nullptr;
-
-            return &rval.toObject();
-        }
-
-        if (!IsAnyArrayBuffer(bufobj)) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
-            return nullptr; // must be arrayBuffer
-        }
-
-        Rooted<ArrayBufferObjectMaybeShared*> buffer(cx);
-        if (IsArrayBuffer(bufobj)) {
-            ArrayBufferObject& buf = AsArrayBuffer(bufobj);
-            if (buf.isDetached()) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-                return nullptr;
-            }
-
-            buffer = static_cast<ArrayBufferObjectMaybeShared*>(&buf);
-        } else {
-            buffer = static_cast<ArrayBufferObjectMaybeShared*>(&AsSharedArrayBuffer(bufobj));
-        }
-
-        if (byteOffset > buffer->byteLength() || byteOffset % sizeof(NativeType) != 0) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                      JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
-            return nullptr; // invalid byteOffset
-        }
-
-        uint32_t len;
-        if (lengthInt == -1) {
-            len = (buffer->byteLength() - byteOffset) / sizeof(NativeType);
-            if (len * sizeof(NativeType) != buffer->byteLength() - byteOffset) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                          JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
-                return nullptr; // given byte array doesn't map exactly to sizeof(NativeType) * N
-            }
-        } else {
-            len = uint32_t(lengthInt);
-        }
-
-        // Go slowly and check for overflow.
-        uint32_t arrayByteLength = len * sizeof(NativeType);
-        if (len >= INT32_MAX / sizeof(NativeType) || byteOffset >= INT32_MAX - arrayByteLength) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                      JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
-            return nullptr; // overflow when calculating byteOffset + len * sizeof(NativeType)
-        }
-
-        if (arrayByteLength + byteOffset > buffer->byteLength()) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                      JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
-            return nullptr; // byteOffset + len is too big for the arraybuffer
-        }
-
-        return makeInstance(cx, buffer, byteOffset, len, proto);
-    }
-
-    static bool
-    maybeCreateArrayBuffer(JSContext* cx, uint32_t count, uint32_t unit,
-                           HandleObject nonDefaultProto,
-                           MutableHandle<ArrayBufferObject*> buffer)
-    {
-        if (count >= INT32_MAX / unit) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NEED_DIET,
-                                      "size and count");
-            return false;
-        }
-        uint32_t byteLength = count * unit;
-
-        MOZ_ASSERT(byteLength < INT32_MAX);
-        static_assert(INLINE_BUFFER_LIMIT % sizeof(NativeType) == 0,
-                      "ArrayBuffer inline storage shouldn't waste any space");
-
-        if (!nonDefaultProto && byteLength <= INLINE_BUFFER_LIMIT) {
-            // The array's data can be inline, and the buffer created lazily.
-            return true;
-        }
-
-        ArrayBufferObject* buf = ArrayBufferObject::create(cx, byteLength, nonDefaultProto);
-        if (!buf)
-            return false;
-
-        buffer.set(buf);
-        return true;
-    }
-
-    static JSObject*
-    fromLength(JSContext* cx, uint32_t nelements, HandleObject newTarget = nullptr)
-    {
-        RootedObject proto(cx);
-        if (!GetPrototypeForInstance(cx, newTarget, &proto))
-            return nullptr;
-
-        Rooted<ArrayBufferObject*> buffer(cx);
-        if (!maybeCreateArrayBuffer(cx, nelements, BYTES_PER_ELEMENT, nullptr, &buffer))
-            return nullptr;
-
-        return makeInstance(cx, buffer, 0, nelements, proto);
-    }
-
-    static bool
-    AllocateArrayBuffer(JSContext* cx, HandleValue ctor,
-                        uint32_t count, uint32_t unit,
-                        MutableHandle<ArrayBufferObject*> buffer);
-
-    static bool
-    CloneArrayBufferNoCopy(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> srcBuffer,
-                           bool isWrapped, uint32_t srcByteOffset, uint32_t srcLength,
-                           SpeciesConstructorOverride override,
-                           MutableHandle<ArrayBufferObject*> buffer);
-
-    static JSObject*
-    fromArray(JSContext* cx, HandleObject other, HandleObject newTarget = nullptr);
-
-    static JSObject*
-    fromTypedArray(JSContext* cx, HandleObject other, bool isWrapped, HandleObject newTarget);
-
-    static JSObject*
-    fromObject(JSContext* cx, HandleObject other, HandleObject newTarget);
-
-    static const NativeType
-    getIndex(JSObject* obj, uint32_t index)
-    {
-        TypedArrayObject& tarray = obj->as<TypedArrayObject>();
-        MOZ_ASSERT(index < tarray.length());
-        return jit::AtomicOperations::loadSafeWhenRacy(tarray.viewDataEither().cast<NativeType*>() + index);
-    }
-
-    static void
-    setIndex(TypedArrayObject& tarray, uint32_t index, NativeType val)
-    {
-        MOZ_ASSERT(index < tarray.length());
-        jit::AtomicOperations::storeSafeWhenRacy(tarray.viewDataEither().cast<NativeType*>() + index, val);
-    }
-
-    static Value getIndexValue(JSObject* tarray, uint32_t index);
-};
-
-#define CREATE_TYPE_FOR_TYPED_ARRAY(T, N) \
-    typedef TypedArrayObjectTemplate<T> N##Array;
-JS_FOR_EACH_TYPED_ARRAY(CREATE_TYPE_FOR_TYPED_ARRAY)
-#undef CREATE_TYPE_FOR_TYPED_ARRAY
-
-} /* anonymous namespace */
-
-TypedArrayObject*
-js::TypedArrayCreateWithTemplate(JSContext* cx, HandleObject templateObj, int32_t len)
-{
-    MOZ_ASSERT(templateObj->is<TypedArrayObject>());
-    TypedArrayObject* tobj = &templateObj->as<TypedArrayObject>();
-
-    switch (tobj->type()) {
-#define CREATE_TYPED_ARRAY(T, N) \
-      case Scalar::N: \
-        return TypedArrayObjectTemplate<T>::makeTypedArrayWithTemplate(cx, tobj, len);
-JS_FOR_EACH_TYPED_ARRAY(CREATE_TYPED_ARRAY)
-#undef CREATE_TYPED_ARRAY
-      default:
-        MOZ_CRASH("Unsupported TypedArray type");
-    }
-}
-
-template<typename T>
-struct TypedArrayObject::OfType
-{
-    typedef TypedArrayObjectTemplate<T> Type;
-};
-
-// ES 2016 draft Mar 25, 2016 24.1.1.1.
-// byteLength = count * unit
-template<typename T>
-/* static */ bool
-TypedArrayObjectTemplate<T>::AllocateArrayBuffer(JSContext* cx, HandleValue ctor,
-                                                 uint32_t count, uint32_t unit,
-                                                 MutableHandle<ArrayBufferObject*> buffer)
-{
-    // ES 2016 draft Mar 25, 2016 24.1.1.1 step 1 (partially).
-    // ES 2016 draft Mar 25, 2016 9.1.14 steps 1-2.
-    MOZ_ASSERT(ctor.isObject());
-    RootedObject proto(cx);
-    RootedObject ctorObj(cx, &ctor.toObject());
-    if (!GetPrototypeFromConstructor(cx, ctorObj, &proto))
-        return false;
-    JSObject* arrayBufferProto = GlobalObject::getOrCreateArrayBufferPrototype(cx, cx->global());
-    if (!arrayBufferProto)
-        return false;
-    if (proto == arrayBufferProto)
-        proto = nullptr;
-
-    // ES 2016 draft Mar 25, 2016 24.1.1.1 steps 1 (remaining part), 2-6.
-    if (!maybeCreateArrayBuffer(cx, count, unit, proto, buffer))
-        return false;
-
-    return true;
-}
-
-static bool
-IsArrayBufferConstructor(const Value& v)
-{
-    return v.isObject() &&
-           v.toObject().is<JSFunction>() &&
-           v.toObject().as<JSFunction>().isNative() &&
-           v.toObject().as<JSFunction>().native() == ArrayBufferObject::class_constructor;
-}
-
-static bool
-IsArrayBufferSpecies(JSContext* cx, HandleObject origBuffer)
-{
-    RootedValue ctor(cx);
-    if (!GetPropertyPure(cx, origBuffer, NameToId(cx->names().constructor), ctor.address()))
-        return false;
-
-    if (!IsArrayBufferConstructor(ctor))
-        return false;
-
-    RootedObject ctorObj(cx, &ctor.toObject());
-    RootedId speciesId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().species));
-    JSFunction* getter;
-    if (!GetGetterPure(cx, ctorObj, speciesId, &getter))
-        return false;
-
-    if (!getter)
-        return false;
-
-    return IsSelfHostedFunctionWithName(getter, cx->names().ArrayBufferSpecies);
-}
-
-static bool
-GetSpeciesConstructor(JSContext* cx, HandleObject obj, bool isWrapped,
-                      SpeciesConstructorOverride override, MutableHandleValue ctor)
-{
-    if (!isWrapped) {
-        if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
-            return false;
-        RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
-        // The second disjunct is an optimization.
-        if (override == SpeciesConstructorOverride::ArrayBuffer || IsArrayBufferSpecies(cx, obj))
-            ctor.set(defaultCtor);
-        else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
-            return false;
-
-        return true;
-    }
-
-    {
-        JSAutoCompartment ac(cx, obj);
-        if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
-            return false;
-        RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
-        if (override == SpeciesConstructorOverride::ArrayBuffer)
-            ctor.set(defaultCtor);
-        else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
-            return false;
-    }
-
-    return JS_WrapValue(cx, ctor);
-}
-
-// ES 2017 draft rev 8633ffd9394b203b8876bb23cb79aff13eb07310 24.1.1.4.
-template<typename T>
-/* static */ bool
-TypedArrayObjectTemplate<T>::CloneArrayBufferNoCopy(JSContext* cx,
-                                                    Handle<ArrayBufferObjectMaybeShared*> srcBuffer,
-                                                    bool isWrapped, uint32_t srcByteOffset,
-                                                    uint32_t srcLength,
-                                                    SpeciesConstructorOverride override,
-                                                    MutableHandle<ArrayBufferObject*> buffer)
-{
-    // Step 1 (skipped).
-
-    // Step 2.a.
-    RootedValue cloneCtor(cx);
-    if (!GetSpeciesConstructor(cx, srcBuffer, isWrapped, override, &cloneCtor))
-        return false;
-
-    // Step 2.b.
-    if (srcBuffer->isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return false;
-    }
-
-    // Steps 3-4 (skipped).
-
-    // Steps 5.
-    if (!AllocateArrayBuffer(cx, cloneCtor, srcLength, 1, buffer))
-        return false;
-
-    // Step 6.
-    if (srcBuffer->isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return false;
-    }
-
-    // Steps 7-8 (done in caller).
-
-    // Step 9.
-    return true;
-}
-
-template<typename T>
-/* static */ JSObject*
-TypedArrayObjectTemplate<T>::fromArray(JSContext* cx, HandleObject other,
-                                       HandleObject newTarget /* = nullptr */)
-{
-    // Allow nullptr newTarget for FriendAPI methods, which don't care about
-    // subclassing.
-    if (other->is<TypedArrayObject>())
-        return fromTypedArray(cx, other, /* wrapped= */ false, newTarget);
-
-    if (other->is<WrapperObject>() && UncheckedUnwrap(other)->is<TypedArrayObject>())
-        return fromTypedArray(cx, other, /* wrapped= */ true, newTarget);
-
-    return fromObject(cx, other, newTarget);
-}
-
-// ES 2017 draft rev 8633ffd9394b203b8876bb23cb79aff13eb07310 22.2.4.3.
-template<typename T>
-/* static */ JSObject*
-TypedArrayObjectTemplate<T>::fromTypedArray(JSContext* cx, HandleObject other, bool isWrapped,
-                                            HandleObject newTarget)
-{
-    // Step 1.
-    MOZ_ASSERT_IF(!isWrapped, other->is<TypedArrayObject>());
-    MOZ_ASSERT_IF(isWrapped,
-                  other->is<WrapperObject>() &&
-                  UncheckedUnwrap(other)->is<TypedArrayObject>());
-
-    // Step 2 (done in caller).
-
-    // Step 4 (partially).
-    RootedObject proto(cx);
-    if (!GetPrototypeForInstance(cx, newTarget, &proto))
-        return nullptr;
-
-    // Step 5.
-    Rooted<TypedArrayObject*> srcArray(cx);
-    if (!isWrapped) {
-        srcArray = &other->as<TypedArrayObject>();
-        if (!TypedArrayObject::ensureHasBuffer(cx, srcArray))
-            return nullptr;
-    } else {
-        RootedObject unwrapped(cx, CheckedUnwrap(other));
-        if (!unwrapped) {
-            ReportAccessDenied(cx);
-            return nullptr;
-        }
-
-        JSAutoCompartment ac(cx, unwrapped);
-
-        srcArray = &unwrapped->as<TypedArrayObject>();
-        if (!TypedArrayObject::ensureHasBuffer(cx, srcArray))
-            return nullptr;
-    }
-
-    // Step 6.
-    Rooted<ArrayBufferObjectMaybeShared*> srcData(cx, srcArray->bufferEither());
-
-    // Step 7.
-    if (srcData->isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return nullptr;
-    }
-
-    // Steps 10.
-    uint32_t elementLength = srcArray->length();
-
-    // Steps 11-12.
-    Scalar::Type srcType = srcArray->type();
-
-    // Step 13 (skipped).
-
-    // Step 14.
-    uint32_t srcByteOffset = srcArray->byteOffset();
-
-    // Step 17, modified for SharedArrayBuffer.
-    bool isShared = srcArray->isSharedMemory();
-    SpeciesConstructorOverride override = isShared ? SpeciesConstructorOverride::ArrayBuffer
-                                                   : SpeciesConstructorOverride::None;
-
-    // Steps 8-9, 17.
-    Rooted<ArrayBufferObject*> buffer(cx);
-    if (ArrayTypeID() == srcType) {
-        // Step 17.a.
-        uint32_t srcLength = srcArray->byteLength();
-
-        // Step 17.b, modified for SharedArrayBuffer
-        if (!CloneArrayBufferNoCopy(cx, srcData, isWrapped, srcByteOffset, srcLength, override,
-                                    &buffer))
-        {
-            return nullptr;
-        }
-    } else {
-        // Step 18.a, modified for SharedArrayBuffer
-        RootedValue bufferCtor(cx);
-        if (!GetSpeciesConstructor(cx, srcData, isWrapped, override, &bufferCtor))
-            return nullptr;
-
-        // Step 15-16, 18.b.
-        if (!AllocateArrayBuffer(cx, bufferCtor, elementLength, BYTES_PER_ELEMENT, &buffer))
-            return nullptr;
-
-        // Step 18.c.
-        if (srcArray->hasDetachedBuffer()) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-            return nullptr;
-        }
-    }
-
-    // Steps 3, 4 (remaining part), 19-22.
-    Rooted<TypedArrayObject*> obj(cx, makeInstance(cx, buffer, 0, elementLength, proto));
-    if (!obj)
-        return nullptr;
-
-    // Step 18.d-g or 24.1.1.4 step 11.
-    if (!TypedArrayMethods<TypedArrayObject>::setFromTypedArray(cx, obj, srcArray))
-        return nullptr;
-
-    // Step 23.
-    return obj;
-}
-
-static MOZ_ALWAYS_INLINE bool
-IsOptimizableInit(JSContext* cx, HandleObject iterable, bool* optimized)
-{
-    MOZ_ASSERT(!*optimized);
-
-    if (!IsPackedArray(iterable))
-        return true;
-
-    ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx);
-    if (!stubChain)
-        return false;
-
-    return stubChain->tryOptimizeArray(cx, iterable.as<ArrayObject>(), optimized);
-}
-
-// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e
-// 22.2.4.4 TypedArray ( object )
-template<typename T>
-/* static */ JSObject*
-TypedArrayObjectTemplate<T>::fromObject(JSContext* cx, HandleObject other, HandleObject newTarget)
-{
-    // Steps 1-2 (Already performed in caller).
-
-    // Steps 3-4 (Allocation deferred until later).
-    RootedObject proto(cx);
-    if (!GetPrototypeForInstance(cx, newTarget, &proto))
-        return nullptr;
-
-    bool optimized = false;
-    if (!IsOptimizableInit(cx, other, &optimized))
-        return nullptr;
-
-    // Fast path when iterable is a packed array using the default iterator.
-    if (optimized) {
-        // Step 6.a (We don't need to call IterableToList for the fast path).
-        RootedArrayObject array(cx, &other->as<ArrayObject>());
-
-        // Step 6.b.
-        uint32_t len = array->getDenseInitializedLength();
-
-        // Step 6.c.
-        Rooted<ArrayBufferObject*> buffer(cx);
-        if (!maybeCreateArrayBuffer(cx, len, BYTES_PER_ELEMENT, nullptr, &buffer))
-            return nullptr;
-
-        Rooted<TypedArrayObject*> obj(cx, makeInstance(cx, buffer, 0, len, proto));
-        if (!obj)
-            return nullptr;
-
-        // Steps 6.d-e.
-        if (!TypedArrayMethods<TypedArrayObject>::initFromIterablePackedArray(cx, obj, array))
-            return nullptr;
-
-        // Step 6.f (The assertion isn't applicable for the fast path).
-
-        // Step 6.g.
-        return obj;
-    }
-
-    // Step 5.
-    RootedValue callee(cx);
-    RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
-    if (!GetProperty(cx, other, other, iteratorId, &callee))
-        return nullptr;
-
-    // Steps 6-8.
-    RootedObject arrayLike(cx);
-    if (!callee.isNullOrUndefined()) {
-        // Throw if other[Symbol.iterator] isn't callable.
-        if (!callee.isObject() || !callee.toObject().isCallable()) {
-            RootedValue otherVal(cx, ObjectValue(*other));
-            UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, otherVal, nullptr);
-            if (!bytes)
-                return nullptr;
-            JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_ITERABLE,
-                                       bytes.get());
-            return nullptr;
-        }
-
-        FixedInvokeArgs<2> args2(cx);
-        args2[0].setObject(*other);
-        args2[1].set(callee);
-
-        // Step 6.a.
-        RootedValue rval(cx);
-        if (!CallSelfHostedFunction(cx, cx->names().IterableToList, UndefinedHandleValue, args2,
-                                    &rval))
-        {
-            return nullptr;
-        }
-
-        // Steps 6.b-g (Implemented in steps 9-13 below).
-        arrayLike = &rval.toObject();
-    } else {
-        // Step 7 is an assertion: object is not an Iterator. Testing this is
-        // literally the very last thing we did, so we don't assert here.
-
-        // Step 8.
-        arrayLike = other;
-    }
-
-    // Step 9.
-    uint32_t len;
-    if (!GetLengthProperty(cx, arrayLike, &len))
-        return nullptr;
-
-    // Step 10.
-    Rooted<ArrayBufferObject*> buffer(cx);
-    if (!maybeCreateArrayBuffer(cx, len, BYTES_PER_ELEMENT, nullptr, &buffer))
-        return nullptr;
-
-    Rooted<TypedArrayObject*> obj(cx, makeInstance(cx, buffer, 0, len, proto));
-    if (!obj)
-        return nullptr;
-
-    // Steps 11-12.
-    if (!TypedArrayMethods<TypedArrayObject>::setFromNonTypedArray(cx, obj, arrayLike, len))
-        return nullptr;
-
-    // Step 13.
-    return obj;
-}
-
-bool
-TypedArrayConstructor(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_CALL_OR_CONSTRUCT,
-                              args.isConstructing() ? "construct" : "call");
-    return false;
-}
-
-/* static */ bool
-TypedArrayObject::GetTemplateObjectForNative(JSContext* cx, Native native, uint32_t len,
-                                             MutableHandleObject res)
-{
-#define CHECK_TYPED_ARRAY_CONSTRUCTOR(T, N) \
-    if (native == &TypedArrayObjectTemplate<T>::class_constructor) { \
-        size_t nbytes; \
-        if (!js::CalculateAllocSize<T>(len, &nbytes)) \
-            return true; \
-        \
-        if (nbytes < TypedArrayObject::SINGLETON_BYTE_LENGTH) { \
-            res.set(TypedArrayObjectTemplate<T>::makeTemplateObject(cx, len)); \
-            return !!res; \
-        } \
-    }
-JS_FOR_EACH_TYPED_ARRAY(CHECK_TYPED_ARRAY_CONSTRUCTOR)
-#undef CHECK_TYPED_ARRAY_CONSTRUCTOR
-    return true;
-}
-
-/*
- * These next 3 functions are brought to you by the buggy GCC we use to build
- * B2G ICS. Older GCC versions have a bug in which they fail to compile
- * reinterpret_casts of templated functions with the message: "insufficient
- * contextual information to determine type". JS_PSG needs to
- * reinterpret_cast<JSGetterOp>, so this causes problems for us here.
- *
- * We could restructure all this code to make this nicer, but since ICS isn't
- * going to be around forever (and since this bug is fixed with the newer GCC
- * versions we use on JB and KK), the workaround here is designed for ease of
- * removal. When you stop seeing ICS Emulator builds on TBPL, remove these 3
- * JSNatives and insert the templated callee directly into the JS_PSG below.
- */
-static bool
-TypedArray_lengthGetter(JSContext* cx, unsigned argc, Value* vp)
-{
-    return TypedArrayObject::Getter<TypedArrayObject::lengthValue>(cx, argc, vp); \
-}
-
-static bool
-TypedArray_byteLengthGetter(JSContext* cx, unsigned argc, Value* vp)
-{
-    return TypedArrayObject::Getter<TypedArrayObject::byteLengthValue>(cx, argc, vp);
-}
-
-static bool
-TypedArray_byteOffsetGetter(JSContext* cx, unsigned argc, Value* vp)
-{
-    return TypedArrayObject::Getter<TypedArrayObject::byteOffsetValue>(cx, argc, vp);
-}
-
-bool
-BufferGetterImpl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(TypedArrayObject::is(args.thisv()));
-    Rooted<TypedArrayObject*> tarray(cx, &args.thisv().toObject().as<TypedArrayObject>());
-    if (!TypedArrayObject::ensureHasBuffer(cx, tarray))
-        return false;
-    args.rval().set(TypedArrayObject::bufferValue(tarray));
-    return true;
-}
-
-/*static*/ bool
-js::TypedArray_bufferGetter(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<TypedArrayObject::is, BufferGetterImpl>(cx, args);
-}
-
-/* static */ const JSPropertySpec
-TypedArrayObject::protoAccessors[] = {
-    JS_PSG("length", TypedArray_lengthGetter, 0),
-    JS_PSG("buffer", TypedArray_bufferGetter, 0),
-    JS_PSG("byteLength", TypedArray_byteLengthGetter, 0),
-    JS_PSG("byteOffset", TypedArray_byteOffsetGetter, 0),
-    JS_SELF_HOSTED_SYM_GET(toStringTag, "TypedArrayToStringTag", 0),
-    JS_PS_END
-};
-
-/* static */ bool
-TypedArrayObject::set(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<TypedArrayObject::is,
-                                TypedArrayMethods<TypedArrayObject>::set>(cx, args);
-}
-
-/* static */ const JSFunctionSpec
-TypedArrayObject::protoFunctions[] = {
-    JS_SELF_HOSTED_FN("subarray", "TypedArraySubarray", 2, 0),
-#if 0 /* disabled until perf-testing is completed */
-    JS_SELF_HOSTED_FN("set", "TypedArraySet", 2, 0),
-#else
-    JS_FN("set", TypedArrayObject::set, 1, 0),
-#endif
-    JS_SELF_HOSTED_FN("copyWithin", "TypedArrayCopyWithin", 3, 0),
-    JS_SELF_HOSTED_FN("every", "TypedArrayEvery", 1, 0),
-    JS_SELF_HOSTED_FN("fill", "TypedArrayFill", 3, 0),
-    JS_SELF_HOSTED_FN("filter", "TypedArrayFilter", 1, 0),
-    JS_SELF_HOSTED_FN("find", "TypedArrayFind", 1, 0),
-    JS_SELF_HOSTED_FN("findIndex", "TypedArrayFindIndex", 1, 0),
-    JS_SELF_HOSTED_FN("forEach", "TypedArrayForEach", 1, 0),
-    JS_SELF_HOSTED_FN("indexOf", "TypedArrayIndexOf", 2, 0),
-    JS_SELF_HOSTED_FN("join", "TypedArrayJoin", 1, 0),
-    JS_SELF_HOSTED_FN("lastIndexOf", "TypedArrayLastIndexOf", 1, 0),
-    JS_SELF_HOSTED_FN("map", "TypedArrayMap", 1, 0),
-    JS_SELF_HOSTED_FN("reduce", "TypedArrayReduce", 1, 0),
-    JS_SELF_HOSTED_FN("reduceRight", "TypedArrayReduceRight", 1, 0),
-    JS_SELF_HOSTED_FN("reverse", "TypedArrayReverse", 0, 0),
-    JS_SELF_HOSTED_FN("slice", "TypedArraySlice", 2, 0),
-    JS_SELF_HOSTED_FN("some", "TypedArraySome", 1, 0),
-    JS_SELF_HOSTED_FN("sort", "TypedArraySort", 1, 0),
-    JS_SELF_HOSTED_FN("entries", "TypedArrayEntries", 0, 0),
-    JS_SELF_HOSTED_FN("keys", "TypedArrayKeys", 0, 0),
-    JS_SELF_HOSTED_FN("values", "TypedArrayValues", 0, 0),
-    JS_SELF_HOSTED_SYM_FN(iterator, "TypedArrayValues", 0, 0),
-    JS_SELF_HOSTED_FN("includes", "TypedArrayIncludes", 2, 0),
-    JS_SELF_HOSTED_FN("toString", "ArrayToString", 0, 0),
-    JS_SELF_HOSTED_FN("toLocaleString", "TypedArrayToLocaleString", 2, 0),
-    JS_FS_END
-};
-
-/* static */ const JSFunctionSpec
-TypedArrayObject::staticFunctions[] = {
-    JS_SELF_HOSTED_FN("from", "TypedArrayStaticFrom", 3, 0),
-    JS_SELF_HOSTED_FN("of", "TypedArrayStaticOf", 0, 0),
-    JS_FS_END
-};
-
-/* static */ const JSPropertySpec
-TypedArrayObject::staticProperties[] = {
-    JS_SELF_HOSTED_SYM_GET(species, "TypedArraySpecies", 0),
-    JS_PS_END
-};
-
-static const ClassSpec
-TypedArrayObjectSharedTypedArrayPrototypeClassSpec = {
-    GenericCreateConstructor<TypedArrayConstructor, 0, gc::AllocKind::FUNCTION>,
-    GenericCreatePrototype,
-    TypedArrayObject::staticFunctions,
-    TypedArrayObject::staticProperties,
-    TypedArrayObject::protoFunctions,
-    TypedArrayObject::protoAccessors,
-    nullptr,
-    ClassSpec::DontDefineConstructor
-};
-
-/* static */ const Class
-TypedArrayObject::sharedTypedArrayPrototypeClass = {
-    // Actually ({}).toString.call(%TypedArray%.prototype) should throw,
-    // because %TypedArray%.prototype lacks the the typed array internal
-    // slots.  (It's not clear this is desirable -- particularly applied to
-    // the actual typed array prototypes, see below -- but it's what ES6
-    // draft 20140824 requires.)  But this is about as much as we can do
-    // until we implement @@toStringTag.
-    "???",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_TypedArray),
-    JS_NULL_CLASS_OPS,
-    &TypedArrayObjectSharedTypedArrayPrototypeClassSpec
-};
-
-template<typename T>
-bool
-ArrayBufferObject::createTypedArrayFromBufferImpl(JSContext* cx, const CallArgs& args)
-{
-    typedef TypedArrayObjectTemplate<T> ArrayType;
-    MOZ_ASSERT(IsAnyArrayBuffer(args.thisv()));
-    MOZ_ASSERT(args.length() == 3);
-
-    Rooted<JSObject*> buffer(cx, &args.thisv().toObject());
-    Rooted<JSObject*> proto(cx, &args[2].toObject());
-
-    Rooted<JSObject*> obj(cx);
-    double byteOffset = args[0].toNumber();
-    MOZ_ASSERT(0 <= byteOffset);
-    MOZ_ASSERT(byteOffset <= UINT32_MAX);
-    MOZ_ASSERT(byteOffset == uint32_t(byteOffset));
-    obj = ArrayType::fromBufferWithProto(cx, buffer, uint32_t(byteOffset), args[1].toInt32(),
-                                         proto);
-    if (!obj)
-        return false;
-    args.rval().setObject(*obj);
-    return true;
-}
-
-template<typename T>
-bool
-ArrayBufferObject::createTypedArrayFromBuffer(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<IsAnyArrayBuffer, createTypedArrayFromBufferImpl<T> >(cx, args);
-}
-
-// this default implementation is only valid for integer types
-// less than 32-bits in size.
-template<typename NativeType>
-Value
-TypedArrayObjectTemplate<NativeType>::getIndexValue(JSObject* tarray, uint32_t index)
-{
-    static_assert(sizeof(NativeType) < 4,
-                  "this method must only handle NativeType values that are "
-                  "always exact int32_t values");
-
-    return Int32Value(getIndex(tarray, index));
-}
-
-namespace {
-
-// and we need to specialize for 32-bit integers and floats
-template<>
-Value
-TypedArrayObjectTemplate<int32_t>::getIndexValue(JSObject* tarray, uint32_t index)
-{
-    return Int32Value(getIndex(tarray, index));
-}
-
-template<>
-Value
-TypedArrayObjectTemplate<uint32_t>::getIndexValue(JSObject* tarray, uint32_t index)
-{
-    uint32_t val = getIndex(tarray, index);
-    return NumberValue(val);
-}
-
-template<>
-Value
-TypedArrayObjectTemplate<float>::getIndexValue(JSObject* tarray, uint32_t index)
-{
-    float val = getIndex(tarray, index);
-    double dval = val;
-
-    /*
-     * Doubles in typed arrays could be typed-punned arrays of integers. This
-     * could allow user code to break the engine-wide invariant that only
-     * canonical nans are stored into jsvals, which means user code could
-     * confuse the engine into interpreting a double-typed jsval as an
-     * object-typed jsval.
-     *
-     * This could be removed for platforms/compilers known to convert a 32-bit
-     * non-canonical nan to a 64-bit canonical nan.
-     */
-    return DoubleValue(CanonicalizeNaN(dval));
-}
-
-template<>
-Value
-TypedArrayObjectTemplate<double>::getIndexValue(JSObject* tarray, uint32_t index)
-{
-    double val = getIndex(tarray, index);
-
-    /*
-     * Doubles in typed arrays could be typed-punned arrays of integers. This
-     * could allow user code to break the engine-wide invariant that only
-     * canonical nans are stored into jsvals, which means user code could
-     * confuse the engine into interpreting a double-typed jsval as an
-     * object-typed jsval.
-     */
-    return DoubleValue(CanonicalizeNaN(val));
-}
-
-} /* anonymous namespace */
-
 static NewObjectKind
 DataViewNewObjectKind(JSContext* cx, uint32_t byteLength, JSObject* proto)
 {
     if (!proto && byteLength >= TypedArrayObject::SINGLETON_BYTE_LENGTH)
         return SingletonObject;
     jsbytecode* pc;
     JSScript* script = cx->currentScript(&pc);
     if (script && ObjectGroup::useSingletonForAllocationSite(script, pc, &DataViewObject::class_))
@@ -2517,313 +877,16 @@ DataViewObject::setFloat64Impl(JSContext
 
 bool
 DataViewObject::fun_setFloat64(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<is, setFloat64Impl>(cx, args);
 }
 
-Value
-TypedArrayObject::getElement(uint32_t index)
-{
-    switch (type()) {
-      case Scalar::Int8:
-        return Int8Array::getIndexValue(this, index);
-      case Scalar::Uint8:
-        return Uint8Array::getIndexValue(this, index);
-      case Scalar::Int16:
-        return Int16Array::getIndexValue(this, index);
-      case Scalar::Uint16:
-        return Uint16Array::getIndexValue(this, index);
-      case Scalar::Int32:
-        return Int32Array::getIndexValue(this, index);
-      case Scalar::Uint32:
-        return Uint32Array::getIndexValue(this, index);
-      case Scalar::Float32:
-        return Float32Array::getIndexValue(this, index);
-      case Scalar::Float64:
-        return Float64Array::getIndexValue(this, index);
-      case Scalar::Uint8Clamped:
-        return Uint8ClampedArray::getIndexValue(this, index);
-      case Scalar::Int64:
-      case Scalar::Float32x4:
-      case Scalar::Int8x16:
-      case Scalar::Int16x8:
-      case Scalar::Int32x4:
-      case Scalar::MaxTypedArrayViewType:
-        break;
-    }
-
-    MOZ_CRASH("Unknown TypedArray type");
-}
-
-void
-TypedArrayObject::setElement(TypedArrayObject& obj, uint32_t index, double d)
-{
-    MOZ_ASSERT(index < obj.length());
-
-#ifdef JS_MORE_DETERMINISTIC
-    // See the comment in ElementSpecific::doubleToNative.
-    d = JS::CanonicalizeNaN(d);
-#endif
-
-    switch (obj.type()) {
-      case Scalar::Int8:
-        Int8Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Uint8:
-        Uint8Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Uint8Clamped:
-        Uint8ClampedArray::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Int16:
-        Int16Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Uint16:
-        Uint16Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Int32:
-        Int32Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Uint32:
-        Uint32Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Float32:
-        Float32Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Float64:
-        Float64Array::setIndexValue(obj, index, d);
-        return;
-      case Scalar::Int64:
-      case Scalar::Float32x4:
-      case Scalar::Int8x16:
-      case Scalar::Int16x8:
-      case Scalar::Int32x4:
-      case Scalar::MaxTypedArrayViewType:
-        break;
-    }
-
-    MOZ_CRASH("Unknown TypedArray type");
-}
-
-/***
- *** JS impl
- ***/
-
-/*
- * TypedArrayObject boilerplate
- */
-
-#define IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Name,NativeType)                                    \
-  JS_FRIEND_API(JSObject*) JS_New ## Name ## Array(JSContext* cx, uint32_t nelements)           \
-  {                                                                                             \
-      return TypedArrayObjectTemplate<NativeType>::fromLength(cx, nelements);                   \
-  }                                                                                             \
-  JS_FRIEND_API(JSObject*) JS_New ## Name ## ArrayFromArray(JSContext* cx, HandleObject other)  \
-  {                                                                                             \
-      return TypedArrayObjectTemplate<NativeType>::fromArray(cx, other);                        \
-  }                                                                                             \
-  JS_FRIEND_API(JSObject*) JS_New ## Name ## ArrayWithBuffer(JSContext* cx,                     \
-                               HandleObject arrayBuffer, uint32_t byteOffset, int32_t length)   \
-  {                                                                                             \
-      return TypedArrayObjectTemplate<NativeType>::fromBuffer(cx, arrayBuffer, byteOffset,      \
-                                                              length);                          \
-  }                                                                                             \
-  JS_FRIEND_API(bool) JS_Is ## Name ## Array(JSObject* obj)                                     \
-  {                                                                                             \
-      if (!(obj = CheckedUnwrap(obj)))                                                          \
-          return false;                                                                         \
-      const Class* clasp = obj->getClass();                                                     \
-      return clasp == TypedArrayObjectTemplate<NativeType>::instanceClass();                    \
-  }                                                                                             \
-  JS_FRIEND_API(JSObject*) js::Unwrap ## Name ## Array(JSObject* obj)                           \
-  {                                                                                             \
-      obj = CheckedUnwrap(obj);                                                                 \
-      if (!obj)                                                                                 \
-          return nullptr;                                                                       \
-      const Class* clasp = obj->getClass();                                                     \
-      if (clasp == TypedArrayObjectTemplate<NativeType>::instanceClass())                       \
-          return obj;                                                                           \
-      return nullptr;                                                                           \
-  }                                                                                             \
-  const js::Class* const js::detail::Name ## ArrayClassPtr =                                    \
-      &js::TypedArrayObject::classes[TypedArrayObjectTemplate<NativeType>::ArrayTypeID()];
-
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint8, uint8_t)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint8Clamped, uint8_clamped)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int16, int16_t)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint16, uint16_t)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int32, int32_t)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint32, uint32_t)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float32, float)
-IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double)
-
-#define IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Name, ExternalType, InternalType)              \
-  JS_FRIEND_API(JSObject*) JS_GetObjectAs ## Name ## Array(JSObject* obj,                  \
-                                                            uint32_t* length,               \
-                                                            bool* isShared,                 \
-                                                            ExternalType** data)            \
-  {                                                                                         \
-      if (!(obj = CheckedUnwrap(obj)))                                                      \
-          return nullptr;                                                                   \
-                                                                                            \
-      const Class* clasp = obj->getClass();                                                 \
-      if (clasp != TypedArrayObjectTemplate<InternalType>::instanceClass())                 \
-          return nullptr;                                                                   \
-                                                                                            \
-      TypedArrayObject* tarr = &obj->as<TypedArrayObject>();                                \
-      *length = tarr->length();                                                             \
-      *isShared = tarr->isSharedMemory();                                                         \
-      *data = static_cast<ExternalType*>(tarr->viewDataEither().unwrap(/*safe - caller sees isShared flag*/)); \
-                                                                                            \
-      return obj;                                                                           \
-  }
-
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int8, int8_t, int8_t)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint8, uint8_t, uint8_t)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint8Clamped, uint8_t, uint8_clamped)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int16, int16_t, int16_t)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint16, uint16_t, uint16_t)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int32, int32_t, int32_t)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint32, uint32_t, uint32_t)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float32, float, float)
-IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
-
-static const ClassOps TypedArrayClassOps = {
-    nullptr,                 /* addProperty */
-    nullptr,                 /* delProperty */
-    nullptr,                 /* getProperty */
-    nullptr,                 /* setProperty */
-    nullptr,                 /* enumerate   */
-    nullptr,                 /* resolve     */
-    nullptr,                 /* mayResolve  */
-    TypedArrayObject::finalize, /* finalize    */
-    nullptr,                 /* call        */
-    nullptr,                 /* hasInstance */
-    nullptr,                 /* construct   */
-    TypedArrayObject::trace, /* trace  */
-};
-
-static const ClassExtension TypedArrayClassExtension = {
-    nullptr,
-    TypedArrayObject::objectMoved,
-};
-
-#define IMPL_TYPED_ARRAY_PROPERTIES(_type)                                     \
-{                                                                              \
-JS_INT32_PS("BYTES_PER_ELEMENT", _type##Array::BYTES_PER_ELEMENT,              \
-            JSPROP_READONLY | JSPROP_PERMANENT),                               \
-JS_PS_END                                                                      \
-}
-
-static const JSPropertySpec static_prototype_properties[Scalar::MaxTypedArrayViewType][2] = {
-    IMPL_TYPED_ARRAY_PROPERTIES(Int8),
-    IMPL_TYPED_ARRAY_PROPERTIES(Uint8),
-    IMPL_TYPED_ARRAY_PROPERTIES(Int16),
-    IMPL_TYPED_ARRAY_PROPERTIES(Uint16),
-    IMPL_TYPED_ARRAY_PROPERTIES(Int32),
-    IMPL_TYPED_ARRAY_PROPERTIES(Uint32),
-    IMPL_TYPED_ARRAY_PROPERTIES(Float32),
-    IMPL_TYPED_ARRAY_PROPERTIES(Float64),
-    IMPL_TYPED_ARRAY_PROPERTIES(Uint8Clamped)
-};
-
-#define IMPL_TYPED_ARRAY_CLASS_SPEC(_type)                                     \
-{                                                                              \
-    _type##Array::createConstructor,                                           \
-    _type##Array::createPrototype,                                             \
-    nullptr,                                                                   \
-    static_prototype_properties[Scalar::Type::_type],                          \
-    nullptr,                                                                   \
-    static_prototype_properties[Scalar::Type::_type],                          \
-    nullptr,                                                                   \
-    JSProto_TypedArray                                                         \
-}
-
-static const ClassSpec TypedArrayObjectClassSpecs[Scalar::MaxTypedArrayViewType] = {
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Int8),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Uint8),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Int16),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Uint16),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Int32),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Uint32),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Float32),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Float64),
-    IMPL_TYPED_ARRAY_CLASS_SPEC(Uint8Clamped)
-};
-
-#define IMPL_TYPED_ARRAY_CLASS(_type)                                          \
-{                                                                              \
-    #_type "Array",                                                            \
-    JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) |             \
-    JSCLASS_HAS_PRIVATE |                                                      \
-    JSCLASS_HAS_CACHED_PROTO(JSProto_##_type##Array) |                         \
-    JSCLASS_DELAY_METADATA_BUILDER |                                           \
-    JSCLASS_SKIP_NURSERY_FINALIZE |                                            \
-    JSCLASS_BACKGROUND_FINALIZE,                                               \
-    &TypedArrayClassOps,                                                       \
-    &TypedArrayObjectClassSpecs[Scalar::Type::_type],                          \
-    &TypedArrayClassExtension                                                  \
-}
-
-const Class TypedArrayObject::classes[Scalar::MaxTypedArrayViewType] = {
-    IMPL_TYPED_ARRAY_CLASS(Int8),
-    IMPL_TYPED_ARRAY_CLASS(Uint8),
-    IMPL_TYPED_ARRAY_CLASS(Int16),
-    IMPL_TYPED_ARRAY_CLASS(Uint16),
-    IMPL_TYPED_ARRAY_CLASS(Int32),
-    IMPL_TYPED_ARRAY_CLASS(Uint32),
-    IMPL_TYPED_ARRAY_CLASS(Float32),
-    IMPL_TYPED_ARRAY_CLASS(Float64),
-    IMPL_TYPED_ARRAY_CLASS(Uint8Clamped)
-};
-
-// The various typed array prototypes are supposed to 1) be normal objects,
-// 2) stringify to "[object <name of constructor>]", and 3) (Gecko-specific)
-// be xrayable.  The first and second requirements mandate (in the absence of
-// @@toStringTag) a custom class.  The third requirement mandates that each
-// prototype's class have the relevant typed array's cached JSProtoKey in them.
-// Thus we need one class with cached prototype per kind of typed array, with a
-// delegated ClassSpec.
-#define IMPL_TYPED_ARRAY_PROTO_CLASS(_type) \
-{ \
-    /*
-     * Actually ({}).toString.call(Uint8Array.prototype) should throw, because
-     * Uint8Array.prototype lacks the the typed array internal slots.  (Same as
-     * with %TypedArray%.prototype.)  It's not clear this is desirable (see
-     * above), but it's what we've always done, so keep doing it till we
-     * implement @@toStringTag or ES6 changes.
-     */ \
-    #_type "ArrayPrototype", \
-    JSCLASS_HAS_CACHED_PROTO(JSProto_##_type##Array), \
-    JS_NULL_CLASS_OPS, \
-    &TypedArrayObjectClassSpecs[Scalar::Type::_type] \
-}
-
-const Class TypedArrayObject::protoClasses[Scalar::MaxTypedArrayViewType] = {
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Int8),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Uint8),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Int16),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Uint16),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Int32),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Uint32),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Float32),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Float64),
-    IMPL_TYPED_ARRAY_PROTO_CLASS(Uint8Clamped)
-};
-
-/* static */ bool
-TypedArrayObject::isOriginalLengthGetter(Native native)
-{
-    return native == TypedArray_lengthGetter;
-}
-
 const Class DataViewObject::protoClass = {
     "DataViewPrototype",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_DataView)
 };
 
 static const ClassOps DataViewObjectClassOps = {
@@ -2954,322 +1017,16 @@ DataViewObject::notifyBufferDetached(voi
 JSObject*
 js::InitDataViewClass(JSContext* cx, HandleObject obj)
 {
     if (!DataViewObject::initClass(cx))
         return nullptr;
     return &cx->global()->getPrototype(JSProto_DataView).toObject();
 }
 
-bool
-js::IsTypedArrayConstructor(HandleValue v, uint32_t type)
-{
-    switch (type) {
-      case Scalar::Int8:
-        return IsNativeFunction(v, Int8Array::class_constructor);
-      case Scalar::Uint8:
-        return IsNativeFunction(v, Uint8Array::class_constructor);
-      case Scalar::Int16:
-        return IsNativeFunction(v, Int16Array::class_constructor);
-      case Scalar::Uint16:
-        return IsNativeFunction(v, Uint16Array::class_constructor);
-      case Scalar::Int32:
-        return IsNativeFunction(v, Int32Array::class_constructor);
-      case Scalar::Uint32:
-        return IsNativeFunction(v, Uint32Array::class_constructor);
-      case Scalar::Float32:
-        return IsNativeFunction(v, Float32Array::class_constructor);
-      case Scalar::Float64:
-        return IsNativeFunction(v, Float64Array::class_constructor);
-      case Scalar::Uint8Clamped:
-        return IsNativeFunction(v, Uint8ClampedArray::class_constructor);
-      case Scalar::MaxTypedArrayViewType:
-        break;
-    }
-    MOZ_CRASH("unexpected typed array type");
-}
-
-template <typename CharT>
-bool
-js::StringIsTypedArrayIndex(const CharT* s, size_t length, uint64_t* indexp)
-{
-    const CharT* end = s + length;
-
-    if (s == end)
-        return false;
-
-    bool negative = false;
-    if (*s == '-') {
-        negative = true;
-        if (++s == end)
-            return false;
-    }
-
-    if (!JS7_ISDEC(*s))
-        return false;
-
-    uint64_t index = 0;
-    uint32_t digit = JS7_UNDEC(*s++);
-
-    /* Don't allow leading zeros. */
-    if (digit == 0 && s != end)
-        return false;
-
-    index = digit;
-
-    for (; s < end; s++) {
-        if (!JS7_ISDEC(*s))
-            return false;
-
-        digit = JS7_UNDEC(*s);
-
-        /* Watch for overflows. */
-        if ((UINT64_MAX - digit) / 10 < index)
-            index = UINT64_MAX;
-        else
-            index = 10 * index + digit;
-    }
-
-    if (negative)
-        *indexp = UINT64_MAX;
-    else
-        *indexp = index;
-    return true;
-}
-
-template bool
-js::StringIsTypedArrayIndex(const char16_t* s, size_t length, uint64_t* indexp);
-
-template bool
-js::StringIsTypedArrayIndex(const Latin1Char* s, size_t length, uint64_t* indexp);
-
-/* ES6 draft rev 34 (2015 Feb 20) 9.4.5.3 [[DefineOwnProperty]] step 3.c. */
-bool
-js::DefineTypedArrayElement(JSContext* cx, HandleObject obj, uint64_t index,
-                            Handle<PropertyDescriptor> desc, ObjectOpResult& result)
-{
-    MOZ_ASSERT(obj->is<TypedArrayObject>());
-
-    // These are all substeps of 3.b.
-
-    // Steps i-iii are handled by the caller.
-
-    // Steps iv-v.
-    // We (wrongly) ignore out of range defines with a value.
-    uint32_t length = obj->as<TypedArrayObject>().length();
-    if (index >= length)
-        return result.succeed();
-
-    // Step vi.
-    if (desc.isAccessorDescriptor())
-        return result.fail(JSMSG_CANT_REDEFINE_PROP);
-
-    // Step vii.
-    if (desc.hasConfigurable() && desc.configurable())
-        return result.fail(JSMSG_CANT_REDEFINE_PROP);
-
-    // Step viii.
-    if (desc.hasEnumerable() && !desc.enumerable())
-        return result.fail(JSMSG_CANT_REDEFINE_PROP);
-
-    // Step ix.
-    if (desc.hasWritable() && !desc.writable())
-        return result.fail(JSMSG_CANT_REDEFINE_PROP);
-
-    // Step x.
-    if (desc.hasValue()) {
-        // The following step numbers refer to 9.4.5.9
-        // IntegerIndexedElementSet.
-
-        // Steps 1-2 are enforced by the caller.
-
-        // Step 3.
-        double numValue;
-        if (!ToNumber(cx, desc.value(), &numValue))
-            return false;
-
-        // Steps 4-5, 8-9.
-        if (obj->as<TypedArrayObject>().hasDetachedBuffer())
-            return result.fail(JSMSG_TYPED_ARRAY_DETACHED);
-
-        // Steps 10-16.
-        TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, numValue);
-    }
-
-    // Step xii.
-    return result.succeed();
-}
-
-/* JS Friend API */
-
-JS_FRIEND_API(bool)
-JS_IsTypedArrayObject(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    return obj ? obj->is<TypedArrayObject>() : false;
-}
-
-JS_FRIEND_API(uint32_t)
-JS_GetTypedArrayLength(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return 0;
-    return obj->as<TypedArrayObject>().length();
-}
-
-JS_FRIEND_API(uint32_t)
-JS_GetTypedArrayByteOffset(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return 0;
-    return obj->as<TypedArrayObject>().byteOffset();
-}
-
-JS_FRIEND_API(uint32_t)
-JS_GetTypedArrayByteLength(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return 0;
-    return obj->as<TypedArrayObject>().byteLength();
-}
-
-JS_FRIEND_API(bool)
-JS_GetTypedArraySharedness(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return false;
-    return obj->as<TypedArrayObject>().isSharedMemory();
-}
-
-JS_FRIEND_API(js::Scalar::Type)
-JS_GetArrayBufferViewType(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return Scalar::MaxTypedArrayViewType;
-
-    if (obj->is<TypedArrayObject>())
-        return obj->as<TypedArrayObject>().type();
-    if (obj->is<DataViewObject>())
-        return Scalar::MaxTypedArrayViewType;
-    MOZ_CRASH("invalid ArrayBufferView type");
-}
-
-JS_FRIEND_API(int8_t*)
-JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Int8);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<int8_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isShared*/));
-}
-
-JS_FRIEND_API(uint8_t*)
-JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint8);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<uint8_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(uint8_t*)
-JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint8Clamped);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<uint8_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(int16_t*)
-JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Int16);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<int16_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(uint16_t*)
-JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint16);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<uint16_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(int32_t*)
-JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Int32);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<int32_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(uint32_t*)
-JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Uint32);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<uint32_t*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(float*)
-JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Float32);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<float*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(double*)
-JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
-    MOZ_ASSERT((int32_t) tarr->type() == Scalar::Float64);
-    *isSharedMemory = tarr->isSharedMemory();
-    return static_cast<double*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
 JS_FRIEND_API(bool)
 JS_IsDataViewObject(JSObject* obj)
 {
     obj = CheckedUnwrap(obj);
     return obj ? obj->is<DataViewObject>() : false;
 }
 
 JS_FRIEND_API(uint32_t)
copy from js/src/vm/TypedArrayObject.h
copy to js/src/builtin/DataViewObject.h
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/builtin/DataViewObject.h
@@ -1,439 +1,29 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef vm_TypedArrayObject_h
-#define vm_TypedArrayObject_h
+#ifndef vm_DataViewObject_h
+#define vm_DataViewObject_h
 
 #include "mozilla/Attributes.h"
 
 #include "jsobj.h"
 
 #include "gc/Barrier.h"
 #include "js/Class.h"
 #include "vm/ArrayBufferObject.h"
 #include "vm/SharedArrayObject.h"
-
-#define JS_FOR_EACH_TYPED_ARRAY(macro) \
-    macro(int8_t, Int8) \
-    macro(uint8_t, Uint8) \
-    macro(int16_t, Int16) \
-    macro(uint16_t, Uint16) \
-    macro(int32_t, Int32) \
-    macro(uint32_t, Uint32) \
-    macro(float, Float32) \
-    macro(double, Float64) \
-    macro(uint8_clamped, Uint8Clamped)
-
-typedef struct JSProperty JSProperty;
+#include "vm/TypedArrayObject.h"
 
 namespace js {
 
-enum class TypedArrayLength { Fixed, Dynamic };
-
-/*
- * TypedArrayObject
- *
- * The non-templated base class for the specific typed implementations.
- * This class holds all the member variables that are used by
- * the subclasses.
- */
-
-class TypedArrayObject : public NativeObject
-{
-  public:
-    // Underlying (Shared)ArrayBufferObject.
-    static const size_t BUFFER_SLOT = 0;
-    static_assert(BUFFER_SLOT == JS_TYPEDARRAYLAYOUT_BUFFER_SLOT,
-                  "self-hosted code with burned-in constants must get the "
-                  "right buffer slot");
-
-    // Slot containing length of the view in number of typed elements.
-    static const size_t LENGTH_SLOT = 1;
-    static_assert(LENGTH_SLOT == JS_TYPEDARRAYLAYOUT_LENGTH_SLOT,
-                  "self-hosted code with burned-in constants must get the "
-                  "right length slot");
-
-    // Offset of view within underlying (Shared)ArrayBufferObject.
-    static const size_t BYTEOFFSET_SLOT = 2;
-    static_assert(BYTEOFFSET_SLOT == JS_TYPEDARRAYLAYOUT_BYTEOFFSET_SLOT,
-                  "self-hosted code with burned-in constants must get the "
-                  "right byteOffset slot");
-
-    static const size_t RESERVED_SLOTS = 3;
-
-#ifdef DEBUG
-    static const uint8_t ZeroLengthArrayData = 0x4A;
-#endif
-
-    static int lengthOffset();
-    static int dataOffset();
-
-    // The raw pointer to the buffer memory, the "private" value.
-    //
-    // This offset is exposed for performance reasons - so that it
-    // need not be looked up on accesses.
-    static const size_t DATA_SLOT = 3;
-
-    static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
-                  "bad inlined constant in jsfriendapi.h");
-
-    typedef TypedArrayObject SomeTypedArray;
-    typedef ArrayBufferObject BufferType;
-
-    template<typename T> struct OfType;
-
-    static bool sameBuffer(Handle<TypedArrayObject*> a, Handle<TypedArrayObject*> b) {
-        // Inline buffers.
-        if (!a->hasBuffer() || !b->hasBuffer())
-            return a.get() == b.get();
-
-        // Shared buffers.
-        if (a->isSharedMemory() && b->isSharedMemory()) {
-            return (a->bufferObject()->as<SharedArrayBufferObject>().globalID() ==
-                    b->bufferObject()->as<SharedArrayBufferObject>().globalID());
-        }
-
-        return a->bufferObject() == b->bufferObject();
-    }
-
-    static const Class classes[Scalar::MaxTypedArrayViewType];
-    static const Class protoClasses[Scalar::MaxTypedArrayViewType];
-    static const Class sharedTypedArrayPrototypeClass;
-
-    static const Class* classForType(Scalar::Type type) {
-        MOZ_ASSERT(type < Scalar::MaxTypedArrayViewType);
-        return &classes[type];
-    }
-
-    static const Class* protoClassForType(Scalar::Type type) {
-        MOZ_ASSERT(type < Scalar::MaxTypedArrayViewType);
-        return &protoClasses[type];
-    }
-
-    static const size_t FIXED_DATA_START = DATA_SLOT + 1;
-
-    // For typed arrays which can store their data inline, the array buffer
-    // object is created lazily.
-    static const uint32_t INLINE_BUFFER_LIMIT =
-        (NativeObject::MAX_FIXED_SLOTS - FIXED_DATA_START) * sizeof(Value);
-
-    static gc::AllocKind
-    AllocKindForLazyBuffer(size_t nbytes)
-    {
-        MOZ_ASSERT(nbytes <= INLINE_BUFFER_LIMIT);
-        if (nbytes == 0)
-            nbytes += sizeof(uint8_t);
-        size_t dataSlots = AlignBytes(nbytes, sizeof(Value)) / sizeof(Value);
-        MOZ_ASSERT(nbytes <= dataSlots * sizeof(Value));
-        return gc::GetGCObjectKind(FIXED_DATA_START + dataSlots);
-    }
-
-    inline Scalar::Type type() const;
-    inline size_t bytesPerElement() const;
-
-    static Value bufferValue(TypedArrayObject* tarr) {
-        return tarr->getFixedSlot(BUFFER_SLOT);
-    }
-    static Value byteOffsetValue(TypedArrayObject* tarr) {
-        Value v = tarr->getFixedSlot(BYTEOFFSET_SLOT);
-        MOZ_ASSERT(v.toInt32() >= 0);
-        return v;
-    }
-    static Value byteLengthValue(TypedArrayObject* tarr) {
-        return Int32Value(tarr->getFixedSlot(LENGTH_SLOT).toInt32() * tarr->bytesPerElement());
-    }
-    static Value lengthValue(TypedArrayObject* tarr) {
-        return tarr->getFixedSlot(LENGTH_SLOT);
-    }
-
-    static bool
-    ensureHasBuffer(JSContext* cx, Handle<TypedArrayObject*> tarray);
-
-    bool hasBuffer() const {
-        return bufferValue(const_cast<TypedArrayObject*>(this)).isObject();
-    }
-    JSObject* bufferObject() const {
-        return bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull();
-    }
-    uint32_t byteOffset() const {
-        return byteOffsetValue(const_cast<TypedArrayObject*>(this)).toInt32();
-    }
-    uint32_t byteLength() const {
-        return byteLengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
-    }
-    uint32_t length() const {
-        return lengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
-    }
-
-    bool hasInlineElements() const;
-    void setInlineElements();
-    uint8_t* elementsRaw() const {
-        return *(uint8_t **)((((char *)this) + this->dataOffset()));
-    }
-    uint8_t* elements() const {
-        assertZeroLengthArrayData();
-        return elementsRaw();
-    }
-
-#ifdef DEBUG
-    void assertZeroLengthArrayData() const;
-#else
-    void assertZeroLengthArrayData() const {};
-#endif
-
-    Value getElement(uint32_t index);
-    static void setElement(TypedArrayObject& obj, uint32_t index, double d);
-
-    void notifyBufferDetached(JSContext* cx, void* newData);
-
-    static bool
-    GetTemplateObjectForNative(JSContext* cx, Native native, uint32_t len,
-                               MutableHandleObject res);
-
-    /*
-     * Byte length above which created typed arrays and data views will have
-     * singleton types regardless of the context in which they are created.
-     */
-    static const uint32_t SINGLETON_BYTE_LENGTH = 1024 * 1024 * 10;
-
-    static bool isOriginalLengthGetter(Native native);
-
-    ArrayBufferObject* bufferUnshared() const {
-        MOZ_ASSERT(!isSharedMemory());
-        JSObject* obj = bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull();
-        if (!obj)
-            return nullptr;
-        return &obj->as<ArrayBufferObject>();
-    }
-    SharedArrayBufferObject* bufferShared() const {
-        MOZ_ASSERT(isSharedMemory());
-        JSObject* obj = bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull();
-        if (!obj)
-            return nullptr;
-        return &obj->as<SharedArrayBufferObject>();
-    }
-    ArrayBufferObjectMaybeShared* bufferEither() const {
-        JSObject* obj = bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull();
-        if (!obj)
-            return nullptr;
-        if (isSharedMemory())
-            return &obj->as<SharedArrayBufferObject>();
-        return &obj->as<ArrayBufferObject>();
-    }
-
-    SharedMem<void*> viewDataShared() const {
-        return SharedMem<void*>::shared(viewDataEither_());
-    }
-    SharedMem<void*> viewDataEither() const {
-        if (isSharedMemory())
-            return SharedMem<void*>::shared(viewDataEither_());
-        return SharedMem<void*>::unshared(viewDataEither_());
-    }
-    void initViewData(SharedMem<uint8_t*> viewData) {
-        // Install a pointer to the buffer location that corresponds
-        // to offset zero within the typed array.
-        //
-        // The following unwrap is safe because the DATA_SLOT is
-        // accessed only from jitted code and from the
-        // viewDataEither_() accessor below; in neither case does the
-        // raw pointer escape untagged into C++ code.
-        initPrivate(viewData.unwrap(/*safe - see above*/));
-    }
-    void* viewDataUnshared() const {
-        MOZ_ASSERT(!isSharedMemory());
-        return viewDataEither_();
-    }
-
-    bool hasDetachedBuffer() const {
-        // Shared buffers can't be detached.
-        if (isSharedMemory())
-            return false;
-
-        // A typed array with a null buffer has never had its buffer exposed to
-        // become detached.
-        ArrayBufferObject* buffer = bufferUnshared();
-        if (!buffer)
-            return false;
-
-        return buffer->isDetached();
-    }
-
-  private:
-    void* viewDataEither_() const {
-        // Note, do not check whether shared or not
-        // Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
-        return static_cast<void*>(getPrivate(DATA_SLOT));
-    }
-
-  public:
-    static void trace(JSTracer* trc, JSObject* obj);
-    static void finalize(FreeOp* fop, JSObject* obj);
-    static void objectMoved(JSObject* obj, const JSObject* old);
-    static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* obj, const JSObject* old,
-                                           gc::AllocKind allocKind);
-
-    /* Initialization bits */
-
-    template<Value ValueGetter(TypedArrayObject* tarr)>
-    static bool
-    GetterImpl(JSContext* cx, const CallArgs& args)
-    {
-        MOZ_ASSERT(is(args.thisv()));
-        args.rval().set(ValueGetter(&args.thisv().toObject().as<TypedArrayObject>()));
-        return true;
-    }
-
-    // ValueGetter is a function that takes an unwrapped typed array object and
-    // returns a Value. Given such a function, Getter<> is a native that
-    // retrieves a given Value, probably from a slot on the object.
-    template<Value ValueGetter(TypedArrayObject* tarr)>
-    static bool
-    Getter(JSContext* cx, unsigned argc, Value* vp)
-    {
-        CallArgs args = CallArgsFromVp(argc, vp);
-        return CallNonGenericMethod<is, GetterImpl<ValueGetter>>(cx, args);
-    }
-
-    static const JSFunctionSpec protoFunctions[];
-    static const JSPropertySpec protoAccessors[];
-    static const JSFunctionSpec staticFunctions[];
-    static const JSPropertySpec staticProperties[];
-
-    /* Accessors and functions */
-
-    static bool is(HandleValue v);
-
-    static bool set(JSContext* cx, unsigned argc, Value* vp);
-};
-
-MOZ_MUST_USE bool TypedArray_bufferGetter(JSContext* cx, unsigned argc, Value* vp);
-
-extern TypedArrayObject*
-TypedArrayCreateWithTemplate(JSContext* cx, HandleObject templateObj, int32_t len);
-
-inline bool
-IsTypedArrayClass(const Class* clasp)
-{
-    return &TypedArrayObject::classes[0] <= clasp &&
-           clasp < &TypedArrayObject::classes[Scalar::MaxTypedArrayViewType];
-}
-
-bool
-IsTypedArrayConstructor(HandleValue v, uint32_t type);
-
-inline Scalar::Type
-TypedArrayObject::type() const
-{
-    MOZ_ASSERT(IsTypedArrayClass(getClass()));
-    return static_cast<Scalar::Type>(getClass() - &classes[0]);
-}
-
-inline size_t
-TypedArrayObject::bytesPerElement() const
-{
-    return Scalar::byteSize(type());
-}
-
-// Return value is whether the string is some integer. If the string is an
-// integer which is not representable as a uint64_t, the return value is true
-// and the resulting index is UINT64_MAX.
-template <typename CharT>
-bool
-StringIsTypedArrayIndex(const CharT* s, size_t length, uint64_t* indexp);
-
-inline bool
-IsTypedArrayIndex(jsid id, uint64_t* indexp)
-{
-    if (JSID_IS_INT(id)) {
-        int32_t i = JSID_TO_INT(id);
-        MOZ_ASSERT(i >= 0);
-        *indexp = (double)i;
-        return true;
-    }
-
-    if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
-        return false;
-
-    JS::AutoCheckCannotGC nogc;
-    JSAtom* atom = JSID_TO_ATOM(id);
-    size_t length = atom->length();
-
-    if (atom->hasLatin1Chars()) {
-        const Latin1Char* s = atom->latin1Chars(nogc);
-        if (!JS7_ISDEC(*s) && *s != '-')
-            return false;
-        return StringIsTypedArrayIndex(s, length, indexp);
-    }
-
-    const char16_t* s = atom->twoByteChars(nogc);
-    if (!JS7_ISDEC(*s) && *s != '-')
-        return false;
-    return StringIsTypedArrayIndex(s, length, indexp);
-}
-
-/*
- * Implements [[DefineOwnProperty]] for TypedArrays when the property
- * key is a TypedArray index.
- */
-bool
-DefineTypedArrayElement(JSContext* cx, HandleObject arr, uint64_t index,
-                        Handle<PropertyDescriptor> desc, ObjectOpResult& result);
-
-static inline unsigned
-TypedArrayShift(Scalar::Type viewType)
-{
-    switch (viewType) {
-      case Scalar::Int8:
-      case Scalar::Uint8:
-      case Scalar::Uint8Clamped:
-        return 0;
-      case Scalar::Int16:
-      case Scalar::Uint16:
-        return 1;
-      case Scalar::Int32:
-      case Scalar::Uint32:
-      case Scalar::Float32:
-        return 2;
-      case Scalar::Int64:
-      case Scalar::Float64:
-        return 3;
-      case Scalar::Float32x4:
-      case Scalar::Int8x16:
-      case Scalar::Int16x8:
-      case Scalar::Int32x4:
-        return 4;
-      default:;
-    }
-    MOZ_CRASH("Unexpected array type");
-}
-
-static inline unsigned
-TypedArrayElemSize(Scalar::Type viewType)
-{
-    return 1u << TypedArrayShift(viewType);
-}
-
-// Assign
-//
-//   target[targetOffset] = unsafeSrcCrossCompartment[0]
-//   ...
-//   target[targetOffset + unsafeSrcCrossCompartment.length - 1] =
-//       unsafeSrcCrossCompartment[unsafeSrcCrossCompartment.length - 1]
-//
-// where the source element range doesn't overlap the target element range in
-// memory.
-extern void
-SetDisjointTypedElements(TypedArrayObject* target, uint32_t targetOffset,
-                         TypedArrayObject* unsafeSrcCrossCompartment);
-
 extern JSObject*
 InitDataViewClass(JSContext* cx, HandleObject obj);
 
 // In the DataViewObject, the private slot contains a raw pointer into
 // the buffer.  The buffer may be shared memory and the raw pointer
 // should not be exposed without sharedness information accompanying
 // it.
 
@@ -581,46 +171,11 @@ class DataViewObject : public NativeObje
                       const CallArgs& args, const char* method);
 
     void notifyBufferDetached(void* newData);
 
   private:
     static const JSFunctionSpec jsfuncs[];
 };
 
-static inline int32_t
-ClampIntForUint8Array(int32_t x)
-{
-    if (x < 0)
-        return 0;
-    if (x > 255)
-        return 255;
-    return x;
-}
-
-static inline bool
-IsAnyArrayBuffer(HandleObject obj)
-{
-    return IsArrayBuffer(obj) || IsSharedArrayBuffer(obj);
-}
-
-static inline bool
-IsAnyArrayBuffer(JSObject* obj)
-{
-    return IsArrayBuffer(obj) || IsSharedArrayBuffer(obj);
-}
-
-static inline bool
-IsAnyArrayBuffer(HandleValue v)
-{
-    return v.isObject() && IsAnyArrayBuffer(&v.toObject());
-}
-
 } // namespace js
 
-template <>
-inline bool
-JSObject::is<js::TypedArrayObject>() const
-{
-    return js::IsTypedArrayClass(getClass());
-}
-
-#endif /* vm_TypedArrayObject_h */
+#endif /* vm_DataViewObject_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -154,16 +154,17 @@ EXPORTS.js += [
     '../public/Utility.h',
     '../public/Value.h',
     '../public/Vector.h',
     '../public/WeakMapPtr.h',
 ]
 
 UNIFIED_SOURCES += [
     'builtin/AtomicsObject.cpp',
+    'builtin/DataViewObject.cpp',
     'builtin/Eval.cpp',
     'builtin/Intl.cpp',
     'builtin/MapObject.cpp',
     'builtin/ModuleObject.cpp',
     'builtin/Object.cpp',
     'builtin/Profilers.cpp',
     'builtin/Promise.cpp',
     'builtin/Reflect.cpp',
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -32,16 +32,17 @@
 #include "jsobj.h"
 #include "jstypes.h"
 #include "jsutil.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
 #include "jswrapper.h"
 
+#include "builtin/DataViewObject.h"
 #include "gc/Barrier.h"
 #include "gc/Marking.h"
 #include "gc/Memory.h"
 #include "js/Conversions.h"
 #include "js/MemoryMetrics.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/SharedArrayObject.h"
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -11,16 +11,17 @@
 #include "jsexn.h"
 #include "jsfriendapi.h"
 #include "jsmath.h"
 #include "json.h"
 #include "jsprototypes.h"
 #include "jsweakmap.h"
 
 #include "builtin/AtomicsObject.h"
+#include "builtin/DataViewObject.h"
 #include "builtin/Eval.h"
 #if EXPOSE_INTL_API
 # include "builtin/Intl.h"
 #endif
 #include "builtin/MapObject.h"
 #include "builtin/ModuleObject.h"
 #include "builtin/Object.h"
 #include "builtin/Promise.h"
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/ObjectGroup.h"
 
 #include "jsexn.h"
 #include "jshashutil.h"
 #include "jsobj.h"
 
+#include "builtin/DataViewObject.h"
 #include "gc/Marking.h"
 #include "gc/Policy.h"
 #include "gc/StoreBuffer.h"
 #include "gc/Zone.h"
 #include "js/CharacterEncoding.h"
 #include "vm/ArrayObject.h"
 #include "vm/Shape.h"
 #include "vm/TaggedProto.h"
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -34,16 +34,17 @@
 
 #include <algorithm>
 
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsdate.h"
 #include "jswrapper.h"
 
+#include "builtin/DataViewObject.h"
 #include "builtin/MapObject.h"
 #include "js/Date.h"
 #include "js/GCHashTable.h"
 #include "vm/SavedFrame.h"
 #include "vm/SharedArrayObject.h"
 #include "vm/TypedArrayObject.h"
 #include "vm/WrapperObject.h"
 
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -24,16 +24,17 @@
 #include "jsobj.h"
 #include "jstypes.h"
 #include "jsutil.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
 #include "jswrapper.h"
 
+#include "builtin/DataViewObject.h"
 #include "builtin/TypedObjectConstants.h"
 #include "gc/Barrier.h"
 #include "gc/Marking.h"
 #include "jit/InlinableNatives.h"
 #include "js/Conversions.h"
 #include "vm/ArrayBufferObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
@@ -1675,858 +1676,16 @@ TypedArrayObjectTemplate<double>::getInd
      * confuse the engine into interpreting a double-typed jsval as an
      * object-typed jsval.
      */
     return DoubleValue(CanonicalizeNaN(val));
 }
 
 } /* anonymous namespace */
 
-static NewObjectKind
-DataViewNewObjectKind(JSContext* cx, uint32_t byteLength, JSObject* proto)
-{
-    if (!proto && byteLength >= TypedArrayObject::SINGLETON_BYTE_LENGTH)
-        return SingletonObject;
-    jsbytecode* pc;
-    JSScript* script = cx->currentScript(&pc);
-    if (script && ObjectGroup::useSingletonForAllocationSite(script, pc, &DataViewObject::class_))
-        return SingletonObject;
-    return GenericObject;
-}
-
-DataViewObject*
-DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
-                       Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, JSObject* protoArg)
-{
-    if (arrayBuffer->isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return nullptr;
-    }
-
-    MOZ_ASSERT(byteOffset <= INT32_MAX);
-    MOZ_ASSERT(byteLength <= INT32_MAX);
-    MOZ_ASSERT(byteOffset + byteLength < UINT32_MAX);
-
-    RootedObject proto(cx, protoArg);
-    RootedObject obj(cx);
-
-    NewObjectKind newKind = DataViewNewObjectKind(cx, byteLength, proto);
-    obj = NewObjectWithClassProto(cx, &class_, proto, newKind);
-    if (!obj)
-        return nullptr;
-
-    if (!proto) {
-        if (byteLength >= TypedArrayObject::SINGLETON_BYTE_LENGTH) {
-            MOZ_ASSERT(obj->isSingleton());
-        } else {
-            jsbytecode* pc;
-            RootedScript script(cx, cx->currentScript(&pc));
-            if (script && !ObjectGroup::setAllocationSiteObjectGroup(cx, script, pc, obj,
-                                                                     newKind == SingletonObject))
-            {
-                return nullptr;
-            }
-        }
-    }
-
-    // Caller should have established these preconditions, and no
-    // (non-self-hosted) JS code has had an opportunity to run so nothing can
-    // have invalidated them.
-    MOZ_ASSERT(byteOffset <= arrayBuffer->byteLength());
-    MOZ_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
-
-    DataViewObject& dvobj = obj->as<DataViewObject>();
-
-    // The isSharedMemory property is invariant.  Self-hosting code that sets
-    // BUFFER_SLOT or the private slot (if it does) must maintain it by always
-    // setting those to reference shared memory.
-    bool isSharedMemory = IsSharedArrayBuffer(arrayBuffer.get());
-    if (isSharedMemory)
-        dvobj.setIsSharedMemory();
-
-    dvobj.setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(byteOffset));
-    dvobj.setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(byteLength));
-    dvobj.setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectValue(*arrayBuffer));
-
-    SharedMem<uint8_t*> ptr = arrayBuffer->dataPointerEither();
-    // A pointer to raw shared memory is exposed through the private slot.  This
-    // is safe so long as getPrivate() is not used willy-nilly.  It is wrapped in
-    // other accessors in TypedArrayObject.h.
-    dvobj.initPrivate(ptr.unwrap(/*safe - see above*/) + byteOffset);
-
-    // Include a barrier if the data view's data pointer is in the nursery, as
-    // is done for typed arrays.
-    if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(ptr)) {
-        // Shared buffer data should never be nursery-allocated, so we
-        // need to fail here if isSharedMemory.  However, mmap() can
-        // place a SharedArrayRawBuffer up against the bottom end of a
-        // nursery chunk, and a zero-length buffer will erroneously be
-        // perceived as being inside the nursery; sidestep that.
-        if (isSharedMemory) {
-            MOZ_ASSERT(arrayBuffer->byteLength() == 0 &&
-                       (uintptr_t(ptr.unwrapValue()) & gc::ChunkMask) == 0);
-        } else {
-            cx->runtime()->gc.storeBuffer.putWholeCell(obj);
-        }
-    }
-
-    // Verify that the private slot is at the expected place
-    MOZ_ASSERT(dvobj.numFixedSlots() == TypedArrayObject::DATA_SLOT);
-
-    if (arrayBuffer->is<ArrayBufferObject>()) {
-        if (!arrayBuffer->as<ArrayBufferObject>().addView(cx, &dvobj))
-            return nullptr;
-    }
-
-    return &dvobj;
-}
-
-bool
-DataViewObject::getAndCheckConstructorArgs(JSContext* cx, HandleObject bufobj, const CallArgs& args,
-                                           uint32_t* byteOffsetPtr, uint32_t* byteLengthPtr)
-{
-    if (!IsArrayBufferMaybeShared(bufobj)) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
-                                  "DataView", "ArrayBuffer", bufobj->getClass()->name);
-        return false;
-    }
-
-    Rooted<ArrayBufferObjectMaybeShared*> buffer(cx, &AsArrayBufferMaybeShared(bufobj));
-    uint32_t byteOffset = 0;
-    uint32_t byteLength = buffer->byteLength();
-
-    if (args.length() > 1) {
-        if (!ToUint32(cx, args[1], &byteOffset))
-            return false;
-        if (byteOffset > INT32_MAX) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
-                                      "1");
-            return false;
-        }
-    }
-
-    if (buffer->isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return false;
-    }
-
-    if (args.length() > 1) {
-        if (byteOffset > byteLength) {
-            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
-                                      "1");
-            return false;
-        }
-
-        if (args.get(2).isUndefined()) {
-            byteLength -= byteOffset;
-        } else {
-            if (!ToUint32(cx, args[2], &byteLength))
-                return false;
-            if (byteLength > INT32_MAX) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                          JSMSG_ARG_INDEX_OUT_OF_RANGE, "2");
-                return false;
-            }
-
-            MOZ_ASSERT(byteOffset + byteLength >= byteOffset,
-                       "can't overflow: both numbers are less than INT32_MAX");
-            if (byteOffset + byteLength > buffer->byteLength()) {
-                JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                          JSMSG_ARG_INDEX_OUT_OF_RANGE, "1");
-                return false;
-            }
-        }
-    }
-
-    /* The sum of these cannot overflow a uint32_t */
-    MOZ_ASSERT(byteOffset <= INT32_MAX);
-    MOZ_ASSERT(byteLength <= INT32_MAX);
-
-
-    *byteOffsetPtr = byteOffset;
-    *byteLengthPtr = byteLength;
-
-    return true;
-}
-
-bool
-DataViewObject::constructSameCompartment(JSContext* cx, HandleObject bufobj, const CallArgs& args)
-{
-    MOZ_ASSERT(args.isConstructing());
-    assertSameCompartment(cx, bufobj);
-
-    uint32_t byteOffset, byteLength;
-    if (!getAndCheckConstructorArgs(cx, bufobj, args, &byteOffset, &byteLength))
-        return false;
-
-    RootedObject proto(cx);
-    RootedObject newTarget(cx, &args.newTarget().toObject());
-    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
-        return false;
-
-    Rooted<ArrayBufferObjectMaybeShared*> buffer(cx, &AsArrayBufferMaybeShared(bufobj));
-    JSObject* obj = DataViewObject::create(cx, byteOffset, byteLength, buffer, proto);
-    if (!obj)
-        return false;
-    args.rval().setObject(*obj);
-    return true;
-}
-
-// Create a DataView object in another compartment.
-//
-// ES6 supports creating a DataView in global A (using global A's DataView
-// constructor) backed by an ArrayBuffer created in global B.
-//
-// Our DataViewObject implementation doesn't support a DataView in
-// compartment A backed by an ArrayBuffer in compartment B. So in this case,
-// we create the DataView in B (!) and return a cross-compartment wrapper.
-//
-// Extra twist: the spec says the new DataView's [[Prototype]] must be
-// A's DataView.prototype. So even though we're creating the DataView in B,
-// its [[Prototype]] must be (a cross-compartment wrapper for) the
-// DataView.prototype in A.
-//
-// As if this were not confusing enough, the way we actually do this is also
-// tricky. We call compartment A's createDataViewForThis method, passing it
-// bufobj as `this`. That calls ArrayBufferObject::createDataViewForThis(),
-// which uses CallNonGenericMethod to switch to compartment B so that
-// the new DataView is created there.
-bool
-DataViewObject::constructWrapped(JSContext* cx, HandleObject bufobj, const CallArgs& args)
-{
-    MOZ_ASSERT(args.isConstructing());
-    MOZ_ASSERT(bufobj->is<WrapperObject>());
-
-    RootedObject unwrapped(cx, CheckedUnwrap(bufobj));
-    if (!unwrapped) {
-        ReportAccessDenied(cx);
-        return false;
-    }
-
-    // NB: This entails the IsArrayBuffer check
-    uint32_t byteOffset, byteLength;
-    if (!getAndCheckConstructorArgs(cx, unwrapped, args, &byteOffset, &byteLength))
-        return false;
-
-    // Make sure to get the [[Prototype]] for the created view from this
-    // compartment.
-    RootedObject proto(cx);
-    RootedObject newTarget(cx, &args.newTarget().toObject());
-    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
-        return false;
-
-    Rooted<GlobalObject*> global(cx, cx->compartment()->maybeGlobal());
-    if (!proto) {
-        proto = GlobalObject::getOrCreateDataViewPrototype(cx, global);
-        if (!proto)
-            return false;
-    }
-
-    RootedObject dv(cx);
-    {
-        JSAutoCompartment ac(cx, unwrapped);
-
-        Rooted<ArrayBufferObjectMaybeShared*> buffer(cx);
-        buffer = &unwrapped->as<ArrayBufferObjectMaybeShared>();
-
-        RootedObject wrappedProto(cx, proto);
-        if (!cx->compartment()->wrap(cx, &wrappedProto))
-            return false;
-
-        dv = DataViewObject::create(cx, byteOffset, byteLength, buffer, wrappedProto);
-        if (!dv)
-            return false;
-    }
-
-    if (!cx->compartment()->wrap(cx, &dv))
-        return false;
-
-    args.rval().setObject(*dv);
-    return true;
-}
-
-bool
-DataViewObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    if (!ThrowIfNotConstructing(cx, args, "DataView"))
-        return false;
-
-    RootedObject bufobj(cx);
-    if (!GetFirstArgumentAsObject(cx, args, "DataView constructor", &bufobj))
-        return false;
-
-    if (bufobj->is<WrapperObject>())
-        return constructWrapped(cx, bufobj, args);
-    return constructSameCompartment(cx, bufobj, args);
-}
-
-template <typename NativeType>
-/* static */ SharedMem<uint8_t*>
-DataViewObject::getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, uint64_t offset,
-                               bool* isSharedMemory)
-{
-    const size_t TypeSize = sizeof(NativeType);
-    if (offset > UINT32_MAX - TypeSize || offset + TypeSize > obj->byteLength()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
-                                  "1");
-        return SharedMem<uint8_t*>::unshared(nullptr);
-    }
-
-    MOZ_ASSERT(offset < UINT32_MAX);
-    *isSharedMemory = obj->isSharedMemory();
-    return obj->dataPointerEither().cast<uint8_t*>() + uint32_t(offset);
-}
-
-static inline bool
-needToSwapBytes(bool littleEndian)
-{
-#if MOZ_LITTLE_ENDIAN
-    return !littleEndian;
-#else
-    return littleEndian;
-#endif
-}
-
-static inline uint8_t
-swapBytes(uint8_t x)
-{
-    return x;
-}
-
-static inline uint16_t
-swapBytes(uint16_t x)
-{
-    return ((x & 0xff) << 8) | (x >> 8);
-}
-
-static inline uint32_t
-swapBytes(uint32_t x)
-{
-    return ((x & 0xff) << 24) |
-           ((x & 0xff00) << 8) |
-           ((x & 0xff0000) >> 8) |
-           ((x & 0xff000000) >> 24);
-}
-
-static inline uint64_t
-swapBytes(uint64_t x)
-{
-    uint32_t a = x & UINT32_MAX;
-    uint32_t b = x >> 32;
-    return (uint64_t(swapBytes(a)) << 32) | swapBytes(b);
-}
-
-template <typename DataType> struct DataToRepType { typedef DataType result; };
-template <> struct DataToRepType<int8_t>   { typedef uint8_t result; };
-template <> struct DataToRepType<uint8_t>  { typedef uint8_t result; };
-template <> struct DataToRepType<int16_t>  { typedef uint16_t result; };
-template <> struct DataToRepType<uint16_t> { typedef uint16_t result; };
-template <> struct DataToRepType<int32_t>  { typedef uint32_t result; };
-template <> struct DataToRepType<uint32_t> { typedef uint32_t result; };
-template <> struct DataToRepType<float>    { typedef uint32_t result; };
-template <> struct DataToRepType<double>   { typedef uint64_t result; };
-
-static inline void
-Memcpy(uint8_t* dest, uint8_t* src, size_t nbytes)
-{
-    memcpy(dest, src, nbytes);
-}
-
-static inline void
-Memcpy(uint8_t* dest, SharedMem<uint8_t*> src, size_t nbytes)
-{
-    jit::AtomicOperations::memcpySafeWhenRacy(dest, src, nbytes);
-}
-
-static inline void
-Memcpy(SharedMem<uint8_t*> dest, uint8_t* src, size_t nbytes)
-{
-    jit::AtomicOperations::memcpySafeWhenRacy(dest, src, nbytes);
-}
-
-template <typename DataType, typename BufferPtrType>
-struct DataViewIO
-{
-    typedef typename DataToRepType<DataType>::result ReadWriteType;
-
-    static void fromBuffer(DataType* dest, BufferPtrType unalignedBuffer, bool wantSwap)
-    {
-        MOZ_ASSERT((reinterpret_cast<uintptr_t>(dest) & (Min<size_t>(MOZ_ALIGNOF(void*), sizeof(DataType)) - 1)) == 0);
-        Memcpy((uint8_t*) dest, unalignedBuffer, sizeof(ReadWriteType));
-        if (wantSwap) {
-            ReadWriteType* rwDest = reinterpret_cast<ReadWriteType*>(dest);
-            *rwDest = swapBytes(*rwDest);
-        }
-    }
-
-    static void toBuffer(BufferPtrType unalignedBuffer, const DataType* src, bool wantSwap)
-    {
-        MOZ_ASSERT((reinterpret_cast<uintptr_t>(src) & (Min<size_t>(MOZ_ALIGNOF(void*), sizeof(DataType)) - 1)) == 0);
-        ReadWriteType temp = *reinterpret_cast<const ReadWriteType*>(src);
-        if (wantSwap)
-            temp = swapBytes(temp);
-        Memcpy(unalignedBuffer, (uint8_t*) &temp, sizeof(ReadWriteType));
-    }
-};
-
-template<typename NativeType>
-/* static */ bool
-DataViewObject::read(JSContext* cx, Handle<DataViewObject*> obj,
-                     const CallArgs& args, NativeType* val, const char* method)
-{
-    // Steps 1-2. done by the caller
-    // Step 3. unnecessary assert
-
-    // Step 4.
-    uint64_t getIndex;
-    if (!ToIndex(cx, args.get(0), &getIndex))
-        return false;
-
-    // Step 5.
-    bool isLittleEndian = args.length() >= 2 && ToBoolean(args[1]);
-
-    // Steps 6-7.
-    if (obj->arrayBufferEither().isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return false;
-    }
-
-    // Steps 8-12.
-    bool isSharedMemory;
-    SharedMem<uint8_t*> data = DataViewObject::getDataPointer<NativeType>(cx, obj, getIndex,
-                                                                          &isSharedMemory);
-    if (!data)
-        return false;
-
-    // Step 13.
-    if (isSharedMemory) {
-        DataViewIO<NativeType, SharedMem<uint8_t*>>::fromBuffer(val, data,
-                                                                needToSwapBytes(isLittleEndian));
-    } else {
-        DataViewIO<NativeType, uint8_t*>::fromBuffer(val, data.unwrapUnshared(),
-                                                     needToSwapBytes(isLittleEndian));
-    }
-    return true;
-}
-
-template <typename NativeType>
-static inline bool
-WebIDLCast(JSContext* cx, HandleValue value, NativeType* out)
-{
-    int32_t temp;
-    if (!ToInt32(cx, value, &temp))
-        return false;
-    // Technically, the behavior of assigning an out of range value to a signed
-    // variable is undefined. In practice, compilers seem to do what we want
-    // without issuing any warnings.
-    *out = static_cast<NativeType>(temp);
-    return true;
-}
-
-template <>
-inline bool
-WebIDLCast<float>(JSContext* cx, HandleValue value, float* out)
-{
-    double temp;
-    if (!ToNumber(cx, value, &temp))
-        return false;
-    *out = static_cast<float>(temp);
-    return true;
-}
-
-template <>
-inline bool
-WebIDLCast<double>(JSContext* cx, HandleValue value, double* out)
-{
-    return ToNumber(cx, value, out);
-}
-
-template<typename NativeType>
-/* static */ bool
-DataViewObject::write(JSContext* cx, Handle<DataViewObject*> obj,
-                      const CallArgs& args, const char* method)
-{
-    // Steps 1-2. done by the caller
-    // Step 3. unnecessary assert
-
-    // Step 4.
-    uint64_t getIndex;
-    if (!ToIndex(cx, args.get(0), &getIndex))
-        return false;
-
-    // Step 5. Should just call ToNumber (unobservable)
-    NativeType value;
-    if (!WebIDLCast(cx, args.get(1), &value))
-        return false;
-
-#ifdef JS_MORE_DETERMINISTIC
-    // See the comment in ElementSpecific::doubleToNative.
-    if (TypeIsFloatingPoint<NativeType>())
-        value = JS::CanonicalizeNaN(value);
-#endif
-
-    // Step 6.
-    bool isLittleEndian = args.length() >= 3 && ToBoolean(args[2]);
-
-    // Steps 7-8.
-    if (obj->arrayBufferEither().isDetached()) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
-        return false;
-    }
-
-    // Steps 9-13.
-    bool isSharedMemory;
-    SharedMem<uint8_t*> data = DataViewObject::getDataPointer<NativeType>(cx, obj, getIndex,
-                                                                          &isSharedMemory);
-    if (!data)
-        return false;
-
-    // Step 14.
-    if (isSharedMemory) {
-        DataViewIO<NativeType, SharedMem<uint8_t*>>::toBuffer(data, &value,
-                                                              needToSwapBytes(isLittleEndian));
-    } else {
-        DataViewIO<NativeType, uint8_t*>::toBuffer(data.unwrapUnshared(), &value,
-                                                   needToSwapBytes(isLittleEndian));
-    }
-    return true;
-}
-
-bool
-DataViewObject::getInt8Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    int8_t val;
-    if (!read(cx, thisView, args, &val, "getInt8"))
-        return false;
-    args.rval().setInt32(val);
-    return true;
-}
-
-bool
-DataViewObject::fun_getInt8(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getInt8Impl>(cx, args);
-}
-
-bool
-DataViewObject::getUint8Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    uint8_t val;
-    if (!read(cx, thisView, args, &val, "getUint8"))
-        return false;
-    args.rval().setInt32(val);
-    return true;
-}
-
-bool
-DataViewObject::fun_getUint8(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getUint8Impl>(cx, args);
-}
-
-bool
-DataViewObject::getInt16Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    int16_t val;
-    if (!read(cx, thisView, args, &val, "getInt16"))
-        return false;
-    args.rval().setInt32(val);
-    return true;
-}
-
-bool
-DataViewObject::fun_getInt16(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getInt16Impl>(cx, args);
-}
-
-bool
-DataViewObject::getUint16Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    uint16_t val;
-    if (!read(cx, thisView, args, &val, "getUint16"))
-        return false;
-    args.rval().setInt32(val);
-    return true;
-}
-
-bool
-DataViewObject::fun_getUint16(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getUint16Impl>(cx, args);
-}
-
-bool
-DataViewObject::getInt32Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    int32_t val;
-    if (!read(cx, thisView, args, &val, "getInt32"))
-        return false;
-    args.rval().setInt32(val);
-    return true;
-}
-
-bool
-DataViewObject::fun_getInt32(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getInt32Impl>(cx, args);
-}
-
-bool
-DataViewObject::getUint32Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    uint32_t val;
-    if (!read(cx, thisView, args, &val, "getUint32"))
-        return false;
-    args.rval().setNumber(val);
-    return true;
-}
-
-bool
-DataViewObject::fun_getUint32(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getUint32Impl>(cx, args);
-}
-
-bool
-DataViewObject::getFloat32Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    float val;
-    if (!read(cx, thisView, args, &val, "getFloat32"))
-        return false;
-
-    args.rval().setDouble(CanonicalizeNaN(val));
-    return true;
-}
-
-bool
-DataViewObject::fun_getFloat32(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getFloat32Impl>(cx, args);
-}
-
-bool
-DataViewObject::getFloat64Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    double val;
-    if (!read(cx, thisView, args, &val, "getFloat64"))
-        return false;
-
-    args.rval().setDouble(CanonicalizeNaN(val));
-    return true;
-}
-
-bool
-DataViewObject::fun_getFloat64(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getFloat64Impl>(cx, args);
-}
-
-bool
-DataViewObject::setInt8Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<int8_t>(cx, thisView, args, "setInt8"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setInt8(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setInt8Impl>(cx, args);
-}
-
-bool
-DataViewObject::setUint8Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<uint8_t>(cx, thisView, args, "setUint8"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setUint8(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setUint8Impl>(cx, args);
-}
-
-bool
-DataViewObject::setInt16Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<int16_t>(cx, thisView, args, "setInt16"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setInt16(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setInt16Impl>(cx, args);
-}
-
-bool
-DataViewObject::setUint16Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<uint16_t>(cx, thisView, args, "setUint16"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setUint16(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setUint16Impl>(cx, args);
-}
-
-bool
-DataViewObject::setInt32Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<int32_t>(cx, thisView, args, "setInt32"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setInt32(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setInt32Impl>(cx, args);
-}
-
-bool
-DataViewObject::setUint32Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<uint32_t>(cx, thisView, args, "setUint32"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setUint32(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setUint32Impl>(cx, args);
-}
-
-bool
-DataViewObject::setFloat32Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<float>(cx, thisView, args, "setFloat32"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setFloat32(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setFloat32Impl>(cx, args);
-}
-
-bool
-DataViewObject::setFloat64Impl(JSContext* cx, const CallArgs& args)
-{
-    MOZ_ASSERT(is(args.thisv()));
-
-    Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().as<DataViewObject>());
-
-    if (!write<double>(cx, thisView, args, "setFloat64"))
-        return false;
-    args.rval().setUndefined();
-    return true;
-}
-
-bool
-DataViewObject::fun_setFloat64(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, setFloat64Impl>(cx, args);
-}
-
 Value
 TypedArrayObject::getElement(uint32_t index)
 {
     switch (type()) {
       case Scalar::Int8:
         return Int8Array::getIndexValue(this, index);
       case Scalar::Uint8:
         return Uint8Array::getIndexValue(this, index);
@@ -2814,156 +1973,16 @@ const Class TypedArrayObject::protoClass
 };
 
 /* static */ bool
 TypedArrayObject::isOriginalLengthGetter(Native native)
 {
     return native == TypedArray_lengthGetter;
 }
 
-const Class DataViewObject::protoClass = {
-    "DataViewPrototype",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_DataView)
-};
-
-static const ClassOps DataViewObjectClassOps = {
-    nullptr, /* addProperty */
-    nullptr, /* delProperty */
-    nullptr, /* getProperty */
-    nullptr, /* setProperty */
-    nullptr, /* enumerate */
-    nullptr, /* resolve */
-    nullptr, /* mayResolve */
-    nullptr, /* finalize */
-    nullptr, /* call */
-    nullptr, /* hasInstance */
-    nullptr, /* construct */
-    ArrayBufferViewObject::trace
-};
-
-const Class DataViewObject::class_ = {
-    "DataView",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
-    &DataViewObjectClassOps
-};
-
-const JSFunctionSpec DataViewObject::jsfuncs[] = {
-    JS_FN("getInt8",    DataViewObject::fun_getInt8,      1,0),
-    JS_FN("getUint8",   DataViewObject::fun_getUint8,     1,0),
-    JS_FN("getInt16",   DataViewObject::fun_getInt16,     1,0),
-    JS_FN("getUint16",  DataViewObject::fun_getUint16,    1,0),
-    JS_FN("getInt32",   DataViewObject::fun_getInt32,     1,0),
-    JS_FN("getUint32",  DataViewObject::fun_getUint32,    1,0),
-    JS_FN("getFloat32", DataViewObject::fun_getFloat32,   1,0),
-    JS_FN("getFloat64", DataViewObject::fun_getFloat64,   1,0),
-    JS_FN("setInt8",    DataViewObject::fun_setInt8,      2,0),
-    JS_FN("setUint8",   DataViewObject::fun_setUint8,     2,0),
-    JS_FN("setInt16",   DataViewObject::fun_setInt16,     2,0),
-    JS_FN("setUint16",  DataViewObject::fun_setUint16,    2,0),
-    JS_FN("setInt32",   DataViewObject::fun_setInt32,     2,0),
-    JS_FN("setUint32",  DataViewObject::fun_setUint32,    2,0),
-    JS_FN("setFloat32", DataViewObject::fun_setFloat32,   2,0),
-    JS_FN("setFloat64", DataViewObject::fun_setFloat64,   2,0),
-    JS_FS_END
-};
-
-template<Value ValueGetter(DataViewObject* view)>
-bool
-DataViewObject::getterImpl(JSContext* cx, const CallArgs& args)
-{
-    args.rval().set(ValueGetter(&args.thisv().toObject().as<DataViewObject>()));
-    return true;
-}
-
-template<Value ValueGetter(DataViewObject* view)>
-bool
-DataViewObject::getter(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<is, getterImpl<ValueGetter> >(cx, args);
-}
-
-template<Value ValueGetter(DataViewObject* view)>
-bool
-DataViewObject::defineGetter(JSContext* cx, PropertyName* name, HandleNativeObject proto)
-{
-    RootedId id(cx, NameToId(name));
-    RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Get));
-    if (!atom)
-        return false;
-    unsigned attrs = JSPROP_SHARED | JSPROP_GETTER;
-
-    Rooted<GlobalObject*> global(cx, cx->compartment()->maybeGlobal());
-    JSObject* getter =
-        NewNativeFunction(cx, DataViewObject::getter<ValueGetter>, 0, atom);
-    if (!getter)
-        return false;
-
-    return NativeDefineProperty(cx, proto, id, UndefinedHandleValue,
-                                JS_DATA_TO_FUNC_PTR(GetterOp, getter), nullptr, attrs);
-}
-
-/* static */ bool
-DataViewObject::initClass(JSContext* cx)
-{
-    Rooted<GlobalObject*> global(cx, cx->compartment()->maybeGlobal());
-    if (global->isStandardClassResolved(JSProto_DataView))
-        return true;
-
-    RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global,
-                                                                    &DataViewObject::protoClass));
-    if (!proto)
-        return false;
-
-    RootedFunction ctor(cx, GlobalObject::createConstructor(cx, DataViewObject::class_constructor,
-                                                            cx->names().DataView, 3));
-    if (!ctor)
-        return false;
-
-    if (!LinkConstructorAndPrototype(cx, ctor, proto))
-        return false;
-
-    if (!defineGetter<bufferValue>(cx, cx->names().buffer, proto))
-        return false;
-
-    if (!defineGetter<byteLengthValue>(cx, cx->names().byteLength, proto))
-        return false;
-
-    if (!defineGetter<byteOffsetValue>(cx, cx->names().byteOffset, proto))
-        return false;
-
-    if (!JS_DefineFunctions(cx, proto, DataViewObject::jsfuncs))
-        return false;
-
-    if (!DefineToStringTag(cx, proto, cx->names().DataView))
-        return false;
-
-    return GlobalObject::initBuiltinConstructor(cx, global, JSProto_DataView, ctor, proto);
-}
-
-void
-DataViewObject::notifyBufferDetached(void* newData)
-{
-    setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(0));
-    setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(0));
-    setPrivate(newData);
-}
-
-JSObject*
-js::InitDataViewClass(JSContext* cx, HandleObject obj)
-{
-    if (!DataViewObject::initClass(cx))
-        return nullptr;
-    return &cx->global()->getPrototype(JSProto_DataView).toObject();
-}
-
 bool
 js::IsTypedArrayConstructor(HandleValue v, uint32_t type)
 {
     switch (type) {
       case Scalar::Int8:
         return IsNativeFunction(v, Int8Array::class_constructor);
       case Scalar::Uint8:
         return IsNativeFunction(v, Uint8Array::class_constructor);
@@ -3258,66 +2277,9 @@ JS_GetFloat64ArrayData(JSObject* obj, bo
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     TypedArrayObject* tarr = &obj->as<TypedArrayObject>();
     MOZ_ASSERT((int32_t) tarr->type() == Scalar::Float64);
     *isSharedMemory = tarr->isSharedMemory();
     return static_cast<double*>(tarr->viewDataEither().unwrap(/*safe - caller sees isSharedMemory*/));
-}
-
-JS_FRIEND_API(bool)
-JS_IsDataViewObject(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    return obj ? obj->is<DataViewObject>() : false;
-}
-
-JS_FRIEND_API(uint32_t)
-JS_GetDataViewByteOffset(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return 0;
-    return obj->as<DataViewObject>().byteOffset();
-}
-
-JS_FRIEND_API(void*)
-JS_GetDataViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return nullptr;
-    DataViewObject& dv = obj->as<DataViewObject>();
-    *isSharedMemory = dv.isSharedMemory();
-    return dv.dataPointerEither().unwrap(/*safe - caller sees isSharedMemory*/);
-}
-
-JS_FRIEND_API(uint32_t)
-JS_GetDataViewByteLength(JSObject* obj)
-{
-    obj = CheckedUnwrap(obj);
-    if (!obj)
-        return 0;
-    return obj->as<DataViewObject>().byteLength();
-}
-
-JS_FRIEND_API(JSObject*)
-JS_NewDataView(JSContext* cx, HandleObject buffer, uint32_t byteOffset, int32_t byteLength)
-{
-    RootedObject constructor(cx);
-    JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(&DataViewObject::class_);
-    if (!GetBuiltinConstructor(cx, key, &constructor))
-        return nullptr;
-
-    FixedConstructArgs<3> cargs(cx);
-
-    cargs[0].setObject(*buffer);
-    cargs[1].setNumber(byteOffset);
-    cargs[2].setInt32(byteLength);
-
-    RootedValue fun(cx, ObjectValue(*constructor));
-    RootedObject obj(cx);
-    if (!Construct(cx, fun, cargs, fun, &obj))
-        return nullptr;
-    return obj;
-}
+}
\ No newline at end of file
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -423,184 +423,16 @@ TypedArrayElemSize(Scalar::Type viewType
 //   target[targetOffset + unsafeSrcCrossCompartment.length - 1] =
 //       unsafeSrcCrossCompartment[unsafeSrcCrossCompartment.length - 1]
 //
 // where the source element range doesn't overlap the target element range in
 // memory.
 extern void
 SetDisjointTypedElements(TypedArrayObject* target, uint32_t targetOffset,
                          TypedArrayObject* unsafeSrcCrossCompartment);
-
-extern JSObject*
-InitDataViewClass(JSContext* cx, HandleObject obj);
-
-// In the DataViewObject, the private slot contains a raw pointer into
-// the buffer.  The buffer may be shared memory and the raw pointer
-// should not be exposed without sharedness information accompanying
-// it.
-
-class DataViewObject : public NativeObject
-{
-  private:
-    static const Class protoClass;
-
-    static bool is(HandleValue v) {
-        return v.isObject() && v.toObject().hasClass(&class_);
-    }
-
-    template <typename NativeType>
-    static SharedMem<uint8_t*>
-    getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, uint64_t offset, bool* isSharedMemory);
-
-    template<Value ValueGetter(DataViewObject* view)>
-    static bool
-    getterImpl(JSContext* cx, const CallArgs& args);
-
-    template<Value ValueGetter(DataViewObject* view)>
-    static bool
-    getter(JSContext* cx, unsigned argc, Value* vp);
-
-    template<Value ValueGetter(DataViewObject* view)>
-    static bool
-    defineGetter(JSContext* cx, PropertyName* name, HandleNativeObject proto);
-
-    static bool
-    getAndCheckConstructorArgs(JSContext* cx, HandleObject bufobj, const CallArgs& args,
-                               uint32_t* byteOffset, uint32_t* byteLength);
-    static bool constructSameCompartment(JSContext* cx, HandleObject bufobj, const CallArgs& args);
-    static bool constructWrapped(JSContext* cx, HandleObject bufobj, const CallArgs& args);
-
-    static DataViewObject*
-    create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
-           Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, JSObject* proto);
-
-  public:
-    static const Class class_;
-
-    static Value byteOffsetValue(DataViewObject* view) {
-        Value v = view->getFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT);
-        MOZ_ASSERT(v.toInt32() >= 0);
-        return v;
-    }
-
-    static Value byteLengthValue(DataViewObject* view) {
-        Value v = view->getFixedSlot(TypedArrayObject::LENGTH_SLOT);
-        MOZ_ASSERT(v.toInt32() >= 0);
-        return v;
-    }
-
-    static Value bufferValue(DataViewObject* view) {
-        return view->getFixedSlot(TypedArrayObject::BUFFER_SLOT);
-    }
-
-    uint32_t byteOffset() const {
-        return byteOffsetValue(const_cast<DataViewObject*>(this)).toInt32();
-    }
-
-    uint32_t byteLength() const {
-        return byteLengthValue(const_cast<DataViewObject*>(this)).toInt32();
-    }
-
-    ArrayBufferObjectMaybeShared& arrayBufferEither() const {
-        return bufferValue(
-            const_cast<DataViewObject*>(this)).toObject().as<ArrayBufferObjectMaybeShared>();
-    }
-
-    SharedMem<void*> dataPointerEither() const {
-        void *p = getPrivate();
-        if (isSharedMemory())
-            return SharedMem<void*>::shared(p);
-        return SharedMem<void*>::unshared(p);
-    }
-
-    void* dataPointerUnshared() const {
-        MOZ_ASSERT(!isSharedMemory());
-        return getPrivate();
-    }
-
-    void* dataPointerShared() const {
-        MOZ_ASSERT(isSharedMemory());
-        return getPrivate();
-    }
-
-    static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getInt8Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getInt8(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getUint8Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getUint8(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getInt16Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getInt16(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getUint16Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getUint16(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getInt32Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getInt32(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getUint32Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getUint32(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getFloat32Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getFloat32(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool getFloat64Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_getFloat64(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setInt8Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setInt8(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setUint8Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setUint8(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setInt16Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setInt16(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setUint16Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setUint16(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setInt32Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setInt32(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setUint32Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setUint32(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setFloat32Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setFloat32(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool setFloat64Impl(JSContext* cx, const CallArgs& args);
-    static bool fun_setFloat64(JSContext* cx, unsigned argc, Value* vp);
-
-    static bool initClass(JSContext* cx);
-    static void notifyBufferDetached(JSObject* view);
-    template<typename NativeType>
-    static bool read(JSContext* cx, Handle<DataViewObject*> obj,
-                     const CallArgs& args, NativeType* val, const char* method);
-    template<typename NativeType>
-    static bool write(JSContext* cx, Handle<DataViewObject*> obj,
-                      const CallArgs& args, const char* method);
-
-    void notifyBufferDetached(void* newData);
-
-  private:
-    static const JSFunctionSpec jsfuncs[];
-};
-
-static inline int32_t
-ClampIntForUint8Array(int32_t x)
-{
-    if (x < 0)
-        return 0;
-    if (x > 255)
-        return 255;
-    return x;
-}
-
 static inline bool
 IsAnyArrayBuffer(HandleObject obj)
 {
     return IsArrayBuffer(obj) || IsSharedArrayBuffer(obj);
 }
 
 static inline bool
 IsAnyArrayBuffer(JSObject* obj)