Bug 745897. Add the new DOM bindings APIs to WebGLContext. r=bjacob
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 04 May 2012 12:38:44 -0400
changeset 93190 838abb8c06d9b04c3a7b9716bd364bf9d319bece
parent 93189 41e810dd264f0637ec2e944af79e1d87bff9da1f
child 93191 e0a8b01b259abbbea59f4e05c380e253ac2347d3
push id22616
push userMs2ger@gmail.com
push dateSat, 05 May 2012 08:59:35 +0000
treeherdermozilla-central@ea4c62f4c063 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs745897
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 745897. Add the new DOM bindings APIs to WebGLContext. r=bjacob This adds APIs suitable for calling from the new DOM bindings to WebGLContext and makes the XPCOM versions of the WebGL context API call through to the new-binding versions.
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextUtils.cpp
content/canvas/src/WebGLTexelConversions.h
dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -102,11 +102,13 @@ include $(topsrcdir)/ipc/chromium/chromi
 CXXFLAGS	+= $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 
 INCLUDES	+= \
 		-I$(srcdir)/../../../layout/xul/base/src \
 		-I$(srcdir)/../../../layout/style \
 		-I$(srcdir)/../../../layout/generic \
 		-I$(srcdir)/../../base/src \
 		-I$(srcdir)/../../html/content/src \
+		-I$(srcdir)/../../../js/xpconnect/src \
+		-I$(srcdir)/../../../dom/base \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -780,31 +780,43 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
     mResetLayer = false;
 
     return canvasLayer.forget().get();
 }
 
 NS_IMETHODIMP
 WebGLContext::GetContextAttributes(jsval *aResult)
 {
+    nsresult rv = NS_OK;
+    JSObject* obj = GetContextAttributes(rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    *aResult = JS::ObjectOrNullValue(obj);
+    return NS_OK;
+}
+
+JSObject*
+WebGLContext::GetContextAttributes(nsresult &rv)
+{
     if (!IsContextStable())
     {
-        *aResult = OBJECT_TO_JSVAL(NULL);
-        return NS_OK;
+        return NULL;
     }
 
     JSContext *cx = nsContentUtils::GetCurrentJSContext();
-    if (!cx)
-        return NS_ERROR_FAILURE;
+    if (!cx) {
+        rv = NS_ERROR_FAILURE;
+        return NULL;
+    }
 
     JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
-    if (!obj)
-        return NS_ERROR_FAILURE;
-
-    *aResult = OBJECT_TO_JSVAL(obj);
+    if (!obj) {
+        rv = NS_ERROR_FAILURE;
+        return NULL;
+    }
 
     gl::ContextFormat cf = gl->ActualFormat();
 
     if (!JS_DefineProperty(cx, obj, "alpha", cf.alpha > 0 ? JSVAL_TRUE : JSVAL_FALSE,
                            NULL, NULL, JSPROP_ENUMERATE) ||
         !JS_DefineProperty(cx, obj, "depth", cf.depth > 0 ? JSVAL_TRUE : JSVAL_FALSE,
                            NULL, NULL, JSPROP_ENUMERATE) ||
         !JS_DefineProperty(cx, obj, "stencil", cf.stencil > 0 ? JSVAL_TRUE : JSVAL_FALSE,
@@ -813,21 +825,21 @@ WebGLContext::GetContextAttributes(jsval
                            NULL, NULL, JSPROP_ENUMERATE) ||
         !JS_DefineProperty(cx, obj, "premultipliedAlpha",
                            mOptions.premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE,
                            NULL, NULL, JSPROP_ENUMERATE) ||
         !JS_DefineProperty(cx, obj, "preserveDrawingBuffer",
                            mOptions.preserveDrawingBuffer ? JSVAL_TRUE : JSVAL_FALSE,
                            NULL, NULL, JSPROP_ENUMERATE))
     {
-        *aResult = JSVAL_VOID;
-        return NS_ERROR_FAILURE;
+        rv = NS_ERROR_FAILURE;
+        return NULL;
     }
 
-    return NS_OK;
+    return obj;
 }
 
 /* [noscript] DOMString mozGetUnderlyingParamString(in WebGLenum pname); */
 NS_IMETHODIMP
 WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
 {
     if (!IsContextStable())
         return NS_OK;
@@ -879,22 +891,29 @@ bool WebGLContext::IsExtensionSupported(
     }
 
     return isSupported;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
 {
-    *retval = nsnull;
+    *retval = GetExtension(aName);
+    NS_IF_ADDREF(*retval);
+    return NS_OK;
+}
+
+nsIWebGLExtension*
+WebGLContext::GetExtension(const nsAString& aName)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return nsnull;
     
     if (mDisableExtensions) {
-        return NS_OK;
+        return nsnull;
     }
 
     // handle simple extensions that don't need custom objects first
     WebGLExtensionID ei = WebGLExtensionID_Max;
     if (aName.EqualsLiteral("OES_texture_float")) {
         if (IsExtensionSupported(WebGL_OES_texture_float))
             ei = WebGL_OES_texture_float;
     }
@@ -925,20 +944,20 @@ WebGLContext::GetExtension(const nsAStri
                     break;
                 // create an extension for any types that don't
                 // have any additional tokens or methods
                 default:
                     mEnabledExtensions[ei] = new WebGLExtension(this);
                     break;
             }
         }
-        NS_ADDREF(*retval = mEnabledExtensions[ei]);
+        return mEnabledExtensions[ei];
     }
 
-    return NS_OK;
+    return nsnull;
 }
 
 void
 WebGLContext::ForceClearFramebufferWithDefaultValues(PRUint32 mask, const nsIntRect& viewportRect)
 {
     MakeContextCurrent();
 
     bool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
@@ -1021,23 +1040,23 @@ WebGLContext::EnsureBackbufferClearedAsN
     ForceClearFramebufferWithDefaultValues(LOCAL_GL_COLOR_BUFFER_BIT |
                                            LOCAL_GL_DEPTH_BUFFER_BIT |
                                            LOCAL_GL_STENCIL_BUFFER_BIT,
                                            nsIntRect(0, 0, mWidth, mHeight));
 
     Invalidate();
 }
 
-nsresult
+void
 WebGLContext::DummyFramebufferOperation(const char *info)
 {
     WebGLenum status;
     CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER, &status);
     if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE)
-        return NS_OK;
+        return;
     else
         return ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
 }
 
 // We use this timer for many things. Here are the things that it is activated for:
 // 1) If a script is using the MOZ_WEBGL_lose_context extension.
 // 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
 //    CONTEXT_LOST_WEBGL error has been triggered.
@@ -1363,31 +1382,25 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLExt
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLExtension)
 
 DOMCI_DATA(WebGLExtension, WebGLExtension)
 
 /* readonly attribute WebGLsizei drawingBufferWidth; */
 NS_IMETHODIMP
 WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
 {
-    if (!IsContextStable())
-        return NS_OK;
-
-    *aWidth = mWidth;
+    *aWidth = GetDrawingBufferWidth();
     return NS_OK;
 }
 
 /* readonly attribute WebGLsizei drawingBufferHeight; */
 NS_IMETHODIMP
 WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight)
 {
-    if (!IsContextStable())
-        return NS_OK;
-
-    *aHeight = mHeight;
+    *aHeight = GetDrawingBufferHeight();
     return NS_OK;
 }
 
 /* [noscript] attribute WebGLint location; */
 NS_IMETHODIMP
 WebGLUniformLocation::GetLocation(WebGLint *aLocation)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
@@ -1445,57 +1458,79 @@ WebGLShaderPrecisionFormat::GetPrecision
 {
     *aPrecision = mPrecision;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetSupportedExtensions(nsIVariant **retval)
 {
-    *retval = nsnull;
-    if (!IsContextStable())
-        return NS_OK;
-    
-    if (mDisableExtensions) {
+    Nullable< nsTArray<nsString> > extensions;
+    GetSupportedExtensions(extensions);
+
+    if (extensions.IsNull()) {
+        *retval = nsnull;
         return NS_OK;
     }
-    
+
     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
-    nsTArray<const char *> extList;
-
-    if (IsExtensionSupported(WebGL_OES_texture_float))
-        extList.InsertElementAt(extList.Length(), "OES_texture_float");
-    if (IsExtensionSupported(WebGL_OES_standard_derivatives))
-        extList.InsertElementAt(extList.Length(), "OES_standard_derivatives");
-    if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
-        extList.InsertElementAt(extList.Length(), "MOZ_EXT_texture_filter_anisotropic");
-    if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
-        extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context");
+    const nsTArray<nsString>& extList = extensions.Value();
 
     nsresult rv;
     if (extList.Length() > 0) {
-        rv = wrval->SetAsArray(nsIDataType::VTYPE_CHAR_STR, nsnull,
-                               extList.Length(), &extList[0]);
+        // nsIVariant can't handle SetAsArray with the AString or
+        // DOMString type, so we have to spoon-feed it something it
+        // knows how to handle.
+        nsTArray<const PRUnichar*> exts(extList.Length());
+        for (PRUint32 i = 0; i < extList.Length(); ++i) {
+            exts.AppendElement(extList[i].get());
+        }
+        rv = wrval->SetAsArray(nsIDataType::VTYPE_WCHAR_STR, nsnull,
+                               exts.Length(), exts.Elements());
     } else {
         rv = wrval->SetAsEmptyArray();
     }
     if (NS_FAILED(rv))
         return rv;
 
     *retval = wrval.forget().get();
     return NS_OK;
+
+}
+
+void
+WebGLContext::GetSupportedExtensions(Nullable< nsTArray<nsString> > &retval)
+{
+    retval.SetNull();
+    if (!IsContextStable())
+        return;
+    
+    if (mDisableExtensions) {
+        return;
+    }
+
+    nsTArray<nsString>& arr = retval.SetValue();
+    
+    if (IsExtensionSupported(WebGL_OES_texture_float))
+        arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
+    if (IsExtensionSupported(WebGL_OES_standard_derivatives))
+        arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives"));
+    if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
+        arr.AppendElement(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"));
+    if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
+        arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
 }
 
 NS_IMETHODIMP
 WebGLContext::IsContextLost(WebGLboolean *retval)
 {
     *retval = mContextStatus != ContextStable;
     return NS_OK;
 }
 
 // Internalized version of IsContextLost.
 bool
-WebGLContext::IsContextStable()
+WebGLContext::IsContextStable() const
 {
     return mContextStatus == ContextStable;
 }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -62,22 +62,27 @@
 #include "nsIObserver.h"
 
 #include "GLContextProvider.h"
 #include "Layers.h"
 
 #include "CheckedInt.h"
 #include "nsDataHashtable.h"
 
+#include "mozilla/dom/ImageData.h"
+
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
 
 #include "angle/ShaderLang.h"
 
+#include "mozilla/dom/TypedArray.h"
+#include "mozilla/dom/Nullable.h"
+
 /* 
  * Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
  *   https://bugzilla.mozilla.org/show_bug.cgi?id=686732
  * 
  * Exceptions: some of the following values are set to higher values than in the spec because
  * the values in the spec are ridiculously low. They are explicitly marked below
 */
 #define MINVALUE_GL_MAX_TEXTURE_SIZE                  1024  // Different from the spec, which sets it to 64 on page 162
@@ -104,16 +109,18 @@ class WebGLFramebuffer;
 class WebGLRenderbuffer;
 class WebGLUniformLocation;
 class WebGLExtension;
 class WebGLContext;
 struct WebGLVertexAttribData;
 class WebGLMemoryPressureObserver;
 class WebGLRectangleObject;
 class WebGLContextBoundObject;
+class WebGLActiveInfo;
+class WebGLShaderPrecisionFormat;
 
 enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
 
 struct VertexAttrib0Status {
     enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
 };
 
 struct BackbufferClearingStatus {
@@ -545,17 +552,17 @@ public:
     }
 
     NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
 
     NS_DECL_NSITIMERCALLBACK
 
     // nsICanvasRenderingContextInternal
     NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
-    nsHTMLCanvasElement* HTMLCanvasElement() {
+    nsHTMLCanvasElement* HTMLCanvasElement() const {
         return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
     }
 
     NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
     NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height)
         { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Reset()
         { /* (InitializeWithSurface) */ return NS_ERROR_NOT_IMPLEMENTED; }
@@ -579,32 +586,32 @@ public:
                     { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Swap(PRUint32 nativeID,
                     PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
                     { return NS_ERROR_NOT_IMPLEMENTED; }
 
     bool LoseContext();
     bool RestoreContext();
 
-    nsresult SynthesizeGLError(WebGLenum err);
-    nsresult SynthesizeGLError(WebGLenum err, const char *fmt, ...);
-
-    nsresult ErrorInvalidEnum(const char *fmt = 0, ...);
-    nsresult ErrorInvalidOperation(const char *fmt = 0, ...);
-    nsresult ErrorInvalidValue(const char *fmt = 0, ...);
-    nsresult ErrorInvalidFramebufferOperation(const char *fmt = 0, ...);
-    nsresult ErrorInvalidEnumInfo(const char *info, PRUint32 enumvalue) {
+    void SynthesizeGLError(WebGLenum err);
+    void SynthesizeGLError(WebGLenum err, const char *fmt, ...);
+
+    void ErrorInvalidEnum(const char *fmt = 0, ...);
+    void ErrorInvalidOperation(const char *fmt = 0, ...);
+    void ErrorInvalidValue(const char *fmt = 0, ...);
+    void ErrorInvalidFramebufferOperation(const char *fmt = 0, ...);
+    void ErrorInvalidEnumInfo(const char *info, PRUint32 enumvalue) {
         return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
     }
-    nsresult ErrorOutOfMemory(const char *fmt = 0, ...);
+    void ErrorOutOfMemory(const char *fmt = 0, ...);
 
     const char *ErrorName(GLenum error);
     bool IsTextureFormatCompressed(GLenum format);
 
-    nsresult DummyFramebufferOperation(const char *info);
+    void DummyFramebufferOperation(const char *info);
 
     WebGLTexture *activeBoundTextureForTarget(WebGLenum target) {
         return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
                                              : mBoundCubeMapTextures[mActiveTexture];
     }
 
     already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                                  CanvasLayer *aOldLayer,
@@ -667,16 +674,411 @@ public:
 
     void TerminateContextLossTimer() {
         if (mContextLossTimerRunning) {
             mContextRestorer->Cancel();
             mContextLossTimerRunning = false;
         }
     }
 
+    // WebIDL WebGLRenderingContext API
+    nsHTMLCanvasElement* GetCanvas() const {
+        return HTMLCanvasElement();
+    }
+    WebGLsizei GetDrawingBufferWidth() const {
+        if (!IsContextStable())
+            return 0;
+        return mWidth;
+    }
+    WebGLsizei GetDrawingBufferHeight() const {
+        if (!IsContextStable())
+            return 0;
+        return mHeight;
+    }
+        
+    JSObject *GetContextAttributes(nsresult &rv);
+    bool IsContextLost() const { return !IsContextStable(); }
+    void GetSupportedExtensions(dom::Nullable< nsTArray<nsString> > &retval);
+    nsIWebGLExtension* GetExtension(const nsAString& aName);
+    void ActiveTexture(WebGLenum texture);
+    void AttachShader(WebGLProgram* program, WebGLShader* shader);
+    void BindAttribLocation(WebGLProgram* program, WebGLuint location,
+                            const nsAString& name);
+    void BindBuffer(WebGLenum target, WebGLBuffer* buf);
+    void BindFramebuffer(WebGLenum target, WebGLFramebuffer* wfb);
+    void BindRenderbuffer(WebGLenum target, WebGLRenderbuffer* wrb);
+    void BindTexture(WebGLenum target, WebGLTexture *tex);
+    void BlendColor(WebGLclampf r, WebGLclampf g, WebGLclampf b, WebGLclampf a) {
+        if (!IsContextStable())
+            return;
+        MakeContextCurrent();
+        gl->fBlendColor(r, g, b, a);
+    }
+    void BlendEquation(WebGLenum mode);
+    void BlendEquationSeparate(WebGLenum modeRGB, WebGLenum modeAlpha);
+    void BlendFunc(WebGLenum sfactor, WebGLenum dfactor);
+    void BlendFuncSeparate(WebGLenum srcRGB, WebGLenum dstRGB,
+                           WebGLenum srcAlpha, WebGLenum dstAlpha);
+    void BufferData(WebGLenum target, WebGLsizeiptr size, WebGLenum usage);
+    void BufferData(WebGLenum target, dom::ArrayBufferView &data,
+                    WebGLenum usage);
+    void BufferData(WebGLenum target, dom::ArrayBuffer *data, WebGLenum usage);
+    void BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
+                       dom::ArrayBufferView &data);
+    void BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
+                       dom::ArrayBuffer *data);
+    WebGLenum CheckFramebufferStatus(WebGLenum target);
+    void Clear(WebGLbitfield mask);
+    void ClearColor(WebGLclampf r, WebGLclampf g, WebGLclampf b, WebGLclampf a);
+    void ClearDepth(WebGLclampf v);
+    void ClearStencil(WebGLint v);
+    void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a);
+    void CompileShader(WebGLShader *shader);
+    void CompressedTexImage2D(WebGLenum target, WebGLint level,
+                              WebGLenum internalformat, WebGLsizei width,
+                              WebGLsizei height, WebGLint border,
+                              dom::ArrayBufferView& view);
+    void CompressedTexSubImage2D(WebGLenum target, WebGLint level,
+                                 WebGLint xoffset, WebGLint yoffset,
+                                 WebGLsizei width, WebGLsizei height,
+                                 WebGLenum format, dom::ArrayBufferView& view);
+    void CopyTexImage2D(WebGLenum target, WebGLint level,
+                        WebGLenum internalformat, WebGLint x, WebGLint y,
+                        WebGLsizei width, WebGLsizei height, WebGLint border);
+    void CopyTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
+                           WebGLint yoffset, WebGLint x, WebGLint y,
+                           WebGLsizei width, WebGLsizei height);
+    already_AddRefed<WebGLBuffer> CreateBuffer();
+    already_AddRefed<WebGLFramebuffer> CreateFramebuffer();
+    already_AddRefed<WebGLProgram> CreateProgram();
+    already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
+    already_AddRefed<WebGLTexture> CreateTexture();
+    already_AddRefed<WebGLShader> CreateShader(WebGLenum type);
+    void CullFace(WebGLenum face);
+    void DeleteBuffer(WebGLBuffer *buf);
+    void DeleteFramebuffer(WebGLFramebuffer *fbuf);
+    void DeleteProgram(WebGLProgram *prog);
+    void DeleteRenderbuffer(WebGLRenderbuffer *rbuf);
+    void DeleteShader(WebGLShader *shader);
+    void DeleteTexture(WebGLTexture *tex);
+    void DepthFunc(WebGLenum func);
+    void DepthMask(WebGLboolean b);
+    void DepthRange(WebGLclampf zNear, WebGLclampf zFar);
+    void DetachShader(WebGLProgram *program, WebGLShader *shader);
+    void Disable(WebGLenum cap);
+    void DisableVertexAttribArray(WebGLuint index);
+    void DrawArrays(GLenum mode, WebGLint first, WebGLsizei count);
+    void DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
+                      WebGLintptr byteOffset);
+    void Enable(WebGLenum cap);
+    void EnableVertexAttribArray(WebGLuint index);
+    void Flush() {
+        if (!IsContextStable())
+            return;
+        MakeContextCurrent();
+        gl->fFlush();
+    }
+    void Finish() {
+        if (!IsContextStable())
+            return;
+        MakeContextCurrent();
+        gl->fFinish();
+    }
+    void FramebufferRenderbuffer(WebGLenum target, WebGLenum attachment,
+                                 WebGLenum rbtarget, WebGLRenderbuffer *wrb);
+    void FramebufferTexture2D(WebGLenum target, WebGLenum attachment,
+                              WebGLenum textarget, WebGLTexture *tobj,
+                              WebGLint level);
+    void FrontFace(WebGLenum mode);
+    void GenerateMipmap(WebGLenum target);
+    already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram *prog,
+                                                      WebGLuint index);
+    already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram *prog,
+                                                       WebGLuint index);
+    void GetAttachedShaders(WebGLProgram* prog,
+                            dom::Nullable< nsTArray<WebGLShader*> > &retval);
+    WebGLint GetAttribLocation(WebGLProgram* prog, const nsAString& name);
+    JS::Value GetBufferParameter(WebGLenum target, WebGLenum pname);
+    JS::Value GetParameter(JSContext* cx, WebGLenum pname, nsresult& rv);
+    WebGLenum GetError();
+    JS::Value GetFramebufferAttachmentParameter(JSContext* cx,
+                                                WebGLenum target,
+                                                WebGLenum attachment,
+                                                WebGLenum pname,
+                                                nsresult& rv);
+    JS::Value GetProgramParameter(WebGLProgram *prog, WebGLenum pname);
+    void GetProgramInfoLog(WebGLProgram *prog, nsAString& retval, nsresult& rv);
+    JS::Value GetRenderbufferParameter(WebGLenum target, WebGLenum pname);
+    JS::Value GetShaderParameter(WebGLShader *shader, WebGLenum pname);
+    already_AddRefed<WebGLShaderPrecisionFormat>
+      GetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precisiontype);
+    void GetShaderInfoLog(WebGLShader *shader, nsAString& retval, nsresult& rv);
+    void GetShaderSource(WebGLShader *shader, nsAString& retval);
+    JS::Value GetTexParameter(WebGLenum target, WebGLenum pname);
+    JS::Value GetUniform(JSContext* cx, WebGLProgram *prog,
+                         WebGLUniformLocation *location, nsresult& rv);
+    already_AddRefed<WebGLUniformLocation>
+      GetUniformLocation(WebGLProgram *prog, const nsAString& name);
+    JS::Value GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
+                              nsresult& rv);
+    WebGLsizeiptr GetVertexAttribOffset(WebGLuint index, WebGLenum pname);
+    void Hint(WebGLenum target, WebGLenum mode);
+    bool IsBuffer(WebGLBuffer *buffer);
+    bool IsEnabled(WebGLenum cap);
+    bool IsFramebuffer(WebGLFramebuffer *fb);
+    bool IsProgram(WebGLProgram *prog);
+    bool IsRenderbuffer(WebGLRenderbuffer *rb);
+    bool IsShader(WebGLShader *shader);
+    bool IsTexture(WebGLTexture *tex);
+    void LineWidth(WebGLfloat width) {
+        if (!IsContextStable())
+            return;
+        MakeContextCurrent();
+        gl->fLineWidth(width);
+    }
+    void LinkProgram(WebGLProgram *program, nsresult& rv);
+    void PixelStorei(WebGLenum pname, WebGLint param);
+    void PolygonOffset(WebGLfloat factor, WebGLfloat units) {
+        if (!IsContextStable())
+            return;
+        MakeContextCurrent();
+        gl->fPolygonOffset(factor, units);
+    }
+    void ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height,
+                    WebGLenum format, WebGLenum type,
+                    dom::ArrayBufferView* pixels, nsresult& rv);
+    void RenderbufferStorage(WebGLenum target, WebGLenum internalformat,
+                             WebGLsizei width, WebGLsizei height);
+    void SampleCoverage(WebGLclampf value, WebGLboolean invert) {
+        if (!IsContextStable())
+            return;
+        MakeContextCurrent();
+        gl->fSampleCoverage(value, invert);
+    }
+    void Scissor(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height);
+    void ShaderSource(WebGLShader *shader, const nsAString& source);
+    void StencilFunc(WebGLenum func, WebGLint ref, WebGLuint mask);
+    void StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref,
+                             WebGLuint mask);
+    void StencilMask(WebGLuint mask);
+    void StencilMaskSeparate(WebGLenum face, WebGLuint mask);
+    void StencilOp(WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass);
+    void StencilOpSeparate(WebGLenum face, WebGLenum sfail, WebGLenum dpfail,
+                           WebGLenum dppass);
+    void TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                    WebGLenum internalformat, WebGLsizei width,
+                    WebGLsizei height, WebGLint border, WebGLenum format,
+                    WebGLenum type, dom::ArrayBufferView *pixels, nsresult& rv);
+    void TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                    WebGLenum internalformat, WebGLenum format, WebGLenum type,
+                    dom::ImageData* pixels, nsresult& rv);
+    void TexImage2D(JSContext* /* unused */, WebGLenum target, WebGLint level,
+                    WebGLenum internalformat, WebGLenum format, WebGLenum type,
+                    dom::Element* elt, nsresult& rv);
+    void TexParameterf(WebGLenum target, WebGLenum pname, WebGLfloat param) {
+        TexParameter_base(target, pname, nsnull, &param);
+    }
+    void TexParameteri(WebGLenum target, WebGLenum pname, WebGLint param) {
+        TexParameter_base(target, pname, &param, nsnull);
+    }
+    
+    void TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                       WebGLint xoffset, WebGLint yoffset,
+                       WebGLsizei width, WebGLsizei height, WebGLenum format,
+                       WebGLenum type, dom::ArrayBufferView* pixels,
+                       nsresult& rv);
+    void TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                       WebGLint xoffset, WebGLint yoffset, WebGLenum format,
+                       WebGLenum type, dom::ImageData* pixels, nsresult& rv);
+    void TexSubImage2D(JSContext* /* unused */, WebGLenum target, WebGLint level,
+                       WebGLint xoffset, WebGLint yoffset, WebGLenum format,
+                       WebGLenum type, dom::Element* elt, nsresult& rv);
+
+    void Uniform1i(WebGLUniformLocation* location, WebGLint x);
+    void Uniform2i(WebGLUniformLocation* location, WebGLint x, WebGLint y);
+    void Uniform3i(WebGLUniformLocation* location, WebGLint x, WebGLint y,
+                   WebGLint z);
+    void Uniform4i(WebGLUniformLocation* location, WebGLint x, WebGLint y,
+                   WebGLint z, WebGLint w);
+
+    void Uniform1f(WebGLUniformLocation* location, WebGLfloat x);
+    void Uniform2f(WebGLUniformLocation* location, WebGLfloat x, WebGLfloat y);
+    void Uniform3f(WebGLUniformLocation* location, WebGLfloat x, WebGLfloat y,
+                   WebGLfloat z);
+    void Uniform4f(WebGLUniformLocation* location, WebGLfloat x, WebGLfloat y,
+                   WebGLfloat z, WebGLfloat w);
+    
+    void Uniform1iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
+        Uniform1iv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform1iv(WebGLUniformLocation* location, nsTArray<WebGLint>& arr) {
+        Uniform1iv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform1iv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLint* data);
+
+    void Uniform2iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
+        Uniform2iv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform2iv(WebGLUniformLocation* location, nsTArray<WebGLint>& arr) {
+        Uniform2iv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform2iv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLint* data);
+
+    void Uniform3iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
+        Uniform3iv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform3iv(WebGLUniformLocation* location, nsTArray<WebGLint>& arr) {
+        Uniform3iv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform3iv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLint* data);
+    
+    void Uniform4iv(WebGLUniformLocation* location, dom::Int32Array& arr) {
+        Uniform4iv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform4iv(WebGLUniformLocation* location, nsTArray<WebGLint>& arr) {
+        Uniform4iv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform4iv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLint* data);
+
+    void Uniform1fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
+        Uniform1fv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform1fv(WebGLUniformLocation* location, nsTArray<WebGLfloat>& arr) {
+        Uniform1fv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform1fv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLfloat* data);
+
+    void Uniform2fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
+        Uniform2fv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform2fv(WebGLUniformLocation* location, nsTArray<WebGLfloat>& arr) {
+        Uniform2fv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform2fv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLfloat* data);
+
+    void Uniform3fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
+        Uniform3fv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform3fv(WebGLUniformLocation* location, nsTArray<WebGLfloat>& arr) {
+        Uniform3fv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform3fv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLfloat* data);
+    
+    void Uniform4fv(WebGLUniformLocation* location, dom::Float32Array& arr) {
+        Uniform4fv_base(location, arr.mLength, arr.mData);
+    }
+    void Uniform4fv(WebGLUniformLocation* location, nsTArray<WebGLfloat>& arr) {
+        Uniform4fv_base(location, arr.Length(), arr.Elements());
+    }
+    void Uniform4fv_base(WebGLUniformLocation* location, uint32_t arrayLength,
+                         WebGLfloat* data);
+
+    void UniformMatrix2fv(WebGLUniformLocation* location,
+                          WebGLboolean transpose,
+                          dom::Float32Array &value) {
+        UniformMatrix2fv_base(location, transpose, value.mLength, value.mData);
+    }
+    void UniformMatrix2fv(WebGLUniformLocation* location,
+                          WebGLboolean transpose,
+                          nsTArray<float> &value) {
+        UniformMatrix2fv_base(location, transpose, value.Length(),
+                              value.Elements());
+    }
+    void UniformMatrix2fv_base(WebGLUniformLocation* location,
+                               WebGLboolean transpose, uint32_t arrayLength,
+                               float* data);
+
+    void UniformMatrix3fv(WebGLUniformLocation* location,
+                          WebGLboolean transpose,
+                          dom::Float32Array &value) {
+        UniformMatrix3fv_base(location, transpose, value.mLength, value.mData);
+    }
+    void UniformMatrix3fv(WebGLUniformLocation* location,
+                          WebGLboolean transpose,
+                          nsTArray<float> &value) {
+        UniformMatrix3fv_base(location, transpose, value.Length(),
+                              value.Elements());
+    }
+    void UniformMatrix3fv_base(WebGLUniformLocation* location,
+                               WebGLboolean transpose, uint32_t arrayLength,
+                               float* data);
+
+    void UniformMatrix4fv(WebGLUniformLocation* location,
+                          WebGLboolean transpose,
+                          dom::Float32Array &value) {
+        UniformMatrix4fv_base(location, transpose, value.mLength, value.mData);
+    }
+    void UniformMatrix4fv(WebGLUniformLocation* location,
+                          WebGLboolean transpose,
+                          nsTArray<float> &value) {
+        UniformMatrix4fv_base(location, transpose, value.Length(),
+                              value.Elements());
+    }
+    void UniformMatrix4fv_base(WebGLUniformLocation* location,
+                               WebGLboolean transpose, uint32_t arrayLength,
+                               float* data);
+
+    void UseProgram(WebGLProgram *prog);
+    void ValidateProgram(WebGLProgram *prog);
+
+    void VertexAttrib1f(WebGLuint index, WebGLfloat x0);
+    void VertexAttrib2f(WebGLuint index, WebGLfloat x0, WebGLfloat x1);
+    void VertexAttrib3f(WebGLuint index, WebGLfloat x0, WebGLfloat x1,
+                        WebGLfloat x2);
+    void VertexAttrib4f(WebGLuint index, WebGLfloat x0, WebGLfloat x1,
+                        WebGLfloat x2, WebGLfloat x3);
+
+    void VertexAttrib1fv(WebGLuint idx, dom::Float32Array &arr) {
+        VertexAttrib1fv_base(idx, arr.mLength, arr.mData);
+    }
+    void VertexAttrib1fv(WebGLuint idx, nsTArray<WebGLfloat>& arr) {
+        VertexAttrib1fv_base(idx, arr.Length(), arr.Elements());
+    }
+    void VertexAttrib1fv_base(WebGLuint idx, uint32_t arrayLength,
+                              WebGLfloat* ptr);
+
+    void VertexAttrib2fv(WebGLuint idx, dom::Float32Array &arr) {
+        VertexAttrib2fv_base(idx, arr.mLength, arr.mData);
+    }
+    void VertexAttrib2fv(WebGLuint idx, nsTArray<WebGLfloat>& arr) {
+        VertexAttrib2fv_base(idx, arr.Length(), arr.Elements());
+    }
+    void VertexAttrib2fv_base(WebGLuint idx, uint32_t arrayLength,
+                              WebGLfloat* ptr);
+
+    void VertexAttrib3fv(WebGLuint idx, dom::Float32Array &arr) {
+        VertexAttrib3fv_base(idx, arr.mLength, arr.mData);
+    }
+    void VertexAttrib3fv(WebGLuint idx, nsTArray<WebGLfloat>& arr) {
+        VertexAttrib3fv_base(idx, arr.Length(), arr.Elements());
+    }
+    void VertexAttrib3fv_base(WebGLuint idx, uint32_t arrayLength,
+                              WebGLfloat* ptr);
+
+    void VertexAttrib4fv(WebGLuint idx, dom::Float32Array &arr) {
+        VertexAttrib4fv_base(idx, arr.mLength, arr.mData);
+    }
+    void VertexAttrib4fv(WebGLuint idx, nsTArray<WebGLfloat>& arr) {
+        VertexAttrib4fv_base(idx, arr.Length(), arr.Elements());
+    }
+    void VertexAttrib4fv_base(WebGLuint idx, uint32_t arrayLength,
+                              WebGLfloat* ptr);
+    
+    void VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type,
+                             WebGLboolean normalized, WebGLsizei stride,
+                             WebGLintptr byteOffset);
+    void Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height);
+
 protected:
     void SetDontKnowIfNeedFakeBlack() {
         mFakeBlackStatus = DontKnowIfNeedFakeBlack;
     }
 
     bool NeedFakeBlack();
     void BindFakeBlackTextures();
     void UnbindFakeBlackTextures();
@@ -691,23 +1093,16 @@ protected:
                                       PRUint32 pixelSize,
                                       PRUint32 alignment);
 
     // Returns x rounded to the next highest multiple of y.
     static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
         return ((x + y - 1) / y) * y;
     }
 
-    nsresult BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage);
-    nsresult BufferData_buf(WebGLenum target, JSObject* data, WebGLenum usage, JSContext *cx);
-    nsresult BufferData_array(WebGLenum target, JSObject* data, WebGLenum usage, JSContext *cx);
-
-    nsresult BufferSubData_buf(WebGLenum target, PRInt32 offset, JSObject* data, JSContext *cx);
-    nsresult BufferSubData_array(WebGLenum target, PRInt32 offset, JSObject* data, JSContext *cx);
-
     nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
 
     nsRefPtr<gl::GLContext> gl;
 
     CheckedUint32 mGeneration;
 
     WebGLContextOptions mOptions;
 
@@ -798,84 +1193,74 @@ protected:
     static PRUint32 GetTexelSize(WebGLenum format, WebGLenum type);
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
     void MakeContextCurrent() { gl->MakeCurrent(); }
 
     // helpers
-    nsresult TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum internalformat,
-                             WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLint border,
-                             WebGLenum format, WebGLenum type,
-                             void *data, PRUint32 byteLength,
-                             int jsArrayType,
-                             int srcFormat, bool srcPremultiplied);
-    nsresult TexSubImage2D_base(WebGLenum target, WebGLint level,
-                                WebGLint xoffset, WebGLint yoffset,
-                                WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
-                                WebGLenum format, WebGLenum type,
-                                void *pixels, PRUint32 byteLength,
-                                int jsArrayType,
-                                int srcFormat, bool srcPremultiplied);
-    nsresult TexParameter_base(WebGLenum target, WebGLenum pname,
-                               WebGLint *intParamPtr, WebGLfloat *floatParamPtr);
+    void TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum internalformat,
+                         WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLint border,
+                         WebGLenum format, WebGLenum type,
+                         void *data, PRUint32 byteLength,
+                         int jsArrayType,
+                         int srcFormat, bool srcPremultiplied);
+    void TexSubImage2D_base(WebGLenum target, WebGLint level,
+                            WebGLint xoffset, WebGLint yoffset,
+                            WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
+                            WebGLenum format, WebGLenum type,
+                            void *pixels, PRUint32 byteLength,
+                            int jsArrayType,
+                            int srcFormat, bool srcPremultiplied);
+    void TexParameter_base(WebGLenum target, WebGLenum pname,
+                           WebGLint *intParamPtr, WebGLfloat *floatParamPtr);
 
     void ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
                       const PRUint8*src, PRUint8 *dst,
                       int srcFormat, bool srcPremultiplied,
                       int dstFormat, bool dstPremultiplied,
                       size_t dstTexelSize);
 
     nsresult DOMElementToImageSurface(dom::Element* imageOrCanvas,
                                       gfxImageSurface **imageOut,
                                       int *format);
 
-    nsresult CopyTexSubImage2D_base(WebGLenum target,
-                                    WebGLint level,
-                                    WebGLenum internalformat,
-                                    WebGLint xoffset,
-                                    WebGLint yoffset,
-                                    WebGLint x,
-                                    WebGLint y,
-                                    WebGLsizei width,
-                                    WebGLsizei height,
-                                    bool sub
-                                  );
-
-    // Conversion from public nsI* interfaces to concrete objects
-    template<class ConcreteObjectType, class BaseInterfaceType>
-    bool GetConcreteObject(const char *info,
-                             BaseInterfaceType *aInterface,
-                             ConcreteObjectType **aConcreteObject,
-                             bool *isNull = 0,
-                             bool *isDeleted = 0,
-                             bool generateErrors = true);
-
-    template<class ConcreteObjectType, class BaseInterfaceType>
-    bool GetConcreteObjectAndGLName(const char *info,
-                                      BaseInterfaceType *aInterface,
-                                      ConcreteObjectType **aConcreteObject,
-                                      WebGLuint *aGLObjectName,
-                                      bool *isNull = 0,
-                                      bool *isDeleted = 0);
-
-    template<class ConcreteObjectType, class BaseInterfaceType>
-    bool GetGLName(const char *info,
-                     BaseInterfaceType *aInterface,
-                     WebGLuint *aGLObjectName,
-                     bool *isNull = 0,
-                     bool *isDeleted = 0);
-
-    template<class ConcreteObjectType, class BaseInterfaceType>
-    bool CanGetConcreteObject(const char *info,
-                                BaseInterfaceType *aInterface,
-                                bool *isNull = 0,
-                                bool *isDeleted = 0);
-
+    void CopyTexSubImage2D_base(WebGLenum target,
+                                WebGLint level,
+                                WebGLenum internalformat,
+                                WebGLint xoffset,
+                                WebGLint yoffset,
+                                WebGLint x,
+                                WebGLint y,
+                                WebGLsizei width,
+                                WebGLsizei height,
+                                bool sub);
+
+    // Returns false if aObject is null or not valid
+    template<class ObjectType>
+    bool ValidateObject(const char* info, ObjectType *aObject);
+    // Returns false if aObject is not valid.  Considers null to be valid.
+    template<class ObjectType>
+    bool ValidateObjectAllowNull(const char* info, ObjectType *aObject);
+    // Returns false if aObject is not valid, but considers deleted
+    // objects and null objects valid.
+    template<class ObjectType>
+    bool ValidateObjectAllowDeletedOrNull(const char* info, ObjectType *aObject);
+    // Returns false if aObject is null or not valid, but considers deleted
+    // objects valid.
+    template<class ObjectType>
+    bool ValidateObjectAllowDeleted(const char* info, ObjectType *aObject);
+private:
+    // Like ValidateObject, but only for cases when aObject is known
+    // to not be null already.
+    template<class ObjectType>
+    bool ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject);
+
+protected:
     PRInt32 MaxTextureSizeForTarget(WebGLenum target) const {
         return target == LOCAL_GL_TEXTURE_2D ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
     }
     
     /** like glBufferData but if the call may change the buffer size, checks any GL error generated
      * by this glBufferData call and returns it */
     GLenum CheckedBufferData(GLenum target,
                              GLsizeiptr size,
@@ -889,17 +1274,17 @@ protected:
                              GLsizei width,
                              GLsizei height,
                              GLint border,
                              GLenum format,
                              GLenum type,
                              const GLvoid *data);
 
     void MaybeRestoreContext();
-    bool IsContextStable();
+    bool IsContextStable() const;
     void ForceLoseContext();
     void ForceRestoreContext();
 
     // the buffers bound to the current program's attribs
     nsTArray<WebGLVertexAttribData> mAttribBuffers;
 
     nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
     nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
@@ -1047,16 +1432,18 @@ struct WebGLVertexAttribData {
     }
 
     GLuint actualStride() const {
         if (stride) return stride;
         return size * componentSize();
     }
 };
 
+// NOTE: When this class is switched to new DOM bindings, update the
+// (then-slow) WrapObject calls in GetParameter and GetVertexAttrib.
 class WebGLBuffer MOZ_FINAL
     : public nsIWebGLBuffer
     , public WebGLRefCountedObject<WebGLBuffer>
     , public WebGLContextBoundObject
 {
 public:
     WebGLBuffer(WebGLContext *context)
         : WebGLContextBoundObject(context)
@@ -1185,16 +1572,18 @@ protected:
     PRUint8 mCachedMaxUbyteElement;
     bool mHasCachedMaxUbyteElement;
     PRUint16 mCachedMaxUshortElement;
     bool mHasCachedMaxUshortElement;
 
     void* mData; // in the case of an Element Array Buffer, we keep a copy.
 };
 
+// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
+// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
 class WebGLTexture MOZ_FINAL
     : public nsIWebGLTexture
     , public WebGLRefCountedObject<WebGLTexture>
     , public WebGLContextBoundObject
 {
 public:
     WebGLTexture(WebGLContext *context)
         : WebGLContextBoundObject(context)
@@ -1803,16 +2192,18 @@ static bool SplitLastSquareBracket(nsACS
     string.EndWriting();
     string.SetLength(s - string_start);
     return true;
 }
 
 typedef nsDataHashtable<nsCStringHashKey, nsCString> CStringMap;
 typedef nsDataHashtable<nsCStringHashKey, WebGLUniformInfo> CStringToUniformInfoMap;
 
+// NOTE: When this class is switched to new DOM bindings, update the
+// (then-slow) WrapObject call in GetParameter.
 class WebGLProgram MOZ_FINAL
     : public nsIWebGLProgram
     , public WebGLRefCountedObject<WebGLProgram>
     , public WebGLContextBoundObject
 {
 public:
     WebGLProgram(WebGLContext *context)
         : WebGLContextBoundObject(context)
@@ -2050,16 +2441,18 @@ protected:
     // post-link data
     std::vector<bool> mAttribsInUse;
     WebGLMonotonicHandle mMonotonicHandle;
     nsAutoPtr<CStringMap> mIdentifierMap, mIdentifierReverseMap;
     nsAutoPtr<CStringToUniformInfoMap> mUniformInfoMap;
     int mAttribMaxNameLength;
 };
 
+// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
+// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
 class WebGLRenderbuffer MOZ_FINAL
     : public nsIWebGLRenderbuffer
     , public WebGLRefCountedObject<WebGLRenderbuffer>
     , public WebGLRectangleObject
     , public WebGLContextBoundObject
 {
 public:
     WebGLRenderbuffer(WebGLContext *context)
@@ -2256,16 +2649,18 @@ public:
             }
         }
 
         NS_ABORT(); // should never get there
         return false;
     }
 };
 
+// NOTE: When this class is switched to new DOM bindings, update the
+// (then-slow) WrapObject call in GetParameter.
 class WebGLFramebuffer MOZ_FINAL
     : public nsIWebGLFramebuffer
     , public WebGLRefCountedObject<WebGLFramebuffer>
     , public WebGLContextBoundObject
 {
 public:
     WebGLFramebuffer(WebGLContext *context)
         : WebGLContextBoundObject(context)
@@ -2293,29 +2688,24 @@ public:
         mContext->gl->fDeleteFramebuffers(1, &mGLName);
         mContext->mFramebuffers.RemoveElement(mMonotonicHandle);
     }
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     WebGLuint GLName() { return mGLName; }
 
-    nsresult FramebufferRenderbuffer(WebGLenum target,
-                                     WebGLenum attachment,
-                                     WebGLenum rbtarget,
-                                     nsIWebGLRenderbuffer *rbobj)
+    void FramebufferRenderbuffer(WebGLenum target,
+                                 WebGLenum attachment,
+                                 WebGLenum rbtarget,
+                                 WebGLRenderbuffer *wrb)
     {
-        WebGLuint renderbuffername;
-        bool isNull;
-        WebGLRenderbuffer *wrb;
-
-        if (!mContext->GetConcreteObjectAndGLName("framebufferRenderbuffer: renderbuffer",
-                                                  rbobj, &wrb, &renderbuffername, &isNull))
+        if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", wrb))
         {
-            return NS_OK;
+            return;
         }
 
         if (target != LOCAL_GL_FRAMEBUFFER)
             return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
 
         if (rbtarget != LOCAL_GL_RENDERBUFFER)
             return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
 
@@ -2334,40 +2724,35 @@ public:
             if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
                 return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: attachment", attachment);
 
             mColorAttachment.SetRenderbuffer(wrb);
             break;
         }
 
         mContext->MakeContextCurrent();
+        WebGLuint renderbuffername = wrb ? wrb->GLName() : 0;
         if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
             mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_DEPTH_ATTACHMENT, rbtarget, renderbuffername);
             mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_STENCIL_ATTACHMENT, rbtarget, renderbuffername);
         } else {
             mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
         }
-
-        return NS_OK;
     }
 
-    nsresult FramebufferTexture2D(WebGLenum target,
-                                  WebGLenum attachment,
-                                  WebGLenum textarget,
-                                  nsIWebGLTexture *tobj,
-                                  WebGLint level)
+    void FramebufferTexture2D(WebGLenum target,
+                              WebGLenum attachment,
+                              WebGLenum textarget,
+                              WebGLTexture *wtex,
+                              WebGLint level)
     {
-        WebGLuint texturename;
-        bool isNull;
-        WebGLTexture *wtex;
-
-        if (!mContext->GetConcreteObjectAndGLName("framebufferTexture2D: texture",
-                                                  tobj, &wtex, &texturename, &isNull))
+        if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture",
+                                               wtex))
         {
-            return NS_OK;
+            return;
         }
 
         if (target != LOCAL_GL_FRAMEBUFFER)
             return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
 
         if (textarget != LOCAL_GL_TEXTURE_2D &&
             (textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
              textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
@@ -2391,24 +2776,25 @@ public:
             if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
                 return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
 
             mColorAttachment.SetTexture(wtex, level, face);
             break;
         }
 
         mContext->MakeContextCurrent();
+        WebGLuint texturename = wtex ? wtex->GLName() : 0;
         if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
             mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_DEPTH_ATTACHMENT, textarget, texturename, level);
             mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_STENCIL_ATTACHMENT, textarget, texturename, level);
         } else {
             mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level);
         }
 
-        return NS_OK;
+        return;
     }
 
     bool HasIncompleteAttachment() const {
         return (mColorAttachment.IsDefined() && !mColorAttachment.IsComplete()) ||
                (mDepthAttachment.IsDefined() && !mDepthAttachment.IsComplete()) ||
                (mStencilAttachment.IsDefined() && !mStencilAttachment.IsComplete()) ||
                (mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.IsComplete());
     }
@@ -2664,129 +3050,81 @@ inline const WebGLRectangleObject *WebGL
     return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
                              : static_cast<const WebGLRectangleObject*>(this);
 }
 
 /**
  ** Template implementations
  **/
 
-/* Helper function taking a BaseInterfaceType pointer, casting it to
- * ConcreteObjectType and performing some checks along the way.
- *
- * By default, null (respectively: deleted) aInterface pointers are
- * not allowed, but if you pass a non-null isNull (respectively:
- * isDeleted) pointer, then they become allowed and the value at
- * isNull (respecively isDeleted) is overwritten.
- *
- * If generateErrors is true (which is the default) then upon errors,
- * GL errors are synthesized and error messages are printed, prepended by
- * the 'info' string.
- */
-
-template<class ConcreteObjectType, class BaseInterfaceType>
+template<class ObjectType>
 inline bool
-WebGLContext::GetConcreteObject(const char *info,
-                                BaseInterfaceType *aInterface,
-                                ConcreteObjectType **aConcreteObject,
-                                bool *isNull,
-                                bool *isDeleted,
-                                bool generateErrors)
+WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info,
+                                               ObjectType *aObject)
 {
-    if (!aInterface) {
-        if (NS_LIKELY(isNull)) {
-            // non-null isNull means that the caller will accept a null arg
-            *isNull = true;
-            if(isDeleted) *isDeleted = false;
-            *aConcreteObject = 0;
-            return true;
-        } else {
-            if (generateErrors)
-                ErrorInvalidValue("%s: null object passed as argument", info);
-            return false;
-        }
-    }
-
-    if (isNull)
-        *isNull = false;
-
-    // the key to why this static_cast is all we need to do (as opposed to the QueryInterface check we used to do)
-    // is that since bug 638328, WebGL interfaces are marked 'builtinclass' in the IDL
-    ConcreteObjectType *concrete = static_cast<ConcreteObjectType*>(aInterface);
-    *aConcreteObject = concrete;
-
-    if (!concrete->IsCompatibleWithContext(this)) {
-        // the object doesn't belong to this WebGLContext
-        if (generateErrors)
-            ErrorInvalidOperation("%s: object from different WebGL context (or older generation of this one) "
-                                  "passed as argument", info);
+    if (aObject && !aObject->IsCompatibleWithContext(this)) {
+        ErrorInvalidOperation("%s: object from different WebGL context "
+                              "(or older generation of this one) "
+                              "passed as argument", info);
         return false;
     }
 
-    if (concrete->IsDeleted()) {
-        if (NS_LIKELY(isDeleted)) {
-            // non-null isDeleted means that the caller will accept a deleted arg
-            *isDeleted = true;
-            return true;
-        } else {
-            if (generateErrors)
-                ErrorInvalidValue("%s: deleted object passed as argument", info);
-            return false;
-        }
+    return true;
+}
+
+template<class ObjectType>
+inline bool
+WebGLContext::ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject)
+{
+    MOZ_ASSERT(aObject);
+
+    if (!ValidateObjectAllowDeletedOrNull(info, aObject))
+        return false;
+
+    if (aObject->IsDeleted()) {
+        ErrorInvalidValue("%s: deleted object passed as argument", info);
+        return false;
     }
 
-    if (isDeleted)
-      *isDeleted = false;
-
     return true;
 }
 
-/* Same as GetConcreteObject, and in addition gets the GL object name.
- * Null objects give the name 0.
- */
-template<class ConcreteObjectType, class BaseInterfaceType>
+template<class ObjectType>
 inline bool
-WebGLContext::GetConcreteObjectAndGLName(const char *info,
-                                         BaseInterfaceType *aInterface,
-                                         ConcreteObjectType **aConcreteObject,
-                                         WebGLuint *aGLObjectName,
-                                         bool *isNull,
-                                         bool *isDeleted)
+WebGLContext::ValidateObjectAllowNull(const char* info, ObjectType *aObject)
 {
-    bool result = GetConcreteObject(info, aInterface, aConcreteObject, isNull, isDeleted);
-    if (result == false) return false;
-    *aGLObjectName = *aConcreteObject ? (*aConcreteObject)->GLName() : 0;
-    return true;
+    if (!aObject) {
+        return true;
+    }
+
+    return ValidateObjectAssumeNonNull(info, aObject);
 }
 
-/* Same as GetConcreteObjectAndGLName when you don't need the concrete object pointer.
- */
-template<class ConcreteObjectType, class BaseInterfaceType>
+template<class ObjectType>
 inline bool
-WebGLContext::GetGLName(const char *info,
-                        BaseInterfaceType *aInterface,
-                        WebGLuint *aGLObjectName,
-                        bool *isNull,
-                        bool *isDeleted)
+WebGLContext::ValidateObjectAllowDeleted(const char* info, ObjectType *aObject)
 {
-    ConcreteObjectType *aConcreteObject;
-    return GetConcreteObjectAndGLName(info, aInterface, &aConcreteObject, aGLObjectName, isNull, isDeleted);
+    if (!aObject) {
+        ErrorInvalidValue("%s: null object passed as argument", info);
+        return false;
+    }
+
+    return ValidateObjectAllowDeletedOrNull(info, aObject);
 }
 
-/* Same as GetConcreteObject when you only want to check if the conversion succeeds.
- */
-template<class ConcreteObjectType, class BaseInterfaceType>
+template<class ObjectType>
 inline bool
-WebGLContext::CanGetConcreteObject(const char *info,
-                              BaseInterfaceType *aInterface,
-                              bool *isNull,
-                              bool *isDeleted)
+WebGLContext::ValidateObject(const char* info, ObjectType *aObject)
 {
-    ConcreteObjectType *aConcreteObject;
-    return GetConcreteObject(info, aInterface, &aConcreteObject, isNull, isDeleted, false);
+    if (!aObject) {
+        ErrorInvalidValue("%s: null object passed as argument", info);
+        return false;
+    }
+
+    return ValidateObjectAssumeNonNull(info, aObject);
 }
 
 class WebGLMemoryMultiReporterWrapper
 {
     WebGLMemoryMultiReporterWrapper();
     ~WebGLMemoryMultiReporterWrapper();
     static WebGLMemoryMultiReporterWrapper* sUniqueInstance;
 
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -59,177 +59,184 @@
 #include "WebGLTexelConversions.h"
 #include "WebGLValidateStrings.h"
 
 // needed to check if current OS is lower than 10.7
 #if defined(MOZ_WIDGET_COCOA)
 #include "nsCocoaFeatures.h"
 #endif
 
+#include "mozilla/dom/BindingUtils.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static bool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize);
 static WebGLenum InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2);
 
 /* Helper macros for when we're just wrapping a gl method, so that
  * we can avoid having to type this 500 times.  Note that these MUST
  * NOT BE USED if we need to check any of the parameters.
  */
 
-#define GL_SAME_METHOD_0(glname, name)                          \
-NS_IMETHODIMP WebGLContext::name() {                            \
-    if (!IsContextStable()) { return NS_OK; }                         \
-    MakeContextCurrent(); gl->f##glname(); return NS_OK;        \
-}
-
-#define GL_SAME_METHOD_1(glname, name, t1)          \
-NS_IMETHODIMP WebGLContext::name(t1 a1) {           \
-    if (!IsContextStable()) { return NS_OK; }             \
-    MakeContextCurrent(); gl->f##glname(a1); return NS_OK;  \
-}
-
-#define GL_SAME_METHOD_2(glname, name, t1, t2)        \
-NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2) {      \
-    if (!IsContextStable()) { return NS_OK; }               \
-    MakeContextCurrent(); gl->f##glname(a1,a2); return NS_OK;           \
-}
-
-#define GL_SAME_METHOD_3(glname, name, t1, t2, t3)      \
-NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3) { \
-    if (!IsContextStable()) { return NS_OK; }                 \
-    MakeContextCurrent(); gl->f##glname(a1,a2,a3); return NS_OK;        \
-}
-
-#define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4)         \
-NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4) { \
-    if (!IsContextStable()) { return NS_OK; }                        \
-    MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4); return NS_OK;     \
-}
-
-#define GL_SAME_METHOD_5(glname, name, t1, t2, t3, t4, t5)            \
-NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) { \
-    if (!IsContextStable()) { return NS_OK; }                               \
-    MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5); return NS_OK;  \
-}
-
-#define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6)          \
-NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \
-    if (!IsContextStable()) { return NS_OK; }                                 \
-    MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \
+#define GL_SAME_METHOD_0(glname, name)                               \
+NS_IMETHODIMP WebGLContext::Moz##name() {                            \
+    name();                                                          \
+    return NS_OK;                                                    \
+}
+
+#define GL_SAME_METHOD_1(glname, name, t1)                           \
+NS_IMETHODIMP WebGLContext::Moz##name(t1 a1) {                       \
+    name(a1);                                                        \
+    return NS_OK;                                                    \
+}
+
+#define GL_SAME_METHOD_2(glname, name, t1, t2)                       \
+NS_IMETHODIMP WebGLContext::Moz##name(t1 a1, t2 a2) {                \
+    name(a1, a2);                                                    \
+    return NS_OK;                                                    \
+}
+
+#define GL_SAME_METHOD_3(glname, name, t1, t2, t3)                   \
+NS_IMETHODIMP WebGLContext::Moz##name(t1 a1, t2 a2, t3 a3) {         \
+    name(a1, a2, a3);                                                \
+    return NS_OK;                                                    \
+}
+
+#define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4)               \
+NS_IMETHODIMP WebGLContext::Moz##name(t1 a1, t2 a2, t3 a3, t4 a4) {  \
+    name(a1, a2, a3, a4);                                            \
+    return NS_OK;                                                    \
 }
 
 //
 //  WebGL API
 //
 
 
 /* void GlActiveTexture (in GLenum texture); */
 NS_IMETHODIMP
+WebGLContext::MozActiveTexture(WebGLenum texture)
+{
+    ActiveTexture(texture);
+    return NS_OK;
+}
+
+void
 WebGLContext::ActiveTexture(WebGLenum texture)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (texture < LOCAL_GL_TEXTURE0 ||
         texture >= LOCAL_GL_TEXTURE0 + PRUint32(mGLMaxTextureUnits))
     {
         return ErrorInvalidEnum(
             "ActiveTexture: texture unit %d out of range. "
             "Accepted values range from TEXTURE0 to TEXTURE0 + %d. "
             "Notice that TEXTURE0 != 0.",
             texture, mGLMaxTextureUnits);
     }
 
     MakeContextCurrent();
     mActiveTexture = texture - LOCAL_GL_TEXTURE0;
     gl->fActiveTexture(texture);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::AttachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj)
 {
+    AttachShader(static_cast<WebGLProgram*>(pobj),
+                 static_cast<WebGLShader*>(shobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::AttachShader(WebGLProgram *program, WebGLShader *shader)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    // if pobj or shobj are null/not specified, it's an error
-    if (pobj == nsnull || shobj == nsnull)
-        return ErrorInvalidValue("attachShader");
-
-    WebGLuint progname, shadername;
-    WebGLProgram *program;
-    WebGLShader *shader;
-    if (!GetConcreteObjectAndGLName("attachShader: program", pobj, &program, &progname) ||
-        !GetConcreteObjectAndGLName("attachShader: shader", shobj, &shader, &shadername))
-        return NS_OK;
+        return;
+
+    if (!ValidateObject("attachShader: program", program) ||
+        !ValidateObject("attachShader: shader", shader))
+        return;
 
     // Per GLSL ES 2.0, we can only have one of each type of shader
     // attached.  This renders the next test somewhat moot, but we'll
     // leave it for when we support more than one shader of each type.
     if (program->HasAttachedShaderOfType(shader->ShaderType()))
         return ErrorInvalidOperation("AttachShader: only one of each type of shader may be attached to a program");
 
     if (!program->AttachShader(shader))
         return ErrorInvalidOperation("AttachShader: shader is already attached");
-
-    return NS_OK;
 }
 
 
 NS_IMETHODIMP
 WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, const nsAString& name)
 {
+    BindAttribLocation(static_cast<WebGLProgram*>(pobj), location, name);
+    return NS_OK;
+}
+
+void
+WebGLContext::BindAttribLocation(WebGLProgram *prog, WebGLuint location,
+                                 const nsAString& name)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("bindAttribLocation: program", pobj, &prog, &progname))
-        return NS_OK;
+        return;
+
+    if (!ValidateObject("bindAttribLocation: program", prog))
+        return;
+
+    WebGLuint progname = prog->GLName();
 
     if (!ValidateGLSLVariableName(name, "bindAttribLocation"))
-        return NS_OK;
+        return;
 
     if (!ValidateAttribIndex(location, "bindAttribLocation"))
-        return NS_OK;
+        return;
 
     NS_LossyConvertUTF16toASCII cname(name);
     nsCString mappedName;
     prog->MapIdentifier(cname, &mappedName);
     
     MakeContextCurrent();
     gl->fBindAttribLocation(progname, location, mappedName.get());
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindBuffer(WebGLenum target, nsIWebGLBuffer *bobj)
 {
+    BindBuffer(target, static_cast<WebGLBuffer*>(bobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::BindBuffer(WebGLenum target, WebGLBuffer *buf)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint bufname;
-    WebGLBuffer* buf;
-    bool isNull; // allow null objects
-    bool isDeleted; // allow deleted objects
-    if (!GetConcreteObjectAndGLName("bindBuffer", bobj, &buf, &bufname, &isNull, &isDeleted))
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("bindBuffer", buf))
+        return;
+
+    WebGLuint bufname = buf ? buf->GLName() : 0;
 
     // silently ignore a deleted buffer
-    if (isDeleted)
-        return NS_OK;
+    if (buf && buf->IsDeleted())
+        return;
 
     if (target != LOCAL_GL_ARRAY_BUFFER &&
         target != LOCAL_GL_ELEMENT_ARRAY_BUFFER)
     {
         return ErrorInvalidEnumInfo("bindBuffer: target", target);
     }
 
-    if (!isNull) {
+    if (buf) {
         if ((buf->Target() != LOCAL_GL_NONE) && (target != buf->Target()))
             return ErrorInvalidOperation("BindBuffer: buffer already bound to a different target");
         buf->SetTarget(target);
         buf->SetHasEverBeenBound(true);
     }
 
     // we really want to do this AFTER all the validation is done, otherwise our bookkeeping could get confused.
     // see bug 656752
@@ -237,190 +244,213 @@ WebGLContext::BindBuffer(WebGLenum targe
         mBoundArrayBuffer = buf;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         mBoundElementArrayBuffer = buf;
     }
 
     MakeContextCurrent();
 
     gl->fBindBuffer(target, bufname);
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindFramebuffer(WebGLenum target, nsIWebGLFramebuffer *fbobj)
 {
+    BindFramebuffer(target, static_cast<WebGLFramebuffer*>(fbobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::BindFramebuffer(WebGLenum target, WebGLFramebuffer *wfb)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint framebuffername;
-    bool isNull; // allow null objects
-    bool isDeleted; // allow deleted objects
-    WebGLFramebuffer *wfb;
+        return;
 
     if (target != LOCAL_GL_FRAMEBUFFER)
         return ErrorInvalidEnum("BindFramebuffer: target must be GL_FRAMEBUFFER");
 
-    if (!GetConcreteObjectAndGLName("bindFramebuffer", fbobj, &wfb, &framebuffername, &isNull, &isDeleted))
-        return NS_OK;
+    if (!ValidateObjectAllowDeletedOrNull("bindFramebuffer", wfb))
+        return;
 
     // silently ignore a deleted frame buffer
-    if (isDeleted)
-        return NS_OK;
+    if (wfb && wfb->IsDeleted())
+        return;
 
     MakeContextCurrent();
 
-    if (isNull) {
+    if (!wfb) {
         gl->fBindFramebuffer(target, gl->GetOffscreenFBO());
     } else {
+        WebGLuint framebuffername = wfb->GLName();
         gl->fBindFramebuffer(target, framebuffername);
         wfb->SetHasEverBeenBound(true);
     }
 
     mBoundFramebuffer = wfb;
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindRenderbuffer(WebGLenum target, nsIWebGLRenderbuffer *rbobj)
 {
+    BindRenderbuffer(target, static_cast<WebGLRenderbuffer*>(rbobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::BindRenderbuffer(WebGLenum target, WebGLRenderbuffer *wrb)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint renderbuffername;
-    bool isNull; // allow null objects
-    bool isDeleted; // allow deleted objects
-    WebGLRenderbuffer *wrb;
+        return;
 
     if (target != LOCAL_GL_RENDERBUFFER)
         return ErrorInvalidEnumInfo("bindRenderbuffer: target", target);
 
-    if (!GetConcreteObjectAndGLName("bindRenderBuffer", rbobj, &wrb, &renderbuffername, &isNull, &isDeleted))
-        return NS_OK;
+    if (!ValidateObjectAllowDeletedOrNull("bindRenderbuffer", wrb))
+        return;
 
     // silently ignore a deleted buffer
-    if (isDeleted)
-        return NS_OK;
-
-    if (!isNull)
+    if (wrb && wrb->IsDeleted())
+        return;
+
+    if (wrb)
         wrb->SetHasEverBeenBound(true);
 
     MakeContextCurrent();
 
+    WebGLuint renderbuffername = wrb ? wrb->GLName() : 0;
     gl->fBindRenderbuffer(target, renderbuffername);
 
     mBoundRenderbuffer = wrb;
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindTexture(WebGLenum target, nsIWebGLTexture *tobj)
 {
+    BindTexture(target, static_cast<WebGLTexture*>(tobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::BindTexture(WebGLenum target, WebGLTexture *tex)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint texturename;
-    WebGLTexture *tex;
-    bool isNull; // allow null objects
-    bool isDeleted; // allow deleted objects
-    if (!GetConcreteObjectAndGLName("bindTexture", tobj, &tex, &texturename, &isNull, &isDeleted))
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("bindTexture", tex))
+        return;
 
     // silently ignore a deleted texture
-    if (isDeleted)
-        return NS_OK;
+    if (tex && tex->IsDeleted())
+        return;
 
     if (target == LOCAL_GL_TEXTURE_2D) {
         mBound2DTextures[mActiveTexture] = tex;
     } else if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
         mBoundCubeMapTextures[mActiveTexture] = tex;
     } else {
         return ErrorInvalidEnumInfo("bindTexture: target", target);
     }
 
     MakeContextCurrent();
 
     if (tex)
         tex->Bind(target);
     else
         gl->fBindTexture(target, 0 /* == texturename */);
-
+}
+
+GL_SAME_METHOD_4(BlendColor, BlendColor, WebGLclampf, WebGLclampf, WebGLclampf, WebGLclampf)
+
+NS_IMETHODIMP WebGLContext::MozBlendEquation(WebGLenum mode)
+{
+    BlendEquation(mode);
     return NS_OK;
 }
 
-GL_SAME_METHOD_4(BlendColor, BlendColor, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
-
-NS_IMETHODIMP WebGLContext::BlendEquation(WebGLenum mode)
+void WebGLContext::BlendEquation(WebGLenum mode)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateBlendEquationEnum(mode, "blendEquation: mode"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fBlendEquation(mode);
+}
+
+NS_IMETHODIMP WebGLContext::MozBlendEquationSeparate(WebGLenum modeRGB, WebGLenum modeAlpha)
+{
+    BlendEquationSeparate(modeRGB, modeAlpha);
     return NS_OK;
 }
 
-NS_IMETHODIMP WebGLContext::BlendEquationSeparate(WebGLenum modeRGB, WebGLenum modeAlpha)
+void WebGLContext::BlendEquationSeparate(WebGLenum modeRGB, WebGLenum modeAlpha)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateBlendEquationEnum(modeRGB, "blendEquationSeparate: modeRGB") ||
         !ValidateBlendEquationEnum(modeAlpha, "blendEquationSeparate: modeAlpha"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fBlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+NS_IMETHODIMP WebGLContext::MozBlendFunc(WebGLenum sfactor, WebGLenum dfactor)
+{
+    BlendFunc(sfactor, dfactor);
     return NS_OK;
 }
 
-NS_IMETHODIMP WebGLContext::BlendFunc(WebGLenum sfactor, WebGLenum dfactor)
+void WebGLContext::BlendFunc(WebGLenum sfactor, WebGLenum dfactor)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateBlendFuncSrcEnum(sfactor, "blendFunc: sfactor") ||
         !ValidateBlendFuncDstEnum(dfactor, "blendFunc: dfactor"))
-        return NS_OK;
+        return;
 
     if (!ValidateBlendFuncEnumsCompatibility(sfactor, dfactor, "blendFuncSeparate: srcRGB and dstRGB"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fBlendFunc(sfactor, dfactor);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozBlendFuncSeparate(WebGLenum srcRGB, WebGLenum dstRGB,
+                                   WebGLenum srcAlpha, WebGLenum dstAlpha)
+{
+    BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+    return NS_OK;
+}
+
+void
 WebGLContext::BlendFuncSeparate(WebGLenum srcRGB, WebGLenum dstRGB,
                                 WebGLenum srcAlpha, WebGLenum dstAlpha)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateBlendFuncSrcEnum(srcRGB, "blendFuncSeparate: srcRGB") ||
         !ValidateBlendFuncSrcEnum(srcAlpha, "blendFuncSeparate: srcAlpha") ||
         !ValidateBlendFuncDstEnum(dstRGB, "blendFuncSeparate: dstRGB") ||
         !ValidateBlendFuncDstEnum(dstAlpha, "blendFuncSeparate: dstAlpha"))
-        return NS_OK;
+        return;
 
     // note that we only check compatibity for the RGB enums, no need to for the Alpha enums, see
     // "Section 6.8 forgetting to mention alpha factors?" thread on the public_webgl mailing list
     if (!ValidateBlendFuncEnumsCompatibility(srcRGB, dstRGB, "blendFuncSeparate: srcRGB and dstRGB"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
-    return NS_OK;
 }
 
 GLenum WebGLContext::CheckedBufferData(GLenum target,
                                        GLsizeiptr size,
                                        const GLvoid *data,
                                        GLenum usage)
 {
     WebGLBuffer *boundBuffer = NULL;
@@ -444,204 +474,207 @@ GLenum WebGLContext::CheckedBufferData(G
     }
 }
 
 NS_IMETHODIMP
 WebGLContext::BufferData(PRInt32 target, const JS::Value& data, PRInt32 usage,
                          JSContext* cx)
 {
     if (data.isNull()) {
-        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
-        return ErrorInvalidValue("bufferData: null object passed");
+        BufferData(target, static_cast<ArrayBuffer*>(nsnull), usage);
+        return NS_OK;
     }
 
     if (data.isObject()) {
         JSObject& dataObj = data.toObject();
         if (JS_IsArrayBufferObject(&dataObj, cx)) {
-            return BufferData_buf(target, &dataObj, usage, cx);
+            ArrayBuffer buf(cx, &dataObj);
+            BufferData(target, &buf, usage);
+            return NS_OK;
         }
 
         if (JS_IsTypedArrayObject(&dataObj, cx)) {
-            return BufferData_array(target, &dataObj, usage, cx);
+            ArrayBufferView view(cx, &dataObj);
+            BufferData(target, view, usage);
+            return NS_OK;
         }
 
-        return ErrorInvalidValue("bufferData: object passed that is not an "
-                                 "ArrayBufferView or ArrayBuffer");
+        ErrorInvalidValue("bufferData: object passed that is not an "
+                          "ArrayBufferView or ArrayBuffer");
+        return NS_OK;
     }
 
     MOZ_ASSERT(data.isPrimitive());
     int32_t size;
     // ToInt32 cannot fail for primitives.
     MOZ_ALWAYS_TRUE(JS_ValueToECMAInt32(cx, data, &size));
-    return BufferData_size(target, size, usage);
-}
-
-nsresult
-WebGLContext::BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage)
+    BufferData(target, WebGLsizeiptr(size), usage);
+    return NS_OK;
+}
+
+void
+WebGLContext::BufferData(WebGLenum target, WebGLsizeiptr size,
+                         WebGLenum usage)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferData: target", target);
     }
 
     if (size < 0)
         return ErrorInvalidValue("bufferData: negative size");
 
     if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
-        return NS_OK;
+        return;
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
     
     GLenum error = CheckedBufferData(target, size, 0, usage);
     if (error) {
         LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
-        return NS_OK;
+        return;
     }
 
     boundBuffer->SetByteLength(size);
     boundBuffer->InvalidateCachedMaxElements();
     if (!boundBuffer->ZeroDataIfElementArray())
         return ErrorOutOfMemory("bufferData: out of memory");
-
-    return NS_OK;
-}
-
-nsresult
-WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage, JSContext *cx)
+}
+
+void
+WebGLContext::BufferData(WebGLenum target, ArrayBuffer *data, WebGLenum usage)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    if (!JS_IsArrayBufferObject(wb, cx))
-        return ErrorInvalidOperation("BufferData: incorrect type");
+        return;
+
+    if (!data) {
+        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
+        return ErrorInvalidValue("bufferData: null object passed");
+    }
 
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferData: target", target);
     }
 
     if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
-        return NS_OK;
+        return;
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
-    GLenum error = CheckedBufferData(target,
-                                     JS_GetArrayBufferByteLength(wb, cx),
-                                     JS_GetArrayBufferData(wb, cx),
-                                     usage);
+    GLenum error = CheckedBufferData(target, data->mLength, data->mData, usage);
+
     if (error) {
         LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
-        return NS_OK;
-    }
-
-    boundBuffer->SetByteLength(JS_GetArrayBufferByteLength(wb, cx));
+        return;
+    }
+
+    boundBuffer->SetByteLength(data->mLength);
     boundBuffer->InvalidateCachedMaxElements();
-    if (!boundBuffer->CopyDataIfElementArray(JS_GetArrayBufferData(wb, cx)))
+    if (!boundBuffer->CopyDataIfElementArray(data->mData))
         return ErrorOutOfMemory("bufferData: out of memory");
-
-    return NS_OK;
-}
-
-nsresult
-WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage, JSContext *cx)
+}
+
+void
+WebGLContext::BufferData(WebGLenum target, ArrayBufferView& data, WebGLenum usage)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferData: target", target);
     }
 
     if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
-        return NS_OK;
+        return;
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
-    if (!JS_IsTypedArrayObject(wa, cx))
-        return ErrorInvalidOperation("BufferData: incorrect type");
-
-    uint32_t byteLength = JS_GetTypedArrayByteLength(wa, cx);
-    void *data = JS_GetArrayBufferViewData(wa, cx);
-    GLenum error = CheckedBufferData(target, byteLength, data, usage);
+    GLenum error = CheckedBufferData(target, data.mLength, data.mData, usage);
     if (error) {
         LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
-        return NS_OK;
-    }
-
-    boundBuffer->SetByteLength(byteLength);
+        return;
+    }
+
+    boundBuffer->SetByteLength(data.mLength);
     boundBuffer->InvalidateCachedMaxElements();
-    if (!boundBuffer->CopyDataIfElementArray(data))
+    if (!boundBuffer->CopyDataIfElementArray(data.mData))
         return ErrorOutOfMemory("bufferData: out of memory");
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BufferSubData(PRInt32 target, PRInt32 offset, const JS::Value& data, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
     if (data.isNull()) {
-        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
+        BufferSubData(target, offset, nsnull);
         return NS_OK;
     }
 
     if (!data.isObject()) {
         return NS_ERROR_FAILURE;
     }
 
     JSObject& dataObj = data.toObject();
     if (JS_IsArrayBufferObject(&dataObj, cx)) {
-        return BufferSubData_buf(target, offset, &dataObj, cx);
+        ArrayBuffer buf(cx, &dataObj);
+        BufferSubData(target, offset, &buf);
+        return NS_OK;
     }
 
     if (JS_IsTypedArrayObject(&dataObj, cx)) {
-        return BufferSubData_array(target, offset, &dataObj, cx);
+        ArrayBufferView view(cx, &dataObj);
+        BufferSubData(target, offset, view);
+        return NS_OK;
     }
 
     return NS_ERROR_FAILURE;
 }
 
-nsresult
-WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *wb, JSContext *cx)
+void
+WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
+                            ArrayBuffer *data)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    if (!JS_IsArrayBufferObject(wb, cx))
-        return ErrorInvalidOperation("BufferSubData: incorrect type");
+        return;
+
+    if (!data) {
+        // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
+        return;
+    }
 
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
@@ -649,113 +682,117 @@ WebGLContext::BufferSubData_buf(GLenum t
     }
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
-    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetArrayBufferByteLength(wb, cx);
+    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data->mLength;
     if (!checked_neededByteLength.valid())
         return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
 
     if (checked_neededByteLength.value() > boundBuffer->ByteLength())
         return ErrorInvalidOperation("BufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
-                                     byteOffset, JS_GetArrayBufferByteLength(wb, cx), boundBuffer->ByteLength());
+                                     checked_neededByteLength.value(), boundBuffer->ByteLength());
 
     MakeContextCurrent();
 
-    boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetArrayBufferByteLength(wb, cx), JS_GetArrayBufferData(wb, cx));
+    boundBuffer->CopySubDataIfElementArray(byteOffset, data->mLength, data->mData);
     boundBuffer->InvalidateCachedMaxElements();
 
-    gl->fBufferSubData(target, byteOffset, JS_GetArrayBufferByteLength(wb, cx), JS_GetArrayBufferData(wb, cx));
-
-    return NS_OK;
-}
-
-nsresult
-WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObject *wa, JSContext *cx)
+    gl->fBufferSubData(target, byteOffset, data->mLength, data->mData);
+}
+
+void
+WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
+                            ArrayBufferView& data)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    if (!JS_IsTypedArrayObject(wa, cx))
-        return ErrorInvalidOperation("BufferSubData: incorrect type");
+        return;
 
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferSubData: target", target);
     }
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
 
     if (!boundBuffer)
-        return ErrorInvalidOperation("BufferData: no buffer bound!");
-
-    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetTypedArrayByteLength(wa, cx);
+        return ErrorInvalidOperation("BufferSubData: no buffer bound!");
+
+    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.mLength;
     if (!checked_neededByteLength.valid())
         return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
 
     if (checked_neededByteLength.value() > boundBuffer->ByteLength())
         return ErrorInvalidOperation("BufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
-                                     byteOffset, JS_GetTypedArrayByteLength(wa, cx), boundBuffer->ByteLength());
+                                     checked_neededByteLength.value(), boundBuffer->ByteLength());
 
     MakeContextCurrent();
 
-    boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetTypedArrayByteLength(wa, cx), JS_GetArrayBufferViewData(wa, cx));
+    boundBuffer->CopySubDataIfElementArray(byteOffset, data.mLength, data.mData);
     boundBuffer->InvalidateCachedMaxElements();
 
-    gl->fBufferSubData(target, byteOffset, JS_GetTypedArrayByteLength(wa, cx), JS_GetArrayBufferViewData(wa, cx));
-
-    return NS_OK;
+    gl->fBufferSubData(target, byteOffset, data.mLength, data.mData);
 }
 
 NS_IMETHODIMP
 WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval)
 {
+    *retval = CheckFramebufferStatus(target);
+    return NS_OK;
+}
+
+WebGLenum
+WebGLContext::CheckFramebufferStatus(WebGLenum target)
+{
     if (!IsContextStable())
     {
-        *retval = LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
-        return NS_OK;
-    }
-
-    *retval = 0;
+        return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
+    }
 
     MakeContextCurrent();
-    if (target != LOCAL_GL_FRAMEBUFFER)
-        return ErrorInvalidEnum("checkFramebufferStatus: target must be FRAMEBUFFER");
+    if (target != LOCAL_GL_FRAMEBUFFER) {
+        ErrorInvalidEnum("checkFramebufferStatus: target must be FRAMEBUFFER");
+        return 0;
+    }
 
     if (!mBoundFramebuffer)
-        *retval = LOCAL_GL_FRAMEBUFFER_COMPLETE;
-    else if(mBoundFramebuffer->HasDepthStencilConflict())
-        *retval = LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
-    else if(!mBoundFramebuffer->ColorAttachment().IsDefined())
-        *retval = LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
-    else if(mBoundFramebuffer->HasIncompleteAttachment())
-        *retval = LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-    else if(mBoundFramebuffer->HasAttachmentsOfMismatchedDimensions())
-        *retval = LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
-    else
-        *retval = gl->fCheckFramebufferStatus(target);
-
-    return NS_OK;
+        return LOCAL_GL_FRAMEBUFFER_COMPLETE;
+    if(mBoundFramebuffer->HasDepthStencilConflict())
+        return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
+    if(!mBoundFramebuffer->ColorAttachment().IsDefined())
+        return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+    if(mBoundFramebuffer->HasIncompleteAttachment())
+        return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+    if(mBoundFramebuffer->HasAttachmentsOfMismatchedDimensions())
+        return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+    return gl->fCheckFramebufferStatus(target);
 }
 
 NS_IMETHODIMP
-WebGLContext::Clear(PRUint32 mask)
+WebGLContext::MozClear(PRUint32 mask)
+{
+    Clear(mask);
+    return NS_OK;
+}
+
+void
+WebGLContext::Clear(WebGLbitfield mask)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     PRUint32 m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
     if (mask != m)
         return ErrorInvalidValue("clear: invalid mask bits");
 
     bool needClearCallHere = true;
@@ -779,75 +816,98 @@ WebGLContext::Clear(PRUint32 mask)
         }
     }
 
     if (needClearCallHere) {
         gl->fClear(mask);
         mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
         Invalidate();
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::ClearColor(WebGLfloat r, WebGLfloat g, WebGLfloat b, WebGLfloat a)
+WebGLContext::MozClearColor(WebGLfloat r, WebGLfloat g, WebGLfloat b, WebGLfloat a)
+{
+    ClearColor(r, g, b, a);
+    return NS_OK;
+}
+
+void
+WebGLContext::ClearColor(WebGLclampf r, WebGLclampf g,
+                         WebGLclampf b, WebGLclampf a)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     mColorClearValue[0] = r;
     mColorClearValue[1] = g;
     mColorClearValue[2] = b;
     mColorClearValue[3] = a;
     gl->fClearColor(r, g, b, a);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::ClearDepth(WebGLfloat v)
+WebGLContext::MozClearDepth(WebGLfloat v)
+{
+    ClearDepth(v);
+    return NS_OK;
+}
+
+void
+WebGLContext::ClearDepth(WebGLclampf v)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     mDepthClearValue = v;
     gl->fClearDepth(v);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozClearStencil(WebGLint v)
+{
+    ClearStencil(v);
+    return NS_OK;
+}
+
+void
 WebGLContext::ClearStencil(WebGLint v)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     mStencilClearValue = v;
     gl->fClearStencil(v);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
+{
+    ColorMask(r, g, b, a);
+    return NS_OK;
+}
+
+void
 WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     mColorWriteMask[0] = r;
     mColorWriteMask[1] = g;
     mColorWriteMask[2] = b;
     mColorWriteMask[3] = a;
     gl->fColorMask(r, g, b, a);
-    return NS_OK;
-}
-
-nsresult
+}
+
+void
 WebGLContext::CopyTexSubImage2D_base(WebGLenum target,
                                      WebGLint level,
                                      WebGLenum internalformat,
                                      WebGLint xoffset,
                                      WebGLint yoffset,
                                      WebGLint x,
                                      WebGLint y,
                                      WebGLsizei width,
@@ -872,17 +932,17 @@ WebGLContext::CopyTexSubImage2D_base(Web
         // the rect doesn't fit in the framebuffer
 
         /*** first, we initialize the texture as black ***/
 
         // first, compute the size of the buffer we should allocate to initialize the texture as black
 
         PRUint32 texelSize = 0;
         if (!ValidateTexFormatAndType(internalformat, LOCAL_GL_UNSIGNED_BYTE, -1, &texelSize, info))
-            return NS_OK;
+            return;
 
         CheckedUint32 checked_neededByteLength = 
             GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
 
         if (!checked_neededByteLength.valid())
             return ErrorInvalidOperation("%s: integer overflow computing the needed buffer size", info);
 
         PRUint32 bytesNeeded = checked_neededByteLength.value();
@@ -923,32 +983,44 @@ WebGLContext::CopyTexSubImage2D_base(Web
 
         GLint   actual_y             = clamped(y, 0, framebufferHeight);
         GLint   actual_y_plus_height = clamped(y + height, 0, framebufferHeight);
         GLsizei actual_height  = actual_y_plus_height - actual_y;
         GLint   actual_yoffset = yoffset + actual_y - y;
 
         gl->fCopyTexSubImage2D(target, level, actual_xoffset, actual_yoffset, actual_x, actual_y, actual_width, actual_height);
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozCopyTexImage2D(WebGLenum target,
+                                WebGLint level,
+                                WebGLenum internalformat,
+                                WebGLint x,
+                                WebGLint y,
+                                WebGLsizei width,
+                                WebGLsizei height,
+                                WebGLint border)
+{
+    CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+    return NS_OK;
+}
+
+void
 WebGLContext::CopyTexImage2D(WebGLenum target,
                              WebGLint level,
                              WebGLenum internalformat,
                              WebGLint x,
                              WebGLint y,
                              WebGLsizei width,
                              WebGLsizei height,
                              WebGLint border)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     switch (target) {
         case LOCAL_GL_TEXTURE_2D:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
@@ -1023,38 +1095,51 @@ WebGLContext::CopyTexImage2D(WebGLenum t
 
     if (sizeMayChange) {
         UpdateWebGLErrorAndClearGLError();
         CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         if (error) {
             LogMessageIfVerbose("copyTexImage2D generated error %s", ErrorName(error));
-            return NS_OK;
+            return;
         }          
     } else {
         CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
     }
     
     tex->SetImageInfo(target, level, width, height, internalformat, type);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozCopyTexSubImage2D(WebGLenum target,
+                                   WebGLint level,
+                                   WebGLint xoffset,
+                                   WebGLint yoffset,
+                                   WebGLint x,
+                                   WebGLint y,
+                                   WebGLsizei width,
+                                   WebGLsizei height)
+{
+    CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+    return NS_OK;
+}
+
+void
 WebGLContext::CopyTexSubImage2D(WebGLenum target,
                                 WebGLint level,
                                 WebGLint xoffset,
                                 WebGLint yoffset,
                                 WebGLint x,
                                 WebGLint y,
                                 WebGLsizei width,
                                 WebGLsizei height)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     switch (target) {
         case LOCAL_GL_TEXTURE_2D:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
@@ -1112,292 +1197,345 @@ WebGLContext::CopyTexSubImage2D(WebGLenu
 
     return CopyTexSubImage2D_base(target, level, format, xoffset, yoffset, x, y, width, height, true);
 }
 
 
 NS_IMETHODIMP
 WebGLContext::CreateProgram(nsIWebGLProgram **retval)
 {
+    *retval = CreateProgram().get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLProgram>
+WebGLContext::CreateProgram()
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLProgram *prog = new WebGLProgram(this);
-    NS_ADDREF(*retval = prog);
-
-    return NS_OK;
+        return nsnull;
+    nsRefPtr<WebGLProgram> globj = new WebGLProgram(this);
+    return globj.forget();
 }
 
 NS_IMETHODIMP
 WebGLContext::CreateShader(WebGLenum type, nsIWebGLShader **retval)
 {
+    *retval = CreateShader(type).get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLShader>
+WebGLContext::CreateShader(WebGLenum type)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
+        return nsnull;
 
     if (type != LOCAL_GL_VERTEX_SHADER &&
         type != LOCAL_GL_FRAGMENT_SHADER)
     {
-        return ErrorInvalidEnumInfo("createShader: type", type);
-    }
-
-    WebGLShader *shader = new WebGLShader(this, type);
-    NS_ADDREF(*retval = shader);
-
-    return NS_OK;
+        ErrorInvalidEnumInfo("createShader: type", type);
+        return nsnull;
+    }
+
+    nsRefPtr<WebGLShader> shader = new WebGLShader(this, type);
+    return shader.forget();
 }
 
 NS_IMETHODIMP
+WebGLContext::MozCullFace(WebGLenum face)
+{
+    CullFace(face);
+    return NS_OK;
+}
+
+void
 WebGLContext::CullFace(WebGLenum face)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateFaceEnum(face, "cullFace"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fCullFace(face);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteBuffer(nsIWebGLBuffer *bobj)
 {
+    DeleteBuffer(static_cast<WebGLBuffer*>(bobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DeleteBuffer(WebGLBuffer *buf)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint bufname;
-    WebGLBuffer *buf;
-    bool isNull, isDeleted;
-    if (!GetConcreteObjectAndGLName("deleteBuffer", bobj, &buf, &bufname, &isNull, &isDeleted))
-        return NS_OK;
-
-    if (isNull || isDeleted)
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buf))
+        return;
+
+    if (!buf || buf->IsDeleted())
+        return;
 
     if (mBoundArrayBuffer == buf)
-        BindBuffer(LOCAL_GL_ARRAY_BUFFER, nsnull);
+        BindBuffer(LOCAL_GL_ARRAY_BUFFER,
+                   static_cast<WebGLBuffer*>(nsnull));
     if (mBoundElementArrayBuffer == buf)
-        BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, nsnull);
+        BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
+                   static_cast<WebGLBuffer*>(nsnull));
 
     for (int i = 0; i < mGLMaxVertexAttribs; i++) {
         if (mAttribBuffers[i].buf == buf)
             mAttribBuffers[i].buf = nsnull;
     }
 
     buf->RequestDelete();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *fbobj)
 {
+    DeleteFramebuffer(static_cast<WebGLFramebuffer*>(fbobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DeleteFramebuffer(WebGLFramebuffer* fbuf)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLFramebuffer *fbuf;
-    WebGLuint fbufname;
-    bool isNull, isDeleted;
-    if (!GetConcreteObjectAndGLName("deleteFramebuffer", fbobj, &fbuf, &fbufname, &isNull, &isDeleted))
-        return NS_OK;
-
-    if (isNull || isDeleted)
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteFramebuffer", fbuf))
+        return;
+
+    if (!fbuf || fbuf->IsDeleted())
+        return;
 
     fbuf->RequestDelete();
 
     if (mBoundFramebuffer == fbuf)
-        BindFramebuffer(LOCAL_GL_FRAMEBUFFER, nsnull);
-
-    return NS_OK;
+        BindFramebuffer(LOCAL_GL_FRAMEBUFFER,
+                        static_cast<WebGLFramebuffer*>(nsnull));
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *rbobj)
 {
+    DeleteRenderbuffer(static_cast<WebGLRenderbuffer*>(rbobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer *rbuf)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLRenderbuffer *rbuf;
-    WebGLuint rbufname;
-    bool isNull, isDeleted;
-    if (!GetConcreteObjectAndGLName("deleteRenderbuffer", rbobj, &rbuf, &rbufname, &isNull, &isDeleted))
-        return NS_OK;
-
-    if (isNull || isDeleted)
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteRenderbuffer", rbuf))
+        return;
+
+    if (!rbuf || rbuf->IsDeleted())
+        return;
 
     if (mBoundFramebuffer)
         mBoundFramebuffer->DetachRenderbuffer(rbuf);
 
     if (mBoundRenderbuffer == rbuf)
-        BindRenderbuffer(LOCAL_GL_RENDERBUFFER, nsnull);
+        BindRenderbuffer(LOCAL_GL_RENDERBUFFER,
+                         static_cast<WebGLRenderbuffer*>(nsnull));
 
     rbuf->RequestDelete();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteTexture(nsIWebGLTexture *tobj)
 {
+    DeleteTexture(static_cast<WebGLTexture*>(tobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DeleteTexture(WebGLTexture *tex)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLTexture *tex;
-    WebGLuint texname;
-    bool isNull, isDeleted;
-    if (!GetConcreteObjectAndGLName("deleteTexture", tobj, &tex, &texname, &isNull, &isDeleted))
-        return NS_OK;
-
-    if (isNull || isDeleted)
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteTexture", tex))
+        return;
+
+    if (!tex || tex->IsDeleted())
+        return;
 
     if (mBoundFramebuffer)
         mBoundFramebuffer->DetachTexture(tex);
 
     for (int i = 0; i < mGLMaxTextureUnits; i++) {
         if ((tex->Target() == LOCAL_GL_TEXTURE_2D && mBound2DTextures[i] == tex) ||
             (tex->Target() == LOCAL_GL_TEXTURE_CUBE_MAP && mBoundCubeMapTextures[i] == tex))
         {
             ActiveTexture(LOCAL_GL_TEXTURE0 + i);
-            BindTexture(tex->Target(), nsnull);
+            BindTexture(tex->Target(), static_cast<WebGLTexture*>(nsnull));
         }
     }
     ActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
 
     tex->RequestDelete();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteProgram(nsIWebGLProgram *pobj)
 {
+    DeleteProgram(static_cast<WebGLProgram*>(pobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DeleteProgram(WebGLProgram *prog)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    bool isNull, isDeleted;
-    if (!GetConcreteObjectAndGLName("deleteProgram", pobj, &prog, &progname, &isNull, &isDeleted))
-        return NS_OK;
-
-    if (isNull || isDeleted)
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteProgram", prog))
+        return;
+
+    if (!prog || prog->IsDeleted())
+        return;
 
     prog->RequestDelete();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DeleteShader(nsIWebGLShader *sobj)
 {
+    DeleteShader(static_cast<WebGLShader*>(sobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DeleteShader(WebGLShader *shader)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint shadername;
-    WebGLShader *shader;
-    bool isNull, isDeleted;
-    if (!GetConcreteObjectAndGLName("deleteShader", sobj, &shader, &shadername, &isNull, &isDeleted))
-        return NS_OK;
-
-    if (isNull || isDeleted)
-        return NS_OK;
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteShader", shader))
+        return;
+
+    if (!shader || shader->IsDeleted())
+        return;
 
     shader->RequestDelete();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::DetachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj)
 {
+    DetachShader(static_cast<WebGLProgram*>(pobj),
+                 static_cast<WebGLShader*>(shobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::DetachShader(WebGLProgram *program, WebGLShader *shader)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint progname, shadername;
-    WebGLProgram *program;
-    WebGLShader *shader;
-    bool shaderDeleted;
-    if (!GetConcreteObjectAndGLName("detachShader: program", pobj, &program, &progname) ||
-        !GetConcreteObjectAndGLName("detachShader: shader", shobj, &shader, &shadername, nsnull, &shaderDeleted))
-        return NS_OK;
-
-    // shaderDeleted is ignored -- it's valid to attempt to detach a
-    // deleted shader, since it's still a shader
+        return;
+
+    if (!ValidateObject("detachShader: program", program) ||
+        // it's valid to attempt to detach a deleted shader, since it's
+        // still a shader
+        !ValidateObjectAllowDeleted("detashShader: shader", shader))
+        return;
+
     if (!program->DetachShader(shader))
         return ErrorInvalidOperation("DetachShader: shader is not attached");
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozDepthFunc(WebGLenum func)
+{
+    DepthFunc(func);
+    return NS_OK;
+}
+
+void
 WebGLContext::DepthFunc(WebGLenum func)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateComparisonEnum(func, "depthFunc"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fDepthFunc(func);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozDepthMask(WebGLboolean b)
+{
+    DepthMask(b);
+    return NS_OK;
+}
+
+void
 WebGLContext::DepthMask(WebGLboolean b)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     mDepthWriteMask = b;
     gl->fDepthMask(b);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozDepthRange(WebGLclampf zNear, WebGLclampf zFar)
+{
+    DepthRange(zNear, zFar);
+    return NS_OK;
+}
+
+void
 WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (zNear > zFar)
         return ErrorInvalidOperation("depthRange: the near value is greater than the far value!");
 
     MakeContextCurrent();
     gl->fDepthRange(zNear, zFar);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozDisableVertexAttribArray(WebGLuint index)
+{
+    DisableVertexAttribArray(index);
+    return NS_OK;
+}
+
+void
 WebGLContext::DisableVertexAttribArray(WebGLuint index)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateAttribIndex(index, "disableVertexAttribArray"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     if (index || gl->IsGLES2())
         gl->fDisableVertexAttribArray(index);
 
     mAttribBuffers[index].enabled = false;
-
-    return NS_OK;
 }
 
 int
 WebGLContext::WhatDoesVertexAttrib0Need()
 {
   // here we may assume that mCurrentProgram != null
 
     // work around Mac OSX crash, see bug 631420
@@ -1601,42 +1739,49 @@ WebGLContext::UnbindFakeBlackTextures()
             gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName());
         }
     }
 
     gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
 }
 
 NS_IMETHODIMP
+WebGLContext::MozDrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
+{
+    DrawArrays(mode, first, count);
+    return NS_OK;
+}
+
+void
 WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateDrawModeEnum(mode, "drawArrays: mode"))
-        return NS_OK;
+        return;
 
     if (first < 0 || count < 0)
         return ErrorInvalidValue("DrawArrays: negative first or count");
 
     if (!ValidateStencilParamsForDrawCall())
-        return NS_OK;
+        return;
 
     // If count is 0, there's nothing to do.
     if (count == 0)
-        return NS_OK;
+        return;
 
     // If there is no current program, this is silently ignored.
     // Any checks below this depend on a program being available.
     if (!mCurrentProgram)
-        return NS_OK;
+        return;
 
     PRInt32 maxAllowedCount = 0;
     if (!ValidateBuffers(&maxAllowedCount, "drawArrays"))
-        return NS_OK;
+        return;
 
     CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
 
     if (!checked_firstPlusCount.valid())
         return ErrorInvalidOperation("drawArrays: overflow in first+count");
 
     if (checked_firstPlusCount.value() > maxAllowedCount)
         return ErrorInvalidOperation("drawArrays: bound vertex attribute buffers do not have sufficient size for given first and count");
@@ -1647,48 +1792,54 @@ WebGLContext::DrawArrays(GLenum mode, We
         if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
             return ErrorInvalidFramebufferOperation("drawArrays: incomplete framebuffer");
     } else {
         EnsureBackbufferClearedAsNeeded();
     }
 
     BindFakeBlackTextures();
     if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
-        return NS_OK;
+        return;
 
     SetupContextLossTimer();
     gl->fDrawArrays(mode, first, count);
 
     UndoFakeVertexAttrib0();
     UnbindFakeBlackTextures();
 
     mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
     Invalidate();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, WebGLint byteOffset)
+WebGLContext::MozDrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, WebGLintptr byteOffset)
+{
+    DrawElements(mode, count, type, byteOffset);
+    return NS_OK;
+}
+
+void
+WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
+                           WebGLintptr byteOffset)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
-        return NS_OK;
+        return;
 
     if (count < 0 || byteOffset < 0)
         return ErrorInvalidValue("DrawElements: negative count or offset");
 
     if (!ValidateStencilParamsForDrawCall())
-        return NS_OK;
+        return;
 
     // If count is 0, there's nothing to do.
     if (count == 0)
-        return NS_OK;
+        return;
 
     CheckedUint32 checked_byteCount;
 
     if (type == LOCAL_GL_UNSIGNED_SHORT) {
         checked_byteCount = 2 * CheckedUint32(count);
         if (byteOffset % 2 != 0)
             return ErrorInvalidOperation("DrawElements: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)");
     } else if (type == LOCAL_GL_UNSIGNED_BYTE) {
@@ -1698,17 +1849,17 @@ WebGLContext::DrawElements(WebGLenum mod
     }
 
     if (!checked_byteCount.valid())
         return ErrorInvalidValue("DrawElements: overflow in byteCount");
 
     // If there is no current program, this is silently ignored.
     // Any checks below this depend on a program being available.
     if (!mCurrentProgram)
-        return NS_OK;
+        return;
 
     if (!mBoundElementArrayBuffer)
         return ErrorInvalidOperation("DrawElements: must have element array buffer binding");
 
     if (!mBoundElementArrayBuffer->Data())
         return ErrorInvalidOperation("drawElements: bound element array buffer doesn't have any data");
 
     CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
@@ -1716,17 +1867,17 @@ WebGLContext::DrawElements(WebGLenum mod
     if (!checked_neededByteCount.valid())
         return ErrorInvalidOperation("DrawElements: overflow in byteOffset+byteCount");
 
     if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
         return ErrorInvalidOperation("DrawElements: bound element array buffer is too small for given count and offset");
 
     PRInt32 maxAllowedCount = 0;
     if (!ValidateBuffers(&maxAllowedCount, "drawElements"))
-      return NS_OK;
+      return;
 
     PRInt32 maxIndex
       = type == LOCAL_GL_UNSIGNED_SHORT
         ? mBoundElementArrayBuffer->FindMaxUshortElement()
         : mBoundElementArrayBuffer->FindMaxUbyteElement();
 
     CheckedInt32 checked_maxIndexPlusOne = CheckedInt32(maxIndex) + 1;
 
@@ -1758,190 +1909,240 @@ WebGLContext::DrawElements(WebGLenum mod
         if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
             return ErrorInvalidFramebufferOperation("drawElements: incomplete framebuffer");
     } else {
         EnsureBackbufferClearedAsNeeded();
     }
 
     BindFakeBlackTextures();
     if (!DoFakeVertexAttrib0(checked_maxIndexPlusOne.value()))
-        return NS_OK;
+        return;
 
     SetupContextLossTimer();
     gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
 
     UndoFakeVertexAttrib0();
     UnbindFakeBlackTextures();
 
     mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
     Invalidate();
-
+}
+
+NS_IMETHODIMP WebGLContext::MozEnable(WebGLenum cap)
+{
+    Enable(cap);
     return NS_OK;
 }
 
-NS_IMETHODIMP WebGLContext::Enable(WebGLenum cap)
+void
+WebGLContext::Enable(WebGLenum cap)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateCapabilityEnum(cap, "enable"))
-        return NS_OK;
+        return;
 
     switch(cap) {
         case LOCAL_GL_SCISSOR_TEST:
             mScissorTestEnabled = 1;
             break;
         case LOCAL_GL_DITHER:
             mDitherEnabled = 1;
             break;
     }
 
     MakeContextCurrent();
     gl->fEnable(cap);
+}
+
+NS_IMETHODIMP WebGLContext::MozDisable(WebGLenum cap)
+{
+    Disable(cap);
     return NS_OK;
 }
 
-NS_IMETHODIMP WebGLContext::Disable(WebGLenum cap)
+void
+WebGLContext::Disable(WebGLenum cap)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateCapabilityEnum(cap, "disable"))
-        return NS_OK;
+        return;
 
     switch(cap) {
         case LOCAL_GL_SCISSOR_TEST:
             mScissorTestEnabled = 0;
             break;
         case LOCAL_GL_DITHER:
             mDitherEnabled = 0;
             break;
     }
 
     MakeContextCurrent();
     gl->fDisable(cap);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozEnableVertexAttribArray(WebGLuint index)
+{
+    EnableVertexAttribArray(index);
+    return NS_OK;
+}
+
+void
 WebGLContext::EnableVertexAttribArray(WebGLuint index)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     gl->fEnableVertexAttribArray(index);
     mAttribBuffers[index].enabled = true;
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::FramebufferRenderbuffer(WebGLenum target, WebGLenum attachment, WebGLenum rbtarget, nsIWebGLRenderbuffer *rbobj)
 {
+    FramebufferRenderbuffer(target, attachment, rbtarget,
+                            static_cast<WebGLRenderbuffer*>(rbobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::FramebufferRenderbuffer(WebGLenum target, WebGLenum attachment, WebGLenum rbtarget, WebGLRenderbuffer *wrb)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!mBoundFramebuffer)
         return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
 
-    return mBoundFramebuffer->FramebufferRenderbuffer(target, attachment, rbtarget, rbobj);
+    return mBoundFramebuffer->FramebufferRenderbuffer(target, attachment, rbtarget, wrb);
 }
 
 NS_IMETHODIMP
 WebGLContext::FramebufferTexture2D(WebGLenum target,
                                    WebGLenum attachment,
                                    WebGLenum textarget,
                                    nsIWebGLTexture *tobj,
                                    WebGLint level)
 {
+    FramebufferTexture2D(target, attachment, textarget,
+                         static_cast<WebGLTexture*>(tobj), level);
+    return NS_OK;
+}
+
+void
+WebGLContext::FramebufferTexture2D(WebGLenum target,
+                                   WebGLenum attachment,
+                                   WebGLenum textarget,
+                                   WebGLTexture *tobj,
+                                   WebGLint level)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (mBoundFramebuffer)
         return mBoundFramebuffer->FramebufferTexture2D(target, attachment, textarget, tobj, level);
     else
         return ErrorInvalidOperation("framebufferTexture2D: cannot modify framebuffer 0");
 }
 
 GL_SAME_METHOD_0(Flush, Flush)
 
 GL_SAME_METHOD_0(Finish, Finish)
 
 NS_IMETHODIMP
+WebGLContext::MozFrontFace(WebGLenum mode)
+{
+    FrontFace(mode);
+    return NS_OK;
+}
+
+void
 WebGLContext::FrontFace(WebGLenum mode)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     switch (mode) {
         case LOCAL_GL_CW:
         case LOCAL_GL_CCW:
             break;
         default:
             return ErrorInvalidEnumInfo("frontFace: mode", mode);
     }
 
     MakeContextCurrent();
     gl->fFrontFace(mode);
-    return NS_OK;
 }
 
 // returns an object: { size: ..., type: ..., name: ... }
 NS_IMETHODIMP
 WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval)
 {
+    *retval = GetActiveAttrib(static_cast<WebGLProgram*>(pobj), index).get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLActiveInfo>
+WebGLContext::GetActiveAttrib(WebGLProgram *prog, PRUint32 index)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("getActiveAttrib: program", pobj, &prog, &progname))
-        return NS_OK;
+        return nsnull;
+
+    if (!ValidateObject("getActiveAttrib: program", prog))
+        return nsnull;
 
     MakeContextCurrent();
 
     GLint len = 0;
+    WebGLuint progname = prog->GLName();;
     gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &len);
     if (len == 0)
-        return NS_OK;
+        return nsnull;
 
     nsAutoArrayPtr<char> name(new char[len]);
     GLint attrsize = 0;
     GLuint attrtype = 0;
 
     gl->fGetActiveAttrib(progname, index, len, &len, &attrsize, &attrtype, name);
     if (attrsize == 0 || attrtype == 0) {
-        *retval = nsnull;
-        return NS_OK;
+        return nsnull;
     }
 
     nsCString reverseMappedName;
     prog->ReverseMapIdentifier(nsDependentCString(name), &reverseMappedName);
 
-    WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, reverseMappedName);
-    NS_ADDREF(*retval = retActiveInfo);
-
-    return NS_OK;
+    nsRefPtr<WebGLActiveInfo> retActiveInfo =
+        new WebGLActiveInfo(attrsize, attrtype, reverseMappedName);
+    return retActiveInfo.forget();
 }
 
 NS_IMETHODIMP
+WebGLContext::MozGenerateMipmap(WebGLenum target)
+{
+    GenerateMipmap(target);
+    return NS_OK;
+}
+
+void
 WebGLContext::GenerateMipmap(WebGLenum target)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateTextureTargetEnum(target, "generateMipmap"))
-        return NS_OK;
+        return;
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
 
     if (!tex)
         return ErrorInvalidOperation("generateMipmap: No texture is bound to this target.");
 
     if (!tex->HasImageInfoAt(0, 0))
         return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
@@ -1967,48 +2168,50 @@ WebGLContext::GenerateMipmap(WebGLenum t
         //
         // note that the choice of GL_NEAREST_MIPMAP_NEAREST really matters. See Chromium bug 101105.
         gl->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST_MIPMAP_NEAREST);
         gl->fGenerateMipmap(target);
         gl->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, tex->MinFilter());
     } else {
         gl->fGenerateMipmap(target);
     }
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval)
 {
+    *retval = GetActiveUniform(static_cast<WebGLProgram*>(pobj), index).get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLActiveInfo>
+WebGLContext::GetActiveUniform(WebGLProgram *prog, PRUint32 index)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("getActiveUniform: program", pobj, &prog, &progname))
-        return NS_OK;
+        return nsnull;
+
+    if (!ValidateObject("getActiveUniform: program", prog))
+        return nsnull;
 
     MakeContextCurrent();
 
     GLint len = 0;
+    WebGLuint progname = prog->GLName();
     gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &len);
     if (len == 0)
-        *retval = nsnull;
+        return nsnull;
 
     nsAutoArrayPtr<char> name(new char[len]);
 
     GLint usize = 0;
     GLuint utype = 0;
 
     gl->fGetActiveUniform(progname, index, len, &len, &usize, &utype, name);
     if (len == 0 || usize == 0 || utype == 0) {
-        *retval = nsnull;
-        return NS_OK;
+        return nsnull;
     }
 
     nsCString reverseMappedName;
     prog->ReverseMapIdentifier(nsDependentCString(name), &reverseMappedName);
 
     // OpenGL ES 2.0 specifies that if foo is a uniform array, GetActiveUniform returns its name as "foo[0]".
     // See section 2.10 page 35 in the OpenGL ES 2.0.24 specification:
     //
@@ -2020,203 +2223,225 @@ WebGLContext::GetActiveUniform(nsIWebGLP
     // returned name ends in [0], and if it doesn't, append that.
     //
     // In principle we don't need to do that on OpenGL ES, but this is such a tricky difference between the ES and non-ES
     // specs that it seems probable that some ES implementers will overlook it. Since the work-around is quite cheap,
     // we do it unconditionally.
     if (usize > 1 && reverseMappedName.CharAt(reverseMappedName.Length()-1) != ']')
         reverseMappedName.AppendLiteral("[0]");
 
-    WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(usize, utype, reverseMappedName);
-    NS_ADDREF(*retval = retActiveInfo);
-    return NS_OK;
+    nsRefPtr<WebGLActiveInfo> retActiveInfo =
+        new WebGLActiveInfo(usize, utype, reverseMappedName);
+    return retActiveInfo.forget();
 }
 
 NS_IMETHODIMP
 WebGLContext::GetAttachedShaders(nsIWebGLProgram *pobj, nsIVariant **retval)
 {
-    if (!IsContextStable())
+    Nullable< nsTArray<WebGLShader*> > arr;
+    GetAttachedShaders(static_cast<WebGLProgram*>(pobj), arr);
+    if (arr.IsNull()) {
+        *retval = nsnull;
         return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLProgram *prog;
-    bool isNull;
-    if (!GetConcreteObject("getAttachedShaders", pobj, &prog, &isNull)) 
-        return NS_OK;
+    }
 
     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
-    MakeContextCurrent();
-
-    if (isNull) {
-        wrval->SetAsEmpty();
-        // note no return, we still want to return the variant
-        ErrorInvalidValue("getAttachedShaders: invalid program");
-    } else if (prog->AttachedShaders().Length() == 0) {
+    if (arr.Value().IsEmpty()) {
         wrval->SetAsEmptyArray();
     } else {
         wrval->SetAsArray(nsIDataType::VTYPE_INTERFACE,
-                        &NS_GET_IID(nsIWebGLShader),
-                        prog->AttachedShaders().Length(),
-                        const_cast<void*>( // @#$% SetAsArray doesn't accept a const void*
-                            static_cast<const void*>(
-                                prog->AttachedShaders().Elements()
-                            )
-                        )
-                        );
-    }
-
-    *retval = wrval.forget().get();
-
+                          &NS_GET_IID(nsIWebGLShader),
+                          arr.Value().Length(),
+                          const_cast<void*>( // @#$% SetAsArray doesn't accept a const void*
+                              static_cast<const void*>(
+                                  arr.Value().Elements()
+                              )
+                          )
+                          );
+    }
+
+    wrval.forget(retval);
     return NS_OK;
 }
 
+void
+WebGLContext::GetAttachedShaders(WebGLProgram *prog,
+                                 Nullable< nsTArray<WebGLShader*> > &retval)
+{
+    retval.SetNull();
+    if (!IsContextStable())
+        return;
+
+    if (!ValidateObjectAllowNull("getAttachedShaders", prog))
+        return;
+
+    MakeContextCurrent();
+
+    if (!prog) {
+        retval.SetNull();
+        ErrorInvalidValue("getAttachedShaders: invalid program");
+    } else if (prog->AttachedShaders().Length() == 0) {
+        retval.SetValue().TruncateLength(0);
+    } else {
+        retval.SetValue().AppendElements(prog->AttachedShaders());
+    }
+}
+
 NS_IMETHODIMP
 WebGLContext::GetAttribLocation(nsIWebGLProgram *pobj,
                                 const nsAString& name,
                                 PRInt32 *retval)
 {
-    *retval = -1;
-
+    *retval = GetAttribLocation(static_cast<WebGLProgram*>(pobj), name);
+    return NS_OK;
+}
+
+WebGLint
+WebGLContext::GetAttribLocation(WebGLProgram *prog, const nsAString& name)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("getAttribLocation: program", pobj, &prog, &progname))
-        return NS_OK;
+        return -1;
+
+    if (!ValidateObject("getAttribLocation: program", prog))
+        return -1;
 
     if (!ValidateGLSLVariableName(name, "getAttribLocation"))
-        return NS_OK; 
+        return -1; 
 
     NS_LossyConvertUTF16toASCII cname(name);
     nsCString mappedName;
     prog->MapIdentifier(cname, &mappedName);
 
+    WebGLuint progname = prog->GLName();
+
     MakeContextCurrent();
-    *retval = gl->fGetAttribLocation(progname, mappedName.get());
-    return NS_OK;
+    return gl->fGetAttribLocation(progname, mappedName.get());
 }
 
 NS_IMETHODIMP
-WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
-{
-    *retval = nsnull;
-
+WebGLContext::GetParameter(PRUint32 pname, JSContext* cx, JS::Value *retval)
+{
+    nsresult rv = NS_OK;
+    JS::Value v = GetParameter(cx, pname, rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    *retval = v;
+    return NS_OK;
+}
+
+static JS::Value
+StringValue(JSContext* cx, const char* chars, nsresult& rv)
+{
+    JSString* str = JS_NewStringCopyZ(cx, chars);
+    if (!str) {
+        rv = NS_ERROR_OUT_OF_MEMORY;
+        return JS::NullValue();
+    }
+
+    return JS::StringValue(str);
+}
+
+JS::Value
+WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
+        return JS::NullValue();
 
     MakeContextCurrent();
     
     if (MinCapabilityMode()) {
-        bool override = true;
         switch(pname) {
             //
             // Single-value params
             //
                 
 // int
             case LOCAL_GL_MAX_VERTEX_ATTRIBS:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_VERTEX_ATTRIBS);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_ATTRIBS);
             
             case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
             
             case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);
             
             case LOCAL_GL_MAX_VARYING_VECTORS:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_VARYING_VECTORS);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_VARYING_VECTORS);
             
             case LOCAL_GL_MAX_TEXTURE_SIZE:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_TEXTURE_SIZE);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_SIZE);
             
             case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);
             
             case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);
             
             case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
                 
             case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
-                wrval->SetAsInt32(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);
-                break;
+                return JS::Int32Value(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);
             
             default:
-                override = false;
-        }
-        
-        if (override) {
-            *retval = wrval.forget().get();
-            return NS_OK;
+                // Return the real value; we're not overriding this one
+                break;
         }
     }
     
     switch (pname) {
         //
         // String params
         //
-
         case LOCAL_GL_VENDOR:
-            wrval->SetAsDOMString(NS_LITERAL_STRING("Mozilla"));
-            break;
+            return StringValue(cx, "Mozilla", rv);
         case LOCAL_GL_RENDERER:
-            wrval->SetAsDOMString(NS_LITERAL_STRING("Mozilla"));
-            break;
+            return StringValue(cx, "Mozilla", rv);
         case LOCAL_GL_VERSION:
-            wrval->SetAsDOMString(NS_LITERAL_STRING("WebGL 1.0"));
-            break;
+            return StringValue(cx, "WebGL 1.0", rv);
         case LOCAL_GL_SHADING_LANGUAGE_VERSION:
-            wrval->SetAsDOMString(NS_LITERAL_STRING("WebGL GLSL ES 1.0"));
-            break;
+            return StringValue(cx, "WebGL GLSL ES 1.0", rv);
 
         //
         // Single-value params
         //
 
-// int
+        // unsigned int
         case LOCAL_GL_CULL_FACE_MODE:
         case LOCAL_GL_FRONT_FACE:
         case LOCAL_GL_ACTIVE_TEXTURE:
-        case LOCAL_GL_STENCIL_CLEAR_VALUE:
         case LOCAL_GL_STENCIL_FUNC:
-        case LOCAL_GL_STENCIL_REF:
         case LOCAL_GL_STENCIL_FAIL:
         case LOCAL_GL_STENCIL_PASS_DEPTH_FAIL:
         case LOCAL_GL_STENCIL_PASS_DEPTH_PASS:
         case LOCAL_GL_STENCIL_BACK_FUNC:
-        case LOCAL_GL_STENCIL_BACK_REF:
         case LOCAL_GL_STENCIL_BACK_FAIL:
         case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL:
         case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS:
         case LOCAL_GL_DEPTH_FUNC:
         case LOCAL_GL_BLEND_SRC_RGB:
         case LOCAL_GL_BLEND_SRC_ALPHA:
         case LOCAL_GL_BLEND_DST_RGB:
         case LOCAL_GL_BLEND_DST_ALPHA:
         case LOCAL_GL_BLEND_EQUATION_RGB:
         case LOCAL_GL_BLEND_EQUATION_ALPHA:
+        case LOCAL_GL_GENERATE_MIPMAP_HINT:
+        {
+            GLint i = 0;
+            gl->fGetIntegerv(pname, &i);
+            // Unsigned 32-bit values don't fit in Int32Value
+            return JS::DoubleValue(uint32_t(i));
+        }
+        // int
+        case LOCAL_GL_STENCIL_CLEAR_VALUE:
+        case LOCAL_GL_STENCIL_REF:
+        case LOCAL_GL_STENCIL_BACK_REF:
         case LOCAL_GL_UNPACK_ALIGNMENT:
         case LOCAL_GL_PACK_ALIGNMENT:
-        case LOCAL_GL_GENERATE_MIPMAP_HINT:
         case LOCAL_GL_SUBPIXEL_BITS:
         case LOCAL_GL_MAX_TEXTURE_SIZE:
         case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
         case LOCAL_GL_SAMPLE_BUFFERS:
         case LOCAL_GL_SAMPLES:
         case LOCAL_GL_MAX_VERTEX_ATTRIBS:
         case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
@@ -2226,539 +2451,646 @@ WebGLContext::GetParameter(PRUint32 pnam
         case LOCAL_GL_GREEN_BITS:
         case LOCAL_GL_BLUE_BITS:
         case LOCAL_GL_ALPHA_BITS:
         case LOCAL_GL_DEPTH_BITS:
         case LOCAL_GL_STENCIL_BITS:
         {
             GLint i = 0;
             gl->fGetIntegerv(pname, &i);
-            wrval->SetAsInt32(i);
+            return JS::Int32Value(i);
         }
-            break;
         case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
             if (mEnabledExtensions[WebGL_OES_standard_derivatives]) {
                 GLint i = 0;
                 gl->fGetIntegerv(pname, &i);
-                wrval->SetAsInt32(i);
+                return JS::Int32Value(i);
             }
-            else
-                return ErrorInvalidEnum("getParameter: parameter", pname);
-            break;
+            else {
+                ErrorInvalidEnum("getParameter: parameter", pname);
+                return JS::NullValue();
+            }
 
         case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
-            wrval->SetAsInt32(mGLMaxVertexUniformVectors);
-            break;
+            return JS::Int32Value(mGLMaxVertexUniformVectors);
 
         case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
-            wrval->SetAsInt32(mGLMaxFragmentUniformVectors);
-            break;
+            return JS::Int32Value(mGLMaxFragmentUniformVectors);
 
         case LOCAL_GL_MAX_VARYING_VECTORS:
-            wrval->SetAsInt32(mGLMaxVaryingVectors);
-            break;
+            return JS::Int32Value(mGLMaxVaryingVectors);
 
         case LOCAL_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
-            wrval->SetAsInt32(0);
-            break;
+            return JS::Int32Value(0);
         case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS:
-            wrval->SetAsEmptyArray();
-            break;
+        {
+            JSObject* obj = Uint32Array::Create(cx, 0);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
+        }
 
 // unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
 // javascript integer values. We just return them as doubles and javascript doesn't care.
         case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
         case LOCAL_GL_STENCIL_BACK_WRITEMASK:
         case LOCAL_GL_STENCIL_VALUE_MASK:
         case LOCAL_GL_STENCIL_WRITEMASK:
         {
             GLint i = 0; // the GL api (glGetIntegerv) only does signed ints
             gl->fGetIntegerv(pname, &i);
             GLuint i_unsigned(i); // this is where -1 becomes 2^32-1
             double i_double(i_unsigned); // pass as FP value to allow large values such as 2^32-1.
-            wrval->SetAsDouble(i_double);
+            return JS::DoubleValue(i_double);
         }
-            break;
 
 // float
         case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
             if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
                 GLfloat f = 0.f;
                 gl->fGetFloatv(pname, &f);
-                wrval->SetAsFloat(f);
+                return JS::DoubleValue(f);
             } else {
-                return ErrorInvalidEnum("getParameter: parameter", pname);
+                ErrorInvalidEnum("getParameter: parameter", pname);
+                return JS::NullValue();
             }
-            break;
         case LOCAL_GL_DEPTH_CLEAR_VALUE:
         case LOCAL_GL_LINE_WIDTH:
         case LOCAL_GL_POLYGON_OFFSET_FACTOR:
         case LOCAL_GL_POLYGON_OFFSET_UNITS:
         case LOCAL_GL_SAMPLE_COVERAGE_VALUE:
         {
             GLfloat f = 0.f;
             gl->fGetFloatv(pname, &f);
-            wrval->SetAsFloat(f);
+            return JS::DoubleValue(f);
         }
-            break;
 
 // bool
         case LOCAL_GL_BLEND:
         case LOCAL_GL_DEPTH_TEST:
         case LOCAL_GL_STENCIL_TEST:
         case LOCAL_GL_CULL_FACE:
         case LOCAL_GL_DITHER:
         case LOCAL_GL_POLYGON_OFFSET_FILL:
         case LOCAL_GL_SCISSOR_TEST:
         case LOCAL_GL_SAMPLE_COVERAGE_INVERT:
         case LOCAL_GL_DEPTH_WRITEMASK:
         {
             realGLboolean b = 0;
             gl->fGetBooleanv(pname, &b);
-            wrval->SetAsBool(bool(b));
+            return JS::BooleanValue(bool(b));
         }
-            break;
 
 // bool, WebGL-specific
         case UNPACK_FLIP_Y_WEBGL:
-            wrval->SetAsBool(mPixelStoreFlipY);
-            break;
+            return JS::BooleanValue(mPixelStoreFlipY);
         case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
-            wrval->SetAsBool(mPixelStorePremultiplyAlpha);
-            break;
+            return JS::BooleanValue(mPixelStorePremultiplyAlpha);
 
 // uint, WebGL-specific
         case UNPACK_COLORSPACE_CONVERSION_WEBGL:
-            wrval->SetAsUint32(mPixelStoreColorspaceConversion);
-            break;
+            // uint doesn't fit in Int32Value
+            return JS::DoubleValue(uint32_t(mPixelStoreColorspaceConversion));
 
         //
         // Complex values
         //
         case LOCAL_GL_DEPTH_RANGE: // 2 floats
         case LOCAL_GL_ALIASED_POINT_SIZE_RANGE: // 2 floats
         case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE: // 2 floats
         {
             GLfloat fv[2] = { 0 };
             gl->fGetFloatv(pname, fv);
-            wrval->SetAsArray(nsIDataType::VTYPE_FLOAT, nsnull,
-                              2, static_cast<void*>(fv));
+            JSObject* obj = Float32Array::Create(cx, 2, fv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-            break;
         
         case LOCAL_GL_COLOR_CLEAR_VALUE: // 4 floats
         case LOCAL_GL_BLEND_COLOR: // 4 floats
         {
             GLfloat fv[4] = { 0 };
             gl->fGetFloatv(pname, fv);
-            wrval->SetAsArray(nsIDataType::VTYPE_FLOAT, nsnull,
-                              4, static_cast<void*>(fv));
+            JSObject* obj = Float32Array::Create(cx, 4, fv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-            break;
 
         case LOCAL_GL_MAX_VIEWPORT_DIMS: // 2 ints
         {
             GLint iv[2] = { 0 };
             gl->fGetIntegerv(pname, iv);
-            wrval->SetAsArray(nsIDataType::VTYPE_INT32, nsnull,
-                              2, static_cast<void*>(iv));
+            JSObject* obj = Int32Array::Create(cx, 2, iv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-            break;
 
         case LOCAL_GL_SCISSOR_BOX: // 4 ints
         case LOCAL_GL_VIEWPORT: // 4 ints
         {
             GLint iv[4] = { 0 };
             gl->fGetIntegerv(pname, iv);
-            wrval->SetAsArray(nsIDataType::VTYPE_INT32, nsnull,
-                              4, static_cast<void*>(iv));
+            JSObject* obj = Int32Array::Create(cx, 4, iv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-            break;
 
         case LOCAL_GL_COLOR_WRITEMASK: // 4 bools
         {
             realGLboolean gl_bv[4] = { 0 };
             gl->fGetBooleanv(pname, gl_bv);
-            bool pr_bv[4] = { (bool)gl_bv[0], (bool)gl_bv[1], (bool)gl_bv[2], (bool)gl_bv[3] };
-            wrval->SetAsArray(nsIDataType::VTYPE_BOOL, nsnull,
-                              4, static_cast<void*>(pr_bv));
+            JS::Value vals[4] = { JS::BooleanValue(bool(gl_bv[0])),
+                                  JS::BooleanValue(bool(gl_bv[1])),
+                                  JS::BooleanValue(bool(gl_bv[2])),
+                                  JS::BooleanValue(bool(gl_bv[3])) };
+            JSObject* obj = JS_NewArrayObject(cx, 4, vals);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-            break;
 
         case LOCAL_GL_ARRAY_BUFFER_BINDING:
-            wrval->SetAsISupports(mBoundArrayBuffer);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mBoundArrayBuffer.get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING:
-            wrval->SetAsISupports(mBoundElementArrayBuffer);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mBoundElementArrayBuffer.get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_RENDERBUFFER_BINDING:
-            wrval->SetAsISupports(mBoundRenderbuffer);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mBoundRenderbuffer.get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_FRAMEBUFFER_BINDING:
-            wrval->SetAsISupports(mBoundFramebuffer);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mBoundFramebuffer.get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_CURRENT_PROGRAM:
-            wrval->SetAsISupports(mCurrentProgram);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(), mCurrentProgram.get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_TEXTURE_BINDING_2D:
-            wrval->SetAsISupports(mBound2DTextures[mActiveTexture]);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mBound2DTextures[mActiveTexture].get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP:
-            wrval->SetAsISupports(mBoundCubeMapTextures[mActiveTexture]);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mBoundCubeMapTextures[mActiveTexture].get(),
+                                 &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         default:
-            return ErrorInvalidEnumInfo("getParameter: parameter", pname);
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("getParameter: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 NS_IMETHODIMP
-WebGLContext::GetBufferParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval)
+WebGLContext::GetBufferParameter(WebGLenum target, WebGLenum pname, JS::Value *retval)
+{
+    *retval = GetBufferParameter(target, pname);
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetBufferParameter(WebGLenum target, WebGLenum pname)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
-
-    if (target != LOCAL_GL_ARRAY_BUFFER && target != LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-        return ErrorInvalidEnumInfo("getBufferParameter: target", target);
+        return JS::NullValue();
+
+    if (target != LOCAL_GL_ARRAY_BUFFER && target != LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
+        ErrorInvalidEnumInfo("getBufferParameter: target", target);
+        return JS::NullValue();
+    }
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_BUFFER_SIZE:
         case LOCAL_GL_BUFFER_USAGE:
-        case LOCAL_GL_BUFFER_ACCESS:
-        case LOCAL_GL_BUFFER_MAPPED:
         {
             GLint i = 0;
             gl->fGetBufferParameteriv(target, pname, &i);
-            wrval->SetAsInt32(i);
+            if (pname == LOCAL_GL_BUFFER_SIZE) {
+                return JS::Int32Value(i);
+            }
+
+            MOZ_ASSERT(pname == LOCAL_GL_BUFFER_USAGE);
+            // 32-bit unsigned ints don't fit in Int32 values in JS
+            return JS::DoubleValue(uint32_t(i));
         }
             break;
 
         default:
-            return ErrorInvalidEnumInfo("getBufferParameter: parameter", pname);
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("getBufferParameter: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 NS_IMETHODIMP
-WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum attachment, WebGLenum pname, nsIVariant **retval)
+WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum attachment, WebGLenum pname, JSContext* cx, JS::Value *retval)
+{
+    nsresult rv = NS_OK;
+    JS::Value v =
+        GetFramebufferAttachmentParameter(cx, target, attachment, pname, rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    *retval = v;
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
+                                                WebGLenum target,
+                                                WebGLenum attachment,
+                                                WebGLenum pname,
+                                                nsresult& rv)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
-
-    if (target != LOCAL_GL_FRAMEBUFFER)
-        return ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: target", target);
+        return JS::NullValue();
+
+    if (target != LOCAL_GL_FRAMEBUFFER) {
+        ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: target", target);
+        return JS::NullValue();
+    }
 
     switch (attachment) {
         case LOCAL_GL_COLOR_ATTACHMENT0:
         case LOCAL_GL_DEPTH_ATTACHMENT:
         case LOCAL_GL_STENCIL_ATTACHMENT:
         case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
             break;
         default:
-            return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: attachment", attachment);
-    }
-
-    if (!mBoundFramebuffer)
-        return ErrorInvalidOperation("GetFramebufferAttachmentParameter: cannot query framebuffer 0");
+            ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: attachment", attachment);
+            return JS::NullValue();
+    }
+
+    if (!mBoundFramebuffer) {
+        ErrorInvalidOperation("GetFramebufferAttachmentParameter: cannot query framebuffer 0");
+        return JS::NullValue();
+    }
 
     MakeContextCurrent();
 
     const WebGLFramebufferAttachment& fba = mBoundFramebuffer->GetAttachment(attachment);
 
     if (fba.Renderbuffer()) {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
-                wrval->SetAsInt32(LOCAL_GL_RENDERBUFFER);
-                break;
+                return JS::DoubleValue(uint32_t(LOCAL_GL_RENDERBUFFER));
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
-                wrval->SetAsISupports(const_cast<WebGLRenderbuffer*>(fba.Renderbuffer()));
-                break;
+            {
+                JS::Value v;
+                if (!dom::WrapObject(cx, GetWrapper(),
+                                     const_cast<WebGLRenderbuffer*>(fba.Renderbuffer()),
+                                     &v)) {
+                    rv = NS_ERROR_FAILURE;
+                    return JS::NullValue();
+                }
+                return v;
+            }
 
             default:
-                return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
+                ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
+                return JS::NullValue();
         }
     } else if (fba.Texture()) {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
-                wrval->SetAsInt32(LOCAL_GL_TEXTURE);
-                break;
+                return JS::DoubleValue(uint32_t(LOCAL_GL_TEXTURE));
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
-                wrval->SetAsISupports(const_cast<WebGLTexture*>(fba.Texture()));
-                break;
+            {
+                JS::Value v;
+                if (!dom::WrapObject(cx, GetWrapper(),
+                                     const_cast<WebGLTexture*>(fba.Texture()),
+                                     &v)) {
+                    rv = NS_ERROR_FAILURE;
+                    return JS::NullValue();
+                }
+                return v;
+            }
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
-                wrval->SetAsInt32(fba.TextureLevel());
-                break;
+                return JS::Int32Value(fba.TextureLevel());
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
-                wrval->SetAsInt32(fba.TextureCubeMapFace());
-                break;
+                return JS::Int32Value(fba.TextureCubeMapFace());
 
             default:
-                return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
+                ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
+                return JS::NullValue();
         }
     } else {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
-                wrval->SetAsInt32(LOCAL_GL_NONE);
-                break;
+                return JS::DoubleValue(uint32_t(LOCAL_GL_NONE));
 
             default:
-                return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
+                ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
+                return JS::NullValue();
         }
     }
 
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+    return JS::NullValue();
 }
 
 NS_IMETHODIMP
-WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval)
+WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname, JS::Value *retval)
+{
+    *retval = GetRenderbufferParameter(target, pname);
+    return NS_OK;    
+}
+
+JS::Value
+WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
-
-    if (target != LOCAL_GL_RENDERBUFFER)
-        return ErrorInvalidEnumInfo("GetRenderbufferParameter: target", target);
+        return JS::NullValue();
+
+    if (target != LOCAL_GL_RENDERBUFFER) {
+        ErrorInvalidEnumInfo("GetRenderbufferParameter: target", target);
+        return JS::NullValue();
+    }
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_RENDERBUFFER_WIDTH:
         case LOCAL_GL_RENDERBUFFER_HEIGHT:
         case LOCAL_GL_RENDERBUFFER_RED_SIZE:
         case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
         case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
         case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
         case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
         case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
         {
             GLint i = 0;
             gl->fGetRenderbufferParameteriv(target, pname, &i);
-            wrval->SetAsInt32(i);
+            return JS::Int32Value(i);
         }
-            break;
         case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
         {
             GLint i = 0;
             gl->fGetRenderbufferParameteriv(target, pname, &i);
             if (i == LOCAL_GL_DEPTH24_STENCIL8)
             {
                 i = LOCAL_GL_DEPTH_STENCIL;
             }
-            wrval->SetAsInt32(i);
+            // unsigned 32-bit ints need to become double jsvals
+            return JS::DoubleValue(uint32_t(i));
         }
-            break;
         default:
-            return ErrorInvalidEnumInfo("GetRenderbufferParameter: parameter", pname);
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("GetRenderbufferParameter: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 NS_IMETHODIMP
 WebGLContext::CreateBuffer(nsIWebGLBuffer **retval)
 {
+    *retval = CreateBuffer().get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLBuffer>
+WebGLContext::CreateBuffer()
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLBuffer *globj = new WebGLBuffer(this);
-    NS_ADDREF(*retval = globj);
-
-    return NS_OK;
+        return nsnull;
+    nsRefPtr<WebGLBuffer> globj = new WebGLBuffer(this);
+    return globj.forget();
 }
 
 NS_IMETHODIMP
 WebGLContext::CreateTexture(nsIWebGLTexture **retval)
 {
+    *retval = CreateTexture().get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLTexture>
+WebGLContext::CreateTexture()
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    MakeContextCurrent();
-
-    WebGLTexture *globj = new WebGLTexture(this);
-    NS_ADDREF(*retval = globj);
-
-    return NS_OK;
+        return nsnull;
+    nsRefPtr<WebGLTexture> globj = new WebGLTexture(this);
+    return globj.forget();
 }
 
 NS_IMETHODIMP
-WebGLContext::GetError(WebGLenum *_retval)
+WebGLContext::MozGetError(WebGLenum *_retval)
+{
+    *_retval = GetError();
+    return NS_OK;
+}
+
+WebGLenum
+WebGLContext::GetError()
 {
     if (mContextStatus == ContextStable) {
         MakeContextCurrent();
         UpdateWebGLErrorAndClearGLError();
     } else if (!mContextLostErrorSet) {
         mWebGLError = LOCAL_GL_CONTEXT_LOST;
         mContextLostErrorSet = true;
     }
 
-    *_retval = mWebGLError;
+    WebGLenum err = mWebGLError;
     mWebGLError = LOCAL_GL_NO_ERROR;
-
-    return NS_OK;
+    return err;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetProgramParameter(nsIWebGLProgram *pobj, PRUint32 pname, nsIVariant **retval)
+WebGLContext::GetProgramParameter(nsIWebGLProgram *pobj, PRUint32 pname, JS::Value *retval)
+{
+    *retval = GetProgramParameter(static_cast<WebGLProgram*>(pobj), pname);
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetProgramParameter(WebGLProgram *prog, WebGLenum pname)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLuint progname;
-    bool isDeleted;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("getProgramParameter: program", pobj, &prog, &progname, nsnull, &isDeleted))
-        return NS_OK;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
+        return JS::NullValue();
+
+    if (!ValidateObjectAllowDeleted("getProgramParameter: program", prog))
+        return JS::NullValue();
+
+    WebGLuint progname = prog->GLName();
 
     MakeContextCurrent();
 
     switch (pname) {
-        case LOCAL_GL_CURRENT_PROGRAM:
         case LOCAL_GL_ATTACHED_SHADERS:
-        case LOCAL_GL_INFO_LOG_LENGTH:
         case LOCAL_GL_ACTIVE_UNIFORMS:
-        case LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH:
         case LOCAL_GL_ACTIVE_ATTRIBUTES:
-        case LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
         {
             GLint i = 0;
             gl->fGetProgramiv(progname, pname, &i);
-            wrval->SetAsInt32(i);
+            return JS::Int32Value(i);
         }
-            break;
         case LOCAL_GL_DELETE_STATUS:
-            wrval->SetAsBool(prog->IsDeleteRequested());
-            break;
+            return JS::BooleanValue(prog->IsDeleteRequested());
         case LOCAL_GL_LINK_STATUS:
         {
             GLint i = 0;
             gl->fGetProgramiv(progname, pname, &i);
-            wrval->SetAsBool(bool(i));
+            return JS::BooleanValue(bool(i));
         }
-            break;
         case LOCAL_GL_VALIDATE_STATUS:
         {
             GLint i = 0;
 #ifdef XP_MACOSX
             // See comment in ValidateProgram below.
             if (gl->WorkAroundDriverBugs())
                 i = 1;
             else
                 gl->fGetProgramiv(progname, pname, &i);
 #else
             gl->fGetProgramiv(progname, pname, &i);
 #endif
-            wrval->SetAsBool(bool(i));
+            return JS::BooleanValue(bool(i));
         }
             break;
 
         default:
-            return ErrorInvalidEnumInfo("GetProgramParameter: parameter", pname);
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("GetProgramParameter: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 NS_IMETHODIMP
 WebGLContext::GetProgramInfoLog(nsIWebGLProgram *pobj, nsAString& retval)
 {
+    nsresult rv = NS_OK;
+    GetProgramInfoLog(static_cast<WebGLProgram*>(pobj), retval, rv);
+    return rv;
+}
+
+void
+WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsAString& retval,
+                                nsresult& rv)
+{
     if (!IsContextStable())
     {
         retval.SetIsVoid(true);
-        return NS_OK;
-    }
-
-    WebGLuint progname;
-    if (!GetGLName<WebGLProgram>("getProgramInfoLog: program", pobj, &progname))
-        return NS_OK;
+        return;
+    }
+
+    if (!ValidateObject("getProgramInfoLog: program", prog)) {
+        retval.Truncate();
+        return;
+    }
+        
+    WebGLuint progname = prog->GLName();
 
     MakeContextCurrent();
 
     GLint k = -1;
     gl->fGetProgramiv(progname, LOCAL_GL_INFO_LOG_LENGTH, &k);
-    if (k == -1)
-        return NS_ERROR_FAILURE; // XXX GL error? shouldn't happen!
+    if (k == -1) {
+        // XXX GL error? shouldn't happen!
+        rv = NS_ERROR_FAILURE;
+        return;
+    }
 
     if (k == 0) {
         retval.Truncate();
-        return NS_OK;
+        return;
     }
 
     nsCAutoString log;
     log.SetCapacity(k);
 
     gl->fGetProgramInfoLog(progname, k, &k, (char*) log.BeginWriting());
 
     log.SetLength(k);
 
     CopyASCIItoUTF16(log, retval);
-
-    return NS_OK;
 }
 
 // here we have to support all pnames with both int and float params.
 // See this discussion:
 //  https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html
-nsresult WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
-                                         WebGLint *intParamPtr, WebGLfloat *floatParamPtr)
-{
-    NS_ENSURE_TRUE(intParamPtr || floatParamPtr, NS_ERROR_FAILURE);
+void WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname,
+                                     WebGLint *intParamPtr,
+                                     WebGLfloat *floatParamPtr)
+{
+    MOZ_ASSERT(intParamPtr || floatParamPtr);
+
+    if (!IsContextStable())
+        return;
 
     WebGLint intParam = intParamPtr ? *intParamPtr : WebGLint(*floatParamPtr);
     WebGLfloat floatParam = floatParamPtr ? *floatParamPtr : WebGLfloat(*intParamPtr);
 
     if (!ValidateTextureTargetEnum(target, "texParameter: target"))
-        return NS_OK;
+        return;
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     if (!tex)
         return ErrorInvalidOperation("texParameter: no texture is bound to this target");
 
     bool pnameAndParamAreIncompatible = false;
     bool paramValueInvalid = false;
 
@@ -2839,113 +3171,121 @@ nsresult WebGLContext::TexParameter_base
                                     pname, floatParam);
     }
 
     MakeContextCurrent();
     if (intParamPtr)
         gl->fTexParameteri(target, pname, intParam);
     else
         gl->fTexParameterf(target, pname, floatParam);
-
+}
+
+NS_IMETHODIMP
+WebGLContext::MozTexParameterf(WebGLenum target, WebGLenum pname, WebGLfloat param)
+{
+    TexParameterf(target, pname, param);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLContext::MozTexParameteri(WebGLenum target, WebGLenum pname, WebGLint param)
+{
+    TexParameteri(target, pname, param);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::TexParameterf(WebGLenum target, WebGLenum pname, WebGLfloat param)
-{
-    if (!IsContextStable())
-        return NS_OK;
-
-    return TexParameter_base(target, pname, nsnull, &param);
-}
-
-NS_IMETHODIMP
-WebGLContext::TexParameteri(WebGLenum target, WebGLenum pname, WebGLint param)
+WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, JS::Value *retval)
+{
+    *retval = GetTexParameter(target, pname);
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    return TexParameter_base(target, pname, &param, nsnull);
-}
-
-NS_IMETHODIMP
-WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval)
-{
-    *retval = nsnull;
-
-    if (!IsContextStable())
-        return NS_OK;
+        return JS::NullValue();
 
     MakeContextCurrent();
 
     if (!ValidateTextureTargetEnum(target, "getTexParameter: target"))
-        return NS_OK;
-
-    if (!activeBoundTextureForTarget(target))
-        return ErrorInvalidOperation("getTexParameter: no texture bound");
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
+        return JS::NullValue();
+
+    if (!activeBoundTextureForTarget(target)) {
+        ErrorInvalidOperation("getTexParameter: no texture bound");
+        return JS::NullValue();
+    }
 
     switch (pname) {
         case LOCAL_GL_TEXTURE_MIN_FILTER:
         case LOCAL_GL_TEXTURE_MAG_FILTER:
         case LOCAL_GL_TEXTURE_WRAP_S:
         case LOCAL_GL_TEXTURE_WRAP_T:
         {
             GLint i = 0;
             gl->fGetTexParameteriv(target, pname, &i);
-            wrval->SetAsInt32(i);
+            // Unsigned values don't fit in JS Int32 values
+            return JS::DoubleValue(uint32_t(i));
         }
-            break;
         case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
             if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
                 GLfloat f = 0.f;
                 gl->fGetTexParameterfv(target, pname, &f);
-                wrval->SetAsFloat(f);
+                return JS::DoubleValue(f);
             }
-            else
-                return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
+
+            
+            ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
             break;
 
         default:
-            return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 /* any getUniform(in WebGLProgram program, in WebGLUniformLocation location) raises(DOMException); */
 NS_IMETHODIMP
-WebGLContext::GetUniform(nsIWebGLProgram *pobj, nsIWebGLUniformLocation *ploc, nsIVariant **retval)
-{
-    *retval = nsnull;
-
+WebGLContext::GetUniform(nsIWebGLProgram *pobj, nsIWebGLUniformLocation *ploc,
+                         JSContext *cx, JS::Value *retval)
+{
+    nsresult rv = NS_OK;
+    JS::Value v = GetUniform(cx, static_cast<WebGLProgram*>(pobj),
+                             static_cast<WebGLUniformLocation*>(ploc), rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    *retval = v;
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetUniform(JSContext* cx, WebGLProgram *prog,
+                         WebGLUniformLocation *location, nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("getUniform: program", pobj, &prog, &progname))
-        return NS_OK;
-
-    WebGLUniformLocation *location;
-    if (!GetConcreteObject("getUniform: location", ploc, &location))
-        return NS_OK;
-
-    if (location->Program() != prog)
-        return ErrorInvalidValue("GetUniform: this uniform location corresponds to another program");
-
-    if (location->ProgramGeneration() != prog->Generation())
-        return ErrorInvalidOperation("GetUniform: this uniform location is obsolete since the program has been relinked");
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
+        return JS::NullValue();
+
+    if (!ValidateObject("getUniform: program", prog))
+        return JS::NullValue();
+
+    if (!ValidateObject("getUniform: location", location))
+        return JS::NullValue();
+
+    if (location->Program() != prog) {
+        ErrorInvalidValue("GetUniform: this uniform location corresponds to another program");
+        return JS::NullValue();
+    }
+
+    if (location->ProgramGeneration() != prog->Generation()) {
+        ErrorInvalidOperation("GetUniform: this uniform location is obsolete since the program has been relinked");
+        return JS::NullValue();
+    }
+
+    WebGLuint progname = prog->GLName();
 
     MakeContextCurrent();
 
     GLint uniforms = 0;
     GLint uniformNameMaxLength = 0;
     gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORMS, &uniforms);
     gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformNameMaxLength);
 
@@ -2982,198 +3322,241 @@ WebGLContext::GetUniform(nsIWebGLProgram
                     found_it = true;
                     break;
                 }
             }
             if (found_it) break;
         }
     }
 
-    if (index == uniforms)
-        return NS_ERROR_FAILURE; // XXX GL error? shouldn't happen.
+    if (index == uniforms) {
+        rv = NS_ERROR_FAILURE; // XXX GL error? shouldn't happen.
+        return JS::NullValue();
+    }
 
     GLenum baseType;
     GLint unitSize;
-    if (!BaseTypeAndSizeFromUniformType(uniformType, &baseType, &unitSize))
-        return NS_ERROR_FAILURE;
+    if (!BaseTypeAndSizeFromUniformType(uniformType, &baseType, &unitSize)) {
+        rv = NS_ERROR_FAILURE;
+        return JS::NullValue();
+    }
 
     // this should never happen
-    if (unitSize > 16)
-        return NS_ERROR_FAILURE;
+    if (unitSize > 16) {
+        rv = NS_ERROR_FAILURE;
+        return JS::NullValue();
+    }
 
     if (baseType == LOCAL_GL_FLOAT) {
         GLfloat fv[16] = { GLfloat(0) };
         gl->fGetUniformfv(progname, location->Location(), fv);
         if (unitSize == 1) {
-            wrval->SetAsFloat(fv[0]);
+            return JS::DoubleValue(fv[0]);
         } else {
-            wrval->SetAsArray(nsIDataType::VTYPE_FLOAT, nsnull,
-                              unitSize, static_cast<void*>(fv));
+            JSObject* obj = Float32Array::Create(cx, unitSize, fv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
     } else if (baseType == LOCAL_GL_INT) {
         GLint iv[16] = { 0 };
         gl->fGetUniformiv(progname, location->Location(), iv);
         if (unitSize == 1) {
-            wrval->SetAsInt32(iv[0]);
+            return JS::Int32Value(iv[0]);
         } else {
-            wrval->SetAsArray(nsIDataType::VTYPE_INT32, nsnull,
-                              unitSize, static_cast<void*>(iv));
+            JSObject* obj = Int32Array::Create(cx, unitSize, iv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
     } else if (baseType == LOCAL_GL_BOOL) {
         GLint iv[16] = { 0 };
         gl->fGetUniformiv(progname, location->Location(), iv);
         if (unitSize == 1) {
-            wrval->SetAsBool(iv[0] ? true : false);
+            return JS::BooleanValue(iv[0] ? true : false);
         } else {
-            bool uv[16] = { 0 };
+            JS::Value uv[16];
             for (int k = 0; k < unitSize; k++)
-                uv[k] = iv[k] ? true : false;
-            wrval->SetAsArray(nsIDataType::VTYPE_BOOL, nsnull,
-                              unitSize, static_cast<void*>(uv));
+                uv[k] = JS::BooleanValue(iv[k] ? true : false);
+            JSObject* obj = JS_NewArrayObject(cx, unitSize, uv);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-    } else {
-        wrval->SetAsVoid();
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+    }
+
+    // Else preserving behavior, but I'm not sure this is correct per spec
+    return JS::UndefinedValue();
 }
 
 NS_IMETHODIMP
 WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, nsIWebGLUniformLocation **retval)
 {
+    *retval = GetUniformLocation(static_cast<WebGLProgram*>(pobj), name).get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLUniformLocation>
+WebGLContext::GetUniformLocation(WebGLProgram *prog, const nsAString& name)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLuint progname;
-    WebGLProgram *prog;
-    if (!GetConcreteObjectAndGLName("getUniformLocation: program", pobj, &prog, &progname))
-        return NS_OK;
+        return nsnull;
+
+    if (!ValidateObject("getUniformLocation: program", prog))
+        return nsnull;
 
     if (!ValidateGLSLVariableName(name, "getUniformLocation"))
-        return NS_OK;
+        return nsnull;
 
     NS_LossyConvertUTF16toASCII cname(name);
     nsCString mappedName;
     prog->MapIdentifier(cname, &mappedName);
 
+    WebGLuint progname = prog->GLName();
     MakeContextCurrent();
     GLint intlocation = gl->fGetUniformLocation(progname, mappedName.get());
 
     WebGLUniformLocation *loc = nsnull;
     if (intlocation >= 0) {
         WebGLUniformInfo info = prog->GetUniformInfoForMappedIdentifier(mappedName);
         loc = new WebGLUniformLocation(this,
                                        prog,
                                        intlocation,
                                        info);
         NS_ADDREF(loc);
     }
-    *retval = loc;
-    return NS_OK;
+    return loc;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **retval)
-{
-    *retval = nsnull;
-
+WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, JSContext* cx,
+                              JS::Value *retval)
+{
+    nsresult rv = NS_OK;
+    JS::Value v = GetVertexAttrib(cx, index, pname, rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    *retval = v;
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
+                              nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return JS::NullValue();
 
     if (!ValidateAttribIndex(index, "getVertexAttrib"))
-        return NS_OK;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
+        return JS::NullValue();
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
-            wrval->SetAsISupports(mAttribBuffers[index].buf);
-            break;
+        {
+            JS::Value v;
+            if (!dom::WrapObject(cx, GetWrapper(),
+                                 mAttribBuffers[index].buf.get(), &v)) {
+                rv = NS_ERROR_FAILURE;
+                return JS::NullValue();
+            }
+            return v;
+        }
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
-            wrval->SetAsInt32(mAttribBuffers[index].stride);
-            break;
+            return JS::Int32Value(mAttribBuffers[index].stride);
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
         {
             GLint i = 0;
             gl->fGetVertexAttribiv(index, pname, &i);
-            wrval->SetAsInt32(i);
+            if (pname == LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE)
+                return JS::Int32Value(i);
+            MOZ_ASSERT(pname == LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE);
+            // Unsigned long doesn't fit in Int32Value
+            return JS::DoubleValue(uint32_t(i));
         }
-            break;
 
         case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
         {
             WebGLfloat vec[4] = {0, 0, 0, 1};
             if (index) {
                 gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, &vec[0]);
             } else {
                 vec[0] = mVertexAttrib0Vector[0];
                 vec[1] = mVertexAttrib0Vector[1];
                 vec[2] = mVertexAttrib0Vector[2];
                 vec[3] = mVertexAttrib0Vector[3];
             }
-            wrval->SetAsArray(nsIDataType::VTYPE_FLOAT, nsnull,
-                              4, vec);
+            JSObject* obj = Float32Array::Create(cx, 4, vec);
+            if (!obj) {
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            }
+            return JS::ObjectOrNullValue(obj);
         }
-            break;
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
         {
             GLint i = 0;
             gl->fGetVertexAttribiv(index, pname, &i);
-            wrval->SetAsBool(bool(i));
+            return JS::BooleanValue(bool(i));
         }
-            break;
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER:
-            wrval->SetAsUint32(mAttribBuffers[index].byteOffset);
-            break;
+            return JS::DoubleValue(uint32_t(mAttribBuffers[index].byteOffset));
 
         default:
-            return ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 /* GLuint getVertexAttribOffset (in GLuint index, in GLenum pname); */
 NS_IMETHODIMP
 WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname, WebGLuint *retval)
 {
-    *retval = 0;
+    *retval = GetVertexAttribOffset(index, pname);
+    return NS_OK;
+}
+
+WebGLsizeiptr
+WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return 0;
 
     if (!ValidateAttribIndex(index, "getVertexAttribOffset"))
-        return NS_OK;
-
-    if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER)
-        return ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
-
-    *retval = mAttribBuffers[index].byteOffset;
-    return NS_OK;
+        return 0;
+
+    if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER) {
+        ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
+        return 0;
+    }
+
+    return mAttribBuffers[index].byteOffset;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozHint(WebGLenum target, WebGLenum mode)
+{
+    Hint(target, mode);
+    return NS_OK;
+}
+
+void
 WebGLContext::Hint(WebGLenum target, WebGLenum mode)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     bool isValid = false;
 
     switch (target) {
         case LOCAL_GL_GENERATE_MIPMAP_HINT:
             isValid = true;
             break;
         case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
@@ -3181,182 +3564,199 @@ WebGLContext::Hint(WebGLenum target, Web
                 isValid = true;
             break;
     }
 
     if (!isValid)
         return ErrorInvalidEnum("hint: invalid hint");
 
     gl->fHint(target, mode);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::IsBuffer(nsIWebGLBuffer *bobj, WebGLboolean *retval)
 {
+    *retval = IsBuffer(static_cast<WebGLBuffer*>(bobj));
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsBuffer(WebGLBuffer *buffer)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    bool isDeleted;
-    WebGLuint buffername;
-    WebGLBuffer *buffer;
-    *retval = GetConcreteObjectAndGLName("isBuffer", bobj, &buffer, &buffername, nsnull, &isDeleted) && 
-              !isDeleted &&
-              buffer->HasEverBeenBound();
-    return NS_OK;
+        return false;
+
+    return ValidateObjectAllowDeleted("isBuffer", buffer) &&
+        !buffer->IsDeleted() &&
+        buffer->HasEverBeenBound();
 }
 
 NS_IMETHODIMP
 WebGLContext::IsFramebuffer(nsIWebGLFramebuffer *fbobj, WebGLboolean *retval)
 {
+    *retval = IsFramebuffer(static_cast<WebGLFramebuffer*>(fbobj));
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsFramebuffer(WebGLFramebuffer *fb)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    bool isDeleted;
-    WebGLuint fbname;
-    WebGLFramebuffer *fb;
-    *retval = GetConcreteObjectAndGLName("isFramebuffer", fbobj, &fb, &fbname, nsnull, &isDeleted) &&
-              !isDeleted &&
-              fb->HasEverBeenBound();
-    return NS_OK;
+        return false;
+
+    return ValidateObjectAllowDeleted("isFramebuffer", fb) &&
+        !fb->IsDeleted() &&
+        fb->HasEverBeenBound();
 }
 
 NS_IMETHODIMP
 WebGLContext::IsProgram(nsIWebGLProgram *pobj, WebGLboolean *retval)
 {
+    *retval = IsProgram(static_cast<WebGLProgram*>(pobj));
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsProgram(WebGLProgram *prog)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    bool isDeleted;
-    WebGLProgram *prog = nsnull;
-    *retval = GetConcreteObject("isProgram", pobj, &prog, nsnull, &isDeleted, false) &&
-              !isDeleted;
-    return NS_OK;
+        return false;
+
+    return ValidateObjectAllowDeleted("isProgram", prog) && !prog->IsDeleted();
 }
 
 NS_IMETHODIMP
 WebGLContext::IsRenderbuffer(nsIWebGLRenderbuffer *rbobj, WebGLboolean *retval)
 {
+    *retval = IsRenderbuffer(static_cast<WebGLRenderbuffer*>(rbobj));
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsRenderbuffer(WebGLRenderbuffer *rb)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    bool isDeleted;
-    WebGLuint rbname;
-    WebGLRenderbuffer *rb;
-    *retval = GetConcreteObjectAndGLName("isRenderBuffer", rbobj, &rb, &rbname, nsnull, &isDeleted) &&
-              !isDeleted &&
-              rb->HasEverBeenBound();
-    return NS_OK;
+        return false;
+
+    return ValidateObjectAllowDeleted("isRenderBuffer", rb) &&
+        !rb->IsDeleted() &&
+        rb->HasEverBeenBound();
 }
 
 NS_IMETHODIMP
 WebGLContext::IsShader(nsIWebGLShader *sobj, WebGLboolean *retval)
 {
+    *retval = IsShader(static_cast<WebGLShader*>(sobj));
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsShader(WebGLShader *shader)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    bool isDeleted;
-    WebGLShader *shader = nsnull;
-    *retval = GetConcreteObject("isShader", sobj, &shader, nsnull, &isDeleted, false) &&
-              !isDeleted;
-    return NS_OK;
+        return false;
+
+    return ValidateObjectAllowDeleted("isShader", shader) &&
+        !shader->IsDeleted();
 }
 
 NS_IMETHODIMP
 WebGLContext::IsTexture(nsIWebGLTexture *tobj, WebGLboolean *retval)
 {
+    *retval = IsTexture(static_cast<WebGLTexture*>(tobj));
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsTexture(WebGLTexture *tex)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    bool isDeleted;
-    WebGLuint texname;
-    WebGLTexture *tex;
-    *retval = GetConcreteObjectAndGLName("isTexture", tobj, &tex, &texname, nsnull, &isDeleted) &&
-              !isDeleted &&
-              tex->HasEverBeenBound();
-    return NS_OK;
+        return false;
+
+    return ValidateObjectAllowDeleted("isTexture", tex) &&
+        !tex->IsDeleted() &&
+        tex->HasEverBeenBound();
 }
 
 NS_IMETHODIMP
 WebGLContext::IsEnabled(WebGLenum cap, WebGLboolean *retval)
 {
+    *retval = IsEnabled(cap);
+    return NS_OK;
+}
+
+bool
+WebGLContext::IsEnabled(WebGLenum cap)
+{
     if (!IsContextStable())
-    {
-        *retval = false;
-        return NS_OK;
-    }
-
-    *retval = 0;
+        return false;
 
     if (!ValidateCapabilityEnum(cap, "isEnabled"))
-        return NS_OK;
+        return false;
 
     MakeContextCurrent();
-    *retval = gl->fIsEnabled(cap);
-    return NS_OK;
+    return gl->fIsEnabled(cap);
 }
 
 GL_SAME_METHOD_1(LineWidth, LineWidth, WebGLfloat)
 
 NS_IMETHODIMP
 WebGLContext::LinkProgram(nsIWebGLProgram *pobj)
 {
+    nsresult rv = NS_OK;
+    LinkProgram(static_cast<WebGLProgram*>(pobj), rv);
+    return rv;
+}
+
+void
+WebGLContext::LinkProgram(WebGLProgram *program, nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    GLuint progname;
-    WebGLProgram *program;
-    if (!GetConcreteObjectAndGLName("linkProgram", pobj, &program, &progname))
-        return NS_OK;
-
-    if (!program->NextGeneration())
-        return NS_ERROR_FAILURE;
+        return;
+
+    if (!ValidateObject("linkProgram", program))
+        return;
+    
+    GLuint progname = program->GLName();
+
+    if (!program->NextGeneration()) {
+        rv = NS_ERROR_FAILURE;
+        return;
+    }
 
     if (!program->HasBothShaderTypesAttached()) {
         program->SetLinkStatus(false);
-        return NS_OK;
+        return;
     }
 
     MakeContextCurrent();
     gl->fLinkProgram(progname);
 
     GLint ok;
     gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
     if (ok) {
         bool updateInfoSucceeded = program->UpdateInfo();
         program->SetLinkStatus(updateInfoSucceeded);
     } else {
         program->SetLinkStatus(false);
     }
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozPixelStorei(WebGLenum pname, WebGLint param)
+{
+    PixelStorei(pname, param);
+    return NS_OK;
+}
+
+void
 WebGLContext::PixelStorei(WebGLenum pname, WebGLint param)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     switch (pname) {
         case UNPACK_FLIP_Y_WEBGL:
             mPixelStoreFlipY = (param != 0);
             break;
         case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
             mPixelStorePremultiplyAlpha = (param != 0);
             break;
@@ -3378,56 +3778,64 @@ WebGLContext::PixelStorei(WebGLenum pnam
             else if (pname == LOCAL_GL_UNPACK_ALIGNMENT)
                 mPixelStoreUnpackAlignment = param;
             MakeContextCurrent();
             gl->fPixelStorei(pname, param);
             break;
         default:
             return ErrorInvalidEnumInfo("PixelStorei: parameter", pname);
     }
-
-    return NS_OK;
-}
-
+}
 
 GL_SAME_METHOD_2(PolygonOffset, PolygonOffset, WebGLfloat, WebGLfloat)
 
 NS_IMETHODIMP
 WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height,
                          WebGLenum format, WebGLenum type, const JS::Value& pixelsVal, JSContext *cx)
 {
     if (!pixelsVal.isObject()) {
         return NS_ERROR_FAILURE;
     }
 
     if (!JS_IsTypedArrayObject(&pixelsVal.toObject(), cx)) {
         return NS_ERROR_FAILURE;
     }
 
-    JSObject& pixels = pixelsVal.toObject();
-
+    ArrayBufferView pixels(cx, &pixelsVal.toObject());
+    nsresult rv = NS_OK;
+    ReadPixels(x, y, width, height, format, type, &pixels, rv);
+    return rv;
+}
+
+void
+WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width,
+                         WebGLsizei height, WebGLenum format,
+                         WebGLenum type, ArrayBufferView* pixels,
+                         nsresult& rv)
+{
     if (!IsContextStable()) {
-        return NS_OK;
+        return;
     }
 
     if (HTMLCanvasElement()->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
         LogMessageIfVerbose("ReadPixels: Not allowed");
-        return NS_ERROR_DOM_SECURITY_ERR;
+        rv = NS_ERROR_DOM_SECURITY_ERR;
+        return;
     }
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("ReadPixels: negative size passed");
 
     const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
     WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
     WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
 
-    void* data = JS_GetArrayBufferViewData(&pixels, cx);
-    PRUint32 dataByteLen = JS_GetTypedArrayByteLength(&pixels, cx);
-    int dataType = JS_GetTypedArrayType(&pixels, cx);
+    void* data = pixels->mData;
+    PRUint32 dataByteLen = JS_GetTypedArrayByteLength(pixels->mObj, NULL);
+    int dataType = JS_GetTypedArrayType(pixels->mObj, NULL);
 
     PRUint32 channels = 0;
 
     // Check the format param
     switch (format) {
         case LOCAL_GL_ALPHA:
             channels = 1;
             break;
@@ -3608,29 +4016,35 @@ WebGLContext::ReadPixels(WebGLint x, Web
                         *rowp = 0xff;
                         rowp += 4;
                     }
 
                     row += checked_alignedRowSize.value();
                 }
             } else {
                 NS_WARNING("Unhandled case, how'd we get here?");
-                return NS_ERROR_FAILURE;
+                rv = NS_ERROR_FAILURE;
+                return;
             }
         }            
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozRenderbufferStorage(WebGLenum target, WebGLenum internalformat, WebGLsizei width, WebGLsizei height)
+{
+    RenderbufferStorage(target, internalformat, width, height);
+    return NS_OK;
+}
+
+void
 WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, WebGLsizei width, WebGLsizei height)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!mBoundRenderbuffer || !mBoundRenderbuffer->GLName())
         return ErrorInvalidOperation("renderbufferStorage called on renderbuffer 0");
 
     if (target != LOCAL_GL_RENDERBUFFER)
         return ErrorInvalidEnumInfo("renderbufferStorage: target", target);
 
     if (width < 0 || height < 0)
@@ -3681,74 +4095,91 @@ WebGLContext::RenderbufferStorage(WebGLe
                        internalformat != mBoundRenderbuffer->InternalFormat();
     if (sizeChanges) {
         UpdateWebGLErrorAndClearGLError();
         gl->fRenderbufferStorage(target, internalformatForGL, width, height);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         if (error) {
             LogMessageIfVerbose("renderbufferStorage generated error %s", ErrorName(error));
-            return NS_OK;
+            return;
         }
     } else {
         gl->fRenderbufferStorage(target, internalformatForGL, width, height);
     }
 
     mBoundRenderbuffer->SetInternalFormat(internalformat);
     mBoundRenderbuffer->SetInternalFormatForGL(internalformatForGL);
     mBoundRenderbuffer->setDimensions(width, height);
     mBoundRenderbuffer->SetInitialized(false);
-
-    return NS_OK;
-}
-
-GL_SAME_METHOD_2(SampleCoverage, SampleCoverage, WebGLfloat, WebGLboolean)
+}
+
+GL_SAME_METHOD_2(SampleCoverage, SampleCoverage, WebGLclampf, WebGLboolean)
 
 NS_IMETHODIMP
+WebGLContext::MozScissor(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
+{
+    Scissor(x, y, width, height);
+    return NS_OK;
+}
+
+void
 WebGLContext::Scissor(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("Scissor: negative size");
 
     MakeContextCurrent();
     gl->fScissor(x, y, width, height);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozStencilFunc(WebGLenum func, WebGLint ref, WebGLuint mask)
+{
+    StencilFunc(func, ref, mask);
+    return NS_OK;
+}
+
+void
 WebGLContext::StencilFunc(WebGLenum func, WebGLint ref, WebGLuint mask)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateComparisonEnum(func, "stencilFunc: func"))
-        return NS_OK;
+        return;
 
     mStencilRefFront = ref;
     mStencilRefBack = ref;
     mStencilValueMaskFront = mask;
     mStencilValueMaskBack = mask;
 
     MakeContextCurrent();
     gl->fStencilFunc(func, ref, mask);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozStencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref, WebGLuint mask)
+{
+    StencilFuncSeparate(face, func, ref, mask);
+    return NS_OK;
+}
+
+void
 WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref, WebGLuint mask)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateFaceEnum(face, "stencilFuncSeparate: face") ||
         !ValidateComparisonEnum(func, "stencilFuncSeparate: func"))
-        return NS_OK;
+        return;
 
     switch (face) {
         case LOCAL_GL_FRONT_AND_BACK:
             mStencilRefFront = ref;
             mStencilRefBack = ref;
             mStencilValueMaskFront = mask;
             mStencilValueMaskBack = mask;
             break;
@@ -3759,91 +4190,114 @@ WebGLContext::StencilFuncSeparate(WebGLe
         case LOCAL_GL_BACK:
             mStencilRefBack = ref;
             mStencilValueMaskBack = mask;
             break;
     }
 
     MakeContextCurrent();
     gl->fStencilFuncSeparate(face, func, ref, mask);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozStencilMask(WebGLuint mask)
+{
+    StencilMask(mask);
+    return NS_OK;
+}
+
+void
 WebGLContext::StencilMask(WebGLuint mask)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     mStencilWriteMaskFront = mask;
     mStencilWriteMaskBack = mask;
 
     MakeContextCurrent();
     gl->fStencilMask(mask);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozStencilMaskSeparate(WebGLenum face, WebGLuint mask)
+{
+    StencilMaskSeparate(face, mask);
+    return NS_OK;
+}
+
+void
 WebGLContext::StencilMaskSeparate(WebGLenum face, WebGLuint mask)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateFaceEnum(face, "stencilMaskSeparate: face"))
-        return NS_OK;
+        return;
 
     switch (face) {
         case LOCAL_GL_FRONT_AND_BACK:
             mStencilWriteMaskFront = mask;
             mStencilWriteMaskBack = mask;
             break;
         case LOCAL_GL_FRONT:
             mStencilWriteMaskFront = mask;
             break;
         case LOCAL_GL_BACK:
             mStencilWriteMaskBack = mask;
             break;
     }
 
     MakeContextCurrent();
     gl->fStencilMaskSeparate(face, mask);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozStencilOp(WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass)
+{
+    StencilOp(sfail, dpfail, dppass);
+    return NS_OK;
+}
+
+void
 WebGLContext::StencilOp(WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateStencilOpEnum(sfail, "stencilOp: sfail") ||
         !ValidateStencilOpEnum(dpfail, "stencilOp: dpfail") ||
         !ValidateStencilOpEnum(dppass, "stencilOp: dppass"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fStencilOp(sfail, dpfail, dppass);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozStencilOpSeparate(WebGLenum face, WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass)
+{
+    StencilOpSeparate(face, sfail, dpfail, dppass);
+    return NS_OK;
+}
+
+void
 WebGLContext::StencilOpSeparate(WebGLenum face, WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!ValidateFaceEnum(face, "stencilOpSeparate: face") ||
         !ValidateStencilOpEnum(sfail, "stencilOpSeparate: sfail") ||
         !ValidateStencilOpEnum(dpfail, "stencilOpSeparate: dpfail") ||
         !ValidateStencilOpEnum(dppass, "stencilOpSeparate: dppass"))
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
     gl->fStencilOpSeparate(face, sfail, dpfail, dppass);
-    return NS_OK;
 }
 
 struct WebGLImageConverter
 {
     bool flip;
     size_t width, height, srcStride, dstStride, srcTexelSize, dstTexelSize;
     const PRUint8 *src;
     PRUint8 *dst;
@@ -4144,22 +4598,20 @@ GetTypedArray(JSContext* aCx, const JS::
 
 static JSObject*
 GetFloat32Array(JSContext* aCx, const JS::Value& aValue)
 {
     return GetTypedArray<JS_IsFloat32Array, JS_NewFloat32ArrayFromArray>(aCx, aValue);
 }
 
 #define OBTAIN_UNIFORM_LOCATION(info)                                   \
-    WebGLUniformLocation *location_object;                              \
-    bool isNull;                                                      \
-    if (!GetConcreteObject(info, ploc, &location_object, &isNull))      \
-        return NS_OK;                                                   \
-    if (isNull)                                                         \
-        return NS_OK;                                                   \
+    if (!ValidateObjectAllowNull(info, location_object))                \
+        return;                                                         \
+    if (!location_object)                                               \
+        return;                                                         \
     /* the need to check specifically for !mCurrentProgram here is explained in bug 657556 */ \
     if (!mCurrentProgram) \
         return ErrorInvalidOperation("%s: no program is currently bound", info); \
     if (mCurrentProgram != location_object->Program()) \
         return ErrorInvalidOperation("%s: this uniform location doesn't correspond to the current program", info); \
     if (mCurrentProgram->Generation() != location_object->ProgramGeneration())            \
         return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \
     GLint location = location_object->Location();
@@ -4168,32 +4620,36 @@ GetFloat32Array(JSContext* aCx, const JS
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue, \
                    JSContext* aCx)                                              \
 {                                                                               \
     JSObject* wa = GetTypedArray<JS_Is ## arrayType ## Array, JS_New ## arrayType ## ArrayFromArray>(aCx, aValue); \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
-                                                                                \
+    arrayType ## Array arr(aCx, wa);                                            \
+    name(static_cast<WebGLUniformLocation*>(aLocation), arr);                   \
+    return NS_OK;                                                               \
+}                                                                               \
+void                                                                            \
+WebGLContext::name##_base(WebGLUniformLocation *location_object,                \
+                        uint32_t arrayLength, ptrType* data) {                  \
     if (!IsContextStable()) {                                                   \
-        return NS_OK;                                                           \
+        return;                                                                 \
     }                                                                           \
                                                                                 \
-    nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
     int elementSize = location_object->ElementSize();                           \
     if (cnt != elementSize) {                                                   \
         return ErrorInvalidOperation(                                           \
             #name ": this function expected a uniform of element size %d,"      \
             " got a uniform of element size %d",                                \
             cnt,                                                                \
             elementSize);                                                       \
     }                                                                           \
-    PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx);                     \
     const WebGLUniformInfo& info = location_object->Info();                     \
     PRUint32 expectedArrayLength = cnt * info.arraySize;                        \
     if (arrayLength < expectedArrayLength ||                                    \
         (arrayLength % cnt))                                                    \
     {                                                                           \
         return ErrorInvalidValue("%s: expected an array of length a multiple of" \
                                  " %d and at least %d, got an array of length %d", \
                                  #name,                                         \
@@ -4207,49 +4663,50 @@ WebGLContext::name(nsIWebGLUniformLocati
                                      " (since this uniform is not an array uniform)," \
                                      " got an array of length %d", \
                                  #name,                                         \
                                  expectedArrayLength,                           \
                                  arrayLength);                                  \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    gl->f##name(location, info.arraySize,                                       \
-                static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx)));     \
-    return NS_OK;                                                               \
+    gl->f##name(location, info.arraySize, data);                                \
 }
 
 #define SIMPLE_MATRIX_METHOD_UNIFORM(name, dim)                                 \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,         \
                    const JS::Value& aValue, JSContext* aCx)                     \
 {                                                                               \
     JSObject* wa = GetFloat32Array(aCx, aValue);                                \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
-                                                                                \
+    Float32Array arr(aCx, wa);                                                  \
+    name(static_cast<WebGLUniformLocation*>(aLocation), aTranspose, arr);       \
+    return NS_OK;                                                               \
+}                                                                               \
+void                                                                            \
+WebGLContext::name##_base(WebGLUniformLocation* location_object,                \
+                          WebGLboolean aTranspose, uint32_t arrayLength,        \
+                          float* data)                                          \
+{                                                                               \
     if (!IsContextStable()) {                                                   \
-        return NS_OK;                                                           \
+        return;                                                                 \
     }                                                                           \
                                                                                 \
-    nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
-    if (!wa || !JS_IsFloat32Array(wa, aCx)) {                                   \
-        return ErrorInvalidValue(#name ": array must be of Float32 type");      \
-    }                                                                           \
     int elementSize = location_object->ElementSize();                           \
     if (dim*dim != elementSize) {                                               \
         return ErrorInvalidOperation(                                           \
             #name ": this function expected a uniform of element size %d,"      \
             " got a uniform of element size %d",                                \
             dim*dim,                                                            \
             elementSize);                                                       \
     }                                                                           \
-    PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx);                     \
     const WebGLUniformInfo& info = location_object->Info();                     \
     PRUint32 expectedArrayLength = dim * dim * info.arraySize;                  \
     if (arrayLength < expectedArrayLength ||                                    \
         (arrayLength % (dim*dim)))                                              \
     {                                                                           \
         return ErrorInvalidValue("%s: expected an array of length a multiple of" \
                                  " %d and at least %d, got an array of length %d", \
                                  #name,                                         \
@@ -4267,51 +4724,65 @@ WebGLContext::name(nsIWebGLUniformLocati
                                  arrayLength);                                  \
     }                                                                           \
     if (aTranspose) {                                                           \
         return ErrorInvalidValue(#name ": transpose must be FALSE as per the "  \
                                  "OpenGL ES 2.0 spec");                         \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    gl->f##name(location, info.arraySize, false,                  \
-                static_cast<WebGLfloat*>(JS_GetArrayBufferViewData(wa, aCx)));  \
-    return NS_OK;                                                               \
+    gl->f##name(location, info.arraySize, false,  data);                        \
 }
 
 #define SIMPLE_METHOD_UNIFORM_1(glname, name, t1)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) {      \
-    if (!IsContextStable())                                    \
-        return NS_OK;                                    \
-    OBTAIN_UNIFORM_LOCATION(#name ": location") \
-    MakeContextCurrent(); gl->f##glname(location, a1); return NS_OK; \
+    name(static_cast<WebGLUniformLocation*>(ploc), a1);                 \
+    return NS_OK;                                                       \
+}                                                                       \
+void WebGLContext::name(WebGLUniformLocation *location_object, t1 a1) { \
+    if (!IsContextStable())                                             \
+        return;                                                         \
+    OBTAIN_UNIFORM_LOCATION(#name ": location")                         \
+    MakeContextCurrent(); gl->f##glname(location, a1);                  \
 }
 
 #define SIMPLE_METHOD_UNIFORM_2(glname, name, t1, t2)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2) {      \
-    if (!IsContextStable())                                        \
-        return NS_OK;                                        \
-    OBTAIN_UNIFORM_LOCATION(#name ": location") \
-    MakeContextCurrent(); gl->f##glname(location, a1, a2); return NS_OK; \
+    name(static_cast<WebGLUniformLocation*>(ploc), a1, a2);             \
+    return NS_OK;                                                       \
+}                                                                       \
+void WebGLContext::name(WebGLUniformLocation *location_object, t1 a1, t2 a2) {\
+    if (!IsContextStable())                                             \
+        return;                                                         \
+    OBTAIN_UNIFORM_LOCATION(#name ": location")                         \
+    MakeContextCurrent(); gl->f##glname(location, a1, a2);              \
 }
 
 #define SIMPLE_METHOD_UNIFORM_3(glname, name, t1, t2, t3)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2, t3 a3) {      \
-    if (!IsContextStable())                                            \
-        return NS_OK;                                            \
-    OBTAIN_UNIFORM_LOCATION(#name ": location") \
-    MakeContextCurrent(); gl->f##glname(location, a1, a2, a3); return NS_OK; \
+    name(static_cast<WebGLUniformLocation*>(ploc), a1, a2, a3);         \
+    return NS_OK;                                                       \
+}                                                                       \
+void WebGLContext::name(WebGLUniformLocation *location_object, t1 a1, t2 a2, t3 a3) {\
+    if (!IsContextStable())                                             \
+        return;                                                         \
+    OBTAIN_UNIFORM_LOCATION(#name ": location")                         \
+    MakeContextCurrent(); gl->f##glname(location, a1, a2, a3);          \
 }
 
 #define SIMPLE_METHOD_UNIFORM_4(glname, name, t1, t2, t3, t4)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2, t3 a3, t4 a4) {      \
-    if (!IsContextStable())                                                \
-        return NS_OK;                                                \
-    OBTAIN_UNIFORM_LOCATION(#name ": location") \
-    MakeContextCurrent(); gl->f##glname(location, a1, a2, a3, a4); return NS_OK; \
+    name(static_cast<WebGLUniformLocation*>(ploc), a1, a2, a3, a4);     \
+    return NS_OK;                                                       \
+}                                                                       \
+void WebGLContext::name(WebGLUniformLocation *location_object, t1 a1, t2 a2, t3 a3, t4 a4) {\
+    if (!IsContextStable())                                             \
+        return;                                                         \
+    OBTAIN_UNIFORM_LOCATION(#name ": location")                         \
+    MakeContextCurrent(); gl->f##glname(location, a1, a2, a3, a4);      \
 }
 
 SIMPLE_METHOD_UNIFORM_1(Uniform1i, Uniform1i, WebGLint)
 SIMPLE_METHOD_UNIFORM_2(Uniform2i, Uniform2i, WebGLint, WebGLint)
 SIMPLE_METHOD_UNIFORM_3(Uniform3i, Uniform3i, WebGLint, WebGLint, WebGLint)
 SIMPLE_METHOD_UNIFORM_4(Uniform4i, Uniform4i, WebGLint, WebGLint, WebGLint, WebGLint)
 
 SIMPLE_METHOD_UNIFORM_1(Uniform1f, Uniform1f, WebGLfloat)
@@ -4329,242 +4800,293 @@ SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2fv, 
 SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3fv, 3, Float32, WebGLfloat)
 SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4fv, 4, Float32, WebGLfloat)
 
 SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix2fv, 2)
 SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix3fv, 3)
 SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix4fv, 4)
 
 NS_IMETHODIMP
-WebGLContext::VertexAttrib1f(PRUint32 index, WebGLfloat x0)
+WebGLContext::MozVertexAttrib1f(PRUint32 index, WebGLfloat x0)
+{
+    VertexAttrib1f(index, x0);
+    return NS_OK;
+}
+
+void
+WebGLContext::VertexAttrib1f(WebGLuint index, WebGLfloat x0)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     if (index) {
         gl->fVertexAttrib1f(index, x0);
     } else {
         mVertexAttrib0Vector[0] = x0;
         mVertexAttrib0Vector[1] = 0;
         mVertexAttrib0Vector[2] = 0;
         mVertexAttrib0Vector[3] = 1;
         if (gl->IsGLES2())
             gl->fVertexAttrib1f(index, x0);
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::VertexAttrib2f(PRUint32 index, WebGLfloat x0, WebGLfloat x1)
+WebGLContext::MozVertexAttrib2f(PRUint32 index, WebGLfloat x0, WebGLfloat x1)
+{
+    VertexAttrib2f(index, x0, x1);
+    return NS_OK;
+}
+
+void
+WebGLContext::VertexAttrib2f(WebGLuint index, WebGLfloat x0, WebGLfloat x1)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     if (index) {
         gl->fVertexAttrib2f(index, x0, x1);
     } else {
         mVertexAttrib0Vector[0] = x0;
         mVertexAttrib0Vector[1] = x1;
         mVertexAttrib0Vector[2] = 0;
         mVertexAttrib0Vector[3] = 1;
         if (gl->IsGLES2())
             gl->fVertexAttrib2f(index, x0, x1);
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::VertexAttrib3f(PRUint32 index, WebGLfloat x0, WebGLfloat x1, WebGLfloat x2)
+WebGLContext::MozVertexAttrib3f(PRUint32 index, WebGLfloat x0, WebGLfloat x1, WebGLfloat x2)
+{
+    VertexAttrib3f(index, x0, x1, x2);
+    return NS_OK;
+}
+
+void
+WebGLContext::VertexAttrib3f(WebGLuint index, WebGLfloat x0, WebGLfloat x1, WebGLfloat x2)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     if (index) {
         gl->fVertexAttrib3f(index, x0, x1, x2);
     } else {
         mVertexAttrib0Vector[0] = x0;
         mVertexAttrib0Vector[1] = x1;
         mVertexAttrib0Vector[2] = x2;
         mVertexAttrib0Vector[3] = 1;
         if (gl->IsGLES2())
             gl->fVertexAttrib3f(index, x0, x1, x2);
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::VertexAttrib4f(PRUint32 index, WebGLfloat x0, WebGLfloat x1,
-                                             WebGLfloat x2, WebGLfloat x3)
+WebGLContext::MozVertexAttrib4f(PRUint32 index, WebGLfloat x0, WebGLfloat x1,
+                                                WebGLfloat x2, WebGLfloat x3)
+{
+    VertexAttrib4f(index, x0, x1, x2, x3);
+    return NS_OK;
+}
+
+void
+WebGLContext::VertexAttrib4f(WebGLuint index, WebGLfloat x0, WebGLfloat x1,
+                                              WebGLfloat x2, WebGLfloat x3)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     MakeContextCurrent();
 
     if (index) {
         gl->fVertexAttrib4f(index, x0, x1, x2, x3);
     } else {
         mVertexAttrib0Vector[0] = x0;
         mVertexAttrib0Vector[1] = x1;
         mVertexAttrib0Vector[2] = x2;
         mVertexAttrib0Vector[3] = x3;
         if (gl->IsGLES2())
             gl->fVertexAttrib4f(index, x0, x1, x2, x3);
     }
-
-    return NS_OK;
 }
 
 #define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, ptrType)                        \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(WebGLuint idx, const JS::Value& aValue, JSContext* aCx)      \
 {                                                                               \
     JSObject* wa = GetFloat32Array(aCx, aValue);                                \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
-                                                                                \
+    Float32Array arr(aCx, wa);                                                  \
+    name(idx, arr);                                                             \
+    return NS_OK;                                                               \
+}                                                                               \
+void                                                                            \
+WebGLContext::name##_base(WebGLuint idx, uint32_t arrayLength,                  \
+                          WebGLfloat* ptr)                                      \
+{                                                                               \
     if (!IsContextStable()) {                                                   \
-        return NS_OK;                                                           \
+        return;                                                                 \
     }                                                                           \
-    if (JS_GetTypedArrayLength(wa, aCx) < cnt) {                                \
+    if (arrayLength < cnt) {                                                    \
         return ErrorInvalidOperation(#name ": array must be >= %d elements",    \
                                      cnt);                                      \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    ptrType *ptr = static_cast<ptrType*>(JS_GetFloat32ArrayData(wa, aCx));      \
     if (idx) {                                                                  \
         gl->f##name(idx, ptr);                                                  \
     } else {                                                                    \
         mVertexAttrib0Vector[0] = ptr[0];                                       \
         mVertexAttrib0Vector[1] = cnt > 1 ? ptr[1] : ptrType(0);                \
         mVertexAttrib0Vector[2] = cnt > 2 ? ptr[2] : ptrType(0);                \
         mVertexAttrib0Vector[3] = cnt > 3 ? ptr[3] : ptrType(1);                \
         if (gl->IsGLES2())                                                      \
             gl->f##name(idx, ptr);                                              \
     }                                                                           \
-    return NS_OK;                                                               \
 }
 
 SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, WebGLfloat)
 SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, WebGLfloat)
 SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, WebGLfloat)
 SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, WebGLfloat)
 
 NS_IMETHODIMP
 WebGLContext::UseProgram(nsIWebGLProgram *pobj)
 {
+    UseProgram(static_cast<WebGLProgram*>(pobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::UseProgram(WebGLProgram *prog)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLProgram *prog;
-    WebGLuint progname;
-    bool isNull;
-    if (!GetConcreteObjectAndGLName("useProgram", pobj, &prog, &progname, &isNull))
-        return NS_OK;
-
+        return;
+
+    if (!ValidateObjectAllowNull("useProgram", prog))
+        return;
+
+    WebGLuint progname = prog ? prog->GLName() : 0;;
     MakeContextCurrent();
 
     if (prog && !prog->LinkStatus())
         return ErrorInvalidOperation("UseProgram: program was not linked successfully");
 
     gl->fUseProgram(progname);
 
     mCurrentProgram = prog;
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::ValidateProgram(nsIWebGLProgram *pobj)
 {
+    ValidateProgram(static_cast<WebGLProgram*>(pobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::ValidateProgram(WebGLProgram *prog)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLuint progname;
-    if (!GetGLName<WebGLProgram>("validateProgram", pobj, &progname))
-        return NS_OK;
+        return;
+
+    if (!ValidateObject("validateProgram", prog))
+        return;
 
     MakeContextCurrent();
 
 #ifdef XP_MACOSX
     // see bug 593867 for NVIDIA and bug 657201 for ATI. The latter is confirmed with Mac OS 10.6.7
     if (gl->WorkAroundDriverBugs()) {
         LogMessageIfVerbose("validateProgram: implemented as a no-operation on Mac to work around crashes");
-        return NS_OK;
+        return;
     }
 #endif
 
+    WebGLuint progname = prog->GLName();
     gl->fValidateProgram(progname);
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CreateFramebuffer(nsIWebGLFramebuffer **retval)
 {
+    *retval = CreateFramebuffer().get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLFramebuffer>
+WebGLContext::CreateFramebuffer()
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = 0;
-
-    WebGLFramebuffer *globj = new WebGLFramebuffer(this);
-    NS_ADDREF(*retval = globj);
-
-    return NS_OK;
+        return nsnull;
+    nsRefPtr<WebGLFramebuffer> globj = new WebGLFramebuffer(this);
+    return globj.forget();
 }
 
 NS_IMETHODIMP
 WebGLContext::CreateRenderbuffer(nsIWebGLRenderbuffer **retval)
 {
+    *retval = CreateRenderbuffer().get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLRenderbuffer>
+WebGLContext::CreateRenderbuffer()
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = 0;
-
-    WebGLRenderbuffer *globj = new WebGLRenderbuffer(this);
-    NS_ADDREF(*retval = globj);
-
-    return NS_OK;
+        return nsnull;
+    nsRefPtr<WebGLRenderbuffer> globj = new WebGLRenderbuffer(this);
+    return globj.forget();
 }
 
 NS_IMETHODIMP
+WebGLContext::MozViewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
+{
+    Viewport(x, y, width, height);
+    return NS_OK;
+}
+
+void
 WebGLContext::Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
 {
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("Viewport: negative size");
 
     MakeContextCurrent();
     gl->fViewport(x, y, width, height);
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CompileShader(nsIWebGLShader *sobj)
 {
+    CompileShader(static_cast<WebGLShader*>(sobj));
+    return NS_OK;
+}
+
+void
+WebGLContext::CompileShader(WebGLShader *shader)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLShader *shader;
-    WebGLuint shadername;
-    if (!GetConcreteObjectAndGLName("compileShader", sobj, &shader, &shadername))
-        return NS_OK;
+        return;
+
+    if (!ValidateObject("compileShader", shader))
+        return;
+
+    WebGLuint shadername = shader->GLName();
 
     MakeContextCurrent();
 
     ShShaderOutput targetShaderSourceLanguage = gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
     bool useShaderSourceTranslation = true;
 
 #if defined(USE_ANGLE)
     if (shader->NeedsTranslation() && mShaderValidation) {
@@ -4584,17 +5106,17 @@ WebGLContext::CompileShader(nsIWebGLShad
             resources.OES_standard_derivatives = 1;
 
         // We're storing an actual instance of StripComments because, if we don't, the 
         // cleanSource nsAString instance will be destroyed before the reference is
         // actually used.
         StripComments stripComments(shader->Source());
         const nsAString& cleanSource = nsString(stripComments.result().Elements(), stripComments.length());
         if (!ValidateGLSLString(cleanSource, "compileShader"))
-            return NS_OK;
+            return;
 
         const nsPromiseFlatString& flatSource = PromiseFlatString(cleanSource);
 
         // shaderSource() already checks that the source stripped of comments is in the
         // 7-bit ASCII range, so we can skip the NS_IsAscii() check.
         const nsCString& sourceCString = NS_LossyConvertUTF16toASCII(flatSource);
 
         if (gl->WorkAroundDriverBugs()) {
@@ -4634,17 +5156,17 @@ WebGLContext::CompileShader(nsIWebGLShad
                 nsCAutoString info;
                 info.SetLength(len);
                 ShGetInfoLog(compiler, info.BeginWriting());
                 shader->SetTranslationFailure(info);
             } else {
                 shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
             }
             ShDestruct(compiler);
-            return NS_OK;
+            return;
         }
 
         int num_attributes = 0;
         ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
         int num_uniforms = 0;
         ShGetInfo(compiler, SH_ACTIVE_UNIFORMS, &num_uniforms);
         int attrib_max_length = 0;
         ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_max_length);
@@ -4720,31 +5242,39 @@ WebGLContext::CompileShader(nsIWebGLShad
 
         shader->SetTranslationSuccess();
 
         ShDestruct(compiler);
 
         gl->fCompileShader(shadername);
     }
 #endif
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                    WebGLsizei width, WebGLsizei height, WebGLint border,
                                    const JS::Value& pixels, JSContext *cx)
 {
     if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
         return NS_ERROR_FAILURE;
     }
 
+    ArrayBufferView view(cx, &pixels.toObject());
+    CompressedTexImage2D(target, level, internalformat, width, height, border, view);
+    return NS_OK;
+}
+
+void
+WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum internalformat,
+                                   WebGLsizei width, WebGLsizei height, WebGLint border,
+                                   ArrayBufferView& view)
+{
     if (!IsContextStable()) {
-        return NS_OK;
+        return;
     }
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     if (!tex)
         return ErrorInvalidOperation("compressedTexImage2D: no texture is bound to this target");
 
     return ErrorInvalidEnum("compressedTexImage2D: compressed textures are not supported");
 }
@@ -4753,214 +5283,252 @@ NS_IMETHODIMP
 WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
                                       WebGLint yoffset, WebGLsizei width, WebGLsizei height,
                                       WebGLenum format, const JS::Value& pixels, JSContext *cx)
 {
     if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
         return NS_ERROR_FAILURE;
     }
 
+    ArrayBufferView view(cx, &pixels.toObject());
+    CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height,
+                            format, view);
+    return NS_OK;
+}
+
+void
+WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
+                                      WebGLint yoffset, WebGLsizei width, WebGLsizei height,
+                                      WebGLenum format, ArrayBufferView& view)
+{
     if (!IsContextStable()) {
-        return NS_OK;
+        return;
     }
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     if (!tex) {
         return ErrorInvalidOperation("compressedTexSubImage2D: no texture is bound to this target");
     }
 
     return ErrorInvalidEnum("compressedTexSubImage2D: compressed textures are not supported");
 }
 
 NS_IMETHODIMP
-WebGLContext::GetShaderParameter(nsIWebGLShader *sobj, WebGLenum pname, nsIVariant **retval)
+WebGLContext::GetShaderParameter(nsIWebGLShader *sobj, WebGLenum pname, JS::Value *retval)
+{
+    *retval = GetShaderParameter(static_cast<WebGLShader*>(sobj), pname);
+    return NS_OK;
+}
+
+JS::Value
+WebGLContext::GetShaderParameter(WebGLShader *shader, WebGLenum pname)
 {
     if (!IsContextStable())
-        return NS_OK;
-
-    *retval = nsnull;
-
-    WebGLShader *shader;
-    WebGLuint shadername;
-    if (!GetConcreteObjectAndGLName("getShaderParameter: shader", sobj, &shader, &shadername))
-        return NS_OK;
-
-    nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
+        return JS::NullValue();
+
+    if (!ValidateObject("getShaderParameter: shader", shader))
+        return JS::NullValue();
+
+    WebGLuint shadername = shader->GLName();
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_SHADER_TYPE:
-        case LOCAL_GL_INFO_LOG_LENGTH:
         {
             GLint i = 0;
             gl->fGetShaderiv(shadername, pname, &i);
-            wrval->SetAsInt32(i);
-        }
-            break;
-        case LOCAL_GL_SHADER_SOURCE_LENGTH:
-        {
-            wrval->SetAsInt32(PRInt32(shader->Source().Length()) + 1);
+            // uint32_t doesn't fit in Int32Value
+            return JS::DoubleValue(uint32_t(i));
         }
             break;
         case LOCAL_GL_DELETE_STATUS:
-            wrval->SetAsBool(shader->IsDeleteRequested());
+            return JS::BooleanValue(shader->IsDeleteRequested());
             break;
         case LOCAL_GL_COMPILE_STATUS:
         {
             GLint i = 0;
             gl->fGetShaderiv(shadername, pname, &i);
-            wrval->SetAsBool(bool(i));
+            return JS::BooleanValue(bool(i));
         }
             break;
         default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    *retval = wrval.forget().get();
-
-    return NS_OK;
+            ErrorInvalidEnumInfo("GetShaderParameter: parameter", pname);
+    }
+
+    return JS::NullValue();
 }
 
 NS_IMETHODIMP
 WebGLContext::GetShaderInfoLog(nsIWebGLShader *sobj, nsAString& retval)
 {
+    nsresult rv = NS_OK;
+    GetShaderInfoLog(static_cast<WebGLShader*>(sobj), retval, rv);
+    return rv;
+}
+
+void
+WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsAString& retval, nsresult& rv)
+{
     if (!IsContextStable())
     {
         retval.SetIsVoid(true);
-        return NS_OK;
-    }
-
-    WebGLShader *shader;
-    WebGLuint shadername;
-    if (!GetConcreteObjectAndGLName("getShaderInfoLog: shader", sobj, &shader, &shadername))
-        return NS_OK;
+        return;
+    }
+
+    if (!ValidateObject("getShaderInfoLog: shader", shader))
+        return;
 
     const nsCString& tlog = shader->TranslationLog();
     if (!tlog.IsVoid()) {
         CopyASCIItoUTF16(tlog, retval);
-        return NS_OK;
+        return;
     }
 
     MakeContextCurrent();
 
+    WebGLuint shadername = shader->GLName();
     GLint k = -1;
     gl->fGetShaderiv(shadername, LOCAL_GL_INFO_LOG_LENGTH, &k);
-    if (k == -1)
-        return NS_ERROR_FAILURE; // XXX GL Error? should never happen.
+    if (k == -1) {
+        rv = NS_ERROR_FAILURE; // XXX GL Error? should never happen.
+        return;
+    }
 
     if (k == 0) {
         retval.Truncate();
-        return NS_OK;
+        return;
     }
 
     nsCAutoString log;
     log.SetCapacity(k);
 
     gl->fGetShaderInfoLog(shadername, k, &k, (char*) log.BeginWriting());
 
     log.SetLength(k);
 
     CopyASCIItoUTF16(log, retval);
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precisiontype, nsIWebGLShaderPrecisionFormat **retval)
 {
-    *retval = nsnull;
+    *retval = GetShaderPrecisionFormat(shadertype, precisiontype).get();
+    return NS_OK;
+}
+
+already_AddRefed<WebGLShaderPrecisionFormat>
+WebGLContext::GetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precisiontype)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return nsnull;
 
     switch (shadertype) {
         case LOCAL_GL_FRAGMENT_SHADER:
         case LOCAL_GL_VERTEX_SHADER:
             break;
         default:
-            return ErrorInvalidEnumInfo("getShaderPrecisionFormat: shadertype", shadertype);
+            ErrorInvalidEnumInfo("getShaderPrecisionFormat: shadertype", shadertype);
+            return nsnull;
     }
 
     switch (precisiontype) {
         case LOCAL_GL_LOW_FLOAT:
         case LOCAL_GL_MEDIUM_FLOAT:
         case LOCAL_GL_HIGH_FLOAT:
         case LOCAL_GL_LOW_INT:
         case LOCAL_GL_MEDIUM_INT:
         case LOCAL_GL_HIGH_INT:
             break;
         default:
-            return ErrorInvalidEnumInfo("getShaderPrecisionFormat: precisiontype", precisiontype);
+            ErrorInvalidEnumInfo("getShaderPrecisionFormat: precisiontype", precisiontype);
+            return nsnull;
     }
 
     MakeContextCurrent();
 
     GLint range[2], precision;
     gl->fGetShaderPrecisionFormat(shadertype, precisiontype, range, &precision);
 
     WebGLShaderPrecisionFormat *retShaderPrecisionFormat
         = new WebGLShaderPrecisionFormat(range[0], range[1], precision);
-    NS_ADDREF(*retval = retShaderPrecisionFormat);
-
-    return NS_OK;
+    NS_ADDREF(retShaderPrecisionFormat);
+    return retShaderPrecisionFormat;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetShaderSource(nsIWebGLShader *sobj, nsAString& retval)
 {
+    GetShaderSource(static_cast<WebGLShader*>(sobj), retval);
+    return NS_OK;
+}
+
+void
+WebGLContext::GetShaderSource(WebGLShader *shader, nsAString& retval)
+{
     if (!IsContextStable())
     {
         retval.SetIsVoid(true);
-        return NS_OK;
-    }
-
-    WebGLShader *shader;
-    WebGLuint shadername;
-    if (!GetConcreteObjectAndGLName("getShaderSource: shader", sobj, &shader, &shadername))
-        return NS_OK;
+        return;
+    }
+
+    if (!ValidateObject("getShaderSource: shader", shader))
+        return;
 
     retval.Assign(shader->Source());
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::ShaderSource(nsIWebGLShader *sobj, const nsAString& source)
 {
+    ShaderSource(static_cast<WebGLShader*>(sobj), source);
+    return NS_OK;
+}
+
+void
+WebGLContext::ShaderSource(WebGLShader *shader, const nsAString& source)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    WebGLShader *shader;
-    WebGLuint shadername;
-    if (!GetConcreteObjectAndGLName("shaderSource: shader", sobj, &shader, &shadername))
-        return NS_OK;
+        return;
+
+    if (!ValidateObject("shaderSource: shader", shader))
+        return;
 
     // We're storing an actual instance of StripComments because, if we don't, the 
     // cleanSource nsAString instance will be destroyed before the reference is
     // actually used.
     StripComments stripComments(source);
     const nsAString& cleanSource = nsString(stripComments.result().Elements(), stripComments.length());
     if (!ValidateGLSLString(cleanSource, "compileShader"))
-        return NS_OK;
+        return;
 
     shader->SetSource(source);
 
     shader->SetNeedsTranslation();
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
+WebGLContext::MozVertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type,
+                                     WebGLboolean normalized, WebGLsizei stride,
+                                     WebGLintptr byteOffset)
+{
+    VertexAttribPointer(index, size, type, normalized, stride, byteOffset);
+    return NS_OK;
+}
+
+void
 WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type,
                                   WebGLboolean normalized, WebGLsizei stride,
-                                  WebGLsizeiptr byteOffset)
-{
+                                  WebGLintptr byteOffset)
+{
+    // XXXbz Preserving the old (buggy) behavior for now.  See bug 749497.
+    byteOffset = int32_t(byteOffset);
+
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (mBoundArrayBuffer == nsnull)
         return ErrorInvalidOperation("VertexAttribPointer: must have valid GL_ARRAY_BUFFER binding");
 
     WebGLsizei requiredAlignment = 1;
     switch (type) {
       case LOCAL_GL_BYTE:
       case LOCAL_GL_UNSIGNED_BYTE:
@@ -4977,17 +5545,17 @@ WebGLContext::VertexAttribPointer(WebGLu
       default:
           return ErrorInvalidEnumInfo("VertexAttribPointer: type", type);
     }
 
     // requiredAlignment should always be a power of two.
     WebGLsizei requiredAlignmentMask = requiredAlignment - 1;
 
     if (!ValidateAttribIndex(index, "vertexAttribPointer"))
-        return NS_OK;
+        return;
 
     if (size < 1 || size > 4)
         return ErrorInvalidValue("VertexAttribPointer: invalid element size");
 
     if (stride < 0 || stride > 255) // see WebGL spec section 6.6 "Vertex Attribute Data Stride"
         return ErrorInvalidValue("VertexAttribPointer: negative or too large stride");
 
     if (byteOffset < 0)
@@ -5018,18 +5586,16 @@ WebGLContext::VertexAttribPointer(WebGLu
     vd.type = type;
     vd.normalized = normalized;
 
     MakeContextCurrent();
 
     gl->fVertexAttribPointer(index, size, type, normalized,
                              stride,
                              reinterpret_cast<void*>(byteOffset));
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D(PRInt32)
 {
     if (!IsContextStable())
         return NS_OK;
 
@@ -5067,17 +5633,17 @@ GLenum WebGLContext::CheckedTexImage2D(G
         UpdateWebGLErrorAndClearGLError(&error);
         return error;
     } else {
         gl->fTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
         return LOCAL_GL_NO_ERROR;
     }
 }
 
-nsresult
+void
 WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum internalformat,
                               WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
                               WebGLint border,
                               WebGLenum format, WebGLenum type,
                               void *data, PRUint32 byteLength,
                               int jsArrayType, // a TypedArray format enum, or -1 if not relevant
                               int srcFormat, bool srcPremultiplied)
 {
@@ -5131,17 +5697,17 @@ WebGLContext::TexImage2D_base(WebGLenum 
             return ErrorInvalidValue("texImage2D: with level > 0, width and height must be powers of two");
     }
 
     if (border != 0)
         return ErrorInvalidValue("TexImage2D: border must be 0");
 
     PRUint32 texelSize = 0;
     if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texImage2D"))
-        return NS_OK;
+        return;
 
     CheckedUint32 checked_neededByteLength = 
         GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment); 
 
     CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
 
     CheckedUint32 checked_alignedRowSize =
         RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
@@ -5207,74 +5773,120 @@ WebGLContext::TexImage2D_base(WebGLenum 
         error = CheckedTexImage2D(target, level, internalformat,
                                   width, height, border, format, type, tempZeroData);
 
         free(tempZeroData);
     }
     
     if (error) {
         LogMessageIfVerbose("texImage2D generated error %s", ErrorName(error));
-        return NS_OK;
+        return;
     }
 
     tex->SetImageInfo(target, level, width, height, format, type);
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                WebGLsizei width, WebGLsizei height, WebGLint border,
                                WebGLenum format, WebGLenum type,
                                JSObject *pixels, JSContext *cx)
 {
+    nsresult rv = NS_OK;
+    if (!pixels) {
+        TexImage2D(cx, target, level, internalformat, width, height, border,
+                   format, type, nsnull, rv);
+    } else {
+        ArrayBufferView view(cx, pixels);
+        TexImage2D(cx, target, level, internalformat, width, height, border,
+                   format, type, &view, rv);
+    }
+    return rv;
+}
+
+void
+WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                         WebGLenum internalformat, WebGLsizei width,
+                         WebGLsizei height, WebGLint border, WebGLenum format,
+                         WebGLenum type, ArrayBufferView *pixels, nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
-
-    if (pixels && !JS_IsTypedArrayObject(pixels, cx))
-        return ErrorInvalidValue("TexSubImage2D: pixels are wrong type!");
+        return;
 
     return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
-                           pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
-                           pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
-                           pixels ? (int)JS_GetTypedArrayType(pixels, cx) : -1,
+                           pixels ? pixels->mData : 0,
+                           pixels ? pixels->mLength : 0,
+                           pixels ? (int)JS_GetTypedArrayType(pixels->mObj, cx) : -1,
                            WebGLTexelFormat::Auto, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                    WebGLsizei width, WebGLsizei height, WebGLint border,
                                    WebGLenum format, WebGLenum type,
                                    JSObject *pixels, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
     NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
 
-    return TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type,
-                           pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
-                           pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
-                           -1,
+    TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type,
+                    pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
+                    pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
+                    -1,
+                    WebGLTexelFormat::RGBA8, false);
+    return NS_OK;
+}
+
+void
+WebGLContext::TexImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                         WebGLenum internalformat, WebGLenum format,
+                         WebGLenum type, ImageData* pixels, nsresult& rv)
+{
+    if (!IsContextStable())
+        return;
+
+    if (!pixels) {
+        // Spec says to generate an INVALID_VALUE error
+        return ErrorInvalidValue("texImage2D: null ImageData");
+    }
+    
+    Uint8ClampedArray arr(cx, pixels->GetDataObject());
+    return TexImage2D_base(target, level, internalformat, pixels->GetWidth(),
+                           pixels->GetHeight(), 4*pixels->GetWidth(), 0,
+                           format, type, arr.mData, arr.mLength, -1,
                            WebGLTexelFormat::RGBA8, false);
 }
 
+
 NS_IMETHODIMP
 WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum internalformat,
                              WebGLenum format, GLenum type, Element* elt)
 {
+    nsresult rv = NS_OK;
+    TexImage2D(NULL, target, level, internalformat, format, type, elt, rv);
+    return rv;
+}
+
+void
+WebGLContext::TexImage2D(JSContext* /* unused */, WebGLenum target,
+                         WebGLint level, WebGLenum internalformat,
+                         WebGLenum format, WebGLenum type, Element* elt,
+                         nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     nsRefPtr<gfxImageSurface> isurf;
 
     int srcFormat;
-    nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
+    rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
     if (NS_FAILED(rv))
-        return rv;
+        return;
 
     PRUint32 byteLength = isurf->Stride() * isurf->Height();
 
     return TexImage2D_base(target, level, internalformat,
                            isurf->Width(), isurf->Height(), isurf->Stride(), 0,
                            format, type,
                            isurf->Data(), byteLength,
                            -1,
@@ -5285,17 +5897,17 @@ NS_IMETHODIMP
 WebGLContext::TexSubImage2D(PRInt32)
 {
     if (!IsContextStable())
         return NS_OK;
 
     return NS_ERROR_FAILURE;
 }
 
-nsresult
+void
 WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
                                  WebGLint xoffset, WebGLint yoffset,
                                  WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
                                  WebGLenum format, WebGLenum type,
                                  void *pixels, PRUint32 byteLength,
                                  int jsArrayType,
                                  int srcFormat, bool srcPremultiplied)
 {
@@ -5329,20 +5941,20 @@ WebGLContext::TexSubImage2D_base(WebGLen
     if (level >= 1) {
         if (!(is_pot_assuming_nonnegative(width) &&
               is_pot_assuming_nonnegative(height)))
             return ErrorInvalidValue("texSubImage2D: with level > 0, width and height must be powers of two");
     }
 
     PRUint32 texelSize = 0;
     if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texSubImage2D"))
-        return NS_OK;
+        return;
 
     if (width == 0 || height == 0)
-        return NS_OK; // ES 2.0 says it has no effect, we better return right now
+        return; // ES 2.0 says it has no effect, we better return right now
 
     CheckedUint32 checked_neededByteLength = 
         GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
 
     CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
 
     CheckedUint32 checked_alignedRowSize = 
         RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
@@ -5396,79 +6008,130 @@ WebGLContext::TexSubImage2D_base(WebGLen
         nsAutoArrayPtr<PRUint8> convertedData(new PRUint8[bytesNeeded]);
         ConvertImage(width, height, srcStride, dstStride,
                     (const PRUint8*)pixels, convertedData,
                     actualSrcFormat, srcPremultiplied,
                     dstFormat, mPixelStorePremultiplyAlpha, texelSize);
 
         gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, convertedData);
     }
-
-    return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level,
                                   WebGLint xoffset, WebGLint yoffset,
                                   WebGLsizei width, WebGLsizei height,
                                   WebGLenum format, WebGLenum type,
                                   JSObject *pixels, JSContext *cx)
 {
+    nsresult rv = NS_OK;
+    if (!pixels) {
+        TexSubImage2D(cx, target, level, xoffset, yoffset, width, height,
+                      format, type, nsnull, rv);
+    } else {
+        ArrayBufferView view(cx, pixels);
+        TexSubImage2D(cx, target, level, xoffset, yoffset, width, height,
+                      format, type, &view, rv);
+    }
+    return rv;
+}
+
+void
+WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                            WebGLint xoffset, WebGLint yoffset,
+                            WebGLsizei width, WebGLsizei height,
+                            WebGLenum format, WebGLenum type,
+                            ArrayBufferView* pixels,
+                            nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     if (!pixels)
         return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
 
-    NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
-
     return TexSubImage2D_base(target, level, xoffset, yoffset,
                               width, height, 0, format, type,
-                              JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
-                              JS_GetTypedArrayType(pixels, cx),
+                              pixels->mData, pixels->mLength,
+                              JS_GetTypedArrayType(pixels->mObj, cx),
                               WebGLTexelFormat::Auto, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
                                       WebGLint xoffset, WebGLint yoffset,
                                       WebGLsizei width, WebGLsizei height,
                                       WebGLenum format, WebGLenum type,
                                       JSObject *pixels, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
-    if (!pixels)
-        return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
+    if (!pixels) {
+        ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
+        return NS_OK;
+    }
 
     NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
 
+    TexSubImage2D_base(target, level, xoffset, yoffset,
+                       width, height, 4*width, format, type,
+                       JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
+                       -1,
+                       WebGLTexelFormat::RGBA8, false);
+    return NS_OK;
+}
+
+void
+WebGLContext::TexSubImage2D(JSContext* cx, WebGLenum target, WebGLint level,
+                            WebGLint xoffset, WebGLint yoffset,
+                            WebGLenum format, WebGLenum type, ImageData* pixels,
+                            nsresult& rv)
+{
+    if (!IsContextStable())
+        return;
+
+    if (!pixels)
+        return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
+
+    Uint8ClampedArray arr(cx, pixels->GetDataObject());
     return TexSubImage2D_base(target, level, xoffset, yoffset,
-                              width, height, 4*width, format, type,
-                              JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
+                              pixels->GetWidth(), pixels->GetHeight(),
+                              4*pixels->GetWidth(), format, type,
+                              arr.mData, arr.mLength,
                               -1,
                               WebGLTexelFormat::RGBA8, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level,
                                 WebGLint xoffset, WebGLint yoffset,
                                 WebGLenum format, WebGLenum type,
                                 Element *elt)
 {
+    nsresult rv = NS_OK;
+    TexSubImage2D(NULL, target, level, xoffset, yoffset, format, type, elt, rv);
+    return rv;
+}
+
+void
+WebGLContext::TexSubImage2D(JSContext* /* unused */, WebGLenum target,
+                            WebGLint level, WebGLint xoffset, WebGLint yoffset,
+                            WebGLenum format, WebGLenum type,
+                            dom::Element* elt, nsresult& rv)
+{
     if (!IsContextStable())
-        return NS_OK;
+        return;
 
     nsRefPtr<gfxImageSurface> isurf;
 
     int srcFormat;
-    nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
+    rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
     if (NS_FAILED(rv))
-        return rv;
+        return;
 
     PRUint32 byteLength = isurf->Stride() * isurf->Height();
 
     return TexSubImage2D_base(target, level,
                               xoffset, yoffset,
                               isurf->Width(), isurf->Height(), isurf->Stride(),
                               format, type,
                               isurf->Data(), byteLength,
--- a/content/canvas/src/WebGLContextUtils.cpp
+++ b/content/canvas/src/WebGLContextUtils.cpp
@@ -130,90 +130,88 @@ WebGLContext::GetImageSize(WebGLsizei he
 
     // if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
     CheckedUint32 checked_neededByteLength
         = height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
 
     return checked_neededByteLength;
 }
 
-nsresult
+void
 WebGLContext::SynthesizeGLError(WebGLenum err)
 {
     // If there is already a pending error, don't overwrite it;
     // but if there isn't, then we need to check for a gl error
     // that may have occurred before this one and use that code
     // instead.
     
     MakeContextCurrent();
 
     UpdateWebGLErrorAndClearGLError();
 
     if (!mWebGLError)
         mWebGLError = err;
-
-    return NS_OK;
 }
 
-nsresult
+void
 WebGLContext::SynthesizeGLError(WebGLenum err, const char *fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
     LogMessageIfVerbose(fmt, va);
     va_end(va);
 
     return SynthesizeGLError(err);
 }
 
-nsresult
+void
 WebGLContext::ErrorInvalidEnum(const char *fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
     LogMessageIfVerbose(fmt, va);
     va_end(va);
 
     return SynthesizeGLError(LOCAL_GL_INVALID_ENUM);
 }
 
-nsresult
+void
 WebGLContext::ErrorInvalidOperation(const char *fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
     LogMessageIfVerbose(fmt, va);
     va_end(va);
 
     return SynthesizeGLError(LOCAL_GL_INVALID_OPERATION);
 }
 
-nsresult
+void
 WebGLContext::ErrorInvalidValue(const char *fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
     LogMessageIfVerbose(fmt, va);
     va_end(va);
 
     return SynthesizeGLError(LOCAL_GL_INVALID_VALUE);
 }
 
-nsresult
+void
 WebGLContext::ErrorInvalidFramebufferOperation(const char *fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
     LogMessageIfVerbose(fmt, va);
     va_end(va);
 
     return SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
 }
 
-nsresult
+void
 WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
     LogMessageIfVerbose(fmt, va);
     va_end(va);
 
     return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
--- a/content/canvas/src/WebGLTexelConversions.h
+++ b/content/canvas/src/WebGLTexelConversions.h
@@ -50,19 +50,16 @@
 #elif defined __GNUC__
 #define FORCE_INLINE __attribute__((always_inline)) inline
 #else
 #define FORCE_INLINE inline
 #endif
 
 namespace mozilla {
 
-typedef PRUint8  uint8_t;
-typedef PRUint16 uint16_t;
-
 namespace WebGLTexelConversions {
 
 /****** BEGIN CODE SHARED WITH WEBKIT ******/
 
 //----------------------------------------------------------------------
 // Pixel unpacking routines.
 
 FORCE_INLINE void unpackRGBA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict destination)
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
+++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
@@ -45,17 +45,18 @@ interface nsIPropertyBag;
 
 // XXX should we comment out these typedefs in the C++ header?
 
 typedef unsigned long  WebGLenum;
 typedef boolean        WebGLboolean;
 typedef unsigned long  WebGLbitfield;
 typedef long           WebGLint;
 typedef long           WebGLsizei;
-typedef long           WebGLsizeiptr;
+typedef long long      WebGLsizeiptr;
+typedef long long      WebGLintptr;
 typedef unsigned long  WebGLuint;
 typedef float          WebGLfloat;
 typedef float          WebGLclampf;
 
 %{C++
 // for jsval
 #include "jsapi.h"
 
@@ -172,17 +173,17 @@ interface nsIWebGLExtensionLoseContext :
 
 [scriptable, uuid(73bfb64d-94bd-4a7a-9eab-6b6d32e57aa0)]
 interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
 {
   const WebGLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
   const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
 };
 
-[scriptable, builtinclass, uuid(ba7635d7-98af-41ac-8bf9-9f08cf441958)]
+[scriptable, builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
 interface nsIDOMWebGLRenderingContext : nsISupports
 {
   //
   //  CONSTANTS
   //
 
   /* ClearBufferMask */
   const unsigned long DEPTH_BUFFER_BIT               = 0x00000100;
@@ -603,174 +604,254 @@ interface nsIDOMWebGLRenderingContext : 
   //
   readonly attribute nsIDOMHTMLCanvasElement canvas;
 
   //
   //  METHODS
   //
   jsval getContextAttributes();
 
+  [binaryname(MozActiveTexture)]
   void activeTexture(in WebGLenum texture);
+
   void attachShader([optional] in nsIWebGLProgram program, [optional] in nsIWebGLShader shader);
   void bindAttribLocation(in nsIWebGLProgram program, in WebGLuint index, in DOMString name);
   void bindBuffer(in WebGLenum target, in nsIWebGLBuffer buffer);
   void bindFramebuffer(in WebGLenum target, in nsIWebGLFramebuffer framebuffer);
   void bindRenderbuffer(in WebGLenum target, in nsIWebGLRenderbuffer renderbuffer);
   void bindTexture(in WebGLenum target, in nsIWebGLTexture texture);
+
+  [binaryname(MozBlendColor)]
   void blendColor(in WebGLclampf red, in WebGLclampf green, in WebGLclampf blue, in WebGLclampf alpha);
+
+  [binaryname(MozBlendEquation)]
   void blendEquation(in WebGLenum mode);
+
+  [binaryname(MozBlendEquationSeparate)]
   void blendEquationSeparate(in WebGLenum modeRGB, in WebGLenum modeAlpha);
+
+  [binaryname(MozBlendFunc)]
   void blendFunc(in WebGLenum sfactor, in WebGLenum dfactor);
+
+  [binaryname(MozBlendFuncSeparate)]
   void blendFuncSeparate(in WebGLenum srcRGB, in WebGLenum dstRGB, in WebGLenum srcAlpha, in WebGLenum dstAlpha);
 
   // Modified: void glBufferData(WebGLenum target, long size, const void* data, WebGLenum usage);
   [implicit_jscontext] void bufferData(in long target, in jsval data, in long usage);
 
   [implicit_jscontext] void bufferSubData(in long target, in long offset, in jsval data);
 
   WebGLenum checkFramebufferStatus(in WebGLenum target);
+
+  [binaryname(MozClear)]
   void clear(in WebGLbitfield mask);
+
+  [binaryname(MozClearColor)]
   void clearColor(in WebGLclampf red, in WebGLclampf green, in WebGLclampf blue, in WebGLclampf alpha);
+
+  [binaryname(MozClearDepth)]
   void clearDepth(in WebGLclampf depth);
+
+  [binaryname(MozClearStencil)]
   void clearStencil(in WebGLint s);
+
+  [binaryname(MozColorMask)]
   void colorMask(in WebGLboolean red, in WebGLboolean green, in WebGLboolean blue, in WebGLboolean alpha);
+
   void compileShader([optional] in nsIWebGLShader shader);
 
   [implicit_jscontext] void compressedTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                             in WebGLsizei width, in WebGLsizei height, in WebGLint border,
                             in jsval pixels);
 
   [implicit_jscontext] void compressedTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset,
                                in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
                                in WebGLenum format, in jsval pixels);
 
+  [binaryname(MozCopyTexImage2D)]
   void copyTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat, 
                       in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height, in WebGLint border);
+
+  [binaryname(MozCopyTexSubImage2D)]
   void copyTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset, in WebGLint yoffset, 
                          in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height);
 
   nsIWebGLBuffer createBuffer();
   nsIWebGLProgram createProgram();
   nsIWebGLFramebuffer createFramebuffer();
   nsIWebGLRenderbuffer createRenderbuffer();
   nsIWebGLShader createShader(in WebGLenum type);
   nsIWebGLTexture createTexture();
 
+  [binaryname(MozCullFace)]
   void cullFace(in WebGLenum mode);
 
   void deleteBuffer(in nsIWebGLBuffer buffer);
   void deleteProgram(in nsIWebGLProgram program);
   void deleteFramebuffer(in nsIWebGLFramebuffer framebuffer);
   void deleteRenderbuffer(in nsIWebGLRenderbuffer renderbuffer);
   void deleteShader(in nsIWebGLShader shader);
   void deleteTexture(in nsIWebGLTexture texture);
 
+  [binaryname(MozDepthFunc)]
   void depthFunc(in WebGLenum func);
+
+  [binaryname(MozDepthMask)]
   void depthMask(in WebGLboolean flag);
+
+  [binaryname(MozDepthRange)]
   void depthRange(in WebGLclampf zNear, in WebGLclampf zFar);
+
   void detachShader(in nsIWebGLProgram program, in nsIWebGLShader shader);
+
+  [binaryname(MozDisable)]
   void disable(in WebGLenum cap);
+
+  [binaryname(MozDisableVertexAttribArray)]
   void disableVertexAttribArray(in WebGLuint index);
+
+  [binaryname(MozDrawArrays)]
   void drawArrays(in WebGLenum mode, in WebGLint first, in WebGLsizei count);
 
   // Modified: void glDrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, const void* indices);
-  void drawElements(in WebGLenum mode, in WebGLsizei count, in WebGLenum type, in WebGLint offset);
+  [binaryname(MozDrawElements)]
+  void drawElements(in WebGLenum mode, in WebGLsizei count, in WebGLenum type, in WebGLintptr offset);
 
+  [binaryname(MozEnable)]
   void enable(in WebGLenum cap);
+
+  [binaryname(MozEnableVertexAttribArray)]
   void enableVertexAttribArray(in WebGLuint index);
+
+  [binaryname(MozFinish)]
   void finish();
+
+  [binaryname(MozFlush)]
   void flush();
+
   void framebufferRenderbuffer(in WebGLenum target, in WebGLenum attachment, in WebGLenum renderbuffertarget, 
                                in nsIWebGLRenderbuffer renderbuffer);
   void framebufferTexture2D(in WebGLenum target, in WebGLenum attachment, in WebGLenum textarget, 
                             in nsIWebGLTexture texture, in WebGLint level);
+
+  [binaryname(MozFrontFace)]
   void frontFace(in WebGLenum mode);
 
+  [binaryname(MozGenerateMipmap)]
   void generateMipmap(in WebGLenum target);
 
   nsIWebGLActiveInfo getActiveAttrib(in nsIWebGLProgram program, in PRUint32 index);
   nsIWebGLActiveInfo getActiveUniform(in nsIWebGLProgram program, in PRUint32 index);
 
   nsIVariant getAttachedShaders(in nsIWebGLProgram program);
 
   WebGLint getAttribLocation(in nsIWebGLProgram program, in DOMString name);
 
-  nsIVariant getParameter(in WebGLenum pname);
+  [implicit_jscontext] jsval
+  getParameter(in WebGLenum pname);
 
   // Modified: void glGetBufferParameteriv(WebGLenum target, WebGLenum pname, WebGLint* params);
-  nsIVariant getBufferParameter(in WebGLenum target, in WebGLenum pname);
+  jsval getBufferParameter(in WebGLenum target, in WebGLenum pname);
 
+  [binaryname(MozGetError)]
   WebGLenum getError();
 
   // Modified: void glGetFramebufferAttachmentParameteriv(WebGLenum target, WebGLenum attachment, WebGLenum pname, WebGLint* params);
-  nsIVariant getFramebufferAttachmentParameter(in WebGLenum target, in WebGLenum attachment, in WebGLenum pname);
+  [implicit_jscontext] jsval
+  getFramebufferAttachmentParameter(in WebGLenum target, in WebGLenum attachment, in WebGLenum pname);
 
   // Modified: void glGetProgramiv(nsIWebGLProgram program, WebGLenum pname, WebGLint* params);
-  nsIVariant getProgramParameter(in nsIWebGLProgram program, in WebGLenum pname);
+  jsval getProgramParameter(in nsIWebGLProgram program, in WebGLenum pname);
 
   // Modified: void glGetProgramInfoLog(WebGLuint program, WebGLsizei bufsize, WebGLsizei* length, char* infolog);
   DOMString getProgramInfoLog(in nsIWebGLProgram program);
 
   // Modified: void glGetRenderbufferParameteriv(WebGLenum target, WebGLenum pname, WebGLint* params);
   //nsIWebGLIntArray getRenderbufferParameteriv(in WebGLenum target, in WebGLenum pname);
-  nsIVariant getRenderbufferParameter(in WebGLenum target, in WebGLenum pname);
+  jsval getRenderbufferParameter(in WebGLenum target, in WebGLenum pname);
 
-  nsIVariant getShaderParameter(in nsIWebGLShader shader, in WebGLenum pname);
+  jsval getShaderParameter(in nsIWebGLShader shader, in WebGLenum pname);
 
   // Modified: void glGetShaderInfoLog(WebGLuint shader, WebGLsizei bufsize, WebGLsizei* length, char* infolog);
   DOMString getShaderInfoLog(in nsIWebGLShader shader);
 
   nsIWebGLShaderPrecisionFormat getShaderPrecisionFormat(in WebGLenum shadertype, in WebGLenum precisiontype);
 
   DOMString getShaderSource(in nsIWebGLShader shader);
 
-  nsIVariant getTexParameter(in WebGLenum target, in WebGLenum pname);
+  jsval getTexParameter(in WebGLenum target, in WebGLenum pname);
 
-  nsIVariant getUniform(in nsIWebGLProgram program, in nsIWebGLUniformLocation location);
+  [implicit_jscontext]
+  jsval getUniform(in nsIWebGLProgram program, in nsIWebGLUniformLocation location);
 
   nsIWebGLUniformLocation getUniformLocation (in nsIWebGLProgram program, in DOMString name);
 
-  nsIVariant getVertexAttrib(in WebGLuint index, in WebGLenum pname);
+  [implicit_jscontext] jsval
+  getVertexAttrib(in WebGLuint index, in WebGLenum pname);
 
   // TBD
   // void glGetVertexAttribPointerv(WebGLuint index, WebGLenum pname, void** pointer);
   WebGLuint getVertexAttribOffset(in WebGLuint index, in WebGLenum pname);
 
+  [binaryname(MozHint)]
   void hint(in WebGLenum target, in WebGLenum mode);
 
   WebGLboolean isBuffer(in nsIWebGLBuffer buffer);
   WebGLboolean isFramebuffer(in nsIWebGLFramebuffer framebuffer);
   WebGLboolean isProgram(in nsIWebGLProgram program);
   WebGLboolean isRenderbuffer(in nsIWebGLRenderbuffer renderbuffer);
   WebGLboolean isShader(in nsIWebGLShader shader);
   WebGLboolean isTexture(in nsIWebGLTexture texture);
 
   WebGLboolean isEnabled(in WebGLenum cap);
+
+  [binaryname(MozLineWidth)]
   void lineWidth(in WebGLfloat width);
+
   void linkProgram([optional] in nsIWebGLProgram program);
+
+  [binaryname(MozPixelStorei)]
   void pixelStorei(in WebGLenum pname, in WebGLint param);
+
+  [binaryname(MozPolygonOffset)]
   void polygonOffset(in WebGLfloat factor, in WebGLfloat units);
 
   [implicit_jscontext] void readPixels(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
                   in WebGLenum format, in WebGLenum type, in jsval pixels);
 
   //void glReleaseShaderCompiler();
 
+  [binaryname(MozRenderbufferStorage)]
   void renderbufferStorage(in WebGLenum target, in WebGLenum internalformat, in WebGLsizei width, in WebGLsizei height);
+
+  [binaryname(MozSampleCoverage)]
   void sampleCoverage(in WebGLclampf value, in WebGLboolean invert);
+
+  [binaryname(MozScissor)]
   void scissor(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height);
 
   // Modified: void glShaderSource(WebGLuint shader, WebGLsizei count, const char** string, const WebGLint* length);
   void shaderSource([optional] in nsIWebGLShader shader, [optional] in DOMString source);
 
+  [binaryname(MozStencilFunc)]
   void stencilFunc(in WebGLenum func, in WebGLint ref, in WebGLuint mask);
+
+  [binaryname(MozStencilFuncSeparate)]
   void stencilFuncSeparate(in WebGLenum face, in WebGLenum func, in WebGLint ref, in WebGLuint mask);
+
+  [binaryname(MozStencilMask)]
   void stencilMask(in WebGLuint mask);
+
+  [binaryname(MozStencilMaskSeparate)]
   void stencilMaskSeparate(in WebGLenum face, in WebGLuint mask);
+
+  [binaryname(MozStencilOp)]
   void stencilOp(in WebGLenum fail, in WebGLenum zfail, in WebGLenum zpass);
+
+  [binaryname(MozStencilOpSeparate)]
   void stencilOpSeparate(in WebGLenum face, in WebGLenum fail, in WebGLenum zfail, in WebGLenum zpass);
 
   void texImage2D([optional] in long dummy);
   [noscript,implicit_jscontext] void texImage2D_array(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                                    in WebGLsizei width, in WebGLsizei height,
                                    in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
   [noscript,implicit_jscontext] void texImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                                    in WebGLsizei width, in WebGLsizei height,
@@ -788,17 +869,20 @@ interface nsIDOMWebGLRenderingContext : 
                                       in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
                                       in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
   // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement
   [noscript] void texSubImage2D_dom(in WebGLenum target, in WebGLint level,
                                     in WebGLint xoffset, in WebGLint yoffset, in WebGLenum format, in WebGLenum type,
                                     in Element element);
 
   // Modified: This replaces glTexParameterf, glTexParameterfv, glTexParameteri and glTexParameteriv
+  [binaryname(MozTexParameterf)]
   void texParameterf(in WebGLenum target, in WebGLenum pname, in WebGLfloat param);
+
+  [binaryname(MozTexParameteri)]
   void texParameteri(in WebGLenum target, in WebGLenum pname, in WebGLint param);
   //void glTexParameter(in WebGLenum target, in WebGLenum pname, in nsIWebGLArray params);
 
   // Modified: All the glUniform*v forms below are modified by replacing 'count' and 'v' with a nsIWebGLArray
   void uniform1f (in nsIWebGLUniformLocation location, in WebGLfloat x);
   void uniform1i (in nsIWebGLUniformLocation location, in WebGLint x);
   void uniform2f (in nsIWebGLUniformLocation location, in WebGLfloat x, in WebGLfloat y);
   void uniform2i (in nsIWebGLUniformLocation location, in WebGLint x, in WebGLint y);
@@ -822,29 +906,38 @@ interface nsIDOMWebGLRenderingContext : 
 
   // Added API using top entry from the passed nsIWebGLMatrixStack
   //ZZ void glUniformMatrix(in WebGLint location, in WebGLboolean transpose, in nsIWebGLMatrixStack value);
 
   void useProgram(in nsIWebGLProgram program);
   void validateProgram(in nsIWebGLProgram program);
 
   // Modified: All the glVertexAttrib*v forms below are modified by replacing 'values' with a WebGLJSObjectPtr
+  [binaryname(MozVertexAttrib1f)]
   void vertexAttrib1f(in WebGLuint indx, in WebGLfloat x);
+
+  [binaryname(MozVertexAttrib2f)]
   void vertexAttrib2f(in WebGLuint indx, in WebGLfloat x, in WebGLfloat y);
+
+  [binaryname(MozVertexAttrib3f)]
   void vertexAttrib3f(in WebGLuint indx, in WebGLfloat x, in WebGLfloat y, in WebGLfloat z);
+
+  [binaryname(MozVertexAttrib4f)]
   void vertexAttrib4f(in WebGLuint indx, in WebGLfloat x, in WebGLfloat y, in WebGLfloat z, in WebGLfloat w);
 
   [implicit_jscontext] void vertexAttrib1fv(in WebGLuint indx, in jsval values);
   [implicit_jscontext] void vertexAttrib2fv(in WebGLuint indx, in jsval values);
   [implicit_jscontext] void vertexAttrib3fv(in WebGLuint indx, in jsval values);
   [implicit_jscontext] void vertexAttrib4fv(in WebGLuint indx, in jsval values);
 
   // size is number of elements per attrib; offset, stride are in bytes
-  void vertexAttribPointer(in WebGLuint idx, in WebGLint size, in WebGLenum type, in WebGLboolean normalized, in WebGLsizei stride, in WebGLsizeiptr offset);
+  [binaryname(MozVertexAttribPointer)]
+  void vertexAttribPointer(in WebGLuint idx, in WebGLint size, in WebGLenum type, in WebGLboolean normalized, in WebGLsizei stride, in WebGLintptr offset);
 
+  [binaryname(MozViewport)]
   void viewport(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height);
 
   // get an underlying GL parameter, without any WebGL intervention.
   // Most useful for querying GL_VENDOR/GL_RENDERER for identifying
   // the underlying renderer to the user.
   [noscript] DOMString mozGetUnderlyingParamString(in WebGLenum pname);
 
   // extensions