Bug 1320030 - Simplify marking and deletion checks. - r=ethlin
authorJeff Gilbert <jdashg@gmail.com>
Tue, 29 Nov 2016 18:30:28 -0800
changeset 325378 d7a7e352abec80fbe76fb1f9bf235e2272c1e917
parent 325377 e333afeac179b7919eef15620782e5ee0bda35f3
child 325379 513dde2c67208df5c723f20c3fd46b78bbdb380a
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersethlin
bugs1320030
milestone53.0a1
Bug 1320030 - Simplify marking and deletion checks. - r=ethlin
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextPrograms.cpp
dom/canvas/WebGL2ContextQueries.cpp
dom/canvas/WebGL2ContextSamplers.cpp
dom/canvas/WebGL2ContextSync.cpp
dom/canvas/WebGL2ContextTransformFeedback.cpp
dom/canvas/WebGL2ContextUniforms.cpp
dom/canvas/WebGLBuffer.cpp
dom/canvas/WebGLBuffer.h
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextBuffers.cpp
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLContextTextures.cpp
dom/canvas/WebGLContextValidate.cpp
dom/canvas/WebGLContextVertexArray.cpp
dom/canvas/WebGLExtensionDebugShaders.cpp
dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
dom/canvas/WebGLExtensionVertexArray.cpp
dom/canvas/WebGLExtensions.h
dom/canvas/WebGLFramebuffer.cpp
dom/canvas/WebGLFramebuffer.h
dom/canvas/WebGLObjectModel.h
dom/canvas/WebGLProgram.cpp
dom/canvas/WebGLProgram.h
dom/canvas/WebGLQuery.cpp
dom/canvas/WebGLQuery.h
dom/canvas/WebGLRenderbuffer.cpp
dom/canvas/WebGLRenderbuffer.h
dom/canvas/WebGLSampler.cpp
dom/canvas/WebGLSampler.h
dom/canvas/WebGLShader.cpp
dom/canvas/WebGLShader.h
dom/canvas/WebGLSync.cpp
dom/canvas/WebGLSync.h
dom/canvas/WebGLTexture.cpp
dom/canvas/WebGLTexture.h
dom/canvas/WebGLTransformFeedback.cpp
dom/canvas/WebGLTransformFeedback.h
dom/canvas/WebGLVertexArray.cpp
dom/canvas/WebGLVertexArray.h
dom/canvas/WebGLVertexArrayFake.cpp
dom/canvas/WebGLVertexArrayFake.h
dom/canvas/WebGLVertexArrayGL.cpp
dom/canvas/WebGLVertexArrayGL.h
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -309,42 +309,42 @@ public:
 
     void ClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil);
 
     // -------------------------------------------------------------------------
     // Sampler Objects - WebGL2ContextSamplers.cpp
 
     already_AddRefed<WebGLSampler> CreateSampler();
     void DeleteSampler(WebGLSampler* sampler);
-    bool IsSampler(WebGLSampler* sampler);
+    bool IsSampler(const WebGLSampler* sampler);
     void BindSampler(GLuint unit, WebGLSampler* sampler);
     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);
+    bool IsSync(const WebGLSync* sync);
     void DeleteSync(WebGLSync* sync);
     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);
+    bool IsTransformFeedback(const 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);
--- a/dom/canvas/WebGL2ContextPrograms.cpp
+++ b/dom/canvas/WebGL2ContextPrograms.cpp
@@ -14,15 +14,15 @@ namespace mozilla {
 // Programs and shaders
 
 GLint
 WebGL2Context::GetFragDataLocation(const WebGLProgram& prog, const nsAString& name)
 {
     if (IsContextLost())
         return -1;
 
-    if (!ValidateObjectRef("getFragDataLocation: program", prog))
+    if (!ValidateObject("getFragDataLocation: program", prog))
         return -1;
 
     return prog.GetFragDataLocation(name);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextQueries.cpp
+++ b/dom/canvas/WebGL2ContextQueries.cpp
@@ -73,63 +73,48 @@ WebGLContext::CreateQuery(const char* fu
 
 void
 WebGLContext::DeleteQuery(WebGLQuery* query, const char* funcName)
 {
     if (!funcName) {
         funcName = "deleteQuery";
     }
 
-    if (IsContextLost())
-        return;
-
-    if (!query)
-        return;
-
-    if (!ValidateObjectAllowDeleted(funcName, query))
+    if (!ValidateDeleteObject(funcName, query))
         return;
 
     query->DeleteQuery();
 }
 
 bool
 WebGLContext::IsQuery(const WebGLQuery* query, const char* funcName)
 {
     if (!funcName) {
         funcName = "isQuery";
     }
 
-    if (IsContextLost())
-        return false;
-
-    if (!query)
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isQuery", query))
+    if (!ValidateIsObject(funcName, query))
         return false;
 
     return query->IsQuery();
 }
 
 void
 WebGLContext::BeginQuery(GLenum target, WebGLQuery& query, const char* funcName)
 {
     if (!funcName) {
         funcName = "beginQuery";
     }
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeleted(funcName, &query))
+    if (!ValidateObject(funcName, query))
         return;
 
-    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);
 
     ////
@@ -233,18 +218,15 @@ WebGLContext::GetQueryParameter(JSContex
     if (!funcName) {
         funcName = "getQueryParameter";
     }
 
     retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeleted(funcName, &query))
+    if (!ValidateObject(funcName, query))
         return;
 
-    if (query.IsDeleted())
-        return ErrorInvalidOperation("%s: Query must not be deleted.", funcName);
-
     query.GetQueryParameter(pname, retval);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextSamplers.cpp
+++ b/dom/canvas/WebGL2ContextSamplers.cpp
@@ -21,116 +21,98 @@ WebGL2Context::CreateSampler()
 
     RefPtr<WebGLSampler> globj = new WebGLSampler(this, sampler);
     return globj.forget();
 }
 
 void
 WebGL2Context::DeleteSampler(WebGLSampler* sampler)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteSampler", sampler))
-        return;
-
-    if (!sampler || sampler->IsDeleted())
+    if (!ValidateDeleteObject("deleteSampler", sampler))
         return;
 
     for (int n = 0; n < mGLMaxTextureUnits; n++) {
         if (mBoundSamplers[n] == sampler) {
             mBoundSamplers[n] = nullptr;
 
             InvalidateResolveCacheForTextureWithTexUnit(n);
         }
     }
 
     sampler->RequestDelete();
 }
 
 bool
-WebGL2Context::IsSampler(WebGLSampler* sampler)
+WebGL2Context::IsSampler(const WebGLSampler* sampler)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!sampler)
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isSampler", sampler))
-        return false;
-
-    if (sampler->IsDeleted())
+    if (!ValidateIsObject("isSampler", sampler))
         return false;
 
     MakeContextCurrent();
     return gl->fIsSampler(sampler->mGLName);
 }
 
 void
 WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull("bindSampler", sampler))
+    if (sampler && !ValidateObject("bindSampler", *sampler))
         return;
 
     if (GLint(unit) >= mGLMaxTextureUnits)
         return ErrorInvalidValue("bindSampler: unit must be < %d", mGLMaxTextureUnits);
 
-    if (sampler && sampler->IsDeleted())
-        return ErrorInvalidOperation("bindSampler: binding deleted sampler");
-
     ////
 
     gl->MakeCurrent();
     gl->fBindSampler(unit, sampler ? sampler->mGLName : 0);
 
     InvalidateResolveCacheForTextureWithTexUnit(unit);
     mBoundSamplers[unit] = sampler;
 }
 
 void
 WebGL2Context::SamplerParameteri(WebGLSampler& sampler, GLenum pname, GLint paramInt)
 {
     const char funcName[] = "samplerParameteri";
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef(funcName, sampler))
+    if (!ValidateObject(funcName, sampler))
         return;
 
     sampler.SamplerParameter(funcName, pname, paramInt);
 }
 
 void
 WebGL2Context::SamplerParameterf(WebGLSampler& sampler, GLenum pname, GLfloat paramFloat)
 {
     const char funcName[] = "samplerParameterf";
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef(funcName, sampler))
+    if (!ValidateObject(funcName, sampler))
         return;
 
     sampler.SamplerParameter(funcName, pname, WebGLIntOrFloat(paramFloat).AsInt());
 }
 
 void
 WebGL2Context::GetSamplerParameter(JSContext*, const WebGLSampler& sampler, GLenum pname,
                                    JS::MutableHandleValue retval)
 {
     const char funcName[] = "getSamplerParameter";
     retval.setNull();
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef(funcName, sampler))
+    if (!ValidateObject(funcName, sampler))
         return;
 
     ////
 
     gl->MakeCurrent();
 
     switch (pname) {
     case LOCAL_GL_TEXTURE_MIN_FILTER:
--- a/dom/canvas/WebGL2ContextSync.cpp
+++ b/dom/canvas/WebGL2ContextSync.cpp
@@ -11,66 +11,60 @@
 namespace mozilla {
 
 // -------------------------------------------------------------------------
 // Sync objects
 
 already_AddRefed<WebGLSync>
 WebGL2Context::FenceSync(GLenum condition, GLbitfield flags)
 {
-   if (IsContextLost())
-       return nullptr;
+    if (IsContextLost())
+        return nullptr;
 
-   if (condition != LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE) {
-       ErrorInvalidEnum("fenceSync: condition must be SYNC_GPU_COMMANDS_COMPLETE");
-       return nullptr;
-   }
+    if (condition != LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE) {
+        ErrorInvalidEnum("fenceSync: condition must be SYNC_GPU_COMMANDS_COMPLETE");
+        return nullptr;
+    }
 
-   if (flags != 0) {
-       ErrorInvalidValue("fenceSync: flags must be 0");
-       return nullptr;
-   }
+    if (flags != 0) {
+        ErrorInvalidValue("fenceSync: flags must be 0");
+        return nullptr;
+    }
 
-   MakeContextCurrent();
-   RefPtr<WebGLSync> globj = new WebGLSync(this, condition, flags);
-   return globj.forget();
+    MakeContextCurrent();
+    RefPtr<WebGLSync> globj = new WebGLSync(this, condition, flags);
+    return globj.forget();
 }
 
 bool
-WebGL2Context::IsSync(WebGLSync* sync)
+WebGL2Context::IsSync(const WebGLSync* sync)
 {
-   if (IsContextLost())
-       return false;
+    if (!ValidateIsObject("isSync", sync))
+        return false;
 
-   return ValidateObjectAllowDeleted("isSync", sync) && !sync->IsDeleted();
+    return true;
 }
 
 void
 WebGL2Context::DeleteSync(WebGLSync* sync)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteSync", sync))
-        return;
-
-    if (!sync || sync->IsDeleted())
+    if (!ValidateDeleteObject("deleteSync", sync))
         return;
 
     sync->RequestDelete();
 }
 
 GLenum
 WebGL2Context::ClientWaitSync(const WebGLSync& sync, GLbitfield flags, GLuint64 timeout)
 {
     const char funcName[] = "clientWaitSync";
     if (IsContextLost())
         return LOCAL_GL_WAIT_FAILED;
 
-    if (!ValidateObjectRef(funcName, sync))
+    if (!ValidateObject(funcName, sync))
         return LOCAL_GL_WAIT_FAILED;
 
     if (flags != 0 && flags != LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT) {
         ErrorInvalidValue("%s: `flags` must be SYNC_FLUSH_COMMANDS_BIT or 0.", funcName);
         return LOCAL_GL_WAIT_FAILED;
     }
 
     MakeContextCurrent();
@@ -79,17 +73,17 @@ WebGL2Context::ClientWaitSync(const WebG
 
 void
 WebGL2Context::WaitSync(const WebGLSync& sync, GLbitfield flags, GLint64 timeout)
 {
     const char funcName[] = "waitSync";
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef(funcName, sync))
+    if (!ValidateObject(funcName, sync))
         return;
 
     if (flags != 0) {
         ErrorInvalidValue("%s: `flags` must be 0.", funcName);
         return;
     }
 
     if (timeout != -1) {
@@ -105,17 +99,17 @@ void
 WebGL2Context::GetSyncParameter(JSContext*, const WebGLSync& sync, GLenum pname,
                                 JS::MutableHandleValue retval)
 {
     const char funcName[] = "getSyncParameter";
     retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef(funcName, sync))
+    if (!ValidateObject(funcName, sync))
         return;
 
     ////
 
     gl->MakeCurrent();
 
     GLint result = 0;
     switch (pname) {
--- a/dom/canvas/WebGL2ContextTransformFeedback.cpp
+++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp
@@ -27,66 +27,54 @@ WebGL2Context::CreateTransformFeedback()
     RefPtr<WebGLTransformFeedback> ret = new WebGLTransformFeedback(this, tf);
     return ret.forget();
 }
 
 void
 WebGL2Context::DeleteTransformFeedback(WebGLTransformFeedback* tf)
 {
     const char funcName[] = "deleteTransformFeedback";
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObject(funcName, tf))
+    if (!ValidateDeleteObject(funcName, tf))
         return;
 
     if (tf->mIsActive) {
         ErrorInvalidOperation("%s: Cannot delete active transform feedbacks.", funcName);
         return;
     }
 
     if (mBoundTransformFeedback == tf) {
         BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, nullptr);
     }
 
     tf->RequestDelete();
 }
 
 bool
-WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf)
+WebGL2Context::IsTransformFeedback(const WebGLTransformFeedback* tf)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!ValidateObjectAllowDeletedOrNull("isTransformFeedback", tf))
-        return false;
-
-    if (!tf || tf->IsDeleted())
+    if (!ValidateIsObject("isTransformFeedback", tf))
         return false;
 
     MakeContextCurrent();
     return gl->fIsTransformFeedback(tf->mGLName);
 }
 
 void
 WebGL2Context::BindTransformFeedback(GLenum target, WebGLTransformFeedback* tf)
 {
     const char funcName[] = "bindTransformFeedback";
     if (IsContextLost())
         return;
 
     if (target != LOCAL_GL_TRANSFORM_FEEDBACK)
         return ErrorInvalidEnum("%s: `target` must be TRANSFORM_FEEDBACK.", funcName);
 
-    if (!ValidateObjectAllowDeletedOrNull(funcName, tf))
+    if (tf && !ValidateObject(funcName, *tf))
         return;
 
-    if (tf && tf->IsDeleted())
-        return ErrorInvalidOperation("%s: TFO already deleted.", funcName);
-
     if (mBoundTransformFeedback->mIsActive &&
         !mBoundTransformFeedback->mIsPaused)
     {
         ErrorInvalidOperation("%s: Currently bound transform feedback is active and not"
                               " paused.",
                               funcName);
         return;
     }
@@ -138,27 +126,27 @@ WebGL2Context::ResumeTransformFeedback()
 void
 WebGL2Context::TransformFeedbackVaryings(WebGLProgram& program,
                                          const dom::Sequence<nsString>& varyings,
                                          GLenum bufferMode)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("transformFeedbackVaryings: program", program))
+    if (!ValidateObject("transformFeedbackVaryings: program", program))
         return;
 
     program.TransformFeedbackVaryings(varyings, bufferMode);
 }
 
 already_AddRefed<WebGLActiveInfo>
 WebGL2Context::GetTransformFeedbackVarying(const WebGLProgram& program, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObjectRef("getTransformFeedbackVarying: program", program))
+    if (!ValidateObject("getTransformFeedbackVarying: program", program))
         return nullptr;
 
     return program.GetTransformFeedbackVarying(index);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -133,17 +133,17 @@ void
 WebGL2Context::GetUniformIndices(const WebGLProgram& program,
                                  const dom::Sequence<nsString>& uniformNames,
                                  dom::Nullable< nsTArray<GLuint> >& retval)
 {
     retval.SetNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getUniformIndices: program", program))
+    if (!ValidateObject("getUniformIndices: program", program))
         return;
 
     if (!uniformNames.Length())
         return;
 
     program.GetUniformIndices(uniformNames, retval);
 }
 
@@ -174,17 +174,17 @@ WebGL2Context::GetActiveUniforms(JSConte
     const char funcName[] = "getActiveUniforms";
     retval.setNull();
     if (IsContextLost())
         return;
 
     if (!ValidateUniformEnum(this, pname, funcName))
         return;
 
-    if (!ValidateObjectRef("getActiveUniforms: program", program))
+    if (!ValidateObject("getActiveUniforms: program", program))
         return;
 
     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);
@@ -226,33 +226,33 @@ WebGL2Context::GetActiveUniforms(JSConte
 
 GLuint
 WebGL2Context::GetUniformBlockIndex(const WebGLProgram& program,
                                     const nsAString& uniformBlockName)
 {
     if (IsContextLost())
         return 0;
 
-    if (!ValidateObjectRef("getUniformBlockIndex: program", program))
+    if (!ValidateObject("getUniformBlockIndex: program", program))
         return 0;
 
     return program.GetUniformBlockIndex(uniformBlockName);
 }
 
 void
 WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, const WebGLProgram& program,
                                               GLuint uniformBlockIndex, GLenum pname,
                                               JS::MutableHandleValue out_retval,
                                               ErrorResult& out_error)
 {
     out_retval.setNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getActiveUniformBlockParameter: program", program))
+    if (!ValidateObject("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:
@@ -273,28 +273,28 @@ WebGL2Context::GetActiveUniformBlockPara
 void
 WebGL2Context::GetActiveUniformBlockName(const WebGLProgram& program,
                                          GLuint uniformBlockIndex, nsAString& retval)
 {
     retval.SetIsVoid(true);
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getActiveUniformBlockName: program", program))
+    if (!ValidateObject("getActiveUniformBlockName: program", program))
         return;
 
     program.GetActiveUniformBlockName(uniformBlockIndex, retval);
 }
 
 void
 WebGL2Context::UniformBlockBinding(WebGLProgram& program, GLuint uniformBlockIndex,
                                    GLuint uniformBlockBinding)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("uniformBlockBinding: program", program))
+    if (!ValidateObject("uniformBlockBinding: program", program))
         return;
 
     program.UniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -8,17 +8,17 @@
 #include "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 #include "WebGLElementArrayCache.h"
 
 namespace mozilla {
 
 WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(buf)
     , mContent(Kind::Undefined)
     , mUsage(LOCAL_GL_STATIC_DRAW)
     , mByteLength(0)
 {
     mContext->mBuffers.insertBack(this);
 }
 
--- a/dom/canvas/WebGLBuffer.h
+++ b/dom/canvas/WebGLBuffer.h
@@ -17,17 +17,16 @@
 namespace mozilla {
 
 class WebGLElementArrayCache;
 
 class WebGLBuffer final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLBuffer>
     , public LinkedListElement<WebGLBuffer>
-    , public WebGLContextBoundObject
 {
     friend class WebGLContext;
     friend class WebGL2Context;
     friend class WebGLTexture;
     friend class WebGLTransformFeedback;
 
 public:
     enum class Kind {
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -217,17 +217,17 @@ WebGLContext::~WebGLContext()
     DestroyResourcesAndContext();
     if (NS_IsMainThread()) {
         // XXX mtseng: bug 709490, not thread safe
         WebGLMemoryTracker::RemoveWebGLContext(this);
     }
 }
 
 template<typename T>
-static void
+void
 ClearLinkedList(LinkedList<T>& list)
 {
     while (!list.isEmpty()) {
         list.getLast()->DeleteOnce();
     }
 }
 
 void
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -611,21 +611,21 @@ public:
     {
         retval.set(GetUniform(cx, prog, loc));
     }
 
     already_AddRefed<WebGLUniformLocation>
     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);
+    bool IsFramebuffer(const WebGLFramebuffer* fb);
+    bool IsProgram(const WebGLProgram* prog);
+    bool IsRenderbuffer(const WebGLRenderbuffer* rb);
+    bool IsShader(const WebGLShader* shader);
+    bool IsVertexArray(const WebGLVertexArray* vao);
     void LineWidth(GLfloat width);
     void LinkProgram(WebGLProgram& prog);
     void PixelStorei(GLenum pname, GLint param);
     void PolygonOffset(GLfloat factor, GLfloat units);
 
     already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
     bool StartVRPresentation();
 protected:
@@ -1623,43 +1623,79 @@ 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);
+    bool ValidateObjectAllowDeleted(const char* funcName,
+                                    const WebGLContextBoundObject& object)
+    {
+        if (!object.IsCompatibleWithContext(this)) {
+            ErrorInvalidOperation("%s: Object from different WebGL context (or older"
+                                  " generation of this one) passed as argument.",
+                                  funcName);
+            return false;
+        }
+
+        return true;
+    }
 
-    // Returns false if `object` is not valid.
-    template<class ObjectType>
-    bool ValidateObjectRef(const char* info, const ObjectType& object);
+    bool ValidateObject(const char* funcName, const WebGLDeletableObject& object) {
+        if (!ValidateObjectAllowDeleted(funcName, object))
+            return false;
 
-    // Returns false if `object` is not valid.  Considers null to be valid.
-    template<class ObjectType>
-    bool ValidateObjectAllowNull(const char* info, const ObjectType* object);
+        if (object.IsDeleteRequested()) {
+            ErrorInvalidOperation("%s: Object argument cannot be marked for deletion.",
+                                  funcName);
+            return false;
+        }
+
+        return true;
+    }
+
+    ////
 
-    // 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);
+    bool ValidateIsObject(const char* funcName,
+                          const WebGLDeletableObject* object) const
+    {
+        if (IsContextLost())
+            return false;
+
+        if (!object)
+            return false;
+
+        if (!object->IsCompatibleWithContext(this))
+            return false;
+
+        if (object->IsDeleted())
+            return false;
+
+        return true;
+    }
 
-    // Returns false if `object` is null or not valid, but considers deleted
-    // objects valid.
-    template<class ObjectType>
-    bool ValidateObjectAllowDeleted(const char* info, const ObjectType* object);
+    bool ValidateDeleteObject(const char* funcName, const WebGLDeletableObject* object) {
+        if (IsContextLost())
+            return false;
+
+        if (!object)
+            return false;
 
-private:
-    // Like ValidateObject, but only for cases when `object` is known to not be
-    // null already.
-    template<class ObjectType>
-    bool ValidateObjectAssumeNonNull(const char* info, const ObjectType* object);
+        if (!ValidateObjectAllowDeleted(funcName, *object))
+            return false;
+
+        if (object->IsDeleteRequested())
+            return false;
+
+        return true;
+    }
+
+    ////
 
 private:
     // -------------------------------------------------------------------------
     // Context customization points
     virtual WebGLVertexArray* CreateVertexArrayImpl();
 
     virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, uint32_t* alignment, const char* info) = 0;
     virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0;
@@ -1948,92 +1984,16 @@ public:
 
 // used by DOM bindings in conjunction with GetParentObject
 inline nsISupports*
 ToSupports(WebGLContext* webgl)
 {
     return static_cast<nsIDOMWebGLRenderingContext*>(webgl);
 }
 
-/**
- ** Template implementations
- **/
-
-template<class ObjectType>
-inline bool
-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;
-    }
-
-    return true;
-}
-
-template<class ObjectType>
-inline bool
-WebGLContext::ValidateObjectAssumeNonNull(const char* info, const ObjectType* object)
-{
-    MOZ_ASSERT(object);
-
-    if (!ValidateObjectAllowDeletedOrNull(info, object))
-        return false;
-
-    if (object->IsDeleted()) {
-        ErrorInvalidValue("%s: Deleted object passed as argument.", info);
-        return false;
-    }
-
-    return true;
-}
-
-template<class ObjectType>
-inline bool
-WebGLContext::ValidateObjectAllowNull(const char* info, const ObjectType* object)
-{
-    if (!object)
-        return true;
-
-    return ValidateObjectAssumeNonNull(info, object);
-}
-
-template<class ObjectType>
-inline bool
-WebGLContext::ValidateObjectAllowDeleted(const char* info, const ObjectType* object)
-{
-    if (!object) {
-        ErrorInvalidValue("%s: null object passed as argument", info);
-        return false;
-    }
-
-    return ValidateObjectAllowDeletedOrNull(info, object);
-}
-
-template<class ObjectType>
-inline bool
-WebGLContext::ValidateObject(const char* info, const ObjectType* object)
-{
-    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)
-{
-    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
@@ -114,22 +114,19 @@ WebGLContext::ValidateIndexedBufferSlot(
 
 void
 WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
 {
     const char funcName[] = "bindBuffer";
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
+    if (buffer && !ValidateObject(funcName, *buffer))
         return;
 
-    if (buffer && buffer->IsDeleted())
-        return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);
-
     const auto& slot = ValidateBufferSlot(funcName, target);
     if (!slot)
         return;
 
     if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
         return;
 
     gl->MakeCurrent();
@@ -178,22 +175,19 @@ WebGLContext::ValidateIndexedBufferBindi
 
 void
 WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
 {
     const char funcName[] = "bindBufferBase";
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
+    if (buffer && !ValidateObject(funcName, *buffer))
         return;
 
-    if (buffer && buffer->IsDeleted())
-        return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);
-
     WebGLRefPtr<WebGLBuffer>* genericBinding;
     IndexedBufferBinding* indexedBinding;
     if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
                                       &indexedBinding))
     {
         return;
     }
 
@@ -229,22 +223,19 @@ WebGLContext::BindBufferBase(GLenum targ
 void
 WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
                               WebGLintptr offset, WebGLsizeiptr size)
 {
     const char funcName[] = "bindBufferRange";
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
+    if (buffer && !ValidateObject(funcName, *buffer))
         return;
 
-    if (buffer && buffer->IsDeleted())
-        return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);
-
     if (!ValidateNonNegative(funcName, "offset", offset) ||
         !ValidateNonNegative(funcName, "size", size))
     {
         return;
     }
 
     WebGLRefPtr<WebGLBuffer>* genericBinding;
     IndexedBufferBinding* indexedBinding;
@@ -471,23 +462,17 @@ WebGLContext::CreateBuffer()
 
     RefPtr<WebGLBuffer> globj = new WebGLBuffer(this, buf);
     return globj.forget();
 }
 
 void
 WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buffer))
-        return;
-
-    if (!buffer || buffer->IsDeleted())
+    if (!ValidateDeleteObject("deleteBuffer", buffer))
         return;
 
     ////
 
     const auto fnClearIfBuffer = [&](WebGLRefPtr<WebGLBuffer>& bindPoint) {
         if (bindPoint == buffer) {
             bindPoint = nullptr;
         }
@@ -525,22 +510,16 @@ WebGLContext::DeleteBuffer(WebGLBuffer* 
     ////
 
     buffer->RequestDelete();
 }
 
 bool
 WebGLContext::IsBuffer(WebGLBuffer* buffer)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isBuffer", buffer))
-        return false;
-
-    if (buffer->IsDeleted())
+    if (!ValidateIsObject("isBuffer", buffer))
         return false;
 
     MakeContextCurrent();
     return gl->fIsBuffer(buffer->mGLName);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -87,53 +87,50 @@ WebGLContext::ActiveTexture(GLenum textu
 }
 
 void
 WebGLContext::AttachShader(WebGLProgram& program, WebGLShader& shader)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("attachShader: program", program) ||
-        !ValidateObjectRef("attachShader: shader", shader))
+    if (!ValidateObject("attachShader: program", program) ||
+        !ValidateObject("attachShader: shader", shader))
     {
         return;
     }
 
     program.AttachShader(&shader);
 }
 
 void
 WebGLContext::BindAttribLocation(WebGLProgram& prog, GLuint location,
                                  const nsAString& name)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("bindAttribLocation: program", prog))
+    if (!ValidateObject("bindAttribLocation: program", prog))
         return;
 
     prog.BindAttribLocation(location, name);
 }
 
 void
 WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer* wfb)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateFramebufferTarget(target, "bindFramebuffer"))
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull("bindFramebuffer", wfb))
+    if (wfb && !ValidateObject("bindFramebuffer", *wfb))
         return;
 
-    if (wfb && wfb->IsDeleted())
-        return ErrorInvalidOperation("bindFramebuffer: Cannot bind a deleted object.");
-
     MakeContextCurrent();
 
     if (!wfb) {
         gl->fBindFramebuffer(target, 0);
     } else {
         GLuint framebuffername = wfb->mGLName;
         gl->fBindFramebuffer(target, framebuffername);
 #ifdef ANDROID
@@ -161,22 +158,19 @@ void
 WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer* wrb)
 {
     if (IsContextLost())
         return;
 
     if (target != LOCAL_GL_RENDERBUFFER)
         return ErrorInvalidEnumInfo("bindRenderbuffer: target", target);
 
-    if (!ValidateObjectAllowDeletedOrNull("bindRenderbuffer", wrb))
+    if (wrb && !ValidateObject("bindRenderbuffer", *wrb))
         return;
 
-    if (wrb && wrb->IsDeleted())
-        return ErrorInvalidOperation("bindRenderbuffer: Cannot bind a deleted object.");
-
     // Usually, we would now call into glBindRenderbuffer. However, since we have to
     // potentially emulate packed-depth-stencil, there's not a specific renderbuffer that
     // we know we should bind here.
     // Instead, we do all renderbuffer binding lazily.
 
     if (wrb) {
         wrb->mHasBeenBound = true;
     }
@@ -315,23 +309,17 @@ WebGLContext::CullFace(GLenum face)
 
     MakeContextCurrent();
     gl->fCullFace(face);
 }
 
 void
 WebGLContext::DeleteFramebuffer(WebGLFramebuffer* fbuf)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteFramebuffer", fbuf))
-        return;
-
-    if (!fbuf || fbuf->IsDeleted())
+    if (!ValidateDeleteObject("deleteFramebuffer", fbuf))
         return;
 
     fbuf->RequestDelete();
 
     if (mBoundReadFramebuffer == mBoundDrawFramebuffer) {
         if (mBoundDrawFramebuffer == fbuf) {
             BindFramebuffer(LOCAL_GL_FRAMEBUFFER,
                             static_cast<WebGLFramebuffer*>(nullptr));
@@ -343,23 +331,17 @@ WebGLContext::DeleteFramebuffer(WebGLFra
         BindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER,
                         static_cast<WebGLFramebuffer*>(nullptr));
     }
 }
 
 void
 WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer* rbuf)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteRenderbuffer", rbuf))
-        return;
-
-    if (!rbuf || rbuf->IsDeleted())
+    if (!ValidateDeleteObject("deleteRenderbuffer", rbuf))
         return;
 
     if (mBoundDrawFramebuffer)
         mBoundDrawFramebuffer->DetachRenderbuffer(rbuf);
 
     if (mBoundReadFramebuffer)
         mBoundReadFramebuffer->DetachRenderbuffer(rbuf);
 
@@ -369,23 +351,17 @@ WebGLContext::DeleteRenderbuffer(WebGLRe
         BindRenderbuffer(LOCAL_GL_RENDERBUFFER, nullptr);
 
     rbuf->RequestDelete();
 }
 
 void
 WebGLContext::DeleteTexture(WebGLTexture* tex)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteTexture", tex))
-        return;
-
-    if (!tex || tex->IsDeleted())
+    if (!ValidateDeleteObject("deleteTexture", tex))
         return;
 
     if (mBoundDrawFramebuffer)
         mBoundDrawFramebuffer->DetachTexture(tex);
 
     if (mBoundReadFramebuffer)
         mBoundReadFramebuffer->DetachTexture(tex);
 
@@ -403,53 +379,41 @@ WebGLContext::DeleteTexture(WebGLTexture
     ActiveTexture(LOCAL_GL_TEXTURE0 + activeTexture);
 
     tex->RequestDelete();
 }
 
 void
 WebGLContext::DeleteProgram(WebGLProgram* prog)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteProgram", prog))
-        return;
-
-    if (!prog || prog->IsDeleted())
+    if (!ValidateDeleteObject("deleteProgram", prog))
         return;
 
     prog->RequestDelete();
 }
 
 void
 WebGLContext::DeleteShader(WebGLShader* shader)
 {
-    if (IsContextLost())
-        return;
-
-    if (!ValidateObjectAllowDeletedOrNull("deleteShader", shader))
-        return;
-
-    if (!shader || shader->IsDeleted())
+    if (!ValidateDeleteObject("deleteShader", shader))
         return;
 
     shader->RequestDelete();
 }
 
 void
 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 (!ValidateObjectRef("detachShader: program", program) ||
-        !ValidateObjectAllowDeleted("detachShader: shader", &shader))
+    if (!ValidateObject("detachShader: program", program) ||
+        !ValidateObjectAllowDeleted("detachShader: shader", shader))
     {
         return;
     }
 
     program.DetachShader(&shader);
 }
 
 void
@@ -564,55 +528,55 @@ WebGLContext::FrontFace(GLenum mode)
 }
 
 already_AddRefed<WebGLActiveInfo>
 WebGLContext::GetActiveAttrib(const WebGLProgram& prog, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObjectRef("getActiveAttrib: program", prog))
+    if (!ValidateObject("getActiveAttrib: program", prog))
         return nullptr;
 
     return prog.GetActiveAttrib(index);
 }
 
 already_AddRefed<WebGLActiveInfo>
 WebGLContext::GetActiveUniform(const WebGLProgram& prog, GLuint index)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObjectRef("getActiveUniform: program", prog))
+    if (!ValidateObject("getActiveUniform: program", prog))
         return nullptr;
 
     return prog.GetActiveUniform(index);
 }
 
 void
 WebGLContext::GetAttachedShaders(const WebGLProgram& prog,
                                  dom::Nullable<nsTArray<RefPtr<WebGLShader>>>& retval)
 {
     retval.SetNull();
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getAttachedShaders", prog))
+    if (!ValidateObject("getAttachedShaders", prog))
         return;
 
     prog.GetAttachedShaders(&retval.SetValue());
 }
 
 GLint
 WebGLContext::GetAttribLocation(const WebGLProgram& prog, const nsAString& name)
 {
     if (IsContextLost())
         return -1;
 
-    if (!ValidateObjectRef("getAttribLocation: program", prog))
+    if (!ValidateObject("getAttribLocation: program", prog))
         return -1;
 
     return prog.GetAttribLocation(name);
 }
 
 JS::Value
 WebGLContext::GetBufferParameter(GLenum target, GLenum pname)
 {
@@ -905,62 +869,62 @@ WebGLContext::GetError()
 }
 
 JS::Value
 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);
 }
 
 void
 WebGLContext::GetProgramInfoLog(const WebGLProgram& prog, nsAString& retval)
 {
     retval.SetIsVoid(true);
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getProgramInfoLog: program", prog))
+    if (!ValidateObject("getProgramInfoLog: program", prog))
         return;
 
     prog.GetProgramInfoLog(&retval);
 }
 
 JS::Value
 WebGLContext::GetUniform(JSContext* js, const WebGLProgram& prog,
                          const WebGLUniformLocation& loc)
 {
     if (IsContextLost())
         return JS::NullValue();
 
-    if (!ValidateObjectRef("getUniform: `program`", prog))
+    if (!ValidateObject("getUniform: `program`", prog))
         return JS::NullValue();
 
-    if (!ValidateObjectRef("getUniform: `location`", loc))
+    if (!ValidateObjectAllowDeleted("getUniform: `location`", loc))
         return JS::NullValue();
 
     if (!loc.ValidateForProgram(&prog, "getUniform"))
         return JS::NullValue();
 
     return loc.GetUniform(js);
 }
 
 already_AddRefed<WebGLUniformLocation>
 WebGLContext::GetUniformLocation(const WebGLProgram& prog, const nsAString& name)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!ValidateObjectRef("getUniformLocation: program", prog))
+    if (!ValidateObject("getUniformLocation: program", prog))
         return nullptr;
 
     return prog.GetUniformLocation(name);
 }
 
 void
 WebGLContext::Hint(GLenum target, GLenum mode)
 {
@@ -990,80 +954,67 @@ WebGLContext::Hint(GLenum target, GLenum
     if (!isValid)
         return ErrorInvalidEnum("hint: invalid hint");
 
     MakeContextCurrent();
     gl->fHint(target, mode);
 }
 
 bool
-WebGLContext::IsFramebuffer(WebGLFramebuffer* fb)
+WebGLContext::IsFramebuffer(const WebGLFramebuffer* fb)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isFramebuffer", fb))
-        return false;
-
-    if (fb->IsDeleted())
+    if (!ValidateIsObject("isFramebuffer", fb))
         return false;
 
 #ifdef ANDROID
     if (gl->WorkAroundDriverBugs() &&
         gl->Renderer() == GLRenderer::AndroidEmulator)
     {
         return fb->mIsFB;
     }
 #endif
 
     MakeContextCurrent();
     return gl->fIsFramebuffer(fb->mGLName);
 }
 
 bool
-WebGLContext::IsProgram(WebGLProgram* prog)
+WebGLContext::IsProgram(const WebGLProgram* prog)
 {
-    if (IsContextLost())
+    if (!ValidateIsObject("isProgram", prog))
         return false;
 
-    return ValidateObjectAllowDeleted("isProgram", prog) && !prog->IsDeleted();
+    return true;
 }
 
 bool
-WebGLContext::IsRenderbuffer(WebGLRenderbuffer* rb)
+WebGLContext::IsRenderbuffer(const WebGLRenderbuffer* rb)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isRenderBuffer", rb))
-        return false;
-
-    if (rb->IsDeleted())
+    if (!ValidateIsObject("isRenderbuffer", rb))
         return false;
 
     return rb->mHasBeenBound;
 }
 
 bool
-WebGLContext::IsShader(WebGLShader* shader)
+WebGLContext::IsShader(const WebGLShader* shader)
 {
-    if (IsContextLost())
+    if (!ValidateIsObject("isShader", shader))
         return false;
 
-    return ValidateObjectAllowDeleted("isShader", shader) &&
-        !shader->IsDeleted();
+    return true;
 }
 
 void
 WebGLContext::LinkProgram(WebGLProgram& prog)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("linkProgram", prog))
+    if (!ValidateObject("linkProgram", prog))
         return;
 
     prog.LinkProgram();
 
     if (!prog.IsLinked()) {
         // If we failed to link, but `prog == mCurrentProgram`, we are *not* supposed to
         // null out mActiveProgramLinkInfo.
         return;
@@ -2096,32 +2047,32 @@ WebGLContext::UseProgram(WebGLProgram* p
         return;
 
     if (!prog) {
         mCurrentProgram = nullptr;
         mActiveProgramLinkInfo = nullptr;
         return;
     }
 
-    if (!ValidateObject("useProgram", prog))
+    if (!ValidateObject("useProgram", *prog))
         return;
 
     if (prog->UseProgram()) {
         mCurrentProgram = prog;
         mActiveProgramLinkInfo = mCurrentProgram->LinkInfo();
     }
 }
 
 void
 WebGLContext::ValidateProgram(const WebGLProgram& prog)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("validateProgram", prog))
+    if (!ValidateObject("validateProgram", prog))
         return;
 
     prog.ValidateProgram();
 }
 
 already_AddRefed<WebGLFramebuffer>
 WebGLContext::CreateFramebuffer()
 {
@@ -2166,43 +2117,43 @@ WebGLContext::Viewport(GLint x, GLint y,
 }
 
 void
 WebGLContext::CompileShader(WebGLShader& shader)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("compileShader", shader))
+    if (!ValidateObject("compileShader", shader))
         return;
 
     shader.CompileShader();
 }
 
 JS::Value
 WebGLContext::GetShaderParameter(const WebGLShader& shader, GLenum pname)
 {
     if (IsContextLost())
         return JS::NullValue();
 
-    if (!ValidateObjectRef("getShaderParameter: shader", shader))
+    if (!ValidateObjectAllowDeleted("getShaderParameter: shader", shader))
         return JS::NullValue();
 
     return shader.GetShaderParameter(pname);
 }
 
 void
 WebGLContext::GetShaderInfoLog(const WebGLShader& shader, nsAString& retval)
 {
     retval.SetIsVoid(true);
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getShaderInfoLog: shader", shader))
+    if (!ValidateObject("getShaderInfoLog: shader", shader))
         return;
 
     shader.GetShaderInfoLog(&retval);
 }
 
 already_AddRefed<WebGLShaderPrecisionFormat>
 WebGLContext::GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype)
 {
@@ -2254,29 +2205,29 @@ WebGLContext::GetShaderPrecisionFormat(G
 void
 WebGLContext::GetShaderSource(const WebGLShader& shader, nsAString& retval)
 {
     retval.SetIsVoid(true);
 
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("getShaderSource: shader", shader))
+    if (!ValidateObject("getShaderSource: shader", shader))
         return;
 
     shader.GetShaderSource(&retval);
 }
 
 void
 WebGLContext::ShaderSource(WebGLShader& shader, const nsAString& source)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectRef("shaderSource: shader", shader))
+    if (!ValidateObject("shaderSource: shader", shader))
         return;
 
     shader.ShaderSource(source);
 }
 
 void
 WebGLContext::LoseContext()
 {
--- a/dom/canvas/WebGLContextTextures.cpp
+++ b/dom/canvas/WebGLContextTextures.cpp
@@ -204,17 +204,17 @@ WebGLContext::InvalidateResolveCacheForT
 // GL calls
 
 void
 WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
 {
     if (IsContextLost())
         return;
 
-     if (!ValidateObjectAllowDeletedOrNull("bindTexture", newTex))
+     if (newTex && !ValidateObject("bindTexture", *newTex))
         return;
 
     // Need to check rawTarget first before comparing against newTex->Target() as
     // newTex->Target() returns a TexTarget, which will assert on invalid value.
     WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
     switch (rawTarget) {
     case LOCAL_GL_TEXTURE_2D:
         currentTexPtr = &mBound2DTextures[mActiveTexture];
@@ -285,20 +285,17 @@ WebGLContext::GetTexParameter(GLenum raw
     }
 
     return tex->GetTexParameter(texTarget, pname);
 }
 
 bool
 WebGLContext::IsTexture(WebGLTexture* tex)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isTexture", tex))
+    if (!ValidateIsObject("isTexture", tex))
         return false;
 
     return tex->IsTexture();
 }
 
 void
 WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeIntParam,
                                 GLfloat* maybeFloatParam)
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -202,17 +202,17 @@ WebGLContext::ValidateUniformLocation(We
     /* 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.
      */
     if (!loc)
         return false;
 
-    if (!ValidateObject(funcName, loc))
+    if (!ValidateObjectAllowDeleted(funcName, *loc))
         return false;
 
     if (!mCurrentProgram) {
         ErrorInvalidOperation("%s: No program is currently bound.", funcName);
         return false;
     }
 
     return loc->ValidateForProgram(mCurrentProgram, funcName);
--- a/dom/canvas/WebGLContextVertexArray.cpp
+++ b/dom/canvas/WebGLContextVertexArray.cpp
@@ -13,30 +13,19 @@
 namespace mozilla {
 
 void
 WebGLContext::BindVertexArray(WebGLVertexArray* array)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull("bindVertexArrayObject", array))
+    if (array && !ValidateObject("bindVertexArrayObject", *array))
         return;
 
-    if (array && array->IsDeleted()) {
-        /* http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt
-         * BindVertexArrayOES fails and an INVALID_OPERATION error is
-         * generated if array is not a name returned from a previous call to
-         * GenVertexArraysOES, or if such a name has since been deleted with
-         * DeleteVertexArraysOES
-         */
-        ErrorInvalidOperation("bindVertexArray: can't bind a deleted array!");
-        return;
-    }
-
     InvalidateBufferFetching();
 
     MakeContextCurrent();
 
     if (array == nullptr) {
         array = mDefaultVertexArray;
     }
 
@@ -63,43 +52,28 @@ WebGLVertexArray*
 WebGLContext::CreateVertexArrayImpl()
 {
     return WebGLVertexArray::Create(this);
 }
 
 void
 WebGLContext::DeleteVertexArray(WebGLVertexArray* array)
 {
-    if (IsContextLost())
-        return;
-
-    if (array == nullptr)
-        return;
-
-    if (array->IsDeleted())
+    if (!ValidateDeleteObject("deleteVertexArray", array))
         return;
 
     if (mBoundVertexArray == array)
         BindVertexArray(static_cast<WebGLVertexArray*>(nullptr));
 
     array->RequestDelete();
 }
 
 bool
-WebGLContext::IsVertexArray(WebGLVertexArray* array)
+WebGLContext::IsVertexArray(const WebGLVertexArray* array)
 {
-    if (IsContextLost())
-        return false;
-
-    if (!array)
-        return false;
-
-    if (!ValidateObjectAllowDeleted("isVertexArray", array))
-        return false;
-
-    if (array->IsDeleted())
+    if (!ValidateIsObject("isVertexArray", array))
         return false;
 
     MakeContextCurrent();
     return array->IsVertexArray();
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDebugShaders.cpp
+++ b/dom/canvas/WebGLExtensionDebugShaders.cpp
@@ -33,17 +33,17 @@ WebGLExtensionDebugShaders::GetTranslate
         mContext->ErrorInvalidOperation("%s: Extension is lost.",
                                         "getTranslatedShaderSource");
         return;
     }
 
     if (mContext->IsContextLost())
         return;
 
-    if (!mContext->ValidateObjectRef("getShaderTranslatedSource: shader", shader))
+    if (!mContext->ValidateObject("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
@@ -78,17 +78,17 @@ WebGLExtensionDisjointTimerQuery::EndQue
 
 void
 WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery& query, GLenum target) const
 {
     const char funcName[] = "queryCounterEXT";
     if (mIsLost)
         return;
 
-    if (!mContext->ValidateObjectRef(funcName, query))
+    if (!mContext->ValidateObject(funcName, query))
         return;
 
     query.QueryCounter(funcName, target);
 }
 
 void
 WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, GLenum pname,
                                               JS::MutableHandleValue retval) const
--- a/dom/canvas/WebGLExtensionVertexArray.cpp
+++ b/dom/canvas/WebGLExtensionVertexArray.cpp
@@ -36,17 +36,17 @@ WebGLExtensionVertexArray::DeleteVertexA
 {
     if (mIsLost)
         return;
 
     mContext->DeleteVertexArray(array);
 }
 
 bool
-WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
+WebGLExtensionVertexArray::IsVertexArrayOES(const WebGLVertexArray* array)
 {
     if (mIsLost)
         return false;
 
     return mContext->IsVertexArray(array);
 }
 
 void
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -339,17 +339,17 @@ class WebGLExtensionVertexArray
     : public WebGLExtensionBase
 {
 public:
     explicit WebGLExtensionVertexArray(WebGLContext* webgl);
     virtual ~WebGLExtensionVertexArray();
 
     already_AddRefed<WebGLVertexArray> CreateVertexArrayOES();
     void DeleteVertexArrayOES(WebGLVertexArray* array);
-    bool IsVertexArrayOES(WebGLVertexArray* array);
+    bool IsVertexArrayOES(const WebGLVertexArray* array);
     void BindVertexArrayOES(WebGLVertexArray* array);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
 class WebGLExtensionInstancedArrays
     : public WebGLExtensionBase
 {
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -599,17 +599,17 @@ WebGLFBAttachPoint::GetParameter(const c
     return JS::Int32Value(ret);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 // WebGLFramebuffer
 
 WebGLFramebuffer::WebGLFramebuffer(WebGLContext* webgl, GLuint fbo)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(fbo)
 #ifdef ANDROID
     , mIsFB(false)
 #endif
     , mDepthAttachment(this, LOCAL_GL_DEPTH_ATTACHMENT)
     , mStencilAttachment(this, LOCAL_GL_STENCIL_ATTACHMENT)
     , mDepthStencilAttachment(this, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
 {
@@ -1296,17 +1296,17 @@ WebGLFramebuffer::FramebufferRenderbuffe
 
     // `rbTarget`
     if (rbtarget != LOCAL_GL_RENDERBUFFER) {
         mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: rbtarget:", rbtarget);
         return;
     }
 
     // `rb`
-    if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: rb", rb))
+    if (rb && !mContext->ValidateObject("framebufferRenderbuffer: rb", *rb))
         return;
 
     // End of validation.
 
     if (mContext->IsWebGL2() && attachEnum == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
         mDepthAttachment.SetRenderbuffer(rb);
         mStencilAttachment.SetRenderbuffer(rb);
     } else {
@@ -1338,20 +1338,20 @@ WebGLFramebuffer::FramebufferTexture2D(c
          texImageTarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
     {
         mContext->ErrorInvalidEnumInfo("framebufferTexture2D: texImageTarget:",
                                        texImageTarget);
         return;
     }
 
     // `texture`
-    if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture", tex))
-        return;
+    if (tex) {
+        if (!mContext->ValidateObject("framebufferTexture2D: texture", *tex))
+            return;
 
-    if (tex) {
         if (!tex->HasEverBeenBound()) {
             mContext->ErrorInvalidOperation("%s: `texture` has never been bound.",
                                             funcName);
             return;
         }
 
         const TexTarget destTexTarget = TexImageTargetToTexTarget(texImageTarget);
         if (tex->Target() != destTexTarget) {
@@ -1414,34 +1414,35 @@ WebGLFramebuffer::FramebufferTextureLaye
     // `attachment`
     const auto maybeAttach = GetAttachPoint(attachEnum);
     if (!maybeAttach) {
         mContext->ErrorInvalidEnum("%s: Bad `attachment`: 0x%x.", funcName, attachEnum);
         return;
     }
     const auto& attach = maybeAttach.value();
 
-    // `texture`
-    if (!mContext->ValidateObjectAllowNull("framebufferTextureLayer: texture", tex))
-        return;
-
-    if (tex && !tex->HasEverBeenBound()) {
-        mContext->ErrorInvalidOperation("%s: `texture` has never been bound.", funcName);
-        return;
-    }
-
     // `level`, `layer`
     if (layer < 0)
         return mContext->ErrorInvalidValue("%s: `layer` must be >= 0.", funcName);
 
     if (level < 0)
         return mContext->ErrorInvalidValue("%s: `level` must be >= 0.", funcName);
 
+    // `texture`
     TexImageTarget texImageTarget = LOCAL_GL_TEXTURE_3D;
     if (tex) {
+        if (!mContext->ValidateObject("framebufferTextureLayer: texture", *tex))
+            return;
+
+        if (!tex->HasEverBeenBound()) {
+            mContext->ErrorInvalidOperation("%s: `texture` has never been bound.",
+                                            funcName);
+            return;
+        }
+
         texImageTarget = tex->Target().get();
         switch (texImageTarget.get()) {
         case LOCAL_GL_TEXTURE_3D:
             if (uint32_t(layer) >= mContext->mImplMax3DTextureSize) {
                 mContext->ErrorInvalidValue("%s: `layer` must be < %s.", funcName,
                                             "MAX_3D_TEXTURE_SIZE");
                 return;
             }
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -127,17 +127,16 @@ public:
         }
     };
 };
 
 class WebGLFramebuffer final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLFramebuffer>
     , public LinkedListElement<WebGLFramebuffer>
-    , public WebGLContextBoundObject
     , public SupportsWeakPtr<WebGLFramebuffer>
 {
     friend class WebGLContext;
 
 public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer)
 
     const GLuint mGLName;
--- a/dom/canvas/WebGLObjectModel.h
+++ b/dom/canvas/WebGLObjectModel.h
@@ -7,18 +7,65 @@
 #define WEBGLOBJECTMODEL_H_
 
 #include "nsCycleCollectionNoteChild.h"
 
 #include "WebGLTypes.h"
 
 namespace mozilla {
 
+template<typename> class LinkedList;
 class WebGLContext;
 
+////
+
+// This class is a mixin for objects that are tied to a specific
+// context (which is to say, all of them).  They provide initialization
+// as well as comparison with the current context.
+class WebGLContextBoundObject
+{
+public:
+    WebGLContext* const mContext;
+private:
+    const uint32_t mContextGeneration;
+
+public:
+    explicit WebGLContextBoundObject(WebGLContext* webgl);
+
+    bool IsCompatibleWithContext(const WebGLContext* other) const;
+};
+
+////
+
+class WebGLDeletableObject : public WebGLContextBoundObject
+{
+    template<typename> friend class WebGLRefCountedObject;
+
+private:
+    enum DeletionStatus { Default, DeleteRequested, Deleted };
+
+    DeletionStatus mDeletionStatus;
+
+    ////
+
+    explicit WebGLDeletableObject(WebGLContext* webgl)
+      : WebGLContextBoundObject(webgl)
+      , mDeletionStatus(Default)
+    {}
+
+    ~WebGLDeletableObject() {
+        MOZ_ASSERT(mDeletionStatus == Deleted,
+                   "Derived class destructor must call DeleteOnce().");
+    }
+
+public:
+    bool IsDeleted() const { return mDeletionStatus == Deleted; }
+    bool IsDeleteRequested() const { return mDeletionStatus != Default; }
+};
+
 /* Each WebGL object class WebGLFoo wants to:
  *  - inherit WebGLRefCountedObject<WebGLFoo>
  *  - implement a Delete() method
  *  - have its destructor call DeleteOnce()
  *
  * This base class provides two features to WebGL object types:
  * 1. support for OpenGL object reference counting
  * 2. support for OpenGL deletion statuses
@@ -86,32 +133,35 @@ class WebGLContext;
  * derived class were final, but that would be impossible to enforce and would
  * lead to strange bugs if it were subclassed.
  *
  * This WebGLRefCountedObject class takes the Derived type as template
  * parameter, as a means to allow DeleteOnce to call Delete() on the Derived
  * class, without either method being virtual. This is a common C++ pattern
  * known as the "curiously recursive template pattern (CRTP)".
  */
+
 template<typename Derived>
-class WebGLRefCountedObject
+class WebGLRefCountedObject : public WebGLDeletableObject
 {
+    friend class WebGLContext;
+    template<typename T> friend void ClearLinkedList(LinkedList<T>& list);
+
+private:
+    nsAutoRefCnt mWebGLRefCnt;
+
 public:
-    enum DeletionStatus { Default, DeleteRequested, Deleted };
-
-    WebGLRefCountedObject()
-      : mDeletionStatus(Default)
-    {}
+    WebGLRefCountedObject(WebGLContext* webgl)
+        : WebGLDeletableObject(webgl)
+    { }
 
     ~WebGLRefCountedObject() {
         MOZ_ASSERT(mWebGLRefCnt == 0,
                    "Destroying WebGL object still referenced by other WebGL"
                    " objects.");
-        MOZ_ASSERT(mDeletionStatus == Deleted,
-                   "Derived class destructor must call DeleteOnce().");
     }
 
     // called by WebGLRefPtr
     void WebGLAddRef() {
         ++mWebGLRefCnt;
     }
 
     // called by WebGLRefPtr
@@ -124,43 +174,32 @@ public:
 
     // this is the function that WebGL.deleteXxx() functions want to call
     void RequestDelete() {
         if (mDeletionStatus == Default)
             mDeletionStatus = DeleteRequested;
         MaybeDelete();
     }
 
-    bool IsDeleted() const {
-        return mDeletionStatus == Deleted;
-    }
-
-    bool IsDeleteRequested() const {
-        return mDeletionStatus != Default;
-    }
-
+protected:
     void DeleteOnce() {
         if (mDeletionStatus != Deleted) {
             static_cast<Derived*>(this)->Delete();
             mDeletionStatus = Deleted;
         }
     }
 
 private:
     void MaybeDelete() {
         if (mWebGLRefCnt == 0 &&
             mDeletionStatus == DeleteRequested)
         {
             DeleteOnce();
         }
     }
-
-protected:
-    nsAutoRefCnt mWebGLRefCnt;
-    DeletionStatus mDeletionStatus;
 };
 
 /* This WebGLRefPtr class is meant to be used for references between WebGL
  * objects. For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's
  * attached to it.
  *
  * Why the need for a separate refptr class? The only special thing that
  * WebGLRefPtr does is that it increments and decrements the WebGL refcount of
@@ -254,31 +293,16 @@ private:
         mRawPtr = newPtr;
         ReleasePtr(oldPtr);
     }
 
 protected:
     T* mRawPtr;
 };
 
-// This class is a mixin for objects that are tied to a specific
-// context (which is to say, all of them).  They provide initialization
-// as well as comparison with the current context.
-class WebGLContextBoundObject
-{
-public:
-    explicit WebGLContextBoundObject(WebGLContext* webgl);
-
-    bool IsCompatibleWithContext(const WebGLContext* other) const;
-
-    WebGLContext* const mContext;
-protected:
-    const uint32_t mContextGeneration;
-};
-
 // this class is a mixin for GL objects that have dimensions
 // that we need to track.
 class WebGLRectangleObject
 {
 public:
     WebGLRectangleObject()
         : mWidth(0)
         , mHeight(0)
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -438,17 +438,17 @@ webgl::LinkedProgramInfo::~LinkedProgram
 static GLuint
 CreateProgram(gl::GLContext* gl)
 {
     gl->MakeCurrent();
     return gl->fCreateProgram();
 }
 
 WebGLProgram::WebGLProgram(WebGLContext* webgl)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(CreateProgram(webgl->GL()))
     , mNumActiveTFOs(0)
     , mNextLink_TransformFeedbackBufferMode(LOCAL_GL_SEPARATE_ATTRIBS)
 {
     mContext->mPrograms.insertBack(this);
 }
 
 WebGLProgram::~WebGLProgram()
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -125,17 +125,16 @@ struct LinkedProgramInfo final
 };
 
 } // namespace webgl
 
 class WebGLProgram final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLProgram>
     , public LinkedListElement<WebGLProgram>
-    , public WebGLContextBoundObject
 {
     friend class WebGLTransformFeedback;
 
 public:
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgram)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLProgram)
 
     explicit WebGLProgram(WebGLContext* webgl);
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -35,17 +35,17 @@ GenQuery(gl::GLContext* gl)
     gl->MakeCurrent();
 
     GLuint ret = 0;
     gl->fGenQueries(1, &ret);
     return ret;
 }
 
 WebGLQuery::WebGLQuery(WebGLContext* webgl)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(GenQuery(mContext->gl))
     , mTarget(0)
     , mActiveSlot(nullptr)
     , mCanBeAvailable(false)
 {
     mContext->mQueries.insertBack(this);
 }
 
@@ -206,30 +206,28 @@ WebGLQuery::GetQueryParameter(GLenum pna
     default:
         MOZ_CRASH("Bad `pname`.");
     }
 }
 
 bool
 WebGLQuery::IsQuery() const
 {
-    if (IsDeleted())
-        return false;
+    MOZ_ASSERT(!IsDeleted());
 
     if (!mTarget)
         return false;
 
     return true;
 }
 
 void
 WebGLQuery::DeleteQuery()
 {
-    if (IsDeleted())
-        return;
+    MOZ_ASSERT(!IsDeleteRequested());
 
     if (mActiveSlot) {
         EndQuery();
     }
 
     RequestDelete();
 }
 
--- a/dom/canvas/WebGLQuery.h
+++ b/dom/canvas/WebGLQuery.h
@@ -13,17 +13,16 @@
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 
 class WebGLQuery final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLQuery>
     , public LinkedListElement<WebGLQuery>
-    , public WebGLContextBoundObject
 {
     friend class AvailableRunnable;
     friend class WebGLRefCountedObject<WebGLQuery>;
 
 public:
     const GLuint mGLName;
 private:
     GLenum mTarget;
--- a/dom/canvas/WebGLRenderbuffer.cpp
+++ b/dom/canvas/WebGLRenderbuffer.cpp
@@ -42,17 +42,17 @@ DoCreateRenderbuffer(gl::GLContext* gl)
 
 static bool
 EmulatePackedDepthStencil(gl::GLContext* gl)
 {
     return !gl->IsSupported(gl::GLFeature::packed_depth_stencil);
 }
 
 WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mPrimaryRB( DoCreateRenderbuffer(webgl->gl) )
     , mEmulatePackedDepthStencil( EmulatePackedDepthStencil(webgl->gl) )
     , mSecondaryRB(0)
     , mFormat(nullptr)
     , mSamples(0)
     , mImageDataStatus(WebGLImageDataStatus::NoImageData)
     , mHasBeenBound(false)
 {
--- a/dom/canvas/WebGLRenderbuffer.h
+++ b/dom/canvas/WebGLRenderbuffer.h
@@ -18,17 +18,16 @@ namespace webgl {
 struct FormatUsageInfo;
 }
 
 class WebGLRenderbuffer final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLRenderbuffer>
     , public LinkedListElement<WebGLRenderbuffer>
     , public WebGLRectangleObject
-    , public WebGLContextBoundObject
     , public WebGLFramebufferAttachable
 {
     friend class WebGLContext;
     friend class WebGLFramebuffer;
     friend class WebGLFBAttachPoint;
 
 public:
     const GLuint mPrimaryRB;
--- a/dom/canvas/WebGLSampler.cpp
+++ b/dom/canvas/WebGLSampler.cpp
@@ -7,17 +7,17 @@
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
 WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(sampler)
     , mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
     , mMagFilter(LOCAL_GL_LINEAR)
     , mWrapS(LOCAL_GL_REPEAT)
     , mWrapT(LOCAL_GL_REPEAT)
     , mWrapR(LOCAL_GL_REPEAT)
     , mMinLod(-1000)
     , mMaxLod(1000)
--- a/dom/canvas/WebGLSampler.h
+++ b/dom/canvas/WebGLSampler.h
@@ -12,17 +12,16 @@
 #include "WebGLStrongTypes.h"
 
 namespace mozilla {
 
 class WebGLSampler final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLSampler>
     , public LinkedListElement<WebGLSampler>
-    , public WebGLContextBoundObject
 {
     friend class WebGLContext2;
     friend class WebGLTexture;
 
 public:
     WebGLSampler(WebGLContext* webgl, GLuint sampler);
 
     const GLuint mGLName;
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -136,17 +136,17 @@ GetCompilationStatusAndLog(gl::GLContext
 static GLuint
 CreateShader(gl::GLContext* gl, GLenum type)
 {
     gl->MakeCurrent();
     return gl->fCreateShader(type);
 }
 
 WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(CreateShader(webgl->GL(), type))
     , mType(type)
     , mTranslationSuccessful(false)
     , mCompilationSuccessful(false)
 {
     mContext->mShaders.insertBack(this);
 }
 
--- a/dom/canvas/WebGLShader.h
+++ b/dom/canvas/WebGLShader.h
@@ -23,17 +23,16 @@ namespace mozilla {
 namespace webgl {
 class ShaderValidator;
 } // namespace webgl
 
 class WebGLShader final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLShader>
     , public LinkedListElement<WebGLShader>
-    , public WebGLContextBoundObject
 {
     friend class WebGLContext;
     friend class WebGLProgram;
 
 public:
     WebGLShader(WebGLContext* webgl, GLenum type);
 
 protected:
--- a/dom/canvas/WebGLSync.cpp
+++ b/dom/canvas/WebGLSync.cpp
@@ -7,17 +7,17 @@
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
 WebGLSync::WebGLSync(WebGLContext* webgl, GLenum condition, GLbitfield flags)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
 {
    mContext->mSyncs.insertBack(this);
    mGLName = mContext->gl->fFenceSync(condition, flags);
 }
 
 WebGLSync::~WebGLSync()
 {
     DeleteOnce();
--- a/dom/canvas/WebGLSync.h
+++ b/dom/canvas/WebGLSync.h
@@ -11,17 +11,16 @@
 #include "WebGLObjectModel.h"
 
 namespace mozilla {
 
 class WebGLSync final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLSync>
     , public LinkedListElement<WebGLSync>
-    , public WebGLContextBoundObject
 {
     friend class WebGL2Context;
 
 public:
     WebGLSync(WebGLContext* webgl, GLenum condition, GLbitfield flags);
 
     void Delete();
     WebGLContext* GetParentObject() const;
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -122,17 +122,17 @@ WebGLTexture::ImageInfo::SetIsDataInitia
 ////////////////////////////////////////
 
 JSObject*
 WebGLTexture::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) {
     return dom::WebGLTextureBinding::Wrap(cx, this, givenProto);
 }
 
 WebGLTexture::WebGLTexture(WebGLContext* webgl, GLuint tex)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(tex)
     , mTarget(LOCAL_GL_NONE)
     , mFaceCount(0)
     , mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
     , mMagFilter(LOCAL_GL_LINEAR)
     , mWrapS(LOCAL_GL_REPEAT)
     , mWrapT(LOCAL_GL_REPEAT)
     , mImmutable(false)
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -52,17 +52,16 @@ DoesTargetMatchDimensions(WebGLContext* 
 
 
 // NOTE: When this class is switched to new DOM bindings, update the (then-slow)
 // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
 class WebGLTexture final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLTexture>
     , public LinkedListElement<WebGLTexture>
-    , public WebGLContextBoundObject
 {
     // Friends
     friend class WebGLContext;
     friend class WebGLFramebuffer;
 
     ////////////////////////////////////
     // Members
 public:
--- a/dom/canvas/WebGLTransformFeedback.cpp
+++ b/dom/canvas/WebGLTransformFeedback.cpp
@@ -7,17 +7,17 @@
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "WebGL2Context.h"
 
 namespace mozilla {
 
 WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl, GLuint tf)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(tf)
     , mIndexedBindings(webgl->mGLMaxTransformFeedbackSeparateAttribs)
     , mIsPaused(false)
     , mIsActive(false)
     , mBuffersForTF_Dirty(true)
 {
     mContext->mTransformFeedbacks.insertBack(this);
 }
--- a/dom/canvas/WebGLTransformFeedback.h
+++ b/dom/canvas/WebGLTransformFeedback.h
@@ -11,17 +11,16 @@
 #include "WebGLObjectModel.h"
 
 namespace mozilla {
 
 class WebGLTransformFeedback final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLTransformFeedback>
     , public LinkedListElement<WebGLTransformFeedback>
-    , public WebGLContextBoundObject
 {
     friend class ScopedDrawWithTransformFeedback;
     friend class WebGLContext;
     friend class WebGL2Context;
     friend class WebGLProgram;
 
 public:
     const GLuint mGLName;
--- a/dom/canvas/WebGLVertexArray.cpp
+++ b/dom/canvas/WebGLVertexArray.cpp
@@ -16,17 +16,17 @@ namespace mozilla {
 
 JSObject*
 WebGLVertexArray::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
     return dom::WebGLVertexArrayObjectBinding::Wrap(cx, this, givenProto);
 }
 
 WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl)
-    : WebGLContextBoundObject(webgl)
+    : WebGLRefCountedObject(webgl)
     , mGLName(0)
 {
     mContext->mVertexArrays.insertBack(this);
 }
 
 WebGLVertexArray*
 WebGLVertexArray::Create(WebGLContext* webgl)
 {
@@ -45,17 +45,17 @@ WebGLVertexArray::Delete()
     DeleteImpl();
 
     LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
     mElementArrayBuffer = nullptr;
     mAttribs.Clear();
 }
 
 bool
-WebGLVertexArray::IsVertexArray()
+WebGLVertexArray::IsVertexArray() const
 {
     return IsVertexArrayImpl();
 }
 
 void
 WebGLVertexArray::EnsureAttrib(GLuint index)
 {
     MOZ_ASSERT(index < GLuint(mContext->mGLMaxVertexAttribs));
--- a/dom/canvas/WebGLVertexArray.h
+++ b/dom/canvas/WebGLVertexArray.h
@@ -18,17 +18,16 @@
 namespace mozilla {
 
 class WebGLVertexArrayFake;
 
 class WebGLVertexArray
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLVertexArray>
     , public LinkedListElement<WebGLVertexArray>
-    , public WebGLContextBoundObject
 {
 public:
     static WebGLVertexArray* Create(WebGLContext* webgl);
 
     void BindVertexArray() {
         // Bind to dummy value to signal that this vertex array has ever been
         // bound.
         BindVertexArrayImpl();
@@ -39,17 +38,17 @@ public:
         return index < mAttribs.Length();
     }
     bool IsAttribArrayEnabled(GLuint index) const {
         return HasAttrib(index) && mAttribs[index].mEnabled;
     }
 
     // Implement parent classes:
     void Delete();
-    bool IsVertexArray();
+    bool IsVertexArray() const;
 
     WebGLContext* GetParentObject() const {
         return mContext;
     }
 
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArray)
@@ -62,17 +61,17 @@ protected:
 
     virtual ~WebGLVertexArray() {
         MOZ_ASSERT(IsDeleted());
     }
 
     virtual void GenVertexArray() = 0;
     virtual void BindVertexArrayImpl() = 0;
     virtual void DeleteImpl() = 0;
-    virtual bool IsVertexArrayImpl() = 0;
+    virtual bool IsVertexArrayImpl() const = 0;
 
     GLuint mGLName;
     nsTArray<WebGLVertexAttribData> mAttribs;
     WebGLRefPtr<WebGLBuffer> mElementArrayBuffer;
 
     friend class WebGLContext;
     friend class WebGLVertexArrayFake;
     friend class WebGL2Context;
--- a/dom/canvas/WebGLVertexArrayFake.cpp
+++ b/dom/canvas/WebGLVertexArrayFake.cpp
@@ -57,14 +57,14 @@ WebGLVertexArrayFake::BindVertexArrayImp
 
 void
 WebGLVertexArrayFake::DeleteImpl()
 {
     mIsVAO = false;
 }
 
 bool
-WebGLVertexArrayFake::IsVertexArrayImpl()
+WebGLVertexArrayFake::IsVertexArrayImpl() const
 {
     return mIsVAO;
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLVertexArrayFake.h
+++ b/dom/canvas/WebGLVertexArrayFake.h
@@ -14,17 +14,17 @@ class WebGLVertexArrayFake final
     : public WebGLVertexArray
 {
     friend class WebGLVertexArray;
 
 protected:
     virtual void BindVertexArrayImpl() override;
     virtual void DeleteImpl() override;
     virtual void GenVertexArray() override {};
-    virtual bool IsVertexArrayImpl() override;
+    virtual bool IsVertexArrayImpl() const override;
 
 private:
     explicit WebGLVertexArrayFake(WebGLContext* webgl);
 
     ~WebGLVertexArrayFake() {
         DeleteOnce();
     }
 
--- a/dom/canvas/WebGLVertexArrayGL.cpp
+++ b/dom/canvas/WebGLVertexArrayGL.cpp
@@ -42,17 +42,17 @@ WebGLVertexArrayGL::BindVertexArrayImpl(
 
 void
 WebGLVertexArrayGL::GenVertexArray()
 {
     mContext->gl->fGenVertexArrays(1, &mGLName);
 }
 
 bool
-WebGLVertexArrayGL::IsVertexArrayImpl()
+WebGLVertexArrayGL::IsVertexArrayImpl() const
 {
     gl::GLContext* gl = mContext->gl;
     if (gl->WorkAroundDriverBugs())
     {
         return mIsVAO;
     }
 
     mContext->MakeContextCurrent();
--- a/dom/canvas/WebGLVertexArrayGL.h
+++ b/dom/canvas/WebGLVertexArrayGL.h
@@ -14,17 +14,17 @@ class WebGLVertexArrayGL
     : public WebGLVertexArray
 {
     friend class WebGLVertexArray;
 
 public:
     virtual void DeleteImpl() override;
     virtual void BindVertexArrayImpl() override;
     virtual void GenVertexArray() override;
-    virtual bool IsVertexArrayImpl() override;
+    virtual bool IsVertexArrayImpl() const override;
 
 protected:
     explicit WebGLVertexArrayGL(WebGLContext* webgl);
     ~WebGLVertexArrayGL();
 
     // Bug 1140459: Some drivers (including our test slaves!) don't
     // give reasonable answers for IsVertexArray, maybe others.
     //