Bug 1147441 - Add SharedArrayBuffer support to WebGL and WebGL 2. r=jgilbert, r=bzbarsky
authorJukka Jylanki <jjylanki@mozilla.com>
Wed, 14 Oct 2015 11:18:19 +0530
changeset 300995 003b744576bd685879fbe7e3d1893b78ac12e65b
parent 300994 9ba7db03684cfd4ba44de7f14613e933b0a8c7c6
child 300996 89add5fc9f9778a870be8e74ed21e1837ad7c4f3
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, bzbarsky
bugs1147441
milestone44.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 1147441 - Add SharedArrayBuffer support to WebGL and WebGL 2. r=jgilbert, r=bzbarsky
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextBuffers.cpp
dom/canvas/WebGL2ContextTextures.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextBuffers.cpp
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLContextTextures.cpp
dom/canvas/WebGLTexture.h
dom/canvas/WebGLTextureUpload.cpp
dom/canvas/test/webgl-mochitest.ini
dom/canvas/test/webgl-mochitest/test_sab_with_webgl.html
dom/webidl/WebGL2RenderingContext.webidl
dom/webidl/WebGLRenderingContext.webidl
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -19,16 +19,17 @@ namespace mozilla {
 class ErrorResult;
 class WebGLSampler;
 class WebGLSync;
 class WebGLTransformFeedback;
 class WebGLVertexArrayObject;
 namespace dom {
 class OwningUnsignedLongOrUint32ArrayOrBoolean;
 class OwningWebGLBufferOrLongLong;
+class ArrayBufferViewOrSharedArrayBufferView;
 } // namespace dom
 
 class WebGL2Context
     : public WebGLContext
 {
 public:
 
     virtual ~WebGL2Context();
@@ -46,18 +47,26 @@ public:
 
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
 
     // -------------------------------------------------------------------------
     // Buffer objects - WebGL2ContextBuffers.cpp
 
     void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
                            GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+
+private:
+    template<typename BufferT>
+    void GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data);
+
+public:
     void GetBufferSubData(GLenum target, GLintptr offset,
                           const dom::Nullable<dom::ArrayBuffer>& maybeData);
+    void GetBufferSubData(GLenum target, GLintptr offset,
+                          const dom::SharedArrayBuffer& data);
 
 
     // -------------------------------------------------------------------------
     // Framebuffer objects - WebGL2ContextFramebuffers.cpp
 
     void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                          GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                          GLbitfield mask, GLenum filter);
@@ -83,41 +92,41 @@ public:
     // Texture objects - WebGL2ContextTextures.cpp
 
     void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
     void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
                       GLsizei depth);
     void TexImage3D(GLenum target, GLint level, GLenum internalformat,
                     GLsizei width, GLsizei height, GLsizei depth,
                     GLint border, GLenum format, GLenum type,
-                    const dom::Nullable<dom::ArrayBufferView>& pixels,
+                    const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
                     ErrorResult& rv);
     void TexSubImage3D(GLenum target, GLint level,
                        GLint xoffset, GLint yoffset, GLint zoffset,
                        GLsizei width, GLsizei height, GLsizei depth,
-                       GLenum format, GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
+                       GLenum format, GLenum type, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
                        ErrorResult& rv);
     void TexSubImage3D(GLenum target, GLint level,
                        GLint xoffset, GLint yoffset, GLint zoffset,
                        GLenum format, GLenum type, dom::ImageData* data,
                        ErrorResult& rv);
     template<class ElementType>
     void TexSubImage3D(GLenum target, GLint level,
                        GLint xoffset, GLint yoffset, GLint zoffset,
                        GLenum format, GLenum type, ElementType& elt, ErrorResult& rv)
     {}
 
     void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                            GLint x, GLint y, GLsizei width, GLsizei height);
     void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
                               GLsizei width, GLsizei height, GLsizei depth,
-                              GLint border, GLsizei imageSize, const dom::ArrayBufferView& data);
+                              GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
     void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                  GLsizei width, GLsizei height, GLsizei depth,
-                                 GLenum format, GLsizei imageSize, const dom::ArrayBufferView& data);
+                                 GLenum format, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
 
 
     // -------------------------------------------------------------------------
     // Programs and shaders - WebGL2ContextPrograms.cpp
     GLint GetFragDataLocation(WebGLProgram* program, const nsAString& name);
 
 
     // -------------------------------------------------------------------------
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -133,19 +133,22 @@ WebGL2Context::CopyBufferSubData(GLenum 
 
     if (writeType == WebGLBuffer::Kind::Undefined) {
         writeBuffer->BindTo(
             (readType == WebGLBuffer::Kind::OtherData) ? LOCAL_GL_ARRAY_BUFFER
                                                        : LOCAL_GL_ELEMENT_ARRAY_BUFFER);
     }
 }
 
+// BufferT may be one of
+// const dom::ArrayBuffer&
+// const dom::SharedArrayBuffer&
+template<typename BufferT>
 void
-WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
-                                const dom::Nullable<dom::ArrayBuffer>& maybeData)
+WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data)
 {
     if (IsContextLost())
         return;
 
     // For the WebGLBuffer bound to the passed target, read
     // returnedData.byteLength bytes from the buffer starting at byte
     // offset offset and write them to returnedData.
 
@@ -154,29 +157,23 @@ WebGL2Context::GetBufferSubData(GLenum t
     if (!ValidateBufferTarget(target, "getBufferSubData"))
         return;
 
     // If offset is less than zero, an INVALID_VALUE error is
     // generated.
     if (offset < 0)
         return ErrorInvalidValue("getBufferSubData: negative offset");
 
-    // If returnedData is null then an INVALID_VALUE error is
-    // generated.
-    if (maybeData.IsNull())
-        return ErrorInvalidValue("getBufferSubData: returnedData is null");
-
     WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
     WebGLBuffer* boundBuffer = bufferSlot.get();
     if (!boundBuffer)
         return ErrorInvalidOperation("getBufferSubData: no buffer bound");
 
     // If offset + returnedData.byteLength would extend beyond the end
     // of the buffer an INVALID_VALUE error is generated.
-    const dom::ArrayBuffer& data = maybeData.Value();
     data.ComputeLengthAndData();
 
     CheckedInt<WebGLsizeiptr> neededByteLength = CheckedInt<WebGLsizeiptr>(offset) + data.Length();
     if (!neededByteLength.isValid()) {
         ErrorInvalidValue("getBufferSubData: Integer overflow computing the needed"
                           " byte length.");
         return;
     }
@@ -220,9 +217,27 @@ WebGL2Context::GetBufferSubData(GLenum t
     memcpy(data.Data(), ptr, data.Length());
     gl->fUnmapBuffer(target);
 
     if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER && currentTF) {
         BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, currentTF);
     }
 }
 
+void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
+                                     const dom::Nullable<dom::ArrayBuffer>& maybeData)
+{
+    // If returnedData is null then an INVALID_VALUE error is
+    // generated.
+    if (maybeData.IsNull())
+        return ErrorInvalidValue("getBufferSubData: returnedData is null");
+
+    const dom::ArrayBuffer& data = maybeData.Value();
+    GetBufferSubDataT(target, offset, data);
+}
+
+void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
+                                     const dom::SharedArrayBuffer& data)
+{
+    GetBufferSubDataT(target, offset, data);
+}
+
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextTextures.cpp
+++ b/dom/canvas/WebGL2ContextTextures.cpp
@@ -34,17 +34,17 @@ WebGL2Context::TexStorage3D(GLenum rawTe
 
     tex->TexStorage3D(texTarget, levels, internalFormat, width, height, depth);
 }
 
 void
 WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
                           GLsizei width, GLsizei height, GLsizei depth,
                           GLint border, GLenum unpackFormat, GLenum unpackType,
-                          const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                          const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                           ErrorResult& out_rv)
 {
     const char funcName[] = "texImage3D";
     TexImageTarget texImageTarget;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
     {
         return;
@@ -54,17 +54,17 @@ WebGL2Context::TexImage3D(GLenum rawTexI
                     unpackFormat, unpackType, maybeView, &out_rv);
 }
 
 void
 WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
                              GLint xOffset, GLint yOffset, GLint zOffset,
                              GLsizei width, GLsizei height, GLsizei depth,
                              GLenum unpackFormat, GLenum unpackType,
-                             const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                             const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                              ErrorResult& out_rv)
 {
     const char funcName[] = "texSubImage3D";
     TexImageTarget texImageTarget;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
     {
         return;
@@ -90,25 +90,25 @@ WebGL2Context::CopyTexSubImage3D(GLenum 
                                  GLint x, GLint y, GLsizei width, GLsizei height)
 {
     GenerateWarning("copyTexSubImage3D: Not implemented.");
 }
 
 void
 WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
                                     GLsizei width, GLsizei height, GLsizei depth,
-                                    GLint border, GLsizei imageSize, const dom::ArrayBufferView& view)
+                                    GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
 {
     GenerateWarning("compressedTexImage3D: Not implemented.");
 }
 
 void
 WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
                                        GLsizei width, GLsizei height, GLsizei depth,
-                                       GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferView& view)
+                                       GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
 {
     GenerateWarning("compressedTexSubImage3D: Not implemented.");
 }
 
 bool
 WebGL2Context::IsTexParamValid(GLenum pname) const
 {
     switch (pname) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -40,17 +40,17 @@
 // Generated
 #include "nsIDOMEventListener.h"
 #include "nsIDOMWebGLRenderingContext.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsIObserver.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsWrapperCache.h"
 #include "nsLayoutUtils.h"
-
+#include "mozilla/dom/UnionTypes.h"
 
 class nsIDocShell;
 
 /*
  * Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
  *   https://bugzilla.mozilla.org/show_bug.cgi?id=686732
  *
  * Exceptions: some of the following values are set to higher values than in the spec because
@@ -95,16 +95,17 @@ class WebGLTransformFeedback;
 class WebGLUniformLocation;
 class WebGLVertexArray;
 
 namespace dom {
 class Element;
 class ImageData;
 class OwningHTMLCanvasElementOrOffscreenCanvas;
 struct WebGLContextAttributes;
+class ArrayBufferViewOrSharedArrayBufferView;
 template<typename> struct Nullable;
 } // namespace dom
 
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
 
 namespace webgl {
@@ -523,17 +524,17 @@ public:
     bool IsShader(WebGLShader* shader);
     bool IsVertexArray(WebGLVertexArray* vao);
     void LineWidth(GLfloat width);
     void LinkProgram(WebGLProgram* prog);
     void PixelStorei(GLenum pname, GLint param);
     void PolygonOffset(GLfloat factor, GLfloat units);
     void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                     GLenum format, GLenum type,
-                    const dom::Nullable<dom::ArrayBufferView>& pixels,
+                    const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
                     ErrorResult& rv);
     void RenderbufferStorage(GLenum target, GLenum internalFormat,
                              GLsizei width, GLsizei height);
 protected:
     void RenderbufferStorage_base(const char* funcName, GLenum target,
                                   GLsizei samples, GLenum internalformat,
                                   GLsizei width, GLsizei height);
 public:
@@ -744,35 +745,44 @@ private:
 
 public:
     void BindBuffer(GLenum target, WebGLBuffer* buffer);
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buf);
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf,
                          WebGLintptr offset, WebGLsizeiptr size);
 
 private:
-    void BufferDataUnchecked(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
-    void BufferData(GLenum target, WebGLsizeiptr size, void* data, GLenum usage);
+    template<typename BufferT>
+    void BufferDataT(GLenum target, const BufferT& data, GLenum usage);
 
 public:
     void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage);
     void BufferData(GLenum target, const dom::ArrayBufferView& data,
                     GLenum usage);
     void BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeData,
                     GLenum usage);
+    void BufferData(GLenum target, const dom::SharedArrayBuffer& data,
+                    GLenum usage);
+    void BufferData(GLenum target, const dom::SharedArrayBufferView& data,
+                    GLenum usage);
 
 private:
-    void BufferSubDataUnchecked(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
-    void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+    template<typename BufferT>
+    void BufferSubDataT(GLenum target, WebGLsizeiptr byteOffset,
+                        const BufferT& data);
 
 public:
     void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
                        const dom::ArrayBufferView& data);
     void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
                        const dom::Nullable<dom::ArrayBuffer>& maybeData);
+    void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
+                       const dom::SharedArrayBuffer& data);
+    void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
+                       const dom::SharedArrayBufferView& data);
     already_AddRefed<WebGLBuffer> CreateBuffer();
     void DeleteBuffer(WebGLBuffer* buf);
     bool IsBuffer(WebGLBuffer* buf);
 
 protected:
     // bound buffer state
     WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
     WebGLRefPtr<WebGLBuffer> mBoundCopyReadBuffer;
@@ -859,44 +869,44 @@ protected:
                            GLfloat* maybeFloatParam);
 
     virtual bool IsTexParamValid(GLenum pname) const;
 
     // Upload funcs
 public:
     void CompressedTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                               GLsizei width, GLsizei height, GLint border,
-                              const dom::ArrayBufferView& view);
+                              const dom::ArrayBufferViewOrSharedArrayBufferView& view);
     void CompressedTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
                                  GLint yOffset, GLsizei width, GLsizei height,
-                                 GLenum unpackFormat, const dom::ArrayBufferView& view);
+                                 GLenum unpackFormat, const dom::ArrayBufferViewOrSharedArrayBufferView& view);
 
     void CopyTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                         GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
     void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
                            GLint yOffset, GLint x, GLint y, GLsizei width,
                            GLsizei height);
 
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
                     GLenum unpackType,
-                    const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                    const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                     ErrorResult& out_rv);
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
                     ErrorResult& out_rv);
     void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
                     ErrorResult* const out_rv);
 
 
     void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
                        GLsizei width, GLsizei height, GLenum unpackFormat,
                        GLenum unpackType,
-                       const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                       const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                        ErrorResult& out_rv);
     void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
                        GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
                        ErrorResult& out_rv);
     void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
                        GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
                        ErrorResult* const out_rv);
 
@@ -1629,11 +1639,16 @@ ValidateTexTarget(WebGLContext* webgl, G
 bool
 ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
                        const char* funcName, TexImageTarget* const out_texImageTarget,
                        WebGLTexture** const out_tex);
 
 // Returns x rounded to the next highest multiple of y.
 CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y);
 
+void
+ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
+                     void** const out_data, size_t* const out_length,
+                     js::Scalar::Type* const out_type);
+
 } // namespace mozilla
 
 #endif
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -177,35 +177,35 @@ WebGLContext::BufferData(GLenum target, 
     }
 
     boundBuffer->SetByteLength(size);
     if (!boundBuffer->ElementArrayCacheBufferData(nullptr, size)) {
         return ErrorOutOfMemory("bufferData: out of memory");
     }
 }
 
+// BufferT may be one of
+// const dom::ArrayBuffer&
+// const dom::SharedArrayBuffer&
+// const dom::ArrayBufferView&
+// const dom::SharedArrayBufferView&
+template<typename BufferT>
 void
-WebGLContext::BufferData(GLenum target,
-                         const dom::Nullable<dom::ArrayBuffer>& maybeData,
-                         GLenum usage)
+WebGLContext::BufferDataT(GLenum target,
+                          const BufferT& data,
+                          GLenum usage)
 {
     if (IsContextLost())
         return;
 
-    if (maybeData.IsNull()) {
-        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
-        return ErrorInvalidValue("bufferData: null object passed");
-    }
-
     if (!ValidateBufferTarget(target, "bufferData"))
         return;
 
     const WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
 
-    const dom::ArrayBuffer& data = maybeData.Value();
     data.ComputeLengthAndData();
 
     // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
     // is like intptr_t.
     if (!CheckedInt<GLsizeiptr>(data.Length()).isValid())
         return ErrorOutOfMemory("bufferData: bad size");
 
     if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
@@ -227,80 +227,75 @@ WebGLContext::BufferData(GLenum target,
     }
 
     boundBuffer->SetByteLength(data.Length());
     if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length()))
         return ErrorOutOfMemory("bufferData: out of memory");
 }
 
 void
+WebGLContext::BufferData(GLenum target,
+                         const dom::SharedArrayBuffer& data,
+                         GLenum usage)
+{
+    BufferDataT(target, data, usage);
+}
+
+void
+WebGLContext::BufferData(GLenum target,
+                         const dom::Nullable<dom::ArrayBuffer>& maybeData,
+                         GLenum usage)
+{
+    if (maybeData.IsNull()) {
+        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
+        return ErrorInvalidValue("bufferData: null object passed");
+    }
+    BufferDataT(target, maybeData.Value(), usage);
+}
+
+void
 WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data,
                          GLenum usage)
 {
+    BufferDataT(target, data, usage);
+}
+
+void
+WebGLContext::BufferData(GLenum target, const dom::SharedArrayBufferView& data,
+                         GLenum usage)
+{
+    BufferDataT(target, data, usage);
+}
+
+// BufferT may be one of
+// const dom::ArrayBuffer&
+// const dom::SharedArrayBuffer&
+// const dom::ArrayBufferView&
+// const dom::SharedArrayBufferView&
+template<typename BufferT>
+void
+WebGLContext::BufferSubDataT(GLenum target,
+                             WebGLsizeiptr byteOffset,
+                             const BufferT& data)
+{
     if (IsContextLost())
         return;
 
-    if (!ValidateBufferTarget(target, "bufferData"))
-        return;
-
-    WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
-
-    if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
-        return;
-
-    WebGLBuffer* boundBuffer = bufferSlot.get();
-    if (!boundBuffer)
-        return ErrorInvalidOperation("bufferData: no buffer bound!");
-
-    data.ComputeLengthAndData();
-
-    // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
-    // is like intptr_t.
-    if (!CheckedInt<GLsizeiptr>(data.Length()).isValid())
-        return ErrorOutOfMemory("bufferData: bad size");
-
-    InvalidateBufferFetching();
-    MakeContextCurrent();
-
-    GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
-    if (error) {
-        GenerateWarning("bufferData generated error %s", ErrorName(error));
-        return;
-    }
-
-    boundBuffer->SetByteLength(data.Length());
-    if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length()))
-        return ErrorOutOfMemory("bufferData: out of memory");
-}
-
-void
-WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
-                            const dom::Nullable<dom::ArrayBuffer>& maybeData)
-{
-    if (IsContextLost())
-        return;
-
-    if (maybeData.IsNull()) {
-        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
-        return;
-    }
-
     if (!ValidateBufferTarget(target, "bufferSubData"))
         return;
 
     WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
 
     WebGLBuffer* boundBuffer = bufferSlot.get();
     if (!boundBuffer)
         return ErrorInvalidOperation("bufferData: no buffer bound!");
 
-    const dom::ArrayBuffer& data = maybeData.Value();
     data.ComputeLengthAndData();
 
     CheckedInt<WebGLsizeiptr> checked_neededByteLength =
         CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
 
     if (!checked_neededByteLength.isValid()) {
         ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
                           " byte length.");
@@ -319,57 +314,44 @@ WebGLContext::BufferSubData(GLenum targe
                                                 data.Length());
 
     MakeContextCurrent();
     gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
 }
 
 void
 WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
+                            const dom::Nullable<dom::ArrayBuffer>& maybeData)
+{
+    if (maybeData.IsNull()) {
+        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
+        return;
+    }
+    BufferSubDataT(target, byteOffset, maybeData.Value());
+}
+
+void
+WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
+                            const dom::SharedArrayBuffer& data)
+{
+    BufferSubDataT(target, byteOffset, data);
+}
+
+void
+WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
                             const dom::ArrayBufferView& data)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateBufferTarget(target, "bufferSubData"))
-        return;
-
-    WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
-
-    if (byteOffset < 0)
-        return ErrorInvalidValue("bufferSubData: negative offset");
-
-    WebGLBuffer* boundBuffer = bufferSlot.get();
-    if (!boundBuffer)
-        return ErrorInvalidOperation("bufferSubData: no buffer bound!");
-
-    data.ComputeLengthAndData();
-
-    CheckedInt<WebGLsizeiptr> checked_neededByteLength =
-        CheckedInt<WebGLsizeiptr>(byteOffset) + data.Length();
+    BufferSubDataT(target, byteOffset, data);
+}
 
-    if (!checked_neededByteLength.isValid()) {
-        ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
-                          " byte length.");
-        return;
-    }
-
-    if (checked_neededByteLength.value() > boundBuffer->ByteLength()) {
-        ErrorInvalidValue("bufferSubData: Not enough data. Operation requires"
-                          " %d bytes, but buffer only has %d bytes.",
-                          checked_neededByteLength.value(),
-                          boundBuffer->ByteLength());
-        return;
-    }
-
-    boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(),
-                                                data.Length());
-
-    MakeContextCurrent();
-    gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
+void
+WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
+                            const dom::SharedArrayBufferView& data)
+{
+    BufferSubDataT(target, byteOffset, data);
 }
 
 already_AddRefed<WebGLBuffer>
 WebGLContext::CreateBuffer()
 {
     if (IsContextLost())
         return nullptr;
 
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1376,20 +1376,42 @@ IsFormatAndTypeUnpackable(GLenum format,
     case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
         return format == LOCAL_GL_RGB;
 
     default:
         return false;
     }
 }
 
+// This function is temporary, and will be removed once https://bugzilla.mozilla.org/show_bug.cgi?id=1176214 lands, which will
+// collapse the SharedArrayBufferView and ArrayBufferView into one.
+void
+ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
+                     void** const out_data, size_t* const out_length,
+                     js::Scalar::Type* const out_type)
+{
+    if (view.IsArrayBufferView()) {
+        const dom::ArrayBufferView& pixbuf = view.GetAsArrayBufferView();
+        pixbuf.ComputeLengthAndData();
+        *out_length = pixbuf.Length();
+        *out_data = pixbuf.Data();
+        *out_type = JS_GetArrayBufferViewType(pixbuf.Obj());
+    } else {
+        const dom::SharedArrayBufferView& pixbuf = view.GetAsSharedArrayBufferView();
+        pixbuf.ComputeLengthAndData();
+        *out_length = pixbuf.Length();
+        *out_data = pixbuf.Data();
+        *out_type = JS_GetSharedArrayBufferViewType(pixbuf.Obj());
+    }
+}
+
 void
 WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
                          GLsizei height, GLenum format,
-                         GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
+                         GLenum type, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
                          ErrorResult& rv)
 {
     if (IsContextLost())
         return;
 
     if (mCanvasElement &&
         mCanvasElement->IsWriteOnly() &&
         !nsContentUtils::IsCallerChrome())
@@ -1455,18 +1477,23 @@ WebGLContext::ReadPixels(GLint x, GLint 
         bytesPerPixel = 2*channels;
         requiredDataType = js::Scalar::Uint16;
         break;
 
     default:
         MOZ_CRASH("bad `type`");
     }
 
-    const dom::ArrayBufferView& pixbuf = pixels.Value();
-    int dataType = pixbuf.Type();
+    const dom::ArrayBufferViewOrSharedArrayBufferView &view = pixels.Value();
+    // Compute length and data.  Don't reenter after this point, lest the
+    // precomputed go out of sync with the instant length/data.
+    size_t dataByteLen;
+    void* data;
+    js::Scalar::Type dataType;
+    ComputeLengthAndData(view, &data, &dataByteLen, &dataType);
 
     // Check the pixels param type
     if (dataType != requiredDataType)
         return ErrorInvalidOperation("readPixels: Mismatched type/pixels types");
 
     // Check the pixels param size
     CheckedUint32 checked_neededByteLength =
         GetImageSize(height, width, 1, bytesPerPixel, mPixelStorePackAlignment);
@@ -1474,25 +1501,19 @@ WebGLContext::ReadPixels(GLint x, GLint 
     CheckedUint32 checked_plainRowSize = CheckedUint32(width) * bytesPerPixel;
 
     CheckedUint32 checked_alignedRowSize =
         RoundedToNextMultipleOf(checked_plainRowSize, mPixelStorePackAlignment);
 
     if (!checked_neededByteLength.isValid())
         return ErrorInvalidOperation("readPixels: integer overflow computing the needed buffer size");
 
-    // Compute length and data.  Don't reenter after this point, lest the
-    // precomputed go out of sync with the instant length/data.
-    pixbuf.ComputeLengthAndData();
-
-    uint32_t dataByteLen = pixbuf.Length();
     if (checked_neededByteLength.value() > dataByteLen)
         return ErrorInvalidOperation("readPixels: buffer too small");
 
-    void* data = pixbuf.Data();
     if (!data) {
         ErrorOutOfMemory("readPixels: buffer storage is null. Did we run out of memory?");
         return rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     }
 
     MakeContextCurrent();
 
     bool isSourceTypeFloat;
--- a/dom/canvas/WebGLContextTextures.cpp
+++ b/dom/canvas/WebGLContextTextures.cpp
@@ -293,17 +293,17 @@ WebGLContext::TexImage2D(GLenum rawTexIm
     tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, elem,
                     out_rv);
 }
 
 void
 WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
                          GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
                          GLenum unpackType,
-                         const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                         const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                          ErrorResult& out_rv)
 {
     TexImageTarget texImageTarget;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
                                 &tex))
     {
         return;
@@ -351,17 +351,17 @@ WebGLContext::TexSubImage2D(GLenum rawTe
     tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
                        elem, out_rv);
 }
 
 void
 WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
                             GLint yOffset, GLsizei width, GLsizei height,
                             GLenum unpackFormat, GLenum unpackType,
-                            const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                            const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                             ErrorResult& out_rv)
 {
     TexImageTarget texImageTarget;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
                                 &tex))
     {
         return;
@@ -429,17 +429,17 @@ WebGLContext::CopyTexSubImage2D(GLenum r
 
 //////////////////////////////////////////////////////////////////////////////////////////
 // CompressedTex(Sub)Image
 
 
 void
 WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
                                    GLenum internalFormat, GLsizei width, GLsizei height,
-                                   GLint border, const dom::ArrayBufferView& view)
+                                   GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
 {
     TexImageTarget texImageTarget;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexImage2D",
                                 &texImageTarget, &tex))
     {
         return;
     }
@@ -447,17 +447,17 @@ WebGLContext::CompressedTexImage2D(GLenu
     tex->CompressedTexImage2D(texImageTarget, level, internalFormat, width, height,
                               border, view);
 }
 
 void
 WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
                                       GLint xOffset, GLint yOffset, GLsizei width,
                                       GLsizei height, GLenum unpackFormat,
-                                      const dom::ArrayBufferView& view)
+                                      const dom::ArrayBufferViewOrSharedArrayBufferView& view)
 {
     TexImageTarget texImageTarget;
     WebGLTexture* tex;
     if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexSubImage2D",
                                 &texImageTarget, &tex))
     {
         return;
     }
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -19,16 +19,17 @@
 #include "WebGLStrongTypes.h"
 
 namespace mozilla {
 class ErrorResult;
 
 namespace dom {
 class Element;
 class ImageData;
+class ArrayBufferViewOrSharedArrayBufferView;
 } // namespace dom
 
 // Zero is not an integer power of two.
 inline bool
 IsPOTAssumingNonnegative(GLsizei x)
 {
     MOZ_ASSERT(x >= 0);
     return x && (x & (x-1)) == 0;
@@ -103,34 +104,34 @@ public:
     void TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntParam,
                       GLfloat* maybeFloatParam);
 
     ////////////////////////////////////
     // WebGLTextureUpload.cpp
 
     void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level,
                               GLenum internalFormat, GLsizei width, GLsizei height,
-                              GLint border, const dom::ArrayBufferView& view);
+                              GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view);
 
     void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level,
                               GLenum internalFormat, GLsizei width, GLsizei height,
                               GLsizei depth, GLint border, GLsizei imageSize,
-                              const dom::ArrayBufferView& view);
+                              const dom::ArrayBufferViewOrSharedArrayBufferView& view);
 
 
     void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level,
                                  GLint xOffset, GLint yOffset, GLsizei width,
                                  GLsizei height, GLenum unpackFormat,
-                                 const dom::ArrayBufferView& view);
+                                 const dom::ArrayBufferViewOrSharedArrayBufferView& view);
 
     void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level,
                                  GLint xOffset, GLint yOffset, GLint zOffset,
                                  GLsizei width, GLsizei height, GLsizei depth,
                                  GLenum unpackFormat, GLsizei imageSize,
-                                 const dom::ArrayBufferView& view);
+                                 const dom::ArrayBufferViewOrSharedArrayBufferView& view);
 
 
     void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
                         GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
 
 
     void CopyTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                            GLint yOffset, GLint x, GLint y, GLsizei width,
@@ -139,54 +140,54 @@ public:
     void CopyTexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                            GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width,
                            GLsizei height);
 
 
     void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
                     GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
                     GLenum unpackType,
-                    const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                    const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                     ErrorResult* const out_rv);
     void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
                     ErrorResult* const out_rv);
     void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
                     GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
                     ErrorResult* const out_rv);
 
     void TexImage3D(TexImageTarget target, GLint level, GLenum internalFormat,
                     GLsizei width, GLsizei height, GLsizei depth, GLint border,
                     GLenum unpackFormat, GLenum unpackType,
-                    const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                    const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                     ErrorResult* const out_rv);
 
 
     void TexStorage2D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
                       GLsizei width, GLsizei height);
     void TexStorage3D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
                       GLsizei width, GLsizei height, GLsizei depth);
 
 
     void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                        GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat,
                        GLenum unpackType,
-                       const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                       const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                        ErrorResult* const out_rv);
     void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                        GLint yOffset, GLenum unpackFormat, GLenum unpackType,
                        dom::ImageData* imageData, ErrorResult* const out_rv);
     void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                        GLint yOffset, GLenum unpackFormat, GLenum unpackType,
                        dom::Element* elem, ErrorResult* const out_rv);
 
     void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                        GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
                        GLsizei depth, GLenum unpackFormat, GLenum unpackType,
-                       const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                       const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                        ErrorResult* const out_rv);
     void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                        GLint yOffset, GLint zOffset, GLenum unpackFormat,
                        GLenum unpackType, dom::ImageData* imageData,
                        ErrorResult* const out_rv);
     void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                        GLint yOffset, GLint zOffset, GLenum unpackFormat,
                        GLenum unpackType, dom::Element* elem, ErrorResult* const out_rv);
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -53,17 +53,17 @@ DoesTargetMatchDimensions(WebGLContext* 
     return true;
 }
 
 void
 WebGLTexture::CompressedTexImage2D(TexImageTarget texImageTarget,
                                    GLint level,
                                    GLenum internalFormat,
                                    GLsizei width, GLsizei height, GLint border,
-                                   const dom::ArrayBufferView& view)
+                                   const dom::ArrayBufferViewOrSharedArrayBufferView& view)
 {
     const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexImage;
     const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
 
     const char funcName[] = "compressedTexImage2D";
     if (!DoesTargetMatchDimensions(mContext, texImageTarget, 2, funcName))
         return;
 
@@ -71,19 +71,21 @@ WebGLTexture::CompressedTexImage2D(TexIm
                           0, 0, 0, width, height, 0,
                           border, LOCAL_GL_NONE,
                           LOCAL_GL_NONE,
                           func, dims))
     {
         return;
     }
 
-    view.ComputeLengthAndData();
+    size_t byteLength;
+    void* data;
+    js::Scalar::Type dataType;
+    ComputeLengthAndData(view, &data, &byteLength, &dataType);
 
-    uint32_t byteLength = view.Length();
     if (!mContext->ValidateCompTexImageDataSize(level, internalFormat, width, height, byteLength, func, dims)) {
         return;
     }
 
     if (!mContext->ValidateCompTexImageSize(level, internalFormat, 0, 0, width, height, width, height, func, dims))
     {
         return;
     }
@@ -91,27 +93,27 @@ WebGLTexture::CompressedTexImage2D(TexIm
     if (mImmutable) {
         return mContext->ErrorInvalidOperation(
             "compressedTexImage2D: disallowed because the texture bound to "
             "this target has already been made immutable by texStorage2D");
     }
 
     mContext->MakeContextCurrent();
     gl::GLContext* gl = mContext->gl;
-    gl->fCompressedTexImage2D(texImageTarget.get(), level, internalFormat, width, height, border, byteLength, view.Data());
+    gl->fCompressedTexImage2D(texImageTarget.get(), level, internalFormat, width, height, border, byteLength, data);
 
     SetImageInfo(texImageTarget, level, width, height, 1, internalFormat,
                       WebGLImageDataStatus::InitializedImageData);
 }
 
 void
 WebGLTexture::CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
                                       GLint yOffset, GLsizei width, GLsizei height,
                                       GLenum internalFormat,
-                                      const dom::ArrayBufferView& view)
+                                      const dom::ArrayBufferViewOrSharedArrayBufferView& view)
 {
     const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexSubImage;
     const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
 
     const char funcName[] = "compressedTexSubImage2D";
     if (!DoesTargetMatchDimensions(mContext, texImageTarget, 2, funcName))
         return;
 
@@ -126,19 +128,21 @@ WebGLTexture::CompressedTexSubImage2D(Te
     }
 
     WebGLTexture::ImageInfo& levelInfo = ImageInfoAt(texImageTarget, level);
 
     if (internalFormat != levelInfo.EffectiveInternalFormat()) {
         return mContext->ErrorInvalidOperation("compressedTexImage2D: internalFormat does not match the existing image");
     }
 
-    view.ComputeLengthAndData();
+    size_t byteLength;
+    void* data;
+    js::Scalar::Type dataType;
+    ComputeLengthAndData(view, &data, &byteLength, &dataType);
 
-    uint32_t byteLength = view.Length();
     if (!mContext->ValidateCompTexImageDataSize(level, internalFormat, width, height, byteLength, func, dims))
         return;
 
     if (!mContext->ValidateCompTexImageSize(level, internalFormat,
                                   xOffset, yOffset,
                                   width, height,
                                   levelInfo.Width(), levelInfo.Height(),
                                   func, dims))
@@ -156,17 +160,17 @@ WebGLTexture::CompressedTexSubImage2D(Te
         } else {
             if (!EnsureInitializedImageData(texImageTarget, level))
                 return;
         }
     }
 
     mContext->MakeContextCurrent();
     gl::GLContext* gl = mContext->gl;
-    gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, internalFormat, byteLength, view.Data());
+    gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, internalFormat, byteLength, data);
 }
 
 void
 WebGLTexture::CopyTexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
                                      TexInternalFormat internalFormat,
                                      GLint xOffset, GLint yOffset, GLint x,
                                      GLint y, GLsizei width, GLsizei height,
                                      bool sub)
@@ -609,33 +613,29 @@ WebGLTexture::TexImage2D_base(TexImageTa
     SetImageInfo(texImageTarget, level, width, height, 1,
                       effectiveInternalFormat, imageInfoStatusIfSuccess);
 }
 
 void
 WebGLTexture::TexImage2D(TexImageTarget texImageTarget, GLint level,
                          GLenum internalFormat, GLsizei width,
                          GLsizei height, GLint border, GLenum unpackFormat,
-                         GLenum unpackType, const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                         GLenum unpackType, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                          ErrorResult* const out_rv)
 {
     void* data;
-    uint32_t length;
+    size_t length;
     js::Scalar::Type jsArrayType;
     if (maybeView.IsNull()) {
         data = nullptr;
         length = 0;
         jsArrayType = js::Scalar::MaxTypedArrayViewType;
     } else {
-        const dom::ArrayBufferView& view = maybeView.Value();
-        view.ComputeLengthAndData();
-
-        data = view.Data();
-        length = view.Length();
-        jsArrayType = view.Type();
+        const auto& view = maybeView.Value();
+        ComputeLengthAndData(view, &data, &length, &jsArrayType);
     }
 
     const char funcName[] = "texImage2D";
     if (!DoesTargetMatchDimensions(mContext, texImageTarget, 2, funcName))
         return;
 
     return TexImage2D_base(texImageTarget, level, internalFormat, width, height, 0, border, unpackFormat, unpackType,
                            data, length, jsArrayType,
@@ -845,32 +845,35 @@ WebGLTexture::TexSubImage2D_base(TexImag
     gl->fTexSubImage2D(texImageTarget.get(), level, xOffset, yOffset, width, height, driverFormat, driverType, pixels);
 }
 
 void
 WebGLTexture::TexSubImage2D(TexImageTarget texImageTarget, GLint level,
                             GLint xOffset, GLint yOffset,
                             GLsizei width, GLsizei height,
                             GLenum unpackFormat, GLenum unpackType,
-                            const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                            const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                             ErrorResult* const out_rv)
 {
     if (maybeView.IsNull())
         return mContext->ErrorInvalidValue("texSubImage2D: pixels must not be null!");
 
-    const dom::ArrayBufferView& view = maybeView.Value();
-    view.ComputeLengthAndData();
+    const auto& view = maybeView.Value();
+    size_t length;
+    void* data;
+    js::Scalar::Type jsArrayType;
+    ComputeLengthAndData(view, &data, &length, &jsArrayType);
 
     const char funcName[] = "texSubImage2D";
     if (!DoesTargetMatchDimensions(mContext, texImageTarget, 2, funcName))
         return;
 
     return TexSubImage2D_base(texImageTarget, level, xOffset, yOffset,
                               width, height, 0, unpackFormat, unpackType,
-                              view.Data(), view.Length(), view.Type(),
+                              data, length, jsArrayType,
                               WebGLTexelFormat::Auto, false);
 }
 
 void
 WebGLTexture::TexSubImage2D(TexImageTarget texImageTarget, GLint level,
                             GLint xOffset, GLint yOffset,
                             GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
                             ErrorResult* const out_rv)
@@ -1206,33 +1209,29 @@ WebGLTexture::TexStorage3D(TexTarget tex
         d = std::max(1, d >> 1);
     }
 }
 
 void
 WebGLTexture::TexImage3D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
                           GLsizei width, GLsizei height, GLsizei depth,
                           GLint border, GLenum unpackFormat, GLenum unpackType,
-                          const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                          const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                           ErrorResult* const out_rv)
 {
     void* data;
     size_t dataLength;
     js::Scalar::Type jsArrayType;
     if (maybeView.IsNull()) {
         data = nullptr;
         dataLength = 0;
         jsArrayType = js::Scalar::MaxTypedArrayViewType;
     } else {
-        const dom::ArrayBufferView& view = maybeView.Value();
-        view.ComputeLengthAndData();
-
-        data = view.Data();
-        dataLength = view.Length();
-        jsArrayType = view.Type();
+        const auto& view = maybeView.Value();
+        ComputeLengthAndData(view, &data, &dataLength, &jsArrayType);
     }
 
     const char funcName[] = "texImage3D";
     if (!DoesTargetMatchDimensions(mContext, texImageTarget, 3, funcName))
         return;
 
     const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
     const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
@@ -1313,24 +1312,27 @@ WebGLTexture::TexImage3D(TexImageTarget 
                            : WebGLImageDataStatus::UninitializedImageData);
 }
 
 void
 WebGLTexture::TexSubImage3D(TexImageTarget texImageTarget, GLint level,
                              GLint xOffset, GLint yOffset, GLint zOffset,
                              GLsizei width, GLsizei height, GLsizei depth,
                              GLenum unpackFormat, GLenum unpackType,
-                             const dom::Nullable<dom::ArrayBufferView>& maybeView,
+                             const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
                              ErrorResult* const out_rv)
 {
     if (maybeView.IsNull())
         return mContext->ErrorInvalidValue("texSubImage3D: pixels must not be null!");
 
-    const dom::ArrayBufferView& view = maybeView.Value();
-    view.ComputeLengthAndData();
+    const auto& view = maybeView.Value();
+    void* data;
+    size_t dataLength;
+    js::Scalar::Type jsArrayType;
+    ComputeLengthAndData(view, &data, &dataLength, &jsArrayType);
 
     const char funcName[] = "texSubImage3D";
     if (!DoesTargetMatchDimensions(mContext, texImageTarget, 3, funcName))
         return;
 
     const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
     const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
 
@@ -1353,20 +1355,16 @@ WebGLTexture::TexSubImage3D(TexImageTarg
     {
         return;
     }
 
     if (unpackType != existingType) {
         return mContext->ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image");
     }
 
-    js::Scalar::Type jsArrayType = view.Type();
-    void* data = view.Data();
-    size_t dataLength = view.Length();
-
     if (!mContext->ValidateTexInputData(unpackType, jsArrayType, func, dims))
         return;
 
     const size_t bitsPerTexel = GetBitsPerTexel(existingEffectiveInternalFormat);
     MOZ_ASSERT((bitsPerTexel % 8) == 0); // should not have compressed formats here.
     size_t srcTexelSize = bitsPerTexel / 8;
 
     if (width == 0 || height == 0 || depth == 0)
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -18,16 +18,17 @@ support-files = captureStream_common.js
 skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
 [webgl-mochitest/test_implicit_color_buffer_float.html]
 [webgl-mochitest/test_highp_fs.html]
 [webgl-mochitest/test_no_arr_points.html]
 skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
 [webgl-mochitest/test_noprog_draw.html]
 [webgl-mochitest/test_privileged_exts.html]
 [webgl-mochitest/test_renderer_strings.html]
+[webgl-mochitest/test_sab_with_webgl.html]
 [webgl-mochitest/test_texsubimage_float.html]
 [webgl-mochitest/test_uninit_data.html]
 [webgl-mochitest/test_webgl_available.html]
 skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
 #[webgl-mochitest/test_webgl_color_buffer_float.html]
 # We haven't cleaned up the Try results yet, but let's get this on the books first.
 [webgl-mochitest/test_webgl_conformance.html]
 skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/test_sab_with_webgl.html
@@ -0,0 +1,200 @@
+<html>
+  <head>
+    <meta charset='UTF-8'>
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' href='/tests/SimpleTest/test.css'>
+  </head>
+  <body>
+<canvas id='c' width='200' height='200'></canvas>
+<canvas id='c2' width='200' height='200'></canvas>
+
+<script>
+
+var gl;
+
+function RGBAToString(arr) {
+  return '[' + arr[0].toPrecision(4) + ', ' +
+               arr[1].toPrecision(4) + ', ' +
+               arr[2].toPrecision(4) + ', ' +
+               arr[3].toPrecision(4) + ']';
+}
+
+function TestScreenColor(gl, r, g, b, a) {
+  var arr = new SharedArrayBuffer(4);
+  var view = new SharedUint8Array(arr);
+  gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, view);
+
+  var err = gl.getError();
+  ok(err == 0, 'Should be no errors.');
+  if (err)
+    return;
+
+  var floatArr;
+  floatArr = new Float32Array(4);
+  floatArr[0] = view[0] / 255.0;
+  floatArr[1] = view[1] / 255.0;
+  floatArr[2] = view[2] / 255.0;
+  floatArr[3] = view[3] / 255.0;
+
+  var testText = RGBAToString(floatArr);
+  var refText = RGBAToString([r, g, b, a]);
+
+  var eps = 1.0 / 255.0;
+  var isSame = (Math.abs(floatArr[0] - r) < eps &&
+                Math.abs(floatArr[1] - g) < eps &&
+                Math.abs(floatArr[2] - b) < eps &&
+                Math.abs(floatArr[3] - a) < eps);
+
+  ok(isSame, 'Should be ' + refText + ', was ' + testText + ',');
+}
+
+// Give ourselves a scope to return early from:
+(function() {
+  var canvas = document.getElementById('c');
+  var attribs = {
+    antialias: false,
+    depth: false,
+  };
+  gl = canvas.getContext('experimental-webgl', attribs);
+  if (!gl) {
+    todo(false, 'WebGL is unavailable.');
+    return;
+  }
+  if (typeof SharedArrayBuffer === 'undefined') {
+    todo(false, 'SharedArrayBuffer is unavailable.');
+    return;
+  }
+  if (SharedFloat32Array === 'undefined') {
+    todo(false, 'SharedFloat32Array is unavailable.');
+    return;
+  }
+
+  var vs = gl.createShader(gl.VERTEX_SHADER);
+  gl.shaderSource(vs, "attribute vec2 aVertCoord; void main(void) { gl_Position = vec4(aVertCoord, 0.0, 1.0); }");
+  gl.compileShader(vs);
+  var fs = gl.createShader(gl.FRAGMENT_SHADER);
+  gl.shaderSource(fs, "precision mediump float; uniform vec4 uFragColor; void main(void) { gl_FragColor = uFragColor; }");
+  gl.compileShader(fs);
+  var prog = gl.createProgram();
+  gl.attachShader(prog, vs);
+  gl.attachShader(prog, fs);
+  gl.linkProgram(prog);
+
+  var success = gl.getProgramParameter(prog, gl.LINK_STATUS);
+  if (!success) {
+    console.log('Error linking program for \'' + vsId + '\' and \'' + fsId + '\'.');
+    console.log('\nLink log: ' + gl.getProgramInfoLog(prog));
+    console.log('\nVert shader log: ' + gl.getShaderInfoLog(vs));
+    console.log('\nFrag shader log: ' + gl.getShaderInfoLog(fs));
+  }
+  ok(prog, 'Program should link.');
+  if (!prog) {
+    return;
+  }
+
+  prog.aVertCoord = gl.getAttribLocation(prog, 'aVertCoord');
+  prog.uFragColor = gl.getUniformLocation(prog, 'uFragColor');
+
+  gl.useProgram(prog);
+
+  // Test gl.bufferData(), gl.bufferSubData() and gl.readPixels() APIs with SAB as input.
+  var arr = new SharedArrayBuffer(8*4);
+  var view = new SharedFloat32Array(arr);
+  view.set(new Float32Array([-1, -1, 1, -1, -1,  1, 1,  1]));
+  var vb = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vb);
+  gl.bufferData(gl.ARRAY_BUFFER, arr, gl.STATIC_DRAW);
+  ok(gl.getError() == 0, 'bufferData with SAB as input parameter works ok.');
+  gl.bufferSubData(gl.ARRAY_BUFFER, 0, arr);
+  ok(gl.getError() == 0, 'bufferSubData with SAB as input parameter works ok.');
+  gl.enableVertexAttribArray(0);
+  gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+  gl.clearColor(0, 0, 0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+  gl.uniform4f(prog.uFragColor, 0.2, 0.4, 0.6, 1.0);
+  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+  var arr = new Uint8Array(4);
+  TestScreenColor(gl, 0.2, 0.4, 0.6, 1.0);
+
+  // Test gl.texImage2D() and gl.texSubImage2D() APIs with SAB as input.
+  var tex = gl.createTexture();
+  gl.bindTexture(gl.TEXTURE_2D, tex);
+  var width = 4;
+  var height = 4;
+  var numChannels = 4;
+  var sab = new SharedArrayBuffer(width * height * numChannels);
+  var data = new SharedUint8Array(sab);
+  for (var i = 0; i < data.length; ++i) {
+    data[i] = i;
+  }
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+  ok(gl.getError() == 0, 'texImage2D() with SAB as input parameter works ok.');
+  gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
+  ok(gl.getError() == 0, 'texSubImage2D() with SAB as input parameter works ok.');
+
+  ok(gl.getError() == 0, 'Should be no errors after test.');
+})();
+
+// Test WebGL 2
+(function() {
+  var canvas = document.getElementById('c2');
+  var attribs = {
+    antialias: false,
+    depth: false,
+  };
+  gl = canvas.getContext('webgl2', attribs);
+  if (!gl) {
+    todo(false, 'WebGL 2 is unavailable.');
+    return;
+  }
+  if (typeof SharedArrayBuffer === 'undefined') {
+    todo(false, 'SharedArrayBuffer is unavailable.');
+    return;
+  }
+  if (SharedFloat32Array === 'undefined') {
+    todo(false, 'SharedFloat32Array is unavailable.');
+    return;
+  }
+
+  var arr = new SharedArrayBuffer(8*4);
+  var view = new SharedFloat32Array(arr);
+  view.set(new Float32Array([-1, -1, 1, -1, -1,  1, 1,  1]));
+  var vb = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vb);
+  gl.bufferData(gl.ARRAY_BUFFER, arr, gl.STATIC_DRAW);
+
+  var arr2 = new SharedArrayBuffer(8*4);
+  gl.getBufferSubData(gl.ARRAY_BUFFER, 0, arr2);
+  var view2 = new SharedFloat32Array(arr2);
+  var equal = true;
+  for(var i = 0; i < 8; ++i) {
+    if (view[i] != view2[i]) equal = false;
+  }
+  ok(equal, 'getBufferSubData with SAB as input parameter works ok.');
+
+  // Test gl.texImage3D() and gl.texSubImage3D() APIs with SAB as input.
+  var tex = gl.createTexture();
+  gl.bindTexture(gl.TEXTURE_3D, tex);
+  var width = 4;
+  var height = 4;
+  var depth = 4;
+  var numChannels = 4;
+  var sab = new SharedArrayBuffer(width * height * depth* numChannels);
+  var data = new SharedUint8Array(sab);
+  for (var i = 0; i < data.length; ++i) {
+    data[i] = i;
+  }
+  gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
+  ok(gl.getError() == 0, 'texImage3D() with SAB as input parameter works ok.');
+  gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl.RGBA, gl.UNSIGNED_BYTE, data);
+  ok(gl.getError() == 0, 'texSubImage3D() with SAB as input parameter works ok.');
+
+  ok(gl.getError() == 0, 'Should be no errors after test.');
+})();
+
+ok(true, 'TEST COMPLETE');
+
+</script>
+
+  </body>
+</html>
--- a/dom/webidl/WebGL2RenderingContext.webidl
+++ b/dom/webidl/WebGL2RenderingContext.webidl
@@ -314,16 +314,17 @@ interface WebGL2RenderingContext : WebGL
 
     /* WebGL-specific enums */
     const GLenum MAX_CLIENT_WAIT_TIMEOUT_WEBGL                 = 0x9247;
 
     /* Buffer objects */
     void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset,
                            GLintptr writeOffset, GLsizeiptr size);
     void getBufferSubData(GLenum target, GLintptr offset, ArrayBuffer? returnedData);
+    void getBufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer returnedData);
 
     /* Framebuffer objects */
     void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
                          GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
     void framebufferTextureLayer(GLenum target, GLenum attachment, WebGLTexture? texture, GLint level, GLint layer);
 
     [Throws]
     void invalidateFramebuffer(GLenum target, sequence<GLenum> attachments);
@@ -342,36 +343,36 @@ interface WebGL2RenderingContext : WebGL
     /* Texture objects */
     void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
     void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
                       GLsizei depth);
     [Throws]
     void texImage3D(GLenum target, GLint level, GLenum internalformat,
                     GLsizei width, GLsizei height, GLsizei depth,
                     GLint border, GLenum format,
-                    GLenum type, ArrayBufferView? pixels);
+                    GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
     [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                 GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
-                                ArrayBufferView? pixels);
+                                (ArrayBufferView or SharedArrayBufferView)? pixels);
     [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                 GLenum format, GLenum type, ImageData? data);
     [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                 GLenum format, GLenum type, HTMLImageElement image);
     [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                 GLenum format, GLenum type, HTMLCanvasElement canvas);
     [Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                 GLenum format, GLenum type, HTMLVideoElement video);
     void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                            GLint x, GLint y, GLsizei width, GLsizei height);
     void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
                               GLsizei width, GLsizei height, GLsizei depth,
-                              GLint border, GLsizei imageSize, ArrayBufferView data);
+                              GLint border, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
     void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
                                  GLsizei width, GLsizei height, GLsizei depth,
-                                 GLenum format, GLsizei imageSize, ArrayBufferView data);
+                                 GLenum format, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
 
     /* Programs and shaders */
     [WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram? program, DOMString name);
 
     /* Uniforms and attributes */
     void uniform1ui(WebGLUniformLocation? location, GLuint v0);
     void uniform2ui(WebGLUniformLocation? location, GLuint v0, GLuint v1);
     void uniform3ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2);
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -547,35 +547,39 @@ interface WebGLRenderingContext {
     void blendEquation(GLenum mode);
     void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
     void blendFunc(GLenum sfactor, GLenum dfactor);
     void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
                            GLenum srcAlpha, GLenum dstAlpha);
 
     void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
     void bufferData(GLenum target, ArrayBufferView data, GLenum usage);
+    void bufferData(GLenum target, SharedArrayBufferView data, GLenum usage);
     void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
+    void bufferData(GLenum target, SharedArrayBuffer data, GLenum usage);
     void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView data);
+    void bufferSubData(GLenum target, GLintptr offset, SharedArrayBufferView data);
     void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data);
+    void bufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer data);
 
     [WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target);
     void clear(GLbitfield mask);
     void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
     void clearDepth(GLclampf depth);
     void clearStencil(GLint s);
     void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
     void compileShader(WebGLShader? shader);
 
     void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
                               GLsizei width, GLsizei height, GLint border,
-                              ArrayBufferView data);
+                              (ArrayBufferView or SharedArrayBufferView) data);
     void compressedTexSubImage2D(GLenum target, GLint level,
                                  GLint xoffset, GLint yoffset,
                                  GLsizei width, GLsizei height, GLenum format,
-                                 ArrayBufferView data);
+                                 (ArrayBufferView or SharedArrayBufferView) data);
 
     void copyTexImage2D(GLenum target, GLint level, GLenum internalformat,
                         GLint x, GLint y, GLsizei width, GLsizei height,
                         GLint border);
     void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
                            GLint x, GLint y, GLsizei width, GLsizei height);
 
     WebGLBuffer? createBuffer();
@@ -668,17 +672,17 @@ interface WebGLRenderingContext {
     [WebGLHandlesContextLoss] GLboolean isTexture(WebGLTexture? texture);
     void lineWidth(GLfloat width);
     void linkProgram(WebGLProgram? program);
     void pixelStorei(GLenum pname, GLint param);
     void polygonOffset(GLfloat factor, GLfloat units);
 
     [Throws]
     void readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
-                    GLenum format, GLenum type, ArrayBufferView? pixels);
+                    GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
 
     void renderbufferStorage(GLenum target, GLenum internalformat,
                              GLsizei width, GLsizei height);
     void sampleCoverage(GLclampf value, GLboolean invert);
     void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
 
     void shaderSource(WebGLShader? shader, DOMString source);
 
@@ -688,17 +692,17 @@ interface WebGLRenderingContext {
     void stencilMaskSeparate(GLenum face, GLuint mask);
     void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
     void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
 
 
     [Throws]
     void texImage2D(GLenum target, GLint level, GLenum internalformat,
                     GLsizei width, GLsizei height, GLint border, GLenum format,
-                    GLenum type, ArrayBufferView? pixels);
+                    GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
     [Throws]
     void texImage2D(GLenum target, GLint level, GLenum internalformat,
                     GLenum format, GLenum type, ImageData? pixels);
     [Throws]
     void texImage2D(GLenum target, GLint level, GLenum internalformat,
                     GLenum format, GLenum type, HTMLImageElement image); // May throw DOMException
     [Throws]
     void texImage2D(GLenum target, GLint level, GLenum internalformat,
@@ -708,17 +712,17 @@ interface WebGLRenderingContext {
                     GLenum format, GLenum type, HTMLVideoElement video); // May throw DOMException
 
     void texParameterf(GLenum target, GLenum pname, GLfloat param);
     void texParameteri(GLenum target, GLenum pname, GLint param);
 
     [Throws]
     void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
                        GLsizei width, GLsizei height,
-                       GLenum format, GLenum type, ArrayBufferView? pixels);
+                       GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
     [Throws]
     void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
                        GLenum format, GLenum type, ImageData? pixels);
     [Throws]
     void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
                        GLenum format, GLenum type, HTMLImageElement image); // May throw DOMException
     [Throws]
     void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,