Bug 1288643 - Reduce extension boilerplate. - r=jerry draft
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 20 Jul 2016 16:56:15 -0700
changeset 391212 75f2b17550316ecb4b320bca9325520c2f1c7673
parent 391031 2e3390571fdb3a1ff3d2f7f828adf67dbc237bc8
child 391213 ba1bd91de8858daeeac68e84736e193e87b2a34a
push id23845
push userbmo:jgilbert@mozilla.com
push dateFri, 22 Jul 2016 08:40:49 +0000
reviewersjerry
bugs1288643
milestone50.0a1
Bug 1288643 - Reduce extension boilerplate. - r=jerry MozReview-Commit-ID: 3J4tpY6elHc
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContextExtensions.cpp
dom/canvas/WebGLExtensionBase.cpp
dom/canvas/WebGLExtensionBlendMinMax.cpp
dom/canvas/WebGLExtensionColorBufferFloat.cpp
dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp
dom/canvas/WebGLExtensionCompressedTextureATC.cpp
dom/canvas/WebGLExtensionCompressedTextureES3.cpp
dom/canvas/WebGLExtensionCompressedTextureETC1.cpp
dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp
dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp
dom/canvas/WebGLExtensionDebugRendererInfo.cpp
dom/canvas/WebGLExtensionDebugShaders.cpp
dom/canvas/WebGLExtensionDepthTexture.cpp
dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
dom/canvas/WebGLExtensionDrawBuffers.cpp
dom/canvas/WebGLExtensionEXTColorBufferFloat.cpp
dom/canvas/WebGLExtensionElementIndexUint.cpp
dom/canvas/WebGLExtensionFragDepth.cpp
dom/canvas/WebGLExtensionInstancedArrays.cpp
dom/canvas/WebGLExtensionLoseContext.cpp
dom/canvas/WebGLExtensionSRGB.cpp
dom/canvas/WebGLExtensionShaderTextureLod.cpp
dom/canvas/WebGLExtensionStandardDerivatives.cpp
dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp
dom/canvas/WebGLExtensionTextureFloat.cpp
dom/canvas/WebGLExtensionTextureFloatLinear.cpp
dom/canvas/WebGLExtensionTextureHalfFloat.cpp
dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp
dom/canvas/WebGLExtensionVertexArray.cpp
dom/canvas/WebGLExtensions.h
dom/canvas/WebGLObjectModel.cpp
dom/canvas/WebGLObjectModel.h
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -291,17 +291,17 @@ WebGLContext::DestroyResourcesAndContext
     // disable all extensions except "WEBGL_lose_context". see bug #927969
     // spec: http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
     for (size_t i = 0; i < size_t(WebGLExtensionID::Max); ++i) {
         WebGLExtensionID extension = WebGLExtensionID(i);
 
         if (!IsExtensionEnabled(extension) || (extension == WebGLExtensionID::WEBGL_lose_context))
             continue;
 
-        mExtensions[extension]->MarkLost();
+        mExtensions[extension]->Detach();
         mExtensions[extension] = nullptr;
     }
 
     // We just got rid of everything, so the context had better
     // have been going away.
     if (GLContext::ShouldSpew()) {
         printf_stderr("--- WebGL context destroyed: %p\n", gl.get());
     }
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -5,65 +5,69 @@
 
 #include "WebGLContext.h"
 #include "WebGLContextUtils.h"
 #include "WebGLExtensions.h"
 #include "gfxPrefs.h"
 #include "GLContext.h"
 
 #include "nsString.h"
-#include "mozilla/Preferences.h"
 #include "AccessCheck.h"
 
 namespace mozilla {
 
+#define FOR_EACH_PRIVILEGED_EXT(FUNC) \
+    FUNC(WEBGL_debug_renderer_info, WebGLExtensionDebugRendererInfo) \
+    FUNC(WEBGL_debug_shaders      , WebGLExtensionDebugShaders     )
+
+#define FOR_EACH_EXT(FUNC) \
+    FUNC(ANGLE_instanced_arrays        , WebGLExtensionInstancedArrays         ) \
+    FUNC(EXT_blend_minmax              , WebGLExtensionBlendMinMax             ) \
+    FUNC(EXT_color_buffer_float        , WebGLExtensionEXTColorBufferFloat     ) \
+    FUNC(EXT_color_buffer_half_float   , WebGLExtensionColorBufferHalfFloat    ) \
+    FUNC(EXT_disjoint_timer_query      , WebGLExtensionDisjointTimerQuery      ) \
+    FUNC(EXT_frag_depth                , WebGLExtensionFragDepth               ) \
+    FUNC(EXT_shader_texture_lod        , WebGLExtensionShaderTextureLod        ) \
+    FUNC(EXT_sRGB                      , WebGLExtensionSRGB                    ) \
+    FUNC(EXT_texture_filter_anisotropic, WebGLExtensionTextureFilterAnisotropic) \
+    FUNC(OES_element_index_uint        , WebGLExtensionElementIndexUint        ) \
+    FUNC(OES_standard_derivatives      , WebGLExtensionStandardDerivatives     ) \
+    FUNC(OES_texture_float             , WebGLExtensionTextureFloat            ) \
+    FUNC(OES_texture_float_linear      , WebGLExtensionTextureFloatLinear      ) \
+    FUNC(OES_texture_half_float        , WebGLExtensionTextureHalfFloat        ) \
+    FUNC(OES_texture_half_float_linear , WebGLExtensionTextureHalfFloatLinear  ) \
+    FUNC(OES_vertex_array_object       , WebGLExtensionVertexArray             ) \
+    FUNC(WEBGL_color_buffer_float      , WebGLExtensionColorBufferFloat        ) \
+    FUNC(WEBGL_compressed_texture_atc  , WebGLExtensionCompressedTextureATC    ) \
+    FUNC(WEBGL_compressed_texture_es3  , WebGLExtensionCompressedTextureES3    ) \
+    FUNC(WEBGL_compressed_texture_etc1 , WebGLExtensionCompressedTextureETC1   ) \
+    FUNC(WEBGL_compressed_texture_pvrtc, WebGLExtensionCompressedTexturePVRTC  ) \
+    FUNC(WEBGL_compressed_texture_s3tc , WebGLExtensionCompressedTextureS3TC   ) \
+    FUNC(WEBGL_depth_texture           , WebGLExtensionDepthTexture            ) \
+    FUNC(WEBGL_draw_buffers            , WebGLExtensionDrawBuffers             ) \
+    FUNC(WEBGL_lose_context            , WebGLExtensionLoseContext             )
+
 /*static*/ const char*
 WebGLContext::GetExtensionString(WebGLExtensionID ext)
 {
     typedef EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max,
                             const char*> names_array_t;
 
     static names_array_t sExtensionNamesEnumeratedArray;
     static bool initialized = false;
 
     if (!initialized) {
         initialized = true;
 
-#define WEBGL_EXTENSION_IDENTIFIER(x) \
-        sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x;
+#define FOO(ID,FUNC) sExtensionNamesEnumeratedArray[WebGLExtensionID::ID] = #ID;
 
-        WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_float)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
-        WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
-        WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
-        WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
-        WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
-        WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear)
-        WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
-        WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
-        WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_atc)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_es3)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_renderer_info)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_shaders)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_depth_texture)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_draw_buffers)
-        WEBGL_EXTENSION_IDENTIFIER(WEBGL_lose_context)
+        FOR_EACH_PRIVILEGED_EXT(FOO)
+        FOR_EACH_EXT(FOO)
 
-#undef WEBGL_EXTENSION_IDENTIFIER
+#undef FOO
     }
 
     return sExtensionNamesEnumeratedArray[ext];
 }
 
 bool
 WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const
 {
@@ -84,149 +88,55 @@ bool WebGLContext::IsExtensionSupported(
     }
 
     if (gfxPrefs::WebGLPrivilegedExtensionsEnabled()) {
         allowPrivilegedExts = true;
     }
 
     if (allowPrivilegedExts) {
         switch (ext) {
-        case WebGLExtensionID::WEBGL_debug_renderer_info:
+
+#define FOO(ID,TYPE)               \
+        case WebGLExtensionID::ID: \
             return true;
-        case WebGLExtensionID::WEBGL_debug_shaders:
-            return true;
+
+            FOR_EACH_PRIVILEGED_EXT(FOO)
+
+#undef FOO
+
         default:
             // For warnings-as-errors.
             break;
         }
     }
 
     return IsExtensionSupported(ext);
 }
 
 bool
 WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
 {
     if (mDisableExtensions)
         return false;
 
-    // Extensions for both WebGL 1 and 2.
     switch (ext) {
-    // In alphabetical order
-    // EXT_
-    case WebGLExtensionID::EXT_texture_filter_anisotropic:
-        return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
-
-    // OES_
-    case WebGLExtensionID::OES_texture_float_linear:
-        return gl->IsSupported(gl::GLFeature::texture_float_linear);
 
-    // WEBGL_
-    case WebGLExtensionID::WEBGL_compressed_texture_atc:
-        return gl->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture);
-    case WebGLExtensionID::WEBGL_compressed_texture_etc1:
-        return gl->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture);
-    case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
-        return gl->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc);
-    case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
-        if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
-            return true;
+#define FOO(ID,TYPE)           \
+    case WebGLExtensionID::ID: \
+        return TYPE::IsSupported(this);
 
-        return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
-               gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
-               gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
+        FOR_EACH_EXT(FOO)
 
-    case WebGLExtensionID::WEBGL_debug_renderer_info:
-        return Preferences::GetBool("webgl.enable-debug-renderer-info", false);
-
-    case WebGLExtensionID::WEBGL_lose_context:
-        // We always support this extension.
-        return true;
+#undef FOO
 
     default:
         // For warnings-as-errors.
         break;
     }
 
-    if (IsWebGL2()) {
-        // WebGL2-only extensions
-        switch (ext) {
-        // EXT_
-        case WebGLExtensionID::EXT_color_buffer_float:
-            return WebGLExtensionEXTColorBufferFloat::IsSupported(this);
-
-        default:
-            // For warnings-as-errors.
-            break;
-        }
-    } else {
-        // WebGL1-only extensions
-        switch (ext) {
-        // ANGLE_
-        case WebGLExtensionID::ANGLE_instanced_arrays:
-            return WebGLExtensionInstancedArrays::IsSupported(this);
-
-        // EXT_
-        case WebGLExtensionID::EXT_blend_minmax:
-            return WebGLExtensionBlendMinMax::IsSupported(this);
-        case WebGLExtensionID::EXT_color_buffer_half_float:
-            return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
-        case WebGLExtensionID::EXT_frag_depth:
-            return WebGLExtensionFragDepth::IsSupported(this);
-        case WebGLExtensionID::EXT_shader_texture_lod:
-            return gl->IsSupported(gl::GLFeature::shader_texture_lod);
-        case WebGLExtensionID::EXT_sRGB:
-            return WebGLExtensionSRGB::IsSupported(this);
-
-        // OES_
-        case WebGLExtensionID::OES_element_index_uint:
-            return gl->IsSupported(gl::GLFeature::element_index_uint);
-        case WebGLExtensionID::OES_standard_derivatives:
-            return gl->IsSupported(gl::GLFeature::standard_derivatives);
-        case WebGLExtensionID::OES_texture_float:
-            return WebGLExtensionTextureFloat::IsSupported(this);
-        case WebGLExtensionID::OES_texture_half_float:
-            return WebGLExtensionTextureHalfFloat::IsSupported(this);
-        case WebGLExtensionID::OES_texture_half_float_linear:
-            return gl->IsSupported(gl::GLFeature::texture_half_float_linear);
-
-        case WebGLExtensionID::OES_vertex_array_object:
-            return true;
-
-        // WEBGL_
-        case WebGLExtensionID::WEBGL_color_buffer_float:
-            return WebGLExtensionColorBufferFloat::IsSupported(this);
-        case WebGLExtensionID::WEBGL_depth_texture:
-            // WEBGL_depth_texture supports DEPTH_STENCIL textures
-            if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
-                return false;
-
-            return gl->IsSupported(gl::GLFeature::depth_texture) ||
-                   gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
-        case WebGLExtensionID::WEBGL_draw_buffers:
-            return WebGLExtensionDrawBuffers::IsSupported(this);
-        default:
-            // For warnings-as-errors.
-            break;
-        }
-
-        if (gfxPrefs::WebGLDraftExtensionsEnabled()) {
-            switch (ext) {
-            case WebGLExtensionID::EXT_disjoint_timer_query:
-                return WebGLExtensionDisjointTimerQuery::IsSupported(this);
-            case WebGLExtensionID::WEBGL_compressed_texture_es3:
-                return gl->IsExtensionSupported(gl::GLContext::ARB_ES3_compatibility);
-
-            default:
-                // For warnings-as-errors.
-                break;
-            }
-        }
-    }
-
     return false;
 }
 
 static bool
 CompareWebGLExtensionName(const nsACString& name, const char* other)
 {
     return name.Equals(other, nsCaseInsensitiveCStringComparator());
 }
@@ -328,108 +238,32 @@ WebGLContext::GetExtension(JSContext* cx
 }
 
 void
 WebGLContext::EnableExtension(WebGLExtensionID ext)
 {
     MOZ_ASSERT(IsExtensionEnabled(ext) == false);
 
     WebGLExtensionBase* obj = nullptr;
+
     switch (ext) {
-    // ANGLE_
-    case WebGLExtensionID::ANGLE_instanced_arrays:
-        obj = new WebGLExtensionInstancedArrays(this);
-        break;
 
-    // EXT_
-    case WebGLExtensionID::EXT_blend_minmax:
-        obj = new WebGLExtensionBlendMinMax(this);
-        break;
-    case WebGLExtensionID::EXT_color_buffer_float:
-        obj = new WebGLExtensionEXTColorBufferFloat(this);
-        break;
-    case WebGLExtensionID::EXT_color_buffer_half_float:
-        obj = new WebGLExtensionColorBufferHalfFloat(this);
-        break;
-    case WebGLExtensionID::EXT_disjoint_timer_query:
-        obj = new WebGLExtensionDisjointTimerQuery(this);
-        break;
-    case WebGLExtensionID::EXT_frag_depth:
-        obj = new WebGLExtensionFragDepth(this);
-        break;
-    case WebGLExtensionID::EXT_shader_texture_lod:
-        obj = new WebGLExtensionShaderTextureLod(this);
-        break;
-    case WebGLExtensionID::EXT_sRGB:
-        obj = new WebGLExtensionSRGB(this);
-        break;
-    case WebGLExtensionID::EXT_texture_filter_anisotropic:
-        obj = new WebGLExtensionTextureFilterAnisotropic(this);
+#define FOO(ID,TYPE)           \
+    case WebGLExtensionID::ID: \
+        obj = new TYPE(this);  \
         break;
 
-    // OES_
-    case WebGLExtensionID::OES_element_index_uint:
-        obj = new WebGLExtensionElementIndexUint(this);
-        break;
-    case WebGLExtensionID::OES_standard_derivatives:
-        obj = new WebGLExtensionStandardDerivatives(this);
-        break;
-    case WebGLExtensionID::OES_texture_float:
-        obj = new WebGLExtensionTextureFloat(this);
-        break;
-    case WebGLExtensionID::OES_texture_float_linear:
-        obj = new WebGLExtensionTextureFloatLinear(this);
-        break;
-    case WebGLExtensionID::OES_texture_half_float:
-        obj = new WebGLExtensionTextureHalfFloat(this);
-        break;
-    case WebGLExtensionID::OES_texture_half_float_linear:
-        obj = new WebGLExtensionTextureHalfFloatLinear(this);
-        break;
-    case WebGLExtensionID::OES_vertex_array_object:
-        obj = new WebGLExtensionVertexArray(this);
-        break;
+    FOR_EACH_PRIVILEGED_EXT(FOO)
+    FOR_EACH_EXT(FOO)
 
-    // WEBGL_
-    case WebGLExtensionID::WEBGL_color_buffer_float:
-        obj = new WebGLExtensionColorBufferFloat(this);
-        break;
-    case WebGLExtensionID::WEBGL_compressed_texture_atc:
-        obj = new WebGLExtensionCompressedTextureATC(this);
-        break;
-    case WebGLExtensionID::WEBGL_compressed_texture_es3:
-        obj = new WebGLExtensionCompressedTextureES3(this);
-        break;
-    case WebGLExtensionID::WEBGL_compressed_texture_etc1:
-        obj = new WebGLExtensionCompressedTextureETC1(this);
-        break;
-    case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
-        obj = new WebGLExtensionCompressedTexturePVRTC(this);
-        break;
-    case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
-        obj = new WebGLExtensionCompressedTextureS3TC(this);
-        break;
-    case WebGLExtensionID::WEBGL_debug_renderer_info:
-        obj = new WebGLExtensionDebugRendererInfo(this);
-        break;
-    case WebGLExtensionID::WEBGL_debug_shaders:
-        obj = new WebGLExtensionDebugShaders(this);
-        break;
-    case WebGLExtensionID::WEBGL_depth_texture:
-        obj = new WebGLExtensionDepthTexture(this);
-        break;
-    case WebGLExtensionID::WEBGL_draw_buffers:
-        obj = new WebGLExtensionDrawBuffers(this);
-        break;
-    case WebGLExtensionID::WEBGL_lose_context:
-        obj = new WebGLExtensionLoseContext(this);
-        break;
+#undef FOO
 
     default:
-        MOZ_ASSERT(false, "should not get there.");
+        gfxCriticalNote << "Invalid extension id: " << uint32_t(ext);
+        return;
     }
 
     mExtensions[ext] = obj;
 }
 
 void
 WebGLContext::GetSupportedExtensions(JSContext* cx,
                                      dom::Nullable< nsTArray<nsString> >& retval)
@@ -461,9 +295,12 @@ WebGLContext::GetSupportedExtensions(JSC
     if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_atc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
     if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_pvrtc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
     if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_depth_texture))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
 }
 
+#undef FOR_EACH_PRIVILEGED_EXT
+#undef FOR_EACH_EXT
+
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionBase.cpp
+++ b/dom/canvas/WebGLExtensionBase.cpp
@@ -2,32 +2,14 @@
 /* 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"
 
 namespace mozilla {
 
-WebGLExtensionBase::WebGLExtensionBase(WebGLContext* context)
-    : WebGLContextBoundObject(context)
-    , mIsLost(false)
-{
-}
-
-WebGLExtensionBase::~WebGLExtensionBase()
-{
-}
-
-void
-WebGLExtensionBase::MarkLost()
-{
-    mIsLost = true;
-
-    OnMarkLost();
-}
-
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLExtensionBase)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLExtensionBase, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLExtensionBase, Release)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionBlendMinMax.cpp
+++ b/dom/canvas/WebGLExtensionBlendMinMax.cpp
@@ -5,27 +5,20 @@
 #include "WebGLExtensions.h"
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionBlendMinMax::WebGLExtensionBlendMinMax(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
-{
-    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
-}
-
-WebGLExtensionBlendMinMax::~WebGLExtensionBlendMinMax()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     return webgl->GL()->IsSupported(gl::GLFeature::blend_minmax);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionBlendMinMax, EXT_blend_minmax)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionColorBufferFloat.cpp
+++ b/dom/canvas/WebGLExtensionColorBufferFloat.cpp
@@ -31,23 +31,22 @@ WebGLExtensionColorBufferFloat::WebGLExt
 #define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
 
     // The extension doesn't actually add RGB32F; only RGBA32F.
     FOO(RGBA32F);
 
 #undef FOO
 }
 
-WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
 
     // ANGLE supports this, but doesn't have a way to advertize its support,
     // since it's compliant with WEBGL_color_buffer_float's clamping, but not
     // EXT_color_buffer_float.
     return gl->IsSupported(gl::GLFeature::renderbuffer_color_float) ||
            gl->IsANGLE();
 }
--- a/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp
+++ b/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp
@@ -31,21 +31,20 @@ WebGLExtensionColorBufferHalfFloat::WebG
 #define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
 
     FOO(RGBA16F);
     FOO(RGB16F);
 
 #undef FOO
 }
 
-WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     return webgl->GL()->IsSupported(gl::GLFeature::renderbuffer_color_half_float);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat, EXT_color_buffer_half_float)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionCompressedTextureATC.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureATC.cpp
@@ -31,15 +31,17 @@ WebGLExtensionCompressedTextureATC::WebG
 
     fnAdd(FOO(ATC_RGB_AMD));
     fnAdd(FOO(ATC_RGBA_EXPLICIT_ALPHA_AMD));
     fnAdd(FOO(ATC_RGBA_INTERPOLATED_ALPHA_AMD));
 
 #undef FOO
 }
 
-WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
+/*static*/ bool
+WebGLExtensionCompressedTextureATC::IsSupported(const WebGLContext* webgl)
 {
+    return webgl->GL()->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC, WEBGL_compressed_texture_atc)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionCompressedTextureES3.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureES3.cpp
@@ -41,15 +41,20 @@ WebGLExtensionCompressedTextureES3::WebG
     // versions to support ETC2.
     fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC));
     fnAdd(FOO(COMPRESSED_SRGB8_ETC2));
     fnAdd(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2));
 
 #undef FOO
 }
 
-WebGLExtensionCompressedTextureES3::~WebGLExtensionCompressedTextureES3()
+/*static*/ bool
+WebGLExtensionCompressedTextureES3::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
+    return webgl->GL()->IsExtensionSupported(gl::GLContext::ARB_ES3_compatibility);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureES3, WEBGL_compressed_texture_es3)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp
@@ -29,15 +29,17 @@ WebGLExtensionCompressedTextureETC1::Web
 
 #define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
 
     fnAdd(FOO(ETC1_RGB8_OES));
 
 #undef FOO
 }
 
-WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()
+/*static*/ bool
+WebGLExtensionCompressedTextureETC1::IsSupported(const WebGLContext* webgl)
 {
+    return webgl->GL()->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1, WEBGL_compressed_texture_etc1)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp
@@ -32,15 +32,17 @@ WebGLExtensionCompressedTexturePVRTC::We
     fnAdd(FOO(COMPRESSED_RGB_PVRTC_4BPPV1));
     fnAdd(FOO(COMPRESSED_RGB_PVRTC_2BPPV1));
     fnAdd(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1));
     fnAdd(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1));
 
 #undef FOO
 }
 
-WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
+/*static*/ bool
+WebGLExtensionCompressedTexturePVRTC::IsSupported(const WebGLContext* webgl)
 {
+    return webgl->GL()->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC, WEBGL_compressed_texture_pvrtc)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp
@@ -32,15 +32,24 @@ WebGLExtensionCompressedTextureS3TC::Web
     fnAdd(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT));
     fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT));
     fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT));
     fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT));
 
 #undef FOO
 }
 
-WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
+/*static*/ bool
+WebGLExtensionCompressedTextureS3TC::IsSupported(const WebGLContext* webgl)
 {
+    const auto& gl = webgl->GL();
+
+    if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
+        return true;
+
+    return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
+           gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
+           gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC, WEBGL_compressed_texture_s3tc)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDebugRendererInfo.cpp
+++ b/dom/canvas/WebGLExtensionDebugRendererInfo.cpp
@@ -1,24 +1,21 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "mozilla/Preferences.h"
 
 namespace mozilla {
 
-WebGLExtensionDebugRendererInfo::WebGLExtensionDebugRendererInfo(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
+/*static*/ bool
+WebGLExtensionDebugRendererInfo::IsSupported(const WebGLContext* webgl)
 {
-}
-
-WebGLExtensionDebugRendererInfo::~WebGLExtensionDebugRendererInfo()
-{
+    return Preferences::GetBool("webgl.enable-debug-renderer-info", false);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo, WEBGL_debug_renderer_info)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDebugShaders.cpp
+++ b/dom/canvas/WebGLExtensionDebugShaders.cpp
@@ -5,39 +5,33 @@
 
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.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)
 {
     retval.SetIsVoid(true);
 
-    if (mIsLost) {
-        mContext->ErrorInvalidOperation("%s: Extension is lost.",
-                                        "getTranslatedShaderSource");
+    if (!mContext)
         return;
-    }
 
     retval.SetIsVoid(false);
     mContext->GetShaderTranslatedSource(shader, retval);
 }
 
+/*static*/ bool
+WebGLExtensionDebugShaders::IsSupported(const WebGLContext* webgl)
+{
+    return true;
+}
+
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders, WEBGL_debug_shaders)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDepthTexture.cpp
+++ b/dom/canvas/WebGLExtensionDepthTexture.cpp
@@ -33,15 +33,27 @@ WebGLExtensionDepthTexture::WebGLExtensi
 
     fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT24, LOCAL_GL_DEPTH_COMPONENT,
           LOCAL_GL_UNSIGNED_INT);
 
     fnAdd(webgl::EffectiveFormat::DEPTH24_STENCIL8, LOCAL_GL_DEPTH_STENCIL,
           LOCAL_GL_UNSIGNED_INT_24_8);
 }
 
-WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
+/*static*/ bool
+WebGLExtensionDepthTexture::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
+    const auto& gl = webgl->GL();
+
+    // WEBGL_depth_texture supports DEPTH_STENCIL textures
+    if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
+        return false;
+
+    return gl->IsSupported(gl::GLFeature::depth_texture) ||
+           gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture, WEBGL_depth_texture)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
+++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
@@ -25,55 +25,58 @@ WebGLExtensionDisjointTimerQuery::WebGLE
 
 WebGLExtensionDisjointTimerQuery::~WebGLExtensionDisjointTimerQuery()
 {
 }
 
 already_AddRefed<WebGLTimerQuery>
 WebGLExtensionDisjointTimerQuery::CreateQueryEXT()
 {
-  if (mIsLost)
+  if (!mContext)
     return nullptr;
 
   RefPtr<WebGLTimerQuery> query = WebGLTimerQuery::Create(mContext);
   return query.forget();
 }
 
 void
 WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLTimerQuery* query)
 {
-  if (mIsLost)
+  if (!mContext)
     return;
 
   if (!mContext->ValidateObject("deleteQueryEXT", query))
     return;
 
   query->RequestDelete();
 }
 
 bool
 WebGLExtensionDisjointTimerQuery::IsQueryEXT(WebGLTimerQuery* query)
 {
+  if (!mContext)
+    return false;
+
   if (!query)
     return false;
 
   if (!mContext->ValidateObjectAllowDeleted("isQueryEXT", query))
     return false;
 
   if (query->IsDeleted())
     return false;
 
   return true;
 }
 
 void
 WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target,
                                                 WebGLTimerQuery* query)
 {
-  if (mIsLost)
+  if (!mContext)
     return;
 
   if (!mContext->ValidateObject("beginQueryEXT", query))
     return;
 
   if (query->HasEverBeenBound() && query->Target() != target) {
     mContext->ErrorInvalidOperation("beginQueryEXT: Query is already bound"
                                     " to a different target.");
@@ -97,17 +100,17 @@ WebGLExtensionDisjointTimerQuery::BeginQ
   gl->fBeginQuery(target, query->mGLName);
   query->mTarget = LOCAL_GL_TIME_ELAPSED_EXT;
   mActiveQuery = query;
 }
 
 void
 WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target)
 {
-  if (mIsLost)
+  if (!mContext)
     return;
 
   if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
     mContext->ErrorInvalidEnumInfo("endQueryEXT: Can only end on"
                                    " TIME_ELAPSED_EXT.", target);
     return;
   }
 
@@ -121,17 +124,17 @@ WebGLExtensionDisjointTimerQuery::EndQue
   mActiveQuery->QueueAvailablity();
   mActiveQuery = nullptr;
 }
 
 void
 WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query,
                                                   GLenum target)
 {
-  if (mIsLost)
+  if (!mContext)
     return;
 
   if (!mContext->ValidateObject("queryCounterEXT", query))
     return;
 
   if (target != LOCAL_GL_TIMESTAMP_EXT) {
     mContext->ErrorInvalidEnumInfo("queryCounterEXT: requires"
                                    " TIMESTAMP_EXT.", target);
@@ -144,17 +147,17 @@ WebGLExtensionDisjointTimerQuery::QueryC
   query->QueueAvailablity();
 }
 
 void
 WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target,
                                               GLenum pname,
                                               JS::MutableHandle<JS::Value> retval)
 {
-  if (mIsLost)
+  if (!mContext)
     return;
 
   mContext->MakeContextCurrent();
   switch (pname) {
   case LOCAL_GL_CURRENT_QUERY_EXT: {
     if (target != LOCAL_GL_TIME_ELAPSED_EXT) {
       mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.",
                                      target);
@@ -189,17 +192,17 @@ WebGLExtensionDisjointTimerQuery::GetQue
 }
 
 void
 WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
                                                     WebGLTimerQuery* query,
                                                     GLenum pname,
                                                     JS::MutableHandle<JS::Value> retval)
 {
-  if (mIsLost)
+  if (!mContext)
     return;
 
   if (!mContext->ValidateObject("getQueryObjectEXT", query))
     return;
 
   if (query == mActiveQuery.get()) {
     mContext->ErrorInvalidOperation("getQueryObjectEXT: Query must not be"
                                     " active.");
@@ -230,31 +233,34 @@ WebGLExtensionDisjointTimerQuery::GetQue
   }
   default:
     mContext->ErrorInvalidEnumInfo("getQueryObjectEXT: Invalid query"
                                    " property.", pname);
     break;
   }
 }
 
-bool
+void
+WebGLExtensionDisjointTimerQuery::DetachImpl()
+{
+  mActiveQuery = nullptr;
+}
+
+/*static*/ bool
 WebGLExtensionDisjointTimerQuery::IsSupported(const WebGLContext* webgl)
 {
+  if (webgl->IsWebGL2())
+    return false;
+
   webgl->MakeContextCurrent();
   gl::GLContext* gl = webgl->GL();
   return gl->IsSupported(gl::GLFeature::query_objects) &&
          gl->IsSupported(gl::GLFeature::get_query_object_i64v) &&
          gl->IsSupported(gl::GLFeature::query_counter) && // provides GL_TIMESTAMP
          gl->IsSupported(gl::GLFeature::sync); // provides glGetInteger64v
   // 'sync' provides glGetInteger64v either by supporting ARB_sync, GL3+, or GLES3+.
   // Since there are no differences between support for glGetInteger64v and support for
   // 'sync', we just piggy-back off of 'sync'.
 }
 
-void
-WebGLExtensionDisjointTimerQuery::OnMarkLost()
-{
-  mActiveQuery = nullptr;
-}
-
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery, EXT_disjoint_timer_query)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionDrawBuffers.cpp
+++ b/dom/canvas/WebGLExtensionDrawBuffers.cpp
@@ -23,34 +23,31 @@ WebGLExtensionDrawBuffers::WebGLExtensio
     // WEBGL_draw_buffers:
     // "The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or
     //  equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter."
     webgl->mImplMaxColorAttachments = webgl->mGLMaxColorAttachments;
     webgl->mImplMaxDrawBuffers = std::min(webgl->mGLMaxDrawBuffers,
                                           webgl->mImplMaxColorAttachments);
 }
 
-WebGLExtensionDrawBuffers::~WebGLExtensionDrawBuffers()
-{
-}
-
 void
 WebGLExtensionDrawBuffers::DrawBuffersWEBGL(const dom::Sequence<GLenum>& buffers)
 {
-    if (mIsLost) {
-        mContext->ErrorInvalidOperation("drawBuffersWEBGL: Extension is lost.");
+    if (!mContext)
         return;
-    }
 
     mContext->DrawBuffers(buffers);
 }
 
-bool
+/*static*/ bool
 WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
 
     if (!gl->IsSupported(gl::GLFeature::draw_buffers))
         return false;
 
     // WEBGL_draw_buffers requires at least 4 color attachments.
     if (webgl->mGLMaxDrawBuffers < webgl->kMinMaxDrawBuffers ||
         webgl->mGLMaxColorAttachments < webgl->kMinMaxColorAttachments)
--- a/dom/canvas/WebGLExtensionEXTColorBufferFloat.cpp
+++ b/dom/canvas/WebGLExtensionEXTColorBufferFloat.cpp
@@ -37,15 +37,17 @@ WebGLExtensionEXTColorBufferFloat::WebGL
     FOO(R11F_G11F_B10F);
 
 #undef FOO
 }
 
 /*static*/ bool
 WebGLExtensionEXTColorBufferFloat::IsSupported(const WebGLContext* webgl)
 {
-    const gl::GLContext* gl = webgl->GL();
-    return gl->IsSupported(gl::GLFeature::EXT_color_buffer_float);
+    if (!webgl->IsWebGL2())
+        return false;
+
+    return webgl->gl->IsSupported(gl::GLFeature::EXT_color_buffer_float);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionEXTColorBufferFloat, EXT_color_buffer_float)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionElementIndexUint.cpp
+++ b/dom/canvas/WebGLExtensionElementIndexUint.cpp
@@ -5,20 +5,20 @@
 
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionElementIndexUint::WebGLExtensionElementIndexUint(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
+/*static*/ bool
+WebGLExtensionElementIndexUint::IsSupported(const WebGLContext* webgl)
 {
-}
+    if (webgl->IsWebGL2())
+        return false;
 
-WebGLExtensionElementIndexUint::~WebGLExtensionElementIndexUint()
-{
+    return webgl->GL()->IsSupported(gl::GLFeature::element_index_uint);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint, OES_element_index_uint)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionFragDepth.cpp
+++ b/dom/canvas/WebGLExtensionFragDepth.cpp
@@ -6,29 +6,21 @@
 #include "WebGLExtensions.h"
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
-{
-    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
-}
-
-WebGLExtensionFragDepth::~WebGLExtensionFragDepth()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionFragDepth::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
     return gl->IsSupported(gl::GLFeature::frag_depth);
 }
 
-
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth, EXT_frag_depth)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionInstancedArrays.cpp
+++ b/dom/canvas/WebGLExtensionInstancedArrays.cpp
@@ -6,73 +6,57 @@
 #include "WebGLExtensions.h"
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(WebGLContext* webgl)
-  : WebGLExtensionBase(webgl)
-{
-    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
-}
-
-WebGLExtensionInstancedArrays::~WebGLExtensionInstancedArrays()
-{
-}
-
 void
 WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(GLenum mode,
                                                         GLint first,
                                                         GLsizei count,
                                                         GLsizei primcount)
 {
-    if (mIsLost) {
-        mContext->ErrorInvalidOperation("%s: Extension is lost.",
-                                        "drawArraysInstancedANGLE");
+    if (!mContext)
         return;
-    }
 
     mContext->DrawArraysInstanced(mode, first, count, primcount);
 }
 
 void
 WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(GLenum mode,
                                                           GLsizei count,
                                                           GLenum type,
                                                           WebGLintptr offset,
                                                           GLsizei primcount)
 {
-    if (mIsLost) {
-        mContext->ErrorInvalidOperation("%s: Extension is lost.",
-                                        "drawElementsInstancedANGLE");
+    if (!mContext)
         return;
-    }
 
     mContext->DrawElementsInstanced(mode, count, type, offset, primcount);
 }
 
 void
 WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(GLuint index,
                                                         GLuint divisor)
 {
-    if (mIsLost) {
-        mContext->ErrorInvalidOperation("%s: Extension is lost.",
-                                        "vertexAttribDivisorANGLE");
+    if (!mContext)
         return;
-    }
 
     mContext->VertexAttribDivisor(index, divisor);
 }
 
-bool
+/*static*/ bool
 WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
     return gl->IsSupported(gl::GLFeature::draw_instanced) &&
            gl->IsSupported(gl::GLFeature::instanced_arrays);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays, ANGLE_instanced_arrays)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionLoseContext.cpp
+++ b/dom/canvas/WebGLExtensionLoseContext.cpp
@@ -5,32 +5,29 @@
 
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionLoseContext::WebGLExtensionLoseContext(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
-{
-}
-
-WebGLExtensionLoseContext::~WebGLExtensionLoseContext()
-{
-}
-
 void
 WebGLExtensionLoseContext::LoseContext()
 {
     mContext->LoseContext();
 }
 
 void
 WebGLExtensionLoseContext::RestoreContext()
 {
     mContext->RestoreContext();
 }
 
+/*static*/ bool
+WebGLExtensionLoseContext::IsSupported(const WebGLContext* webgl)
+{
+    return true;
+}
+
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext, WEBGL_lose_context)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionSRGB.cpp
+++ b/dom/canvas/WebGLExtensionSRGB.cpp
@@ -48,25 +48,23 @@ WebGLExtensionSRGB::WebGLExtensionSRGB(W
     fnAdd(webgl::EffectiveFormat::SRGB8, LOCAL_GL_SRGB, LOCAL_GL_RGB);
     fnAdd(webgl::EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA, LOCAL_GL_RGBA);
 
     auto usage = fua->EditUsage(webgl::EffectiveFormat::SRGB8_ALPHA8);
     usage->SetRenderable();
     fua->AllowRBFormat(LOCAL_GL_SRGB8_ALPHA8, usage);
 }
 
-WebGLExtensionSRGB::~WebGLExtensionSRGB()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionSRGB::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
 
     return gl->IsSupported(gl::GLFeature::sRGB_framebuffer) &&
            gl->IsSupported(gl::GLFeature::sRGB_texture);
 }
 
-
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB, EXT_sRGB)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionShaderTextureLod.cpp
+++ b/dom/canvas/WebGLExtensionShaderTextureLod.cpp
@@ -5,20 +5,20 @@
 
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
+/*static*/ bool
+WebGLExtensionShaderTextureLod::IsSupported(const WebGLContext* webgl)
 {
-}
+    if (webgl->IsWebGL2())
+        return false;
 
-WebGLExtensionShaderTextureLod::~WebGLExtensionShaderTextureLod()
-{
+    return webgl->GL()->IsSupported(gl::GLFeature::shader_texture_lod);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod, EXT_shader_texture_lod)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionStandardDerivatives.cpp
+++ b/dom/canvas/WebGLExtensionStandardDerivatives.cpp
@@ -5,20 +5,20 @@
 
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionStandardDerivatives::WebGLExtensionStandardDerivatives(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
+/*static*/ bool
+WebGLExtensionStandardDerivatives::IsSupported(const WebGLContext* webgl)
 {
-}
+    if (webgl->IsWebGL2())
+        return false;
 
-WebGLExtensionStandardDerivatives::~WebGLExtensionStandardDerivatives()
-{
+    return webgl->GL()->IsSupported(gl::GLFeature::standard_derivatives);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives, OES_standard_derivatives)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp
+++ b/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp
@@ -5,20 +5,17 @@
 
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
 
-WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* webgl)
-    : WebGLExtensionBase(webgl)
+/*static*/ bool
+WebGLExtensionTextureFilterAnisotropic::IsSupported(const WebGLContext* webgl)
 {
-}
-
-WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic()
-{
+    return webgl->GL()->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic, EXT_texture_filter_anisotropic)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionTextureFloat.cpp
+++ b/dom/canvas/WebGLExtensionTextureFloat.cpp
@@ -92,23 +92,22 @@ WebGLExtensionTextureFloat::WebGLExtensi
         dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT};
         swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
     } else if (needsSizedFormat) {
         dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
     }
     fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
 }
 
-WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
 
     if (!gl->IsSupported(gl::GLFeature::texture_float))
         return false;
 
     const bool needsSwizzle = gl->IsCoreProfile();
     const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
     if (needsSwizzle && !hasSwizzle)
--- a/dom/canvas/WebGLExtensionTextureFloatLinear.cpp
+++ b/dom/canvas/WebGLExtensionTextureFloatLinear.cpp
@@ -17,15 +17,17 @@ WebGLExtensionTextureFloatLinear::WebGLE
 
     fua->EditUsage(webgl::EffectiveFormat::RGBA32F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::RGB32F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::Luminance32F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::Alpha32F)->isFilterable = true;
 }
 
-WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear()
+/*static*/ bool
+WebGLExtensionTextureFloatLinear::IsSupported(const WebGLContext* webgl)
 {
+    return webgl->GL()->IsSupported(gl::GLFeature::texture_float_linear);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear, OES_texture_float_linear)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
+++ b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
@@ -96,23 +96,22 @@ WebGLExtensionTextureHalfFloat::WebGLExt
         dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType};
         swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
     } else if (needsSizedFormat) {
         dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
     }
     fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
 }
 
-WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
-{
-}
-
-bool
+/*static*/ bool
 WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
     gl::GLContext* gl = webgl->GL();
 
     if (!gl->IsSupported(gl::GLFeature::texture_half_float) &&
         !gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float))
     {
         return false;
     }
 
--- a/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp
+++ b/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp
@@ -17,15 +17,20 @@ WebGLExtensionTextureHalfFloatLinear::We
 
     fua->EditUsage(webgl::EffectiveFormat::RGBA16F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::RGB16F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::Luminance16FAlpha16F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::Luminance16F)->isFilterable = true;
     fua->EditUsage(webgl::EffectiveFormat::Alpha16F)->isFilterable = true;
 }
 
-WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear()
+/*static*/ bool
+WebGLExtensionTextureHalfFloatLinear::IsSupported(const WebGLContext* webgl)
 {
+    if (webgl->IsWebGL2())
+        return false;
+
+    return webgl->GL()->IsSupported(gl::GLFeature::texture_half_float_linear);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear, OES_texture_half_float_linear)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensionVertexArray.cpp
+++ b/dom/canvas/WebGLExtensionVertexArray.cpp
@@ -1,63 +1,60 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "WebGLBuffer.h"
 #include "WebGLContext.h"
-#include "WebGLVertexArray.h"
 
 namespace mozilla {
 
-WebGLExtensionVertexArray::WebGLExtensionVertexArray(WebGLContext* webgl)
-  : WebGLExtensionBase(webgl)
-{
-}
-
-WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
-{
-}
-
 already_AddRefed<WebGLVertexArray>
 WebGLExtensionVertexArray::CreateVertexArrayOES()
 {
-    if (mIsLost)
+    if (!mContext)
         return nullptr;
 
     return mContext->CreateVertexArray();
 }
 
 void
 WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
 {
-    if (mIsLost)
+    if (!mContext)
         return;
 
     mContext->DeleteVertexArray(array);
 }
 
 bool
 WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
 {
-    if (mIsLost)
+    if (!mContext)
         return false;
 
     return mContext->IsVertexArray(array);
 }
 
 void
 WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
 {
-    if (mIsLost)
+    if (!mContext)
         return;
 
     mContext->BindVertexArray(array);
 }
 
+/*static*/ bool
+WebGLExtensionVertexArray::IsSupported(const WebGLContext* webgl)
+{
+    if (webgl->IsWebGL2())
+        return false;
+
+    return true;
+}
+
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray, OES_vertex_array_object)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -25,378 +25,214 @@ class FormatUsageAuthority;
 } // namespace webgl
 
 class WebGLContext;
 class WebGLShader;
 class WebGLQuery;
 class WebGLTimerQuery;
 class WebGLVertexArray;
 
+////////////////////////////////////////
+
 class WebGLExtensionBase
     : public nsWrapperCache
     , public WebGLContextBoundObject
 {
 public:
-    explicit WebGLExtensionBase(WebGLContext* webgl);
-
-    WebGLContext* GetParentObject() const {
-        return mContext;
-    }
-
-    void MarkLost();
-
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLExtensionBase)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLExtensionBase)
 
 protected:
-    virtual ~WebGLExtensionBase();
-
-    virtual void OnMarkLost() { }
-
-    bool mIsLost;
-};
+    explicit WebGLExtensionBase(WebGLContext* webgl)
+        : WebGLContextBoundObject(webgl)
+    { }
 
-#define DECL_WEBGL_EXTENSION_GOOP \
-    virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
-
-#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType, WebGLBindingType)\
-    JSObject*                                                    \
-    WebGLExtensionType::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) {              \
-        return dom::WebGLBindingType##Binding::Wrap(cx, this, givenProto); \
-    }
+    virtual ~WebGLExtensionBase() { }
 
-class WebGLExtensionCompressedTextureATC
-    : public WebGLExtensionBase
-{
 public:
-    explicit WebGLExtensionCompressedTextureATC(WebGLContext*);
-    virtual ~WebGLExtensionCompressedTextureATC();
+    WebGLContext* GetParentObject() const { return mContext; }
 
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionCompressedTextureES3
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionCompressedTextureES3(WebGLContext*);
-    virtual ~WebGLExtensionCompressedTextureES3();
-
-    DECL_WEBGL_EXTENSION_GOOP
+private:
+    virtual void DetachImpl() override { }
 };
 
-class WebGLExtensionCompressedTextureETC1
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionCompressedTextureETC1(WebGLContext*);
-    virtual ~WebGLExtensionCompressedTextureETC1();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionCompressedTexturePVRTC
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionCompressedTexturePVRTC(WebGLContext*);
-    virtual ~WebGLExtensionCompressedTexturePVRTC();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
+////////////////////////////////////////
 
-class WebGLExtensionCompressedTextureS3TC
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionCompressedTextureS3TC(WebGLContext*);
-    virtual ~WebGLExtensionCompressedTextureS3TC();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
+#define DECL_WEBGL_EXTENSION_GOOP \
+    virtual JSObject* WrapObject(JSContext*, JS::Handle<JSObject*>) override; \
+    static bool IsSupported(const WebGLContext*);
 
-class WebGLExtensionDebugRendererInfo
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionDebugRendererInfo(WebGLContext*);
-    virtual ~WebGLExtensionDebugRendererInfo();
+////////////////////////////////////////
 
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionDebugShaders
+class WebGLExtensionDebugShaders final
     : public WebGLExtensionBase
 {
 public:
     explicit WebGLExtensionDebugShaders(WebGLContext*);
-    virtual ~WebGLExtensionDebugShaders();
 
     void GetTranslatedShaderSource(WebGLShader* shader, nsAString& retval);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionDepthTexture
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionDepthTexture(WebGLContext*);
-    virtual ~WebGLExtensionDepthTexture();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionElementIndexUint
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionElementIndexUint(WebGLContext*);
-    virtual ~WebGLExtensionElementIndexUint();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionEXTColorBufferFloat
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionEXTColorBufferFloat(WebGLContext*);
-    virtual ~WebGLExtensionEXTColorBufferFloat() { }
-
-    static bool IsSupported(const WebGLContext*);
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionFragDepth
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionFragDepth(WebGLContext*);
-    virtual ~WebGLExtensionFragDepth();
-
-    static bool IsSupported(const WebGLContext* context);
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionLoseContext
+class WebGLExtensionLoseContext final
     : public WebGLExtensionBase
 {
 public:
     explicit WebGLExtensionLoseContext(WebGLContext*);
-    virtual ~WebGLExtensionLoseContext();
 
     void LoseContext();
     void RestoreContext();
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionSRGB
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionSRGB(WebGLContext*);
-    virtual ~WebGLExtensionSRGB();
-
-    static bool IsSupported(const WebGLContext* context);
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionStandardDerivatives
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionStandardDerivatives(WebGLContext*);
-    virtual ~WebGLExtensionStandardDerivatives();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionShaderTextureLod
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionShaderTextureLod(WebGLContext*);
-    virtual ~WebGLExtensionShaderTextureLod();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionTextureFilterAnisotropic
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionTextureFilterAnisotropic(WebGLContext*);
-    virtual ~WebGLExtensionTextureFilterAnisotropic();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionTextureFloat
+class WebGLExtensionTextureFloat final
     : public WebGLExtensionBase
 {
 public:
     static void InitWebGLFormats(webgl::FormatUsageAuthority* authority);
 
     explicit WebGLExtensionTextureFloat(WebGLContext*);
-    virtual ~WebGLExtensionTextureFloat();
-
-    static bool IsSupported(const WebGLContext*);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionTextureFloatLinear
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionTextureFloatLinear(WebGLContext*);
-    virtual ~WebGLExtensionTextureFloatLinear();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionTextureHalfFloat
+class WebGLExtensionTextureHalfFloat final
     : public WebGLExtensionBase
 {
 public:
     static void InitWebGLFormats(webgl::FormatUsageAuthority* authority);
 
     explicit WebGLExtensionTextureHalfFloat(WebGLContext*);
-    virtual ~WebGLExtensionTextureHalfFloat();
-
-    static bool IsSupported(const WebGLContext*);
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionTextureHalfFloatLinear
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionTextureHalfFloatLinear(WebGLContext*);
-    virtual ~WebGLExtensionTextureHalfFloatLinear();
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionColorBufferFloat
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionColorBufferFloat(WebGLContext*);
-    virtual ~WebGLExtensionColorBufferFloat();
-
-    static bool IsSupported(const WebGLContext*);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionColorBufferHalfFloat
+class WebGLExtensionDrawBuffers final
     : public WebGLExtensionBase
 {
 public:
-    explicit WebGLExtensionColorBufferHalfFloat(WebGLContext*);
-    virtual ~WebGLExtensionColorBufferHalfFloat();
+    explicit WebGLExtensionDrawBuffers(WebGLContext*);
 
-    static bool IsSupported(const WebGLContext*);
+    void DrawBuffersWEBGL(const dom::Sequence<GLenum>& buffers);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionDrawBuffers
-    : public WebGLExtensionBase
-{
-public:
-    explicit WebGLExtensionDrawBuffers(WebGLContext*);
-    virtual ~WebGLExtensionDrawBuffers();
-
-    void DrawBuffersWEBGL(const dom::Sequence<GLenum>& buffers);
-
-    static bool IsSupported(const WebGLContext*);
-
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionVertexArray
+class WebGLExtensionVertexArray final
     : public WebGLExtensionBase
 {
 public:
     explicit WebGLExtensionVertexArray(WebGLContext* webgl);
-    virtual ~WebGLExtensionVertexArray();
 
     already_AddRefed<WebGLVertexArray> CreateVertexArrayOES();
     void DeleteVertexArrayOES(WebGLVertexArray* array);
     bool IsVertexArrayOES(WebGLVertexArray* array);
     void BindVertexArrayOES(WebGLVertexArray* array);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionInstancedArrays
+class WebGLExtensionInstancedArrays final
     : public WebGLExtensionBase
 {
 public:
     explicit WebGLExtensionInstancedArrays(WebGLContext* webgl);
-    virtual ~WebGLExtensionInstancedArrays();
 
     void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count,
                                   GLsizei primcount);
     void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type,
                                     WebGLintptr offset, GLsizei primcount);
     void VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
 
-    static bool IsSupported(const WebGLContext* webgl);
-
     DECL_WEBGL_EXTENSION_GOOP
 };
 
-class WebGLExtensionBlendMinMax
+class WebGLExtensionDisjointTimerQuery final
     : public WebGLExtensionBase
 {
-public:
-    explicit WebGLExtensionBlendMinMax(WebGLContext* webgl);
-    virtual ~WebGLExtensionBlendMinMax();
-
-    static bool IsSupported(const WebGLContext*);
+    /**
+     * An active TIME_ELAPSED query participating in a begin/end block.
+     */
+    WebGLRefPtr<WebGLTimerQuery> mActiveQuery;
 
-    DECL_WEBGL_EXTENSION_GOOP
-};
-
-class WebGLExtensionDisjointTimerQuery
-    : public WebGLExtensionBase
-{
 public:
     explicit WebGLExtensionDisjointTimerQuery(WebGLContext* webgl);
-    virtual ~WebGLExtensionDisjointTimerQuery();
 
     already_AddRefed<WebGLTimerQuery> CreateQueryEXT();
     void DeleteQueryEXT(WebGLTimerQuery* query);
     bool IsQueryEXT(WebGLTimerQuery* query);
     void BeginQueryEXT(GLenum target, WebGLTimerQuery* query);
     void EndQueryEXT(GLenum target);
     void QueryCounterEXT(WebGLTimerQuery* query, GLenum target);
     void GetQueryEXT(JSContext *cx, GLenum target, GLenum pname,
                      JS::MutableHandle<JS::Value> retval);
     void GetQueryObjectEXT(JSContext *cx, WebGLTimerQuery* query,
                            GLenum pname,
                            JS::MutableHandle<JS::Value> retval);
 
-    static bool IsSupported(const WebGLContext*);
-
     DECL_WEBGL_EXTENSION_GOOP
 
 private:
-    virtual void OnMarkLost() override;
+    virtual void DetachImpl() override;
+};
+
+////////////////////////////////////////
+
+#define BASIC_EXT_DECL(T) \
+    class T final : public WebGLExtensionBase \
+    {                                         \
+    public:                                   \
+        explicit T(WebGLContext*);            \
+                                              \
+        DECL_WEBGL_EXTENSION_GOOP             \
+    };
+
+#define BASIC_EXT_DEFINE(T) \
+    class T final : public WebGLExtensionBase \
+    {                                         \
+    public:                                   \
+        explicit T(WebGLContext* webgl);      \
+            : WebGLExtensionBase(webgl)       \
+        {                                     \
+            IsSupported(webgl);               \
+        }                                     \
+                                              \
+        DECL_WEBGL_EXTENSION_GOOP             \
+    };
 
-    /**
-     * An active TIME_ELAPSED query participating in a begin/end block.
-     */
-    WebGLRefPtr<WebGLTimerQuery> mActiveQuery;
-};
+BASIC_EXT_DEFINE(WebGLExtensionBlendMinMax)
+BASIC_EXT_DECL(WebGLExtensionColorBufferFloat)
+BASIC_EXT_DECL(WebGLExtensionColorBufferHalfFloat)
+BASIC_EXT_DECL(WebGLExtensionCompressedTextureATC)
+BASIC_EXT_DECL(WebGLExtensionCompressedTextureES3)
+BASIC_EXT_DECL(WebGLExtensionCompressedTextureETC1)
+BASIC_EXT_DECL(WebGLExtensionCompressedTexturePVRTC)
+BASIC_EXT_DECL(WebGLExtensionCompressedTextureS3TC)
+BASIC_EXT_DEFINE(WebGLExtensionDebugRendererInfo)
+BASIC_EXT_DECL(WebGLExtensionDepthTexture)
+BASIC_EXT_DEFINE(WebGLExtensionElementIndexUint)
+BASIC_EXT_DECL(WebGLExtensionEXTColorBufferFloat)
+BASIC_EXT_DEFINE(WebGLExtensionFragDepth)
+BASIC_EXT_DEFINE(WebGLExtensionShaderTextureLod)
+BASIC_EXT_DECL(WebGLExtensionSRGB)
+BASIC_EXT_DEFINE(WebGLExtensionStandardDerivatives)
+BASIC_EXT_DEFINE(WebGLExtensionTextureFilterAnisotropic)
+BASIC_EXT_DEFINE(WebGLExtensionTextureFloatLinear)
+BASIC_EXT_DEFINE(WebGLExtensionTextureHalfFloatLinear)
+
+#define BASIC_EXT_DECL aaaaaaa
+#undef BASIC_EXT_DECL
+#undef BASIC_EXT_DEFINE
+#undef DECL_WEBGL_EXTENSION_GOOP
+
+////
+
+#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType, WebGLBindingType) \
+    JSObject*                                                           \
+    WebGLExtensionType::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) { \
+        return dom::WebGLBindingType##Binding::Wrap(cx, this, givenProto); \
+    }
 
 } // namespace mozilla
 
 #endif // WEBGL_EXTENSIONS_H_
--- a/dom/canvas/WebGLObjectModel.cpp
+++ b/dom/canvas/WebGLObjectModel.cpp
@@ -1,25 +1,19 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "WebGLObjectModel.h"
 
-#include "WebGLContext.h"
-
 namespace mozilla {
 
-WebGLContextBoundObject::WebGLContextBoundObject(WebGLContext* webgl)
-    : mContext(webgl)
-    , mContextGeneration(webgl->Generation())
+void
+WebGLContextBoundObject::Detach()
 {
-}
+    MOZ_ASSERT(mContext);
 
-bool
-WebGLContextBoundObject::IsCompatibleWithContext(WebGLContext* other)
-{
-    return (mContext == other &&
-            mContextGeneration == other->Generation());
+    DetachImpl();
+    mContext = nullptr;
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLObjectModel.h
+++ b/dom/canvas/WebGLObjectModel.h
@@ -255,28 +255,32 @@ private:
         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.
+// context (which is to say, all of them).
 class WebGLContextBoundObject
 {
-public:
-    explicit WebGLContextBoundObject(WebGLContext* webgl);
+    WebGLContext* mContext;
+
+    explicit WebGLContextBoundObject(WebGLContext* webgl)
+        : mContext(webgl)
+    { }
 
-    bool IsCompatibleWithContext(WebGLContext* other);
+    virtual ~WebGLContextBoundObject() {
+        MOZ_ASSERT(!mContext, "Should be Detach()'d first before destroyed.");
+    }
 
-    WebGLContext* const mContext;
-protected:
-    const uint32_t mContextGeneration;
+private:
+    void Detach();
+    virtual void DetachImpl() = 0;
 };
 
 // this class is a mixin for GL objects that have dimensions
 // that we need to track.
 class WebGLRectangleObject
 {
 public:
     WebGLRectangleObject()