b=565404; add WebGLUniformLocation object; r=vlad
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 01 Jun 2010 23:09:19 -0700
changeset 43010 6b2cd524bcedd06ce7c5b69df003b1898fb5adc4
parent 43009 4d20c3eeed53bf06c08385daa366e7989883f956
child 43011 fd3e5ddb8ddaba8caa8fb5cfd32e4ea6cef66a72
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs565404
milestone1.9.3a5pre
b=565404; add WebGLUniformLocation object; r=vlad
content/canvas/src/CustomQS_WebGL.h
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
js/src/xpconnect/src/dom_quickstubs.qsconf
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -403,19 +403,23 @@ helper_nsICanvasRenderingContextWebGL_Un
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
-    uint32 location;
-    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
+    nsIWebGLUniformLocation *location;
+    xpc_qsSelfRef location_selfref;
+    rv = xpc_qsUnwrapArg(cx, argv[0], &location, &location_selfref.ptr, &argv[0]);
+    if (NS_FAILED(rv)) {
+        xpc_qsThrowBadArg(cx, rv, vp, 0);
         return JS_FALSE;
+    }
 
     if (!JSVAL_IS_OBJECT(argv[1])) {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
         return JS_FALSE;
     }
 
     JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]);
 
@@ -473,19 +477,23 @@ helper_nsICanvasRenderingContextWebGL_Un
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 2)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
-    uint32 location;
-    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
+    nsIWebGLUniformLocation *location;
+    xpc_qsSelfRef location_selfref;
+    rv = xpc_qsUnwrapArg(cx, argv[0], &location, &location_selfref.ptr, &argv[0]);
+    if (NS_FAILED(rv)) {
+        xpc_qsThrowBadArg(cx, rv, vp, 0);
         return JS_FALSE;
+    }
 
     if (!JSVAL_IS_OBJECT(argv[1])) {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
         return JS_FALSE;
     }
 
     JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]);
 
@@ -543,21 +551,25 @@ helper_nsICanvasRenderingContextWebGL_Un
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 3)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
-    uint32 location;
+    nsIWebGLUniformLocation *location;
+    xpc_qsSelfRef location_selfref;
+    rv = xpc_qsUnwrapArg(cx, argv[0], &location, &location_selfref.ptr, &argv[0]);
+    if (NS_FAILED(rv)) {
+        xpc_qsThrowBadArg(cx, rv, vp, 0);
+        return JS_FALSE;
+    }
+    
     int32 transpose;
-    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
-        return JS_FALSE;
-
     if (!JS_ValueToECMAInt32(cx, argv[1], &transpose))
         return JS_FALSE;
 
     if (!JSVAL_IS_OBJECT(argv[2])) {
         xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
         return JS_FALSE;
     }
 
@@ -755,30 +767,40 @@ static JSBool
 nsICanvasRenderingContextWebGL_VertexAttrib4fv(JSContext *cx, uintN argc, jsval *vp)
 {
     return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 4);
 }
 
 #ifdef JS_TRACER
 
 static inline jsval FASTCALL
-helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg, int nElements)
+helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj,
+                                                      JSObject *arg, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
     nsICanvasRenderingContextWebGL *self;
     xpc_qsSelfRef selfref;
     xpc_qsArgValArray<3> vp(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
         js_SetTraceableNativeFailed(cx);
         return JSVAL_VOID;
     }
 
     js::AutoValueRooter obj_tvr(cx);
 
+    nsIWebGLUniformLocation *location;
+    xpc_qsSelfRef location_selfref;
+    nsresult rv_convert_arg0
+        = xpc_qsUnwrapThis(cx, locationobj, nsnull, &location, &location_selfref.ptr, &vp.array[1], nsnull);
+    if (NS_FAILED(rv_convert_arg0)) {
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
     js::TypedArray *wa = 0;
 
     if (helper_isInt32Array(arg)) {
         wa = js::TypedArray::fromJSObject(arg);
     }  else if (JS_IsArrayObject(cx, arg)) {
         JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_INT32, arg);
         if (!nobj) {
             // XXX this will likely return a strange error message if it goes wrong
@@ -810,30 +832,40 @@ helper_nsICanvasRenderingContextWebGL_Un
         xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNiv");
         js_SetTraceableNativeFailed(cx);
     }
 
     return JSVAL_VOID;
 }
 
 static inline jsval FASTCALL
-helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg, int nElements)
+helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj,
+                                                      JSObject *arg, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
     nsICanvasRenderingContextWebGL *self;
     xpc_qsSelfRef selfref;
     xpc_qsArgValArray<3> vp(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
         js_SetTraceableNativeFailed(cx);
         return JSVAL_VOID;
     }
 
     js::AutoValueRooter obj_tvr(cx);
 
+    nsIWebGLUniformLocation *location;
+    xpc_qsSelfRef location_selfref;
+    nsresult rv_convert_arg0
+        = xpc_qsUnwrapThis(cx, locationobj, nsnull, &location, &location_selfref.ptr, &vp.array[1], nsnull);
+    if (NS_FAILED(rv_convert_arg0)) {
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
     js::TypedArray *wa = 0;
 
     if (helper_isFloat32Array(arg)) {
         wa = js::TypedArray::fromJSObject(arg);
     }  else if (JS_IsArrayObject(cx, arg)) {
         JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg);
         if (!nobj) {
             // XXX this will likely return a strange error message if it goes wrong
@@ -865,30 +897,40 @@ helper_nsICanvasRenderingContextWebGL_Un
         xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNfv");
         js_SetTraceableNativeFailed(cx);
     }
 
     return JSVAL_VOID;
 }
 
 static inline jsval FASTCALL
-helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSBool transpose, JSObject *arg, int nElements)
+helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, JSObject *locationobj,
+                                                            JSBool transpose, JSObject *arg, int nElements)
 {
     XPC_QS_ASSERT_CONTEXT_OK(cx);
 
     nsICanvasRenderingContextWebGL *self;
     xpc_qsSelfRef selfref;
     xpc_qsArgValArray<4> vp(cx);
     if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
         js_SetTraceableNativeFailed(cx);
         return JSVAL_VOID;
     }
 
     js::AutoValueRooter obj_tvr(cx);
 
+    nsIWebGLUniformLocation *location;
+    xpc_qsSelfRef location_selfref;
+    nsresult rv_convert_arg0
+        = xpc_qsUnwrapThis(cx, locationobj, nsnull, &location, &location_selfref.ptr, &vp.array[1], nsnull);
+    if (NS_FAILED(rv_convert_arg0)) {
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
     js::TypedArray *wa = 0;
 
     if (helper_isFloat32Array(arg)) {
         wa = js::TypedArray::fromJSObject(arg);
     }  else if (JS_IsArrayObject(cx, arg)) {
         JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg);
         if (!nobj) {
             // XXX this will likely return a strange error message if it goes wrong
@@ -917,107 +959,107 @@ helper_nsICanvasRenderingContextWebGL_Un
         xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv");
         js_SetTraceableNativeFailed(cx);
     }
 
     return JSVAL_VOID;
 }
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 1);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 2);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 3);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 4);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 1);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 2);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 3);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, JSObject *location, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 4);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv,
-    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, OBJECT, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg)
+nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv,
-    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg)
+nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv,
-    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 static jsval FASTCALL
-nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg)
+nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, JSObject *loc, JSBool transpose, JSObject *arg)
 {
     return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4);
 }
 
 JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv,
-    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
+    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, OBJECT, BOOL, OBJECT, 0, nanojit::ACC_STORE_ANY)))
 
 #endif /* JS_TRACER */
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -413,20 +413,42 @@ DOMCI_DATA(WebGLRenderbuffer, WebGLRende
 
 NS_INTERFACE_MAP_BEGIN(WebGLRenderbuffer)
   NS_INTERFACE_MAP_ENTRY(WebGLRenderbuffer)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLRenderbuffer)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderbuffer)
 NS_INTERFACE_MAP_END
 
+NS_IMPL_ADDREF(WebGLUniformLocation)
+NS_IMPL_RELEASE(WebGLUniformLocation)
+
+DOMCI_DATA(WebGLUniformLocation, WebGLUniformLocation)
+
+NS_INTERFACE_MAP_BEGIN(WebGLUniformLocation)
+  NS_INTERFACE_MAP_ENTRY(WebGLUniformLocation)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLUniformLocation)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLUniformLocation)
+NS_INTERFACE_MAP_END
+
 #define NAME_NOT_SUPPORTED(base) \
 NS_IMETHODIMP base::GetName(WebGLuint *aName) \
 { return NS_ERROR_NOT_IMPLEMENTED; } \
 NS_IMETHODIMP base::SetName(WebGLuint aName) \
 { return NS_ERROR_NOT_IMPLEMENTED; }
 
 NAME_NOT_SUPPORTED(WebGLTexture)
 NAME_NOT_SUPPORTED(WebGLBuffer)
 NAME_NOT_SUPPORTED(WebGLProgram)
 NAME_NOT_SUPPORTED(WebGLShader)
 NAME_NOT_SUPPORTED(WebGLFramebuffer)
 NAME_NOT_SUPPORTED(WebGLRenderbuffer)
+
+/* [noscript] attribute WebGLint location; */
+NS_IMETHODIMP WebGLUniformLocation::GetLocation(WebGLint *aLocation)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP WebGLUniformLocation::SetLocation(WebGLint aLocation)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -64,16 +64,17 @@ class nsIDocShell;
 namespace mozilla {
 
 class WebGLTexture;
 class WebGLBuffer;
 class WebGLProgram;
 class WebGLShader;
 class WebGLFramebuffer;
 class WebGLRenderbuffer;
+class WebGLUniformLocation;
 
 class WebGLZeroingObject;
 
 class WebGLObjectBaseRefPtr
 {
 protected:
     friend class WebGLZeroingObject;
 
@@ -653,11 +654,38 @@ public:
     NS_DECL_NSIWEBGLRENDERBUFFER
 protected:
     WebGLuint mName;
     PRBool mDeleted;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(WebGLRenderbuffer, WEBGLRENDERBUFFER_PRIVATE_IID)
 
+#define WEBGLUNIFORMLOCATION_PRIVATE_IID \
+    {0x01a8a614, 0xb109, 0x42f1, {0xb4, 0x40, 0x8d, 0x8b, 0x87, 0x0b, 0x43, 0xa7}}
+class WebGLUniformLocation :
+    public nsIWebGLUniformLocation,
+    public WebGLZeroingObject
+{
+public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLUNIFORMLOCATION_PRIVATE_IID)
+
+    WebGLUniformLocation(WebGLProgram *program, GLint location) :
+        mProgram(program), mLocation(location) { }
+
+    WebGLProgram *Program() const { return mProgram; }
+    GLint Location() const { return mLocation; }
+
+    // needed for our generic helpers to check nsIxxx parameters, see GetConcreteObject.
+    PRBool Deleted() { return PR_FALSE; }
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIWEBGLUNIFORMLOCATION
+protected:
+    WebGLObjectRefPtr<WebGLProgram> mProgram;
+    GLint mLocation;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(WebGLUniformLocation, WEBGLUNIFORMLOCATION_PRIVATE_IID)
+
 }
 
 #endif
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -165,17 +165,17 @@ template<class ConcreteObjectType, class
 static PRBool
 GetConcreteObjectAndGLName(BaseInterfaceType *aInterface,
                            ConcreteObjectType **aConcreteObject,
                            WebGLuint *aGLObjectName,
                            PRBool *isNull = 0,
                            PRBool *isDeleted = 0)
 {
     PRBool result = GetConcreteObject(aInterface, aConcreteObject, isNull, isDeleted);
-    if(result == PR_FALSE) return PR_FALSE;
+    if (result == PR_FALSE) return PR_FALSE;
     *aGLObjectName = *aConcreteObject ? (*aConcreteObject)->GLName() : 0;
     return PR_TRUE;
 }
 
 /* Same as GetConcreteObjectAndGLName when you don't need the concrete object pointer.
  */
 template<class ConcreteObjectType, class BaseInterfaceType>
 static PRBool
@@ -1777,71 +1777,98 @@ WebGLContext::GetTexParameter(WebGLenum 
     }
 
     return NS_OK;
 }
 
 /* XXX fix */
 /* any getUniform(in WebGLProgram program, in WebGLUniformLocation location) raises(DOMException); */
 NS_IMETHODIMP
-WebGLContext::GetUniform(nsIWebGLProgram *pobj, WebGLint location)
+WebGLContext::GetUniform(nsIWebGLProgram *pobj, nsIWebGLUniformLocation *ploc)
 {
     WebGLuint progname;
-    if (!GetGLName<WebGLProgram>(pobj, &progname))
+    WebGLProgram *prog;
+    if (!GetConcreteObjectAndGLName(pobj, &prog, &progname))
         return ErrorInvalidOperation("GetUniform: invalid program");
 
+    WebGLUniformLocation *location;
+    if (!GetConcreteObject(ploc, &location))
+        return ErrorInvalidValue("GetUniform: invalid uniform location");
+
+    if (location->Program() != prog)
+        return ErrorInvalidValue("GetUniform: this uniform location corresponds to another program");
+
     NativeJSContext js;
     if (NS_FAILED(js.error))
         return js.error;
 
     MakeContextCurrent();
 
-    GLint uArraySize = 0;
-    GLenum uType = 0;
-
-    gl->fGetActiveUniform(progname, location, 0, NULL, &uArraySize, &uType, NULL);
-    if (uArraySize == 0)
+    GLint uniforms = 0;
+    gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORMS, &uniforms);
+
+    // we now need the type info to switch between fGetUniformfv and fGetUniformiv
+    // the only way to get that is to iterate through all active uniforms by index until
+    // one matches the given uniform location.
+    GLenum uniformType = 0;
+    GLint uniformNameMaxLength = 0;
+    gl->fGetProgramiv(progname, LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformNameMaxLength);
+    nsAutoArrayPtr<GLchar> uniformName(new GLchar[uniformNameMaxLength+1]);
+    GLint index;
+    for (index = 0; index < uniforms; ++index) {
+        GLsizei dummyLength;
+        GLint dummySize;
+        gl->fGetActiveUniform(progname, index, uniformNameMaxLength, &dummyLength,
+                              &dummySize, &uniformType, uniformName);
+        if (gl->fGetUniformLocation(progname, uniformName) == location->Location())
+            break;
+    }
+
+    if (index == uniforms)
         return NS_ERROR_FAILURE; // XXX GL error? shouldn't happen.
 
-    // glGetUniform needs to be called for each element of an array separately, so we don't
-    // have to deal with uArraySize at all.
-
     GLenum baseType;
     GLint unitSize;
-    if (!BaseTypeAndSizeFromUniformType(uType, &baseType, &unitSize))
+    if (!BaseTypeAndSizeFromUniformType(uniformType, &baseType, &unitSize))
         return NS_ERROR_FAILURE;
 
     // this should never happen
     if (unitSize > 16)
         return NS_ERROR_FAILURE;
 
     if (baseType == LOCAL_GL_FLOAT) {
         GLfloat fv[16];
-        gl->fGetUniformfv(progname, location, fv);
+        gl->fGetUniformfv(progname, location->Location(), fv);
         js.SetRetVal(fv, unitSize);
     } else if (baseType == LOCAL_GL_INT) {
         GLint iv[16];
-        gl->fGetUniformiv(progname, location, iv);
+        gl->fGetUniformiv(progname, location->Location(), iv);
         js.SetRetVal((PRInt32*)iv, unitSize);
     } else {
         js.SetRetValAsJSVal(JSVAL_NULL);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, WebGLint *retval)
+WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, nsIWebGLUniformLocation **retval)
 {
     WebGLuint progname;
-    if (!GetGLName<WebGLProgram>(pobj, &progname))
+    WebGLProgram *prog;
+    if (!GetConcreteObjectAndGLName(pobj, &prog, &progname))
         return ErrorInvalidOperation("GetUniformLocation: invalid program");
 
     MakeContextCurrent();
-    *retval = gl->fGetUniformLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
+
+    GLint intlocation = gl->fGetUniformLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
+
+    nsCOMPtr<WebGLUniformLocation> uloc = new WebGLUniformLocation(prog, intlocation);
+    *retval = uloc.forget().get();
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname)
 {
     NativeJSContext js;
     if (NS_FAILED(js.error))
@@ -2225,100 +2252,134 @@ WebGLContext::DOMElementToImageSurface(n
     }
 
     res.mSurface.forget();
     *imageOut = surf;
 
     return NS_OK;
 }
 
-#define GL_SIMPLE_ARRAY_METHOD(name, cnt, arrayType, ptrType)           \
+#define OBTAIN_UNIFORM_LOCATION                                         \
+    WebGLUniformLocation *location_object;                              \
+    if (!GetConcreteObject(ploc, &location_object))                     \
+        return ErrorInvalidValue("Invalid uniform location parameter"); \
+    if(mCurrentProgram != location_object->Program())                   \
+        return ErrorInvalidValue("This uniform location corresponds to another program"); \
+    GLint location = location_object->Location();
+
+#define SIMPLE_ARRAY_METHOD_UNIFORM(name, cnt, arrayType, ptrType)      \
 NS_IMETHODIMP                                                           \
 WebGLContext::name(PRInt32 dummy) {                                     \
      return NS_ERROR_NOT_IMPLEMENTED;                                   \
 }                                                                       \
 NS_IMETHODIMP                                                           \
-WebGLContext::name##_array(WebGLint idx, js::TypedArray *wa)               \
+WebGLContext::name##_array(nsIWebGLUniformLocation *ploc, js::TypedArray *wa) \
 {                                                                       \
+    OBTAIN_UNIFORM_LOCATION                                             \
     if (!wa || wa->type != js::TypedArray::arrayType)                   \
         return ErrorInvalidOperation("array must be " #arrayType);      \
     if (wa->length == 0 || wa->length % cnt != 0)                       \
         return ErrorInvalidOperation("array must be > 0 elements and have a length multiple of %d", cnt); \
     MakeContextCurrent();                                               \
-    gl->f##name(idx, wa->length / cnt, (ptrType *)wa->data);            \
+    gl->f##name(location, wa->length / cnt, (ptrType *)wa->data);            \
     return NS_OK;                                                       \
 }
 
-#define GL_SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType)  \
+#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType)  \
 NS_IMETHODIMP                                                           \
 WebGLContext::name(PRInt32 dummy) {                                     \
      return NS_ERROR_NOT_IMPLEMENTED;                                   \
 }                                                                       \
 NS_IMETHODIMP                                                           \
 WebGLContext::name##_array(WebGLuint idx, js::TypedArray *wa)              \
 {                                                                       \
     if (!wa || wa->type != js::TypedArray::arrayType)                   \
         return ErrorInvalidOperation("array must be " #arrayType);      \
     if (wa->length < cnt)                                               \
         return ErrorInvalidOperation("array must be >= %d elements", cnt); \
     MakeContextCurrent();                                               \
     gl->f##name(idx, (ptrType *)wa->data);                              \
     return NS_OK;                                                       \
 }
 
-#define GL_SIMPLE_MATRIX_METHOD(name, dim, arrayType, ptrType)          \
+#define SIMPLE_MATRIX_METHOD_UNIFORM(name, dim, arrayType, ptrType)     \
 NS_IMETHODIMP                                                           \
 WebGLContext::name(PRInt32 dummy) {                                     \
      return NS_ERROR_NOT_IMPLEMENTED;                                   \
 }                                                                       \
 NS_IMETHODIMP                                                           \
-WebGLContext::name##_array(WebGLint idx, WebGLboolean transpose, js::TypedArray *wa)  \
+WebGLContext::name##_array(nsIWebGLUniformLocation *ploc, WebGLboolean transpose, js::TypedArray *wa)  \
 {                                                                       \
+    OBTAIN_UNIFORM_LOCATION                                             \
     if (!wa || wa->type != js::TypedArray::arrayType)                   \
         return ErrorInvalidOperation("array must be " #arrayType);      \
     if (wa->length == 0 || wa->length % (dim*dim) != 0)                 \
         return ErrorInvalidOperation("array must be > 0 elements and have a length multiple of %d", dim*dim); \
     MakeContextCurrent();                                               \
-    gl->f##name(idx, wa->length / (dim*dim), transpose, (ptrType *)wa->data); \
+    gl->f##name(location, wa->length / (dim*dim), transpose, (ptrType *)wa->data); \
     return NS_OK;                                                       \
 }
 
-GL_SAME_METHOD_2(Uniform1i, Uniform1i, WebGLint, WebGLint)
-GL_SAME_METHOD_3(Uniform2i, Uniform2i, WebGLint, WebGLint, WebGLint)
-GL_SAME_METHOD_4(Uniform3i, Uniform3i, WebGLint, WebGLint, WebGLint, WebGLint)
-GL_SAME_METHOD_5(Uniform4i, Uniform4i, WebGLint, WebGLint, WebGLint, WebGLint, WebGLint)
-
-GL_SAME_METHOD_2(Uniform1f, Uniform1f, WebGLint, WebGLfloat)
-GL_SAME_METHOD_3(Uniform2f, Uniform2f, WebGLint, WebGLfloat, WebGLfloat)
-GL_SAME_METHOD_4(Uniform3f, Uniform3f, WebGLint, WebGLfloat, WebGLfloat, WebGLfloat)
-GL_SAME_METHOD_5(Uniform4f, Uniform4f, WebGLint, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
-
-GL_SIMPLE_ARRAY_METHOD(Uniform1iv, 1, TYPE_INT32, WebGLint)
-GL_SIMPLE_ARRAY_METHOD(Uniform2iv, 2, TYPE_INT32, WebGLint)
-GL_SIMPLE_ARRAY_METHOD(Uniform3iv, 3, TYPE_INT32, WebGLint)
-GL_SIMPLE_ARRAY_METHOD(Uniform4iv, 4, TYPE_INT32, WebGLint)
-
-GL_SIMPLE_ARRAY_METHOD(Uniform1fv, 1, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_ARRAY_METHOD(Uniform2fv, 2, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_ARRAY_METHOD(Uniform3fv, 3, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_ARRAY_METHOD(Uniform4fv, 4, TYPE_FLOAT32, WebGLfloat)
-
-GL_SIMPLE_MATRIX_METHOD(UniformMatrix2fv, 2, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_MATRIX_METHOD(UniformMatrix3fv, 3, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_MATRIX_METHOD(UniformMatrix4fv, 4, TYPE_FLOAT32, WebGLfloat)
+#define SIMPLE_METHOD_UNIFORM_1(glname, name, t1)        \
+NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) {      \
+    OBTAIN_UNIFORM_LOCATION \
+    MakeContextCurrent(); gl->f##glname(location, a1); return NS_OK; \
+}
+
+#define SIMPLE_METHOD_UNIFORM_2(glname, name, t1, t2)        \
+NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2) {      \
+    OBTAIN_UNIFORM_LOCATION \
+    MakeContextCurrent(); gl->f##glname(location, a1, a2); return NS_OK; \
+}
+
+#define SIMPLE_METHOD_UNIFORM_3(glname, name, t1, t2, t3)        \
+NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2, t3 a3) {      \
+    OBTAIN_UNIFORM_LOCATION \
+    MakeContextCurrent(); gl->f##glname(location, a1, a2, a3); return NS_OK; \
+}
+
+#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) {      \
+    OBTAIN_UNIFORM_LOCATION \
+    MakeContextCurrent(); gl->f##glname(location, a1, a2, a3, a4); return NS_OK; \
+}
+
+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)
+SIMPLE_METHOD_UNIFORM_2(Uniform2f, Uniform2f, WebGLfloat, WebGLfloat)
+SIMPLE_METHOD_UNIFORM_3(Uniform3f, Uniform3f, WebGLfloat, WebGLfloat, WebGLfloat)
+SIMPLE_METHOD_UNIFORM_4(Uniform4f, Uniform4f, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
+
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1iv, 1, TYPE_INT32, WebGLint)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2iv, 2, TYPE_INT32, WebGLint)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3iv, 3, TYPE_INT32, WebGLint)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4iv, 4, TYPE_INT32, WebGLint)
+
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1fv, 1, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2fv, 2, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3fv, 3, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4fv, 4, TYPE_FLOAT32, WebGLfloat)
+
+SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix2fv, 2, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix3fv, 3, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix4fv, 4, TYPE_FLOAT32, WebGLfloat)
 
 GL_SAME_METHOD_2(VertexAttrib1f, VertexAttrib1f, PRUint32, WebGLfloat)
 GL_SAME_METHOD_3(VertexAttrib2f, VertexAttrib2f, PRUint32, WebGLfloat, WebGLfloat)
 GL_SAME_METHOD_4(VertexAttrib3f, VertexAttrib3f, PRUint32, WebGLfloat, WebGLfloat, WebGLfloat)
 GL_SAME_METHOD_5(VertexAttrib4f, VertexAttrib4f, PRUint32, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
 
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, TYPE_FLOAT32, WebGLfloat)
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, WebGLfloat)
 
 NS_IMETHODIMP
 WebGLContext::UseProgram(nsIWebGLProgram *pobj)
 {
     WebGLProgram *prog;
     WebGLuint progname;
     if (!GetConcreteObjectAndGLName(pobj, &prog, &progname))
         return NS_ERROR_DOM_SYNTAX_ERR;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1367,16 +1367,18 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(WebGLProgram, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLShader, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLFramebuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLRenderbuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(WebGLUniformLocation, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PaintRequestList, nsPaintRequestListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(ScrollAreaEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -3808,17 +3810,21 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLShader)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLFramebuffer, nsIWebGLFramebuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLFramebuffer)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLRenderbuffer, nsIWebGLRenderbuffer)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLRenderbuffer)
+     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLRenderbuffer)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLUniformLocation, nsIWebGLUniformLocation)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUniformLocation)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
    DOM_CLASSINFO_MAP_END
  
   DOM_CLASSINFO_MAP_BEGIN(PaintRequestList, nsIDOMPaintRequestList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequestList)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -452,16 +452,17 @@ DOMCI_CLASS(ChromeWorker)
 // WebGL
 DOMCI_CLASS(CanvasRenderingContextWebGL)
 DOMCI_CLASS(WebGLBuffer)
 DOMCI_CLASS(WebGLTexture)
 DOMCI_CLASS(WebGLProgram)
 DOMCI_CLASS(WebGLShader)
 DOMCI_CLASS(WebGLFramebuffer)
 DOMCI_CLASS(WebGLRenderbuffer)
+DOMCI_CLASS(WebGLUniformLocation)
 
 // WebGL Buffers
 DOMCI_CLASS(PaintRequest)
 DOMCI_CLASS(PaintRequestList)
 
 DOMCI_CLASS(ScrollAreaEvent)
 DOMCI_CLASS(PopStateEvent)
 
--- a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
+++ b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
@@ -115,16 +115,22 @@ interface nsIWebGLRenderbuffer : nsISupp
 [scriptable, uuid(a85d4fd0-5b9f-4cb8-aeee-5a2c5c5bad76)]
 interface nsIWebGLActiveInfo : nsISupports
 {
     readonly attribute WebGLint size;
     readonly attribute WebGLenum type;
     readonly attribute DOMString name;
 };
 
+[scriptable, uuid(d38b0467-623e-4c82-9140-5f14a3bd1bad)]
+interface nsIWebGLUniformLocation : nsISupports
+{
+    [noscript] attribute WebGLint location;
+};
+
 
 [scriptable, uuid(f02c85e0-8305-11de-abe2-000c29206271)]
 interface nsICanvasRenderingContextWebGL : nsISupports
 {
   //
   //  ARRAY CONSTRUCTORS
   //
 
@@ -683,24 +689,19 @@ interface nsICanvasRenderingContextWebGL
   // TBD
   //void glGetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precisiontype, WebGLint* range, WebGLint* precision);
 
   DOMString getShaderSource(in nsIWebGLShader shader);
   DOMString getString(in WebGLenum name);
 
   void getTexParameter(in WebGLenum target, in WebGLenum pname);
 
-  // FIXME: This is problematic. We don't implicitly know how big the returned data buffer
-  // needs to be like in the other glGet* calls. The only way to find out is to iterate 
-  // through all the active uniforms with glGetActiveUniform() looking for the corresponding
-  // 'location'. This will give us the type and size of the data. Since this is a get call
-  // maybe that's ok?
-  void getUniform(in nsIWebGLProgram program, in WebGLint location);
+  void getUniform (in nsIWebGLProgram program, in nsIWebGLUniformLocation location);
 
-  WebGLint getUniformLocation(in nsIWebGLProgram program, in DOMString name);
+  nsIWebGLUniformLocation getUniformLocation (in nsIWebGLProgram program, in DOMString name);
 
   void getVertexAttrib(in WebGLuint index, in WebGLenum pname);
 
   // TBD
   // void glGetVertexAttribPointerv(WebGLuint index, WebGLenum pname, void** pointer);
   WebGLuint getVertexAttribOffset(in WebGLuint index, in WebGLenum pname);
 
   void hint(in WebGLenum target, in WebGLenum mode);
@@ -764,51 +765,51 @@ interface nsICanvasRenderingContextWebGL
                                     [optional] in WebGLboolean premultiply, [optional] in WebGLboolean asPremultipliedAlpha);
 
   // Modified: This replaces glTexParameterf, glTexParameterfv, glTexParameteri and glTexParameteriv
   void texParameterf(in WebGLenum target, in WebGLenum pname, in WebGLfloat param);
   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 WebGLint location, in WebGLfloat x);
-  void uniform1i(in WebGLint location, in WebGLint x);
-  void uniform2f(in WebGLint location, in WebGLfloat x, in WebGLfloat y);
-  void uniform2i(in WebGLint location, in WebGLint x, in WebGLint y);
-  void uniform3f(in WebGLint location, in WebGLfloat x, in WebGLfloat y, in WebGLfloat z);
-  void uniform3i(in WebGLint location, in WebGLint x, in WebGLint y, in WebGLint z);
-  void uniform4f(in WebGLint location, in WebGLfloat x, in WebGLfloat y, in WebGLfloat z, in WebGLfloat w);
-  void uniform4i(in WebGLint location, in WebGLint x, in WebGLint y, in WebGLint z, in WebGLint w);
+  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);
+  void uniform3f (in nsIWebGLUniformLocation location, in WebGLfloat x, in WebGLfloat y, in WebGLfloat z);
+  void uniform3i (in nsIWebGLUniformLocation location, in WebGLint x, in WebGLint y, in WebGLint z);
+  void uniform4f (in nsIWebGLUniformLocation location, in WebGLfloat x, in WebGLfloat y, in WebGLfloat z, in WebGLfloat w);
+  void uniform4i (in nsIWebGLUniformLocation location, in WebGLint x, in WebGLint y, in WebGLint z, in WebGLint w);
 
   void uniform1fv([optional] in long dummy);
   void uniform1iv([optional] in long dummy);
   void uniform2fv([optional] in long dummy);
   void uniform2iv([optional] in long dummy);
   void uniform3fv([optional] in long dummy);
   void uniform3iv([optional] in long dummy);
   void uniform4fv([optional] in long dummy);
   void uniform4iv([optional] in long dummy);
 
-  [noscript] void uniform1fv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform1iv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform2fv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform2iv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform3fv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform3iv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform4fv_array(in WebGLint location, in WebGLArrayPtr v);
-  [noscript] void uniform4iv_array(in WebGLint location, in WebGLArrayPtr v);
+  [noscript] void uniform1fv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform1iv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform2fv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform2iv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform3fv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform3iv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform4fv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
+  [noscript] void uniform4iv_array (in nsIWebGLUniformLocation location, in WebGLArrayPtr v);
 
   // Modified. These are modified by replacing 'count' and 'value' with a WebGLArrayPtr
   void uniformMatrix2fv([optional] in long dummy);
   void uniformMatrix3fv([optional] in long dummy);
   void uniformMatrix4fv([optional] in long dummy);
 
-  [noscript] void uniformMatrix2fv_array(in WebGLint location, in WebGLboolean transpose, in WebGLArrayPtr value);
-  [noscript] void uniformMatrix3fv_array(in WebGLint location, in WebGLboolean transpose, in WebGLArrayPtr value);
-  [noscript] void uniformMatrix4fv_array(in WebGLint location, in WebGLboolean transpose, in WebGLArrayPtr value);
+  [noscript] void uniformMatrix2fv_array (in nsIWebGLUniformLocation location, in WebGLboolean transpose, in WebGLArrayPtr value);
+  [noscript] void uniformMatrix3fv_array (in nsIWebGLUniformLocation location, in WebGLboolean transpose, in WebGLArrayPtr value);
+  [noscript] void uniformMatrix4fv_array (in nsIWebGLUniformLocation location, in WebGLboolean transpose, in WebGLArrayPtr value);
 
   // 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 WebGLArrayPtr
--- a/js/src/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/src/xpconnect/src/dom_quickstubs.qsconf
@@ -488,16 +488,17 @@ irregularFilenames = {
     'nsIWebGLTexture': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLBuffer': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLProgram': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLShader': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLShaderArray': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLFramebuffer': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLRenderbuffer': 'nsICanvasRenderingContextWebGL',
     'nsIWebGLActiveInfo': 'nsICanvasRenderingContextWebGL',
+    'nsIWebGLUniformLocation': 'nsICanvasRenderingContextWebGL',
     }
 
 customIncludes = [
     'nsINode.h',
     'nsIContent.h',
     'nsIDocument.h',
     'nsINodeList.h',
     'nsCSSPropertiesQS.h',