Bug 1318507 - Update implementation. - r=ethlin draft
authorJeff Gilbert (:jgilbert) <jgilbert@mozilla.com>
Tue, 01 Nov 2016 14:58:07 -0700
changeset 440659 2e756b2efdfecc0f66c91268a3fa5621d639acdf
parent 440658 cf7cd7122afc693a81fa5b3afbb7273576ee9f6e
child 440660 6d2639f914192ef9c067622893824851096a0eb0
push id36289
push userbmo:jgilbert@mozilla.com
push dateThu, 17 Nov 2016 23:45:22 +0000
reviewersethlin
bugs1318507
milestone53.0a1
Bug 1318507 - Update implementation. - r=ethlin
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextPrograms.cpp
dom/canvas/WebGL2ContextQueries.cpp
dom/canvas/WebGL2ContextSync.cpp
dom/canvas/WebGL2ContextTransformFeedback.cpp
dom/canvas/WebGL2ContextUniforms.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextBuffers.cpp
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLContextValidate.cpp
dom/canvas/WebGLExtensionDebugShaders.cpp
dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
dom/canvas/WebGLExtensions.h
dom/canvas/WebGLProgram.cpp
dom/canvas/WebGLProgram.h
dom/canvas/WebGLSampler.cpp
dom/canvas/WebGLSampler.h
dom/canvas/WebGLUniformLocation.cpp
dom/canvas/WebGLUniformLocation.h
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -197,19 +197,26 @@ public:
         const TexImageSourceAdapter src(anySrc, &out_error);
         TexSubImage3D(target, level, xOffset, yOffset, zOffset, width, height, depth,
                       unpackFormat, unpackType, src);
     }
 
     void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
                        GLenum unpackFormat, GLenum unpackType,
-                       const dom::ArrayBufferView& srcView, GLuint srcElemOffset,
-                       ErrorResult&)
+                       const dom::Nullable<dom::ArrayBufferView>& maybeSrcView,
+                       GLuint srcElemOffset, ErrorResult&)
     {
+        if (IsContextLost())
+            return;
+
+        if (!ValidateNonNull("texSubImage3D", maybeSrcView))
+            return;
+        const auto& srcView = maybeSrcView.Value();
+
         const TexImageSourceAdapter src(srcView, srcElemOffset);
         TexSubImage3D(target, level, xOffset, yOffset, zOffset, width, height, depth,
                       unpackFormat, unpackType, src);
     }
 
 protected:
     void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
                        GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
@@ -219,17 +226,17 @@ protected:
         const uint8_t funcDims = 3;
         TexSubImage(funcName, funcDims, target, level, xOffset, yOffset, zOffset, width,
                     height, depth, unpackFormat, unpackType, src);
     }
 
 public:
     // -------------------------------------------------------------------------
     // Programs and shaders - WebGL2ContextPrograms.cpp
-    GLint GetFragDataLocation(WebGLProgram* program, const nsAString& name);
+    GLint GetFragDataLocation(const WebGLProgram& program, const nsAString& name);
 
 
     // -------------------------------------------------------------------------
     // Uniforms and attributes - WebGL2ContextUniforms.cpp
     void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
 
     ////////////////
 
@@ -304,78 +311,77 @@ public:
 
     // -------------------------------------------------------------------------
     // Sampler Objects - WebGL2ContextSamplers.cpp
 
     already_AddRefed<WebGLSampler> CreateSampler();
     void DeleteSampler(WebGLSampler* sampler);
     bool IsSampler(WebGLSampler* sampler);
     void BindSampler(GLuint unit, WebGLSampler* sampler);
-    void SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param);
-    void SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Int32Array& param);
-    void SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Sequence<GLint>& param);
-    void SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param);
-    void SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Float32Array& param);
-    void SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Sequence<GLfloat>& param);
-    void GetSamplerParameter(JSContext*, WebGLSampler* sampler, GLenum pname, JS::MutableHandleValue retval);
+    void SamplerParameteri(WebGLSampler& sampler, GLenum pname, GLint param);
+    void SamplerParameterf(WebGLSampler& sampler, GLenum pname, GLfloat param);
+    void GetSamplerParameter(JSContext*, const WebGLSampler& sampler, GLenum pname,
+                             JS::MutableHandleValue retval);
 
 
     // -------------------------------------------------------------------------
     // Sync objects - WebGL2ContextSync.cpp
 
     already_AddRefed<WebGLSync> FenceSync(GLenum condition, GLbitfield flags);
     bool IsSync(WebGLSync* sync);
     void DeleteSync(WebGLSync* sync);
-    GLenum ClientWaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout);
-    void WaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout);
-    void GetSyncParameter(JSContext*, WebGLSync* sync, GLenum pname, JS::MutableHandleValue retval);
+    GLenum ClientWaitSync(const WebGLSync& sync, GLbitfield flags, GLuint64 timeout);
+    void WaitSync(const WebGLSync& sync, GLbitfield flags, GLint64 timeout);
+    void GetSyncParameter(JSContext*, const WebGLSync& sync, GLenum pname,
+                          JS::MutableHandleValue retval);
 
 
     // -------------------------------------------------------------------------
     // Transform Feedback - WebGL2ContextTransformFeedback.cpp
 
     already_AddRefed<WebGLTransformFeedback> CreateTransformFeedback();
     void DeleteTransformFeedback(WebGLTransformFeedback* tf);
     bool IsTransformFeedback(WebGLTransformFeedback* tf);
     void BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf);
     void BeginTransformFeedback(GLenum primitiveMode);
     void EndTransformFeedback();
     void PauseTransformFeedback();
     void ResumeTransformFeedback();
-    void TransformFeedbackVaryings(WebGLProgram* program, const dom::Sequence<nsString>& varyings, GLenum bufferMode);
-    already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(WebGLProgram* program, GLuint index);
+    void TransformFeedbackVaryings(WebGLProgram& program,
+                                   const dom::Sequence<nsString>& varyings,
+                                   GLenum bufferMode);
+    already_AddRefed<WebGLActiveInfo>
+    GetTransformFeedbackVarying(const WebGLProgram& program, GLuint index);
 
 
     // -------------------------------------------------------------------------
     // Uniform Buffer Objects and Transform Feedback Buffers - WebGL2ContextUniforms.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size);
 */
     virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) override;
     void GetIndexedParameter(JSContext* cx, GLenum target, GLuint index,
                              JS::MutableHandleValue retval, ErrorResult& rv);
-    void GetUniformIndices(WebGLProgram* program,
+    void GetUniformIndices(const WebGLProgram& program,
                            const dom::Sequence<nsString>& uniformNames,
                            dom::Nullable< nsTArray<GLuint> >& retval);
-    void GetActiveUniforms(JSContext* cx,
-                           WebGLProgram* program,
-                           const dom::Sequence<GLuint>& uniformIndices,
-                           GLenum pname,
+    void GetActiveUniforms(JSContext* cx, const WebGLProgram& program,
+                           const dom::Sequence<GLuint>& uniformIndices, GLenum pname,
                            JS::MutableHandleValue retval);
 
-    GLuint GetUniformBlockIndex(WebGLProgram* program, const nsAString& uniformBlockName);
-    void GetActiveUniformBlockParameter(JSContext*, WebGLProgram* program,
+    GLuint GetUniformBlockIndex(const WebGLProgram& program,
+                                const nsAString& uniformBlockName);
+    void GetActiveUniformBlockParameter(JSContext*, const WebGLProgram& program,
                                         GLuint uniformBlockIndex, GLenum pname,
-                                        JS::MutableHandleValue retval,
-                                        ErrorResult& rv);
-    void GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex,
+                                        JS::MutableHandleValue retval, ErrorResult& rv);
+    void GetActiveUniformBlockName(const WebGLProgram& program, GLuint uniformBlockIndex,
                                    nsAString& retval);
-    void UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex,
+    void UniformBlockBinding(WebGLProgram& program, GLuint uniformBlockIndex,
                              GLuint uniformBlockBinding);
 
 
     // -------------------------------------------------------------------------
     // Vertex Array Object - WebGL2ContextVAOs.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     already_AddRefed<WebGLVertexArrayObject> CreateVertexArray();
--- a/dom/canvas/WebGL2ContextPrograms.cpp
+++ b/dom/canvas/WebGL2ContextPrograms.cpp
@@ -9,20 +9,20 @@
 #include "WebGLProgram.h"
 
 namespace mozilla {
 
 // -------------------------------------------------------------------------
 // Programs and shaders
 
 GLint
-WebGL2Context::GetFragDataLocation(WebGLProgram* prog, const nsAString& name)
+WebGL2Context::GetFragDataLocation(const WebGLProgram& prog, const nsAString& name)
 {
     if (IsContextLost())
         return -1;
 
-    if (!ValidateObject("getFragDataLocation: program", prog))
+    if (!ValidateObjectRef("getFragDataLocation: program", prog))
         return -1;
 
-    return prog->GetFragDataLocation(name);
+    return prog.GetFragDataLocation(name);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextQueries.cpp
+++ b/dom/canvas/WebGL2ContextQueries.cpp
@@ -105,41 +105,41 @@ WebGLContext::IsQuery(const WebGLQuery* 
 
     if (!ValidateObjectAllowDeleted("isQuery", query))
         return false;
 
     return query->IsQuery();
 }
 
 void
-WebGLContext::BeginQuery(GLenum target, WebGLQuery* query, const char* funcName)
+WebGLContext::BeginQuery(GLenum target, WebGLQuery& query, const char* funcName)
 {
     if (!funcName) {
         funcName = "beginQuery";
     }
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeleted(funcName, query))
+    if (!ValidateObjectAllowDeleted(funcName, &query))
         return;
 
-    if (query->IsDeleted())
+    if (query.IsDeleted())
         return ErrorInvalidOperation("%s: Cannot begin a deleted query.", funcName);
 
     const auto& slot = ValidateQuerySlotByTarget(funcName, target);
     if (!slot)
         return;
 
     if (*slot)
         return ErrorInvalidOperation("%s: Query target already active.", funcName);
 
     ////
 
-    query->BeginQuery(target, *slot);
+    query.BeginQuery(target, *slot);
 }
 
 void
 WebGLContext::EndQuery(GLenum target, const char* funcName)
 {
     if (!funcName) {
         funcName = "endQuery";
     }
@@ -222,29 +222,29 @@ WebGLContext::GetQuery(JSContext* cx, GL
         break;
     }
 
     ErrorInvalidEnum("%s: Bad pname.", funcName);
     return;
 }
 
 void
-WebGLContext::GetQueryParameter(JSContext*, const WebGLQuery* query, GLenum pname,
+WebGLContext::GetQueryParameter(JSContext*, const WebGLQuery& query, GLenum pname,
                                 JS::MutableHandleValue retval, const char* funcName)
 {
     if (!funcName) {
         funcName = "getQueryParameter";
     }
 
     retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeleted(funcName, query))
+    if (!ValidateObjectAllowDeleted(funcName, &query))
         return;
 
-    if (query->IsDeleted())
+    if (query.IsDeleted())
         return ErrorInvalidOperation("%s: Query must not be deleted.", funcName);
 
-    query->GetQueryParameter(pname, retval);
+    query.GetQueryParameter(pname, retval);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextSync.cpp
+++ b/dom/canvas/WebGL2ContextSync.cpp
@@ -54,81 +54,83 @@ WebGL2Context::DeleteSync(WebGLSync* syn
 
     if (!sync || sync->IsDeleted())
         return;
 
     sync->RequestDelete();
 }
 
 GLenum
-WebGL2Context::ClientWaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout)
+WebGL2Context::ClientWaitSync(const WebGLSync& sync, GLbitfield flags, GLuint64 timeout)
 {
+    const char funcName[] = "clientWaitSync";
     if (IsContextLost())
         return LOCAL_GL_WAIT_FAILED;
 
-    if (!sync || sync->IsDeleted()) {
-        ErrorInvalidValue("clientWaitSync: sync is not a sync object.");
+    if (!ValidateObjectRef(funcName, sync))
         return LOCAL_GL_WAIT_FAILED;
-    }
 
     if (flags != 0 && flags != LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT) {
-        ErrorInvalidValue("clientWaitSync: flag must be SYNC_FLUSH_COMMANDS_BIT or 0");
+        ErrorInvalidValue("%s: `flags` must be SYNC_FLUSH_COMMANDS_BIT or 0.", funcName);
         return LOCAL_GL_WAIT_FAILED;
     }
 
     MakeContextCurrent();
-    return gl->fClientWaitSync(sync->mGLName, flags, timeout);
+    return gl->fClientWaitSync(sync.mGLName, flags, timeout);
 }
 
 void
-WebGL2Context::WaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout)
+WebGL2Context::WaitSync(const WebGLSync& sync, GLbitfield flags, GLint64 timeout)
 {
+    const char funcName[] = "waitSync";
     if (IsContextLost())
         return;
 
-    if (!sync || sync->IsDeleted()) {
-        ErrorInvalidValue("waitSync: sync is not a sync object.");
+    if (!ValidateObjectRef(funcName, sync))
         return;
-    }
 
     if (flags != 0) {
-        ErrorInvalidValue("waitSync: flags must be 0");
+        ErrorInvalidValue("%s: `flags` must be 0.", funcName);
         return;
     }
 
     if (timeout != LOCAL_GL_TIMEOUT_IGNORED) {
-        ErrorInvalidValue("waitSync: timeout must be TIMEOUT_IGNORED");
+        ErrorInvalidValue("%s: `timeout` must be TIMEOUT_IGNORED.", funcName);
         return;
     }
 
     MakeContextCurrent();
-    gl->fWaitSync(sync->mGLName, flags, timeout);
+    gl->fWaitSync(sync.mGLName, flags, timeout);
 }
 
 void
-WebGL2Context::GetSyncParameter(JSContext*, WebGLSync* sync, GLenum pname, JS::MutableHandleValue retval)
+WebGL2Context::GetSyncParameter(JSContext*, const WebGLSync& sync, GLenum pname,
+                                JS::MutableHandleValue retval)
 {
+    const char funcName[] = "getSyncParameter";
+    retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!sync || sync->IsDeleted()) {
-        ErrorInvalidValue("getSyncParameter: sync is not a sync object.");
+    if (!ValidateObjectRef(funcName, sync))
         return;
-    }
 
-    retval.set(JS::NullValue());
+    ////
+
+    gl->MakeCurrent();
 
     GLint result = 0;
     switch (pname) {
     case LOCAL_GL_OBJECT_TYPE:
     case LOCAL_GL_SYNC_STATUS:
     case LOCAL_GL_SYNC_CONDITION:
     case LOCAL_GL_SYNC_FLAGS:
-        MakeContextCurrent();
-        gl->fGetSynciv(sync->mGLName, pname, 1, nullptr, &result);
+        gl->fGetSynciv(sync.mGLName, pname, 1, nullptr, &result);
         retval.set(JS::Int32Value(result));
         return;
+
+    default:
+        ErrorInvalidEnum("%s: Invalid pname 0x%04x", funcName, pname);
+        return;
     }
-
-    ErrorInvalidEnum("getSyncParameter: Invalid pname 0x%04x", pname);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextTransformFeedback.cpp
+++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp
@@ -131,34 +131,34 @@ WebGL2Context::ResumeTransformFeedback()
 {
     if (IsContextLost())
         return;
 
     mBoundTransformFeedback->ResumeTransformFeedback();
 }
 
 void
-WebGL2Context::TransformFeedbackVaryings(WebGLProgram* program,
+WebGL2Context::TransformFeedbackVaryings(WebGLProgram& program,
                                          const dom::Sequence<nsString>& varyings,
                                          GLenum bufferMode)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("transformFeedbackVaryings: program", program))
+    if (!ValidateObjectRef("transformFeedbackVaryings: program", program))
         return;
 
-    program->TransformFeedbackVaryings(varyings, bufferMode);
+    program.TransformFeedbackVaryings(varyings, bufferMode);
 }
 
 already_AddRefed<WebGLActiveInfo>
-WebGL2Context::GetTransformFeedbackVarying(WebGLProgram* program, GLuint index)
+WebGL2Context::GetTransformFeedbackVarying(const WebGLProgram& program, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObject("getTransformFeedbackVarying: program", program))
+    if (!ValidateObjectRef("getTransformFeedbackVarying: program", program))
         return nullptr;
 
-    return program->GetTransformFeedbackVarying(index);
+    return program.GetTransformFeedbackVarying(index);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -125,31 +125,31 @@ WebGL2Context::GetIndexedParameter(JSCon
         ret = JS::NumberValue(binding.mRangeSize);
         break;
     }
 
     retval.set(ret);
 }
 
 void
-WebGL2Context::GetUniformIndices(WebGLProgram* program,
+WebGL2Context::GetUniformIndices(const WebGLProgram& program,
                                  const dom::Sequence<nsString>& uniformNames,
                                  dom::Nullable< nsTArray<GLuint> >& retval)
 {
     retval.SetNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("getUniformIndices: program", program))
+    if (!ValidateObjectRef("getUniformIndices: program", program))
         return;
 
     if (!uniformNames.Length())
         return;
 
-    program->GetUniformIndices(uniformNames, retval);
+    program.GetUniformIndices(uniformNames, retval);
 }
 
 static bool
 ValidateUniformEnum(WebGLContext* webgl, GLenum pname, const char* info)
 {
     switch (pname) {
     case LOCAL_GL_UNIFORM_TYPE:
     case LOCAL_GL_UNIFORM_SIZE:
@@ -162,149 +162,139 @@ ValidateUniformEnum(WebGLContext* webgl,
 
     default:
         webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
         return false;
     }
 }
 
 void
-WebGL2Context::GetActiveUniforms(JSContext* cx,
-                                 WebGLProgram* program,
+WebGL2Context::GetActiveUniforms(JSContext* cx, const WebGLProgram& program,
                                  const dom::Sequence<GLuint>& uniformIndices,
-                                 GLenum pname,
-                                 JS::MutableHandleValue retval)
+                                 GLenum pname, JS::MutableHandleValue retval)
 {
-    retval.set(JS::NullValue());
+    const char funcName[] = "getActiveUniforms";
+    retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateUniformEnum(this, pname, "getActiveUniforms"))
+    if (!ValidateUniformEnum(this, pname, funcName))
         return;
 
-    if (!ValidateObject("getActiveUniforms: program", program))
-        return;
-
-    size_t count = uniformIndices.Length();
-    if (!count)
+    if (!ValidateObjectRef("getActiveUniforms: program", program))
         return;
 
-    GLuint progname = program->mGLName;
-    Vector<GLint> samples;
-    if (!samples.resize(count)) {
+    const auto& count = uniformIndices.Length();
+
+    JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
+    UniquePtr<GLint[]> samples(new GLint[count]);
+    if (!array || !samples) {
+        ErrorOutOfMemory("%s: Failed to allocate buffers.", funcName);
         return;
     }
+    retval.setObject(*array);
 
     MakeContextCurrent();
-    gl->fGetActiveUniformsiv(progname, count, uniformIndices.Elements(), pname,
-                             samples.begin());
-
-    JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
-    if (!array) {
-        return;
-    }
+    gl->fGetActiveUniformsiv(program.mGLName, count, uniformIndices.Elements(), pname,
+                             samples.get());
 
     switch (pname) {
     case LOCAL_GL_UNIFORM_TYPE:
     case LOCAL_GL_UNIFORM_SIZE:
     case LOCAL_GL_UNIFORM_BLOCK_INDEX:
     case LOCAL_GL_UNIFORM_OFFSET:
     case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
     case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
-        for (uint32_t i = 0; i < count; ++i) {
+        for (size_t i = 0; i < count; ++i) {
             JS::RootedValue value(cx);
             value = JS::Int32Value(samples[i]);
-            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) {
+            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE))
                 return;
-            }
         }
         break;
     case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
-        for (uint32_t i = 0; i < count; ++i) {
+        for (size_t i = 0; i < count; ++i) {
             JS::RootedValue value(cx);
             value = JS::BooleanValue(samples[i]);
-            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) {
+            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE))
                 return;
-            }
         }
         break;
 
     default:
-        return;
+        MOZ_CRASH("Invalid pname");
     }
-
-    retval.setObjectOrNull(array);
 }
 
 GLuint
-WebGL2Context::GetUniformBlockIndex(WebGLProgram* program,
+WebGL2Context::GetUniformBlockIndex(const WebGLProgram& program,
                                     const nsAString& uniformBlockName)
 {
     if (IsContextLost())
         return 0;
 
-    if (!ValidateObject("getUniformBlockIndex: program", program))
+    if (!ValidateObjectRef("getUniformBlockIndex: program", program))
         return 0;
 
-    return program->GetUniformBlockIndex(uniformBlockName);
+    return program.GetUniformBlockIndex(uniformBlockName);
 }
 
 void
-WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, WebGLProgram* program,
+WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, const WebGLProgram& program,
                                               GLuint uniformBlockIndex, GLenum pname,
                                               JS::MutableHandleValue out_retval,
                                               ErrorResult& out_error)
 {
-    out_retval.set(JS::NullValue());
+    out_retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("getActiveUniformBlockParameter: program", program))
+    if (!ValidateObjectRef("getActiveUniformBlockParameter: program", program))
         return;
 
     MakeContextCurrent();
 
     switch(pname) {
     case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
     case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
     case LOCAL_GL_UNIFORM_BLOCK_BINDING:
     case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE:
     case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
-        out_retval.set(program->GetActiveUniformBlockParam(uniformBlockIndex, pname));
+        out_retval.set(program.GetActiveUniformBlockParam(uniformBlockIndex, pname));
         return;
 
     case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
-        out_retval.set(program->GetActiveUniformBlockActiveUniforms(cx, uniformBlockIndex,
-                                                                    &out_error));
+        out_retval.set(program.GetActiveUniformBlockActiveUniforms(cx, uniformBlockIndex,
+                                                                   &out_error));
         return;
     }
 
     ErrorInvalidEnumInfo("getActiveUniformBlockParameter: parameter", pname);
 }
 
 void
-WebGL2Context::GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex,
-                                         nsAString& retval)
+WebGL2Context::GetActiveUniformBlockName(const WebGLProgram& program,
+                                         GLuint uniformBlockIndex, nsAString& retval)
 {
     retval.SetIsVoid(true);
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("getActiveUniformBlockName: program", program))
+    if (!ValidateObjectRef("getActiveUniformBlockName: program", program))
         return;
 
-    program->GetActiveUniformBlockName(uniformBlockIndex, retval);
+    program.GetActiveUniformBlockName(uniformBlockIndex, retval);
 }
 
 void
-WebGL2Context::UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex,
+WebGL2Context::UniformBlockBinding(WebGLProgram& program, GLuint uniformBlockIndex,
                                    GLuint uniformBlockBinding)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("uniformBlockBinding: program", program))
+    if (!ValidateObjectRef("uniformBlockBinding: program", program))
         return;
 
-    program->UniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
+    program.UniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -159,29 +159,29 @@ struct WebGLContextOptions
     bool antialias;
     bool preserveDrawingBuffer;
     bool failIfMajorPerformanceCaveat;
 };
 
 // From WebGLContextUtils
 TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
 
-class WebGLIntOrFloat {
-    enum {
+struct WebGLIntOrFloat {
+    const enum {
         Int,
         Float,
         Uint
     } mType;
+
     union {
         GLint i;
         GLfloat f;
         GLuint u;
     } mValue;
 
-public:
     explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; }
     explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; }
 
     GLint AsInt() const { return (mType == Int) ? mValue.i : NS_lroundf(mValue.f); }
     GLfloat AsFloat() const { return (mType == Float) ? mValue.f : GLfloat(mValue.i); }
 };
 
 struct IndexedBufferBinding
@@ -485,77 +485,77 @@ public:
     GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
 
     bool IsContextLost() const { return mContextStatus != ContextNotLost; }
     void GetSupportedExtensions(dom::Nullable< nsTArray<nsString> >& retval,
                                 dom::CallerType callerType);
     void GetExtension(JSContext* cx, const nsAString& name,
                       JS::MutableHandle<JSObject*> retval,
                       dom::CallerType callerType, ErrorResult& rv);
-    void AttachShader(WebGLProgram* prog, WebGLShader* shader);
-    void BindAttribLocation(WebGLProgram* prog, GLuint location,
+    void AttachShader(WebGLProgram& prog, WebGLShader& shader);
+    void BindAttribLocation(WebGLProgram& prog, GLuint location,
                             const nsAString& name);
     void BindFramebuffer(GLenum target, WebGLFramebuffer* fb);
     void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb);
     void BindVertexArray(WebGLVertexArray* vao);
     void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
     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);
     GLenum CheckFramebufferStatus(GLenum target);
     void Clear(GLbitfield mask);
     void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
     void ClearDepth(GLclampf v);
     void ClearStencil(GLint v);
     void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a);
-    void CompileShader(WebGLShader* shader);
+    void CompileShader(WebGLShader& shader);
     void CompileShaderANGLE(WebGLShader* shader);
     void CompileShaderBypass(WebGLShader* shader, const nsCString& shaderSource);
     already_AddRefed<WebGLFramebuffer> CreateFramebuffer();
     already_AddRefed<WebGLProgram> CreateProgram();
     already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
     already_AddRefed<WebGLShader> CreateShader(GLenum type);
     already_AddRefed<WebGLVertexArray> CreateVertexArray();
     void CullFace(GLenum face);
     void DeleteFramebuffer(WebGLFramebuffer* fb);
     void DeleteProgram(WebGLProgram* prog);
     void DeleteRenderbuffer(WebGLRenderbuffer* rb);
     void DeleteShader(WebGLShader* shader);
     void DeleteVertexArray(WebGLVertexArray* vao);
     void DepthFunc(GLenum func);
     void DepthMask(WebGLboolean b);
     void DepthRange(GLclampf zNear, GLclampf zFar);
-    void DetachShader(WebGLProgram* prog, WebGLShader* shader);
+    void DetachShader(WebGLProgram& prog, const WebGLShader& shader);
     void DrawBuffers(const dom::Sequence<GLenum>& buffers);
     void Flush();
     void Finish();
     void FramebufferRenderbuffer(GLenum target, GLenum attachment,
                                  GLenum rbTarget, WebGLRenderbuffer* rb);
     void FramebufferTexture2D(GLenum target, GLenum attachment,
                               GLenum texImageTarget, WebGLTexture* tex,
                               GLint level);
 
     // Framebuffer validation
     bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
                                        const char* funcName,
                                        bool badColorAttachmentIsInvalidOp = false);
 
     void FrontFace(GLenum mode);
-    already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram* prog,
+    already_AddRefed<WebGLActiveInfo> GetActiveAttrib(const WebGLProgram& prog,
                                                       GLuint index);
-    already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram* prog,
+    already_AddRefed<WebGLActiveInfo> GetActiveUniform(const WebGLProgram& prog,
                                                        GLuint index);
 
     void
-    GetAttachedShaders(WebGLProgram* prog,
+    GetAttachedShaders(const WebGLProgram& prog,
                        dom::Nullable<nsTArray<RefPtr<WebGLShader>>>& retval);
 
-    GLint GetAttribLocation(WebGLProgram* prog, const nsAString& name);
+    GLint GetAttribLocation(const WebGLProgram& prog, const nsAString& name);
     JS::Value GetBufferParameter(GLenum target, GLenum pname);
 
     void GetBufferParameter(JSContext*, GLenum target, GLenum pname,
                             JS::MutableHandle<JS::Value> retval)
     {
         retval.set(GetBufferParameter(target, pname));
     }
 
@@ -568,71 +568,70 @@ public:
                                            GLenum attachment, GLenum pname,
                                            JS::MutableHandle<JS::Value> retval,
                                            ErrorResult& rv)
     {
         retval.set(GetFramebufferAttachmentParameter(cx, target, attachment,
                                                      pname, rv));
     }
 
-    JS::Value GetProgramParameter(WebGLProgram* prog, GLenum pname);
+    JS::Value GetProgramParameter(const WebGLProgram& prog, GLenum pname);
 
-    void  GetProgramParameter(JSContext*, WebGLProgram* prog, GLenum pname,
+    void  GetProgramParameter(JSContext*, const WebGLProgram& prog, GLenum pname,
                               JS::MutableHandle<JS::Value> retval)
     {
         retval.set(GetProgramParameter(prog, pname));
     }
 
-    void GetProgramInfoLog(WebGLProgram* prog, nsACString& retval);
-    void GetProgramInfoLog(WebGLProgram* prog, nsAString& retval);
+    void GetProgramInfoLog(const WebGLProgram& prog, nsACString& retval);
+    void GetProgramInfoLog(const WebGLProgram& prog, nsAString& retval);
     JS::Value GetRenderbufferParameter(GLenum target, GLenum pname);
 
     void GetRenderbufferParameter(JSContext*, GLenum target, GLenum pname,
                                   JS::MutableHandle<JS::Value> retval)
     {
         retval.set(GetRenderbufferParameter(target, pname));
     }
 
-    JS::Value GetShaderParameter(WebGLShader* shader, GLenum pname);
+    JS::Value GetShaderParameter(const WebGLShader& shader, GLenum pname);
 
-    void GetShaderParameter(JSContext*, WebGLShader* shader, GLenum pname,
+    void GetShaderParameter(JSContext*, const WebGLShader& shader, GLenum pname,
                             JS::MutableHandle<JS::Value> retval)
     {
         retval.set(GetShaderParameter(shader, pname));
     }
 
     already_AddRefed<WebGLShaderPrecisionFormat>
     GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
 
-    void GetShaderInfoLog(WebGLShader* shader, nsACString& retval);
-    void GetShaderInfoLog(WebGLShader* shader, nsAString& retval);
-    void GetShaderSource(WebGLShader* shader, nsAString& retval);
-    void GetShaderTranslatedSource(WebGLShader* shader, nsAString& retval);
+    void GetShaderInfoLog(const WebGLShader& shader, nsACString& retval);
+    void GetShaderInfoLog(const WebGLShader& shader, nsAString& retval);
+    void GetShaderSource(const WebGLShader& shader, nsAString& retval);
 
-    JS::Value GetUniform(JSContext* cx, WebGLProgram* prog,
-                         WebGLUniformLocation* loc);
+    JS::Value GetUniform(JSContext* cx, const WebGLProgram& prog,
+                         const WebGLUniformLocation& loc);
 
-    void GetUniform(JSContext* cx, WebGLProgram* prog,
-                    WebGLUniformLocation* loc,
+    void GetUniform(JSContext* cx, const WebGLProgram& prog,
+                    const WebGLUniformLocation& loc,
                     JS::MutableHandle<JS::Value> retval)
     {
         retval.set(GetUniform(cx, prog, loc));
     }
 
     already_AddRefed<WebGLUniformLocation>
-    GetUniformLocation(WebGLProgram* prog, const nsAString& name);
+    GetUniformLocation(const WebGLProgram& prog, const nsAString& name);
 
     void Hint(GLenum target, GLenum mode);
     bool IsFramebuffer(WebGLFramebuffer* fb);
     bool IsProgram(WebGLProgram* prog);
     bool IsRenderbuffer(WebGLRenderbuffer* rb);
     bool IsShader(WebGLShader* shader);
     bool IsVertexArray(WebGLVertexArray* vao);
     void LineWidth(GLfloat width);
-    void LinkProgram(WebGLProgram* prog);
+    void LinkProgram(WebGLProgram& prog);
     void PixelStorei(GLenum pname, GLint param);
     void PolygonOffset(GLfloat factor, GLfloat units);
 
     already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
     bool StartVRPresentation();
 protected:
     bool ReadPixels_SharedPrecheck(ErrorResult* const out_error);
     void ReadPixelsImpl(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
@@ -665,17 +664,17 @@ public:
                              GLsizei width, GLsizei height);
 protected:
     void RenderbufferStorage_base(const char* funcName, GLenum target,
                                   GLsizei samples, GLenum internalformat,
                                   GLsizei width, GLsizei height);
 public:
     void SampleCoverage(GLclampf value, WebGLboolean invert);
     void Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
-    void ShaderSource(WebGLShader* shader, const nsAString& source);
+    void ShaderSource(WebGLShader& shader, const nsAString& source);
     void StencilFunc(GLenum func, GLint ref, GLuint mask);
     void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
     void StencilMask(GLuint mask);
     void StencilMaskSeparate(GLenum face, GLuint mask);
     void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
     void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
                            GLenum dppass);
 
@@ -866,17 +865,17 @@ public:
     bool ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
                                           uint8_t setterCols,
                                           uint8_t setterRows,
                                           GLenum setterType,
                                           uint32_t setterArraySize,
                                           bool setterTranspose,
                                           const char* funcName,
                                           uint32_t* out_numElementsToUpload);
-    void ValidateProgram(WebGLProgram* prog);
+    void ValidateProgram(const WebGLProgram& prog);
     bool ValidateUniformLocation(const char* info, WebGLUniformLocation* loc);
     bool ValidateSamplerUniformSetter(const char* info,
                                       WebGLUniformLocation* loc, GLint value);
     void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 // -----------------------------------------------------------------------------
 // WEBGL_lose_context
 public:
     void LoseContext();
@@ -889,32 +888,31 @@ public:
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf,
                          WebGLintptr offset, WebGLsizeiptr size);
 
 private:
     void BufferDataImpl(GLenum target, size_t dataLen, const uint8_t* data, GLenum usage);
 
 public:
     void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage);
+    void BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeSrc,
+                    GLenum usage);
     void BufferData(GLenum target, const dom::ArrayBufferView& srcData, GLenum usage,
                     GLuint srcElemOffset = 0, GLuint srcElemCountOverride = 0);
-    void BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeData,
-                    GLenum usage);
-    void BufferData(GLenum target, const dom::SharedArrayBuffer& data, GLenum usage);
 
 private:
     void BufferSubDataImpl(GLenum target, WebGLsizeiptr dstByteOffset,
                            size_t srcDataLen, const uint8_t* srcData);
 
 public:
     void BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
                        const dom::ArrayBufferView& src, GLuint srcElemOffset = 0,
                        GLuint srcElemCountOverride = 0);
     void BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
-                       const dom::Nullable<dom::ArrayBuffer>& maybeSrc);
+                       const dom::ArrayBuffer& src);
     void BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
                        const dom::SharedArrayBuffer& src);
 
     already_AddRefed<WebGLBuffer> CreateBuffer();
     void DeleteBuffer(WebGLBuffer* buf);
     bool IsBuffer(WebGLBuffer* buf);
 
 protected:
@@ -941,21 +939,21 @@ protected:
 
     WebGLRefPtr<WebGLQuery>*
     ValidateQuerySlotByTarget(const char* funcName, GLenum target);
 
 public:
     already_AddRefed<WebGLQuery> CreateQuery(const char* funcName = nullptr);
     void DeleteQuery(WebGLQuery* query, const char* funcName = nullptr);
     bool IsQuery(const WebGLQuery* query, const char* funcName = nullptr);
-    void BeginQuery(GLenum target, WebGLQuery* query, const char* funcName = nullptr);
+    void BeginQuery(GLenum target, WebGLQuery& query, const char* funcName = nullptr);
     void EndQuery(GLenum target, const char* funcName = nullptr);
     void GetQuery(JSContext* cx, GLenum target, GLenum pname,
                   JS::MutableHandleValue retval, const char* funcName = nullptr);
-    void GetQueryParameter(JSContext* cx, const WebGLQuery* query, GLenum pname,
+    void GetQueryParameter(JSContext* cx, const WebGLQuery& query, GLenum pname,
                            JS::MutableHandleValue retval, const char* funcName = nullptr);
 
 
 // -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 public:
     void Disable(GLenum cap);
     void Enable(GLenum cap);
@@ -1525,19 +1523,16 @@ protected:
     bool ValidateAttribPointer(bool integerMode, GLuint index, GLint size, GLenum type,
                                WebGLboolean normalized, GLsizei stride,
                                WebGLintptr byteOffset, const char* info);
     bool ValidateStencilParamsForDrawCall();
 
     bool ValidateCopyTexImage(TexInternalFormat srcFormat, TexInternalFormat dstformat,
                               WebGLTexImageFunc func, WebGLTexDimensions dims);
 
-    bool ValidateSamplerParameterName(GLenum pname, const char* info);
-    bool ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info);
-
     bool ValidateTexImage(TexImageTarget texImageTarget,
                           GLint level, GLenum internalFormat,
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLint width, GLint height, GLint depth,
                           GLint border, GLenum format, GLenum type,
                           WebGLTexImageFunc func, WebGLTexDimensions dims);
     bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func,
                                 WebGLTexDimensions dims);
@@ -1597,16 +1592,25 @@ protected:
         if (MOZ_UNLIKELY(val < 0)) {
             ErrorInvalidValue("%s: `%s` must be non-negative.", funcName, argName);
             return false;
         }
         return true;
     }
 
 public:
+    template<typename T>
+    bool ValidateNonNull(const char* funcName, const dom::Nullable<T>& maybe) {
+        if (maybe.IsNull()) {
+            ErrorInvalidValue("%s: `null` is invalid.", funcName);
+            return false;
+        }
+        return true;
+    }
+
     bool ValidateArrayBufferView(const char* funcName, const dom::ArrayBufferView& view,
                                  GLuint elemOffset, GLuint elemCountOverride,
                                  uint8_t** const out_bytes, size_t* const out_byteLen);
 
 protected:
     ////
 
     void Invalidate();
@@ -1618,21 +1622,25 @@ protected:
 
     bool ConvertImage(size_t width, size_t height, size_t srcStride,
                       size_t dstStride, const uint8_t* src, uint8_t* dst,
                       WebGLTexelFormat srcFormat, bool srcPremultiplied,
                       WebGLTexelFormat dstFormat, bool dstPremultiplied,
                       size_t dstTexelSize);
 
     //////
-
+public:
     // Returns false if `object` is null or not valid.
     template<class ObjectType>
     bool ValidateObject(const char* info, const ObjectType* object);
 
+    // Returns false if `object` is not valid.
+    template<class ObjectType>
+    bool ValidateObjectRef(const char* info, const ObjectType& object);
+
     // Returns false if `object` is not valid.  Considers null to be valid.
     template<class ObjectType>
     bool ValidateObjectAllowNull(const char* info, const ObjectType* object);
 
     // Returns false if `object` is not valid, but considers deleted objects and
     // null objects valid.
     template<class ObjectType>
     bool ValidateObjectAllowDeletedOrNull(const char* info, const ObjectType* object);
@@ -1927,18 +1935,17 @@ ToSupports(WebGLContext* webgl)
 }
 
 /**
  ** Template implementations
  **/
 
 template<class ObjectType>
 inline bool
-WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info,
-                                               const ObjectType* object)
+WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info, const ObjectType* object)
 {
     if (object && !object->IsCompatibleWithContext(this)) {
         ErrorInvalidOperation("%s: object from different WebGL context "
                               "(or older generation of this one) "
                               "passed as argument", info);
         return false;
     }
 
@@ -1991,16 +1998,24 @@ WebGLContext::ValidateObject(const char*
     if (!object) {
         ErrorInvalidValue("%s: null object passed as argument", info);
         return false;
     }
 
     return ValidateObjectAssumeNonNull(info, object);
 }
 
+template<class ObjectType>
+inline bool
+WebGLContext::ValidateObjectRef(const char* info, const ObjectType& object)
+{
+    MOZ_ASSERT(bool(&object));
+    return ValidateObjectAssumeNonNull(info, &object);
+}
+
 // Returns `value` rounded to the next highest multiple of `multiple`.
 // AKA PadToAlignment, StrideForAlignment.
 template<typename V, typename M>
 V
 RoundUpToMultipleOf(const V& value, const M& multiple)
 {
     return ((value + multiple - 1) / multiple) * multiple;
 }
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -333,35 +333,25 @@ WebGLContext::BufferData(GLenum target, 
     const UniqueBuffer zeroBuffer(calloc(size, 1));
     if (!zeroBuffer)
         return ErrorOutOfMemory("%s: Failed to allocate zeros.", funcName);
 
     BufferDataImpl(target, size_t(size), (const uint8_t*)zeroBuffer.get(), usage);
 }
 
 void
-WebGLContext::BufferData(GLenum target, const dom::SharedArrayBuffer& src, GLenum usage)
-{
-    if (IsContextLost())
-        return;
-
-    src.ComputeLengthAndData();
-    BufferDataImpl(target, src.LengthAllowShared(), src.DataAllowShared(), usage);
-}
-
-void
 WebGLContext::BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeSrc,
                          GLenum usage)
 {
     if (IsContextLost())
         return;
 
-    if (maybeSrc.IsNull())
-        return ErrorInvalidValue("bufferData: null object passed");
-    auto& src = maybeSrc.Value();
+    if (!ValidateNonNull("bufferData", maybeSrc))
+        return;
+    const auto& src = maybeSrc.Value();
 
     src.ComputeLengthAndData();
     BufferDataImpl(target, src.LengthAllowShared(), src.DataAllowShared(), usage);
 }
 
 void
 WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& src, GLenum usage,
                          GLuint srcElemOffset, GLuint srcElemCountOverride)
@@ -421,33 +411,17 @@ WebGLContext::BufferSubDataImpl(GLenum t
     gl->fBufferSubData(target, dstByteOffset, glDataLen, data);
 
     // Warning: Possibly shared memory.  See bug 1225033.
     buffer->ElementArrayCacheBufferSubData(dstByteOffset, data, size_t(glDataLen));
 }
 
 void
 WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
-                            const dom::Nullable<dom::ArrayBuffer>& maybeSrc)
-{
-    if (IsContextLost())
-        return;
-
-    if (maybeSrc.IsNull())
-        return ErrorInvalidValue("BufferSubData: returnedData is null.");
-    auto& src = maybeSrc.Value();
-
-    src.ComputeLengthAndData();
-    BufferSubDataImpl(target, dstByteOffset, src.LengthAllowShared(),
-                      src.DataAllowShared());
-}
-
-void
-WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
-                            const dom::SharedArrayBuffer& src)
+                            const dom::ArrayBuffer& src)
 {
     if (IsContextLost())
         return;
 
     src.ComputeLengthAndData();
     BufferSubDataImpl(target, dstByteOffset, src.LengthAllowShared(),
                       src.DataAllowShared());
 }
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -82,41 +82,41 @@ WebGLContext::ActiveTexture(GLenum textu
     }
 
     MakeContextCurrent();
     mActiveTexture = texture - LOCAL_GL_TEXTURE0;
     gl->fActiveTexture(texture);
 }
 
 void
-WebGLContext::AttachShader(WebGLProgram* program, WebGLShader* shader)
+WebGLContext::AttachShader(WebGLProgram& program, WebGLShader& shader)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("attachShader: program", program) ||
-        !ValidateObject("attachShader: shader", shader))
+    if (!ValidateObjectRef("attachShader: program", program) ||
+        !ValidateObjectRef("attachShader: shader", shader))
     {
         return;
     }
 
-    program->AttachShader(shader);
+    program.AttachShader(&shader);
 }
 
 void
-WebGLContext::BindAttribLocation(WebGLProgram* prog, GLuint location,
+WebGLContext::BindAttribLocation(WebGLProgram& prog, GLuint location,
                                  const nsAString& name)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("bindAttribLocation: program", prog))
+    if (!ValidateObjectRef("bindAttribLocation: program", prog))
         return;
 
-    prog->BindAttribLocation(location, name);
+    prog.BindAttribLocation(location, name);
 }
 
 void
 WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer* wfb)
 {
     if (IsContextLost())
         return;
 
@@ -433,30 +433,30 @@ WebGLContext::DeleteShader(WebGLShader* 
 
     if (!shader || shader->IsDeleted())
         return;
 
     shader->RequestDelete();
 }
 
 void
-WebGLContext::DetachShader(WebGLProgram* program, WebGLShader* shader)
+WebGLContext::DetachShader(WebGLProgram& program, const WebGLShader& shader)
 {
     if (IsContextLost())
         return;
 
     // It's valid to attempt to detach a deleted shader, since it's still a
     // shader.
-    if (!ValidateObject("detachShader: program", program) ||
-        !ValidateObjectAllowDeleted("detashShader: shader", shader))
+    if (!ValidateObjectRef("detachShader: program", program) ||
+        !ValidateObjectAllowDeleted("detachShader: shader", &shader))
     {
         return;
     }
 
-    program->DetachShader(shader);
+    program.DetachShader(&shader);
 }
 
 void
 WebGLContext::DepthFunc(GLenum func)
 {
     if (IsContextLost())
         return;
 
@@ -561,68 +561,63 @@ WebGLContext::FrontFace(GLenum mode)
             return ErrorInvalidEnumInfo("frontFace: mode", mode);
     }
 
     MakeContextCurrent();
     gl->fFrontFace(mode);
 }
 
 already_AddRefed<WebGLActiveInfo>
-WebGLContext::GetActiveAttrib(WebGLProgram* prog, GLuint index)
+WebGLContext::GetActiveAttrib(const WebGLProgram& prog, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObject("getActiveAttrib: program", prog))
+    if (!ValidateObjectRef("getActiveAttrib: program", prog))
         return nullptr;
 
-    return prog->GetActiveAttrib(index);
+    return prog.GetActiveAttrib(index);
 }
 
 already_AddRefed<WebGLActiveInfo>
-WebGLContext::GetActiveUniform(WebGLProgram* prog, GLuint index)
+WebGLContext::GetActiveUniform(const WebGLProgram& prog, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObject("getActiveUniform: program", prog))
+    if (!ValidateObjectRef("getActiveUniform: program", prog))
         return nullptr;
 
-    return prog->GetActiveUniform(index);
+    return prog.GetActiveUniform(index);
 }
 
 void
-WebGLContext::GetAttachedShaders(WebGLProgram* prog,
+WebGLContext::GetAttachedShaders(const WebGLProgram& prog,
                                  dom::Nullable<nsTArray<RefPtr<WebGLShader>>>& retval)
 {
     retval.SetNull();
     if (IsContextLost())
         return;
 
-    if (!prog) {
-        ErrorInvalidValue("getAttachedShaders: Invalid program.");
+    if (!ValidateObjectRef("getAttachedShaders", prog))
         return;
-    }
-
-    if (!ValidateObject("getAttachedShaders", prog))
-        return;
-
-    prog->GetAttachedShaders(&retval.SetValue());
+
+    prog.GetAttachedShaders(&retval.SetValue());
 }
 
 GLint
-WebGLContext::GetAttribLocation(WebGLProgram* prog, const nsAString& name)
+WebGLContext::GetAttribLocation(const WebGLProgram& prog, const nsAString& name)
 {
     if (IsContextLost())
         return -1;
 
-    if (!ValidateObject("getAttribLocation: program", prog))
+    if (!ValidateObjectRef("getAttribLocation: program", prog))
         return -1;
 
-    return prog->GetAttribLocation(name);
+    return prog.GetAttribLocation(name);
 }
 
 JS::Value
 WebGLContext::GetBufferParameter(GLenum target, GLenum pname)
 {
     if (IsContextLost())
         return JS::NullValue();
 
@@ -907,72 +902,70 @@ WebGLContext::GetError()
     MakeContextCurrent();
     GetAndFlushUnderlyingGLErrors();
 
     err = GetAndClearError(&mUnderlyingGLError);
     return err;
 }
 
 JS::Value
-WebGLContext::GetProgramParameter(WebGLProgram* prog, GLenum pname)
+WebGLContext::GetProgramParameter(const WebGLProgram& prog, GLenum pname)
 {
     if (IsContextLost())
         return JS::NullValue();
 
-    if (!ValidateObjectAllowDeleted("getProgramParameter: program", prog))
+    if (!ValidateObjectAllowDeleted("getProgramParameter: program", &prog))
         return JS::NullValue();
 
-    return prog->GetProgramParameter(pname);
+    return prog.GetProgramParameter(pname);
 }
 
 void
-WebGLContext::GetProgramInfoLog(WebGLProgram* prog, nsAString& retval)
+WebGLContext::GetProgramInfoLog(const WebGLProgram& prog, nsAString& retval)
 {
     retval.SetIsVoid(true);
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("getProgramInfoLog: program", prog))
+    if (!ValidateObjectRef("getProgramInfoLog: program", prog))
         return;
 
-    prog->GetProgramInfoLog(&retval);
-
-    retval.SetIsVoid(false);
+    prog.GetProgramInfoLog(&retval);
 }
 
 JS::Value
-WebGLContext::GetUniform(JSContext* js, WebGLProgram* prog,
-                         WebGLUniformLocation* loc)
+WebGLContext::GetUniform(JSContext* js, const WebGLProgram& prog,
+                         const WebGLUniformLocation& loc)
 {
     if (IsContextLost())
         return JS::NullValue();
 
-    if (!ValidateObject("getUniform: `program`", prog))
+    if (!ValidateObjectRef("getUniform: `program`", prog))
         return JS::NullValue();
 
-    if (!ValidateObject("getUniform: `location`", loc))
+    if (!ValidateObjectRef("getUniform: `location`", loc))
         return JS::NullValue();
 
-    if (!loc->ValidateForProgram(prog, "getUniform"))
+    if (!loc.ValidateForProgram(&prog, "getUniform"))
         return JS::NullValue();
 
-    return loc->GetUniform(js);
+    return loc.GetUniform(js);
 }
 
 already_AddRefed<WebGLUniformLocation>
-WebGLContext::GetUniformLocation(WebGLProgram* prog, const nsAString& name)
+WebGLContext::GetUniformLocation(const WebGLProgram& prog, const nsAString& name)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObject("getUniformLocation: program", prog))
+    if (!ValidateObjectRef("getUniformLocation: program", prog))
         return nullptr;
 
-    return prog->GetUniformLocation(name);
+    return prog.GetUniformLocation(name);
 }
 
 void
 WebGLContext::Hint(GLenum target, GLenum mode)
 {
     if (IsContextLost())
         return;
 
@@ -1057,39 +1050,39 @@ WebGLContext::IsShader(WebGLShader* shad
     if (IsContextLost())
         return false;
 
     return ValidateObjectAllowDeleted("isShader", shader) &&
         !shader->IsDeleted();
 }
 
 void
-WebGLContext::LinkProgram(WebGLProgram* prog)
+WebGLContext::LinkProgram(WebGLProgram& prog)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("linkProgram", prog))
+    if (!ValidateObjectRef("linkProgram", prog))
         return;
 
-    prog->LinkProgram();
-
-    if (!prog->IsLinked()) {
+    prog.LinkProgram();
+
+    if (!prog.IsLinked()) {
         // If we failed to link, but `prog == mCurrentProgram`, we are *not* supposed to
         // null out mActiveProgramLinkInfo.
         return;
     }
 
-    if (prog == mCurrentProgram) {
-        mActiveProgramLinkInfo = prog->LinkInfo();
+    if (&prog == mCurrentProgram) {
+        mActiveProgramLinkInfo = prog.LinkInfo();
 
         if (gl->WorkAroundDriverBugs() &&
             gl->Vendor() == gl::GLVendor::NVIDIA)
         {
-            gl->fUseProgram(prog->mGLName);
+            gl->fUseProgram(prog.mGLName);
         }
     }
 }
 
 void
 WebGLContext::PixelStorei(GLenum pname, GLint param)
 {
     if (IsContextLost())
@@ -2209,25 +2202,25 @@ WebGLContext::UseProgram(WebGLProgram* p
 
     if (prog->UseProgram()) {
         mCurrentProgram = prog;
         mActiveProgramLinkInfo = mCurrentProgram->LinkInfo();
     }
 }
 
 void
-WebGLContext::ValidateProgram(WebGLProgram* prog)
+WebGLContext::ValidateProgram(const WebGLProgram& prog)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("validateProgram", prog))
+    if (!ValidateObjectRef("validateProgram", prog))
         return;
 
-    prog->ValidateProgram();
+    prog.ValidateProgram();
 }
 
 already_AddRefed<WebGLFramebuffer>
 WebGLContext::CreateFramebuffer()
 {
     if (IsContextLost())
         return nullptr;
 
@@ -2264,53 +2257,51 @@ WebGLContext::Viewport(GLint x, GLint y,
 
     mViewportX = x;
     mViewportY = y;
     mViewportWidth = width;
     mViewportHeight = height;
 }
 
 void
-WebGLContext::CompileShader(WebGLShader* shader)
+WebGLContext::CompileShader(WebGLShader& shader)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("compileShader", shader))
+    if (!ValidateObjectRef("compileShader", shader))
         return;
 
-    shader->CompileShader();
+    shader.CompileShader();
 }
 
 JS::Value
-WebGLContext::GetShaderParameter(WebGLShader* shader, GLenum pname)
+WebGLContext::GetShaderParameter(const WebGLShader& shader, GLenum pname)
 {
     if (IsContextLost())
         return JS::NullValue();
 
-    if (!ValidateObject("getShaderParameter: shader", shader))
+    if (!ValidateObjectRef("getShaderParameter: shader", shader))
         return JS::NullValue();
 
-    return shader->GetShaderParameter(pname);
+    return shader.GetShaderParameter(pname);
 }
 
 void
-WebGLContext::GetShaderInfoLog(WebGLShader* shader, nsAString& retval)
+WebGLContext::GetShaderInfoLog(const WebGLShader& shader, nsAString& retval)
 {
     retval.SetIsVoid(true);
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("getShaderInfoLog: shader", shader))
+    if (!ValidateObjectRef("getShaderInfoLog: shader", shader))
         return;
 
-    shader->GetShaderInfoLog(&retval);
-
-    retval.SetIsVoid(false);
+    shader.GetShaderInfoLog(&retval);
 }
 
 already_AddRefed<WebGLShaderPrecisionFormat>
 WebGLContext::GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype)
 {
     if (IsContextLost())
         return nullptr;
 
@@ -2352,53 +2343,39 @@ WebGLContext::GetShaderPrecisionFormat(G
     }
 
     RefPtr<WebGLShaderPrecisionFormat> retShaderPrecisionFormat
         = new WebGLShaderPrecisionFormat(this, range[0], range[1], precision);
     return retShaderPrecisionFormat.forget();
 }
 
 void
-WebGLContext::GetShaderSource(WebGLShader* shader, nsAString& retval)
+WebGLContext::GetShaderSource(const WebGLShader& shader, nsAString& retval)
 {
     retval.SetIsVoid(true);
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("getShaderSource: shader", shader))
+    if (!ValidateObjectRef("getShaderSource: shader", shader))
         return;
 
-    shader->GetShaderSource(&retval);
+    shader.GetShaderSource(&retval);
 }
 
 void
-WebGLContext::ShaderSource(WebGLShader* shader, const nsAString& source)
+WebGLContext::ShaderSource(WebGLShader& shader, const nsAString& source)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObject("shaderSource: shader", shader))
+    if (!ValidateObjectRef("shaderSource: shader", shader))
         return;
 
-    shader->ShaderSource(source);
-}
-
-void
-WebGLContext::GetShaderTranslatedSource(WebGLShader* shader, nsAString& retval)
-{
-    retval.SetIsVoid(true);
-
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObject("getShaderTranslatedSource: shader", shader))
-        return;
-
-    shader->GetShaderTranslatedSource(&retval);
+    shader.ShaderSource(source);
 }
 
 void
 WebGLContext::LoseContext()
 {
     if (IsContextLost())
         return ErrorInvalidOperation("loseContext: Context is already lost.");
 
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -235,127 +235,16 @@ WebGLContext::ValidateFramebufferAttachm
         ErrorInvalidOperation("%s: Bad color attachment: COLOR_ATTACHMENT%u. (0x%04x)",
                               funcName, offset, attachment);
     } else {
         ErrorInvalidEnum("%s: attachment: Bad attachment 0x%x.", funcName, attachment);
     }
     return false;
 }
 
-/**
- * Return true if pname is valid for GetSamplerParameter calls.
- */
-bool
-WebGLContext::ValidateSamplerParameterName(GLenum pname, const char* info)
-{
-    switch (pname) {
-    case LOCAL_GL_TEXTURE_MIN_FILTER:
-    case LOCAL_GL_TEXTURE_MAG_FILTER:
-    case LOCAL_GL_TEXTURE_WRAP_S:
-    case LOCAL_GL_TEXTURE_WRAP_T:
-    case LOCAL_GL_TEXTURE_WRAP_R:
-    case LOCAL_GL_TEXTURE_MIN_LOD:
-    case LOCAL_GL_TEXTURE_MAX_LOD:
-    case LOCAL_GL_TEXTURE_COMPARE_MODE:
-    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
-        return true;
-
-    default:
-        ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname));
-        return false;
-    }
-}
-
-/**
- * Return true if pname and param are valid combination for SamplerParameter calls.
- */
-bool
-WebGLContext::ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info)
-{
-    const GLenum p = param.AsInt();
-
-    switch (pname) {
-    case LOCAL_GL_TEXTURE_MIN_FILTER:
-        switch (p) {
-        case LOCAL_GL_NEAREST:
-        case LOCAL_GL_LINEAR:
-        case LOCAL_GL_NEAREST_MIPMAP_NEAREST:
-        case LOCAL_GL_NEAREST_MIPMAP_LINEAR:
-        case LOCAL_GL_LINEAR_MIPMAP_NEAREST:
-        case LOCAL_GL_LINEAR_MIPMAP_LINEAR:
-            return true;
-
-        default:
-            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
-            return false;
-        }
-
-    case LOCAL_GL_TEXTURE_MAG_FILTER:
-        switch (p) {
-        case LOCAL_GL_NEAREST:
-        case LOCAL_GL_LINEAR:
-            return true;
-
-        default:
-            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
-            return false;
-        }
-
-    case LOCAL_GL_TEXTURE_WRAP_S:
-    case LOCAL_GL_TEXTURE_WRAP_T:
-    case LOCAL_GL_TEXTURE_WRAP_R:
-        switch (p) {
-        case LOCAL_GL_CLAMP_TO_EDGE:
-        case LOCAL_GL_REPEAT:
-        case LOCAL_GL_MIRRORED_REPEAT:
-            return true;
-
-        default:
-            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
-            return false;
-        }
-
-    case LOCAL_GL_TEXTURE_MIN_LOD:
-    case LOCAL_GL_TEXTURE_MAX_LOD:
-        return true;
-
-    case LOCAL_GL_TEXTURE_COMPARE_MODE:
-        switch (param.AsInt()) {
-        case LOCAL_GL_NONE:
-        case LOCAL_GL_COMPARE_REF_TO_TEXTURE:
-            return true;
-
-        default:
-            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
-            return false;
-        }
-
-    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
-        switch (p) {
-        case LOCAL_GL_LEQUAL:
-        case LOCAL_GL_GEQUAL:
-        case LOCAL_GL_LESS:
-        case LOCAL_GL_GREATER:
-        case LOCAL_GL_EQUAL:
-        case LOCAL_GL_NOTEQUAL:
-        case LOCAL_GL_ALWAYS:
-        case LOCAL_GL_NEVER:
-            return true;
-
-        default:
-            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
-            return false;
-        }
-
-    default:
-        ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname));
-        return false;
-    }
-}
-
 bool
 WebGLContext::ValidateUniformLocation(WebGLUniformLocation* loc, const char* funcName)
 {
     /* GLES 2.0.25, p38:
      *   If the value of location is -1, the Uniform* commands will silently
      *   ignore the data passed in, and the current uniform values will not be
      *   changed.
      */
--- a/dom/canvas/WebGLExtensionDebugShaders.cpp
+++ b/dom/canvas/WebGLExtensionDebugShaders.cpp
@@ -2,42 +2,48 @@
 /* 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 "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
+#include "WebGLShader.h"
 
 namespace mozilla {
 
 WebGLExtensionDebugShaders::WebGLExtensionDebugShaders(WebGLContext* webgl)
     : WebGLExtensionBase(webgl)
 {
 }
 
 WebGLExtensionDebugShaders::~WebGLExtensionDebugShaders()
 {
 }
 
 // If no source has been defined, compileShader() has not been called, or the
 // translation has failed for shader, an empty string is returned; otherwise,
 // return the translated source.
 void
-WebGLExtensionDebugShaders::GetTranslatedShaderSource(WebGLShader* shader,
-                                                      nsAString& retval)
+WebGLExtensionDebugShaders::GetTranslatedShaderSource(const WebGLShader& shader,
+                                                      nsAString& retval) const
 {
     retval.SetIsVoid(true);
 
     if (mIsLost) {
         mContext->ErrorInvalidOperation("%s: Extension is lost.",
                                         "getTranslatedShaderSource");
         return;
     }
 
-    retval.SetIsVoid(false);
-    mContext->GetShaderTranslatedSource(shader, retval);
+    if (mContext->IsContextLost())
+        return;
+
+    if (!mContext->ValidateObjectRef("getShaderTranslatedSource: shader", shader))
+        return;
+
+    shader.GetShaderTranslatedSource(&retval);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders, WEBGL_debug_shaders)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
+++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
@@ -52,17 +52,17 @@ WebGLExtensionDisjointTimerQuery::IsQuer
     const char funcName[] = "isQueryEXT";
     if (mIsLost)
         return false;
 
     return mContext->IsQuery(query, funcName);
 }
 
 void
-WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, WebGLQuery* query) const
+WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, WebGLQuery& query) const
 {
     const char funcName[] = "beginQueryEXT";
     if (mIsLost)
         return;
 
     mContext->BeginQuery(target, query, funcName);
 }
 
@@ -72,43 +72,43 @@ WebGLExtensionDisjointTimerQuery::EndQue
     const char funcName[] = "endQueryEXT";
     if (mIsLost)
         return;
 
     mContext->EndQuery(target, funcName);
 }
 
 void
-WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery* query, GLenum target) const
+WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery& query, GLenum target) const
 {
     const char funcName[] = "queryCounterEXT";
     if (mIsLost)
         return;
 
-    if (!mContext->ValidateObject(funcName, query))
+    if (!mContext->ValidateObjectRef(funcName, query))
         return;
 
-    query->QueryCounter(funcName, target);
+    query.QueryCounter(funcName, target);
 }
 
 void
 WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, GLenum pname,
                                               JS::MutableHandleValue retval) const
 {
     const char funcName[] = "getQueryEXT";
     retval.setNull();
     if (mIsLost)
         return;
 
     mContext->GetQuery(cx, target, pname, retval, funcName);
 }
 
 void
 WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
-                                                    const WebGLQuery* query, GLenum pname,
+                                                    const WebGLQuery& query, GLenum pname,
                                                     JS::MutableHandleValue retval) const
 {
     const char funcName[] = "getQueryObjectEXT";
     retval.setNull();
     if (mIsLost)
         return;
 
     mContext->GetQueryParameter(cx, query, pname, retval, funcName);
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -122,17 +122,17 @@ public:
 
 class WebGLExtensionDebugShaders
     : public WebGLExtensionBase
 {
 public:
     explicit WebGLExtensionDebugShaders(WebGLContext*);
     virtual ~WebGLExtensionDebugShaders();
 
-    void GetTranslatedShaderSource(WebGLShader* shader, nsAString& retval);
+    void GetTranslatedShaderSource(const WebGLShader& shader, nsAString& retval) const;
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
 class WebGLExtensionDepthTexture
     : public WebGLExtensionBase
 {
 public:
@@ -367,22 +367,22 @@ class WebGLExtensionDisjointTimerQuery
 {
 public:
     explicit WebGLExtensionDisjointTimerQuery(WebGLContext* webgl);
     virtual ~WebGLExtensionDisjointTimerQuery();
 
     already_AddRefed<WebGLQuery> CreateQueryEXT() const;
     void DeleteQueryEXT(WebGLQuery* query) const;
     bool IsQueryEXT(const WebGLQuery* query) const;
-    void BeginQueryEXT(GLenum target, WebGLQuery* query) const;
+    void BeginQueryEXT(GLenum target, WebGLQuery& query) const;
     void EndQueryEXT(GLenum target) const;
-    void QueryCounterEXT(WebGLQuery* query, GLenum target) const;
+    void QueryCounterEXT(WebGLQuery& query, GLenum target) const;
     void GetQueryEXT(JSContext* cx, GLenum target, GLenum pname,
                      JS::MutableHandleValue retval) const;
-    void GetQueryObjectEXT(JSContext* cx, const WebGLQuery* query,
+    void GetQueryObjectEXT(JSContext* cx, const WebGLQuery& query,
                            GLenum pname, JS::MutableHandleValue retval) const;
 
     static bool IsSupported(const WebGLContext*);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
 } // namespace mozilla
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -532,17 +532,17 @@ WebGLProgram::BindAttribLocation(GLuint 
     const bool wasInserted = res.second;
     if (!wasInserted) {
         auto itr = res.first;
         itr->second = loc;
     }
 }
 
 void
-WebGLProgram::DetachShader(WebGLShader* shader)
+WebGLProgram::DetachShader(const WebGLShader* shader)
 {
     MOZ_ASSERT(shader);
 
     WebGLRefPtr<WebGLShader>* shaderSlot;
     switch (shader->mType) {
     case LOCAL_GL_VERTEX_SHADER:
         shaderSlot = &mVertShader;
         break;
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -140,17 +140,17 @@ public:
 
     explicit WebGLProgram(WebGLContext* webgl);
 
     void Delete();
 
     // GL funcs
     void AttachShader(WebGLShader* shader);
     void BindAttribLocation(GLuint index, const nsAString& name);
-    void DetachShader(WebGLShader* shader);
+    void DetachShader(const WebGLShader* shader);
     already_AddRefed<WebGLActiveInfo> GetActiveAttrib(GLuint index) const;
     already_AddRefed<WebGLActiveInfo> GetActiveUniform(GLuint index) const;
     void GetAttachedShaders(nsTArray<RefPtr<WebGLShader>>* const out) const;
     GLint GetAttribLocation(const nsAString& name) const;
     GLint GetFragDataLocation(const nsAString& name) const;
     void GetProgramInfoLog(nsAString* const out) const;
     JS::Value GetProgramParameter(GLenum pname) const;
     GLuint GetUniformBlockIndex(const nsAString& name) const;
--- a/dom/canvas/WebGLSampler.cpp
+++ b/dom/canvas/WebGLSampler.cpp
@@ -48,116 +48,161 @@ WebGLSampler::GetParentObject() const
 }
 
 JSObject*
 WebGLSampler::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
     return dom::WebGLSamplerBinding::Wrap(cx, this, givenProto);
 }
 
-void
-WebGLSampler::SamplerParameter1i(GLenum pname, GLint param)
+static bool
+ValidateSamplerParameterParams(WebGLContext* webgl, const char* funcName, GLenum pname,
+                               GLint paramInt)
 {
     switch (pname) {
     case LOCAL_GL_TEXTURE_MIN_FILTER:
-        mMinFilter = param;
+        switch (paramInt) {
+        case LOCAL_GL_NEAREST:
+        case LOCAL_GL_LINEAR:
+        case LOCAL_GL_NEAREST_MIPMAP_NEAREST:
+        case LOCAL_GL_NEAREST_MIPMAP_LINEAR:
+        case LOCAL_GL_LINEAR_MIPMAP_NEAREST:
+        case LOCAL_GL_LINEAR_MIPMAP_LINEAR:
+            return true;
+
+        default:
+            break;
+        }
         break;
 
     case LOCAL_GL_TEXTURE_MAG_FILTER:
-        mMagFilter = param;
+        switch (paramInt) {
+        case LOCAL_GL_NEAREST:
+        case LOCAL_GL_LINEAR:
+            return true;
+
+        default:
+            break;
+        }
         break;
 
     case LOCAL_GL_TEXTURE_WRAP_S:
-        mWrapS = param;
+    case LOCAL_GL_TEXTURE_WRAP_T:
+    case LOCAL_GL_TEXTURE_WRAP_R:
+        switch (paramInt) {
+        case LOCAL_GL_CLAMP_TO_EDGE:
+        case LOCAL_GL_REPEAT:
+        case LOCAL_GL_MIRRORED_REPEAT:
+            return true;
+
+        default:
+            break;
+        }
+        break;
+
+    case LOCAL_GL_TEXTURE_MIN_LOD:
+    case LOCAL_GL_TEXTURE_MAX_LOD:
+        return true;
+
+    case LOCAL_GL_TEXTURE_COMPARE_MODE:
+        switch (paramInt) {
+        case LOCAL_GL_NONE:
+        case LOCAL_GL_COMPARE_REF_TO_TEXTURE:
+            return true;
+
+        default:
+            break;
+        }
+        break;
+
+    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
+        switch (paramInt) {
+        case LOCAL_GL_LEQUAL:
+        case LOCAL_GL_GEQUAL:
+        case LOCAL_GL_LESS:
+        case LOCAL_GL_GREATER:
+        case LOCAL_GL_EQUAL:
+        case LOCAL_GL_NOTEQUAL:
+        case LOCAL_GL_ALWAYS:
+        case LOCAL_GL_NEVER:
+            return true;
+
+        default:
+            break;
+        }
+        break;
+
+    default:
+        webgl->ErrorInvalidEnum("%s: invalid pname: %s", funcName,
+                                webgl->EnumName(pname));
+        return false;
+    }
+
+    webgl->ErrorInvalidEnum("%s: invalid param: %s", funcName, webgl->EnumName(paramInt));
+    return false;
+}
+
+void
+WebGLSampler::SamplerParameter(const char* funcName, GLenum pname, GLint paramInt)
+{
+    if (!ValidateSamplerParameterParams(mContext, funcName, pname, paramInt))
+        return;
+
+    switch (pname) {
+    case LOCAL_GL_TEXTURE_MIN_FILTER:
+        mMinFilter = paramInt;
+        break;
+
+    case LOCAL_GL_TEXTURE_MAG_FILTER:
+        mMagFilter = paramInt;
+        break;
+
+    case LOCAL_GL_TEXTURE_WRAP_S:
+        mWrapS = paramInt;
         break;
 
     case LOCAL_GL_TEXTURE_WRAP_T:
-        mWrapT = param;
+        mWrapT = paramInt;
         break;
 
     case LOCAL_GL_TEXTURE_WRAP_R:
-        mWrapR = param;
+        mWrapR = paramInt;
         break;
 
     case LOCAL_GL_TEXTURE_COMPARE_MODE:
-        mCompareMode = param;
+        mCompareMode = paramInt;
         break;
 
     case LOCAL_GL_TEXTURE_COMPARE_FUNC:
-        mCompareFunc = param;
+        mCompareFunc = paramInt;
         break;
 
     case LOCAL_GL_TEXTURE_MIN_LOD:
-        mMinLod = param;
+        mMinLod = paramInt;
         break;
 
     case LOCAL_GL_TEXTURE_MAX_LOD:
-        mMaxLod = param;
+        mMaxLod = paramInt;
         break;
 
     default:
         MOZ_CRASH("GFX: Unhandled pname");
         break;
     }
 
     for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
         if (this == mContext->mBoundSamplers[i])
             mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
     }
+
+    ////
+
+    mContext->gl->MakeCurrent();
+    mContext->gl->fSamplerParameteri(mGLName, pname, paramInt);
 }
 
-void
-WebGLSampler::SamplerParameter1f(GLenum pname, GLfloat param)
-{
-    switch (pname) {
-    case LOCAL_GL_TEXTURE_MIN_LOD:
-        mMinLod = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_MAX_LOD:
-        mMaxLod = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_WRAP_S:
-        mWrapS = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_WRAP_T:
-        mWrapT = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_WRAP_R:
-        mWrapR = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_MAG_FILTER:
-        mMagFilter = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_MIN_FILTER:
-        mMinFilter = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_COMPARE_MODE:
-        mCompareMode = param;
-        break;
-
-    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
-        mCompareFunc = param;
-        break;
-
-    default:
-        MOZ_CRASH("GFX: Unhandled pname");
-        break;
-    }
-
-    for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
-        if (this == mContext->mBoundSamplers[i])
-            mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
-    }
-}
-
+////
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLSampler, Release)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLSampler.h
+++ b/dom/canvas/WebGLSampler.h
@@ -27,21 +27,19 @@ public:
 
     const GLuint mGLName;
 
     void Delete();
     WebGLContext* GetParentObject() const;
 
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
 
-    void SamplerParameter1i(GLenum pname, GLint param);
-    void SamplerParameter1f(GLenum pname, GLfloat param);
+    void SamplerParameter(const char* funcName, GLenum pname, GLint paramInt);
 
 private:
-
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
 
     TexMinFilter mMinFilter;
     TexMagFilter mMagFilter;
     TexWrap mWrapS;
     TexWrap mWrapT;
     TexWrap mWrapR;
--- a/dom/canvas/WebGLUniformLocation.cpp
+++ b/dom/canvas/WebGLUniformLocation.cpp
@@ -24,17 +24,18 @@ WebGLUniformLocation::WebGLUniformLocati
     , mLoc(loc)
     , mArrayIndex(arrayIndex)
 { }
 
 WebGLUniformLocation::~WebGLUniformLocation()
 { }
 
 bool
-WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, const char* funcName) const
+WebGLUniformLocation::ValidateForProgram(const WebGLProgram* prog,
+                                         const char* funcName) const
 {
     // Check the weak-pointer.
     if (!mLinkInfo) {
         mContext->ErrorInvalidOperation("%s: This uniform location is obsolete because"
                                         " its program has been successfully relinked.",
                                         funcName);
         return false;
     }
--- a/dom/canvas/WebGLUniformLocation.h
+++ b/dom/canvas/WebGLUniformLocation.h
@@ -47,17 +47,17 @@ public:
     const GLuint mLoc;
     const size_t mArrayIndex;
 
     //////
 
     WebGLUniformLocation(WebGLContext* webgl, const webgl::LinkedProgramInfo* linkInfo,
                          webgl::UniformInfo* info, GLuint loc, size_t arrayIndex);
 
-    bool ValidateForProgram(WebGLProgram* prog, const char* funcName) const;
+    bool ValidateForProgram(const WebGLProgram* prog, const char* funcName) const;
     bool ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType,
                              const char* funcName) const;
     bool ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize,
                              const char* funcName) const;
 
     JS::Value GetUniform(JSContext* js) const;
 
     // Needed for certain helper functions like ValidateObject.