Bug 585199 - Implement WebGLActiveInfo, remove NativeJSContext, adapt WebGL code to that - r=vladimir a=blocking2.0

This commit is contained in:
Benoit Jacob 2010-08-23 17:03:49 -04:00
parent 996e56543a
commit 8277999173
10 changed files with 91 additions and 438 deletions

View File

@ -5217,7 +5217,7 @@ cairo-cocoa)
cairo-android)
AC_DEFINE(MOZ_WIDGET_ANDROID)
MOZ_WIDGET_TOOLKIT=android
MOZ_WEBGL=
MOZ_WEBGL=1
;;
esac

View File

@ -76,7 +76,6 @@ CPPSRCS += \
WebGLContextGL.cpp \
WebGLContextUtils.cpp \
WebGLContextValidate.cpp \
NativeJSContext.cpp \
$(NULL)
# We can't build ANGLE on linux-64 until build bug 560894 and related

View File

@ -1,19 +0,0 @@
#include "NativeJSContext.h"
#include "nsServiceManagerUtils.h"
#include "nsIJSRuntimeService.h"
PRBool
NativeJSContext::AddGCRoot(JSObject **aPtr, const char *aName)
{
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
PRBool ok;
return ok = ::JS_AddNamedObjectRoot(ctx, aPtr, aName);
}
void
NativeJSContext::ReleaseGCRoot(JSObject **aPtr)
{
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
::JS_RemoveObjectRoot(ctx, aPtr);
}

View File

@ -1,389 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef _NATIVEJSCONTEXT_H_
#define _NATIVEJSCONTEXT_H_
#include "nsDOMError.h"
#include "nsIXPConnect.h"
#include "nsContentUtils.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "jsapi.h"
class JSObjectHelper;
class nsIJSRuntimeService;
class NativeJSContext {
public:
NativeJSContext() {
error = nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&ncc);
if (NS_FAILED(error))
return;
if (!ncc) {
error = NS_ERROR_FAILURE;
return;
}
ctx = nsnull;
error = ncc->GetJSContext(&ctx);
if (NS_FAILED(error))
return;
JS_BeginRequest(ctx);
ncc->GetArgc(&argc);
ncc->GetArgvPtr(&argv);
}
~NativeJSContext() {
if (NS_SUCCEEDED(error))
JS_EndRequest(ctx);
}
PRBool CheckArray (JSObject *obj, jsuint *sz) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
if (obj &&
::JS_IsArrayObject(ctx, obj) &&
::JS_GetArrayLength(ctx, obj, sz))
return PR_TRUE;
return PR_FALSE;
}
PRBool CheckArray (jsval val, jsuint *sz) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
if (!JSVAL_IS_NULL(val) &&
JSVAL_IS_OBJECT(val) &&
::JS_IsArrayObject(ctx, JSVAL_TO_OBJECT(val)) &&
::JS_GetArrayLength(ctx, JSVAL_TO_OBJECT(val), sz))
return PR_TRUE;
return PR_FALSE;
}
PRBool AddGCRoot (JSObject **aPtr, const char *aName);
void ReleaseGCRoot (JSObject **aPtr);
void SetRetVal (PRInt32 val) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
SetRetValAsJSVal(INT_TO_JSVAL(val));
}
void SetRetVal (PRUint32 val) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
SetRetValAsJSVal(UINT_TO_JSVAL(val));
}
void SetRetVal (double val) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
SetRetValAsJSVal(DOUBLE_TO_JSVAL(val));
}
void SetBoolRetVal (PRBool val) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
SetRetValAsJSVal(BOOLEAN_TO_JSVAL(val));
}
void SetRetVal (PRInt32 *vp, PRUint32 len) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
if (!JS_EnterLocalRootScope(ctx))
return; // XXX ???
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = INT_TO_JSVAL(vp[i]);
JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
SetRetVal(jsarr);
JS_LeaveLocalRootScope(ctx);
}
void SetRetVal (PRUint32 *vp, PRUint32 len) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
if (!JS_EnterLocalRootScope(ctx))
return; // XXX ???
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = UINT_TO_JSVAL(vp[i]);
JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
SetRetVal(jsarr);
JS_LeaveLocalRootScope(ctx);
}
void SetRetVal (double *dp, PRUint32 len) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
if (!JS_EnterLocalRootScope(ctx))
return; // XXX ???
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = DOUBLE_TO_JSVAL(dp[i]);
JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
SetRetVal(jsarr);
JS_LeaveLocalRootScope(ctx);
}
void SetRetVal (float *fp, PRUint32 len) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
if (!JS_EnterLocalRootScope(ctx))
return; // XXX ???
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = DOUBLE_TO_JSVAL(fp[i]);
JSObject *jsarr = JS_NewArrayObject(ctx, len, jsvector.get());
SetRetVal(jsarr);
JS_LeaveLocalRootScope(ctx);
}
void SetRetValAsJSVal (jsval val) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
jsval *vp;
ncc->GetRetValPtr(&vp);
*vp = val;
ncc->SetReturnValueWasSet(PR_TRUE);
}
void SetRetVal (JSObject *obj) {
NS_ASSERTION(NS_SUCCEEDED(error), "class failed to initialize and caller used class without checking!");
SetRetValAsJSVal(OBJECT_TO_JSVAL(obj));
}
void SetRetVal (JSObjectHelper& objh);
nsAXPCNativeCallContext *ncc;
nsresult error;
JSContext *ctx;
PRUint32 argc;
jsval *argv;
public:
// static JS helpers
static inline PRBool JSValToFloatArray (JSContext *ctx, jsval val,
jsuint cnt, float *array)
{
JSObject *arrayObj;
jsuint arrayLen;
jsval jv;
jsdouble dv;
if (!::JS_ValueToObject(ctx, val, &arrayObj) ||
arrayObj == NULL ||
!::JS_IsArrayObject(ctx, arrayObj) ||
!::JS_GetArrayLength(ctx, arrayObj, &arrayLen) ||
(arrayLen < cnt))
return PR_FALSE;
for (jsuint i = 0; i < cnt; i++) {
::JS_GetElement(ctx, arrayObj, i, &jv);
if (!::JS_ValueToNumber(ctx, jv, &dv))
return PR_FALSE;
array[i] = (float) dv;
}
return PR_TRUE;
}
static inline PRBool JSValToDoubleArray (JSContext *ctx, jsval val,
jsuint cnt, double *array)
{
JSObject *arrayObj;
jsuint arrayLen;
jsval jv;
jsdouble dv;
if (!::JS_ValueToObject(ctx, val, &arrayObj) ||
arrayObj == NULL ||
!::JS_IsArrayObject(ctx, arrayObj) ||
!::JS_GetArrayLength(ctx, arrayObj, &arrayLen) ||
(arrayLen < cnt))
return PR_FALSE;
for (jsuint i = 0; i < cnt; i++) {
::JS_GetElement(ctx, arrayObj, i, &jv);
if (!::JS_ValueToNumber(ctx, jv, &dv))
return PR_FALSE;
array[i] = dv;
}
return PR_TRUE;
}
static inline PRBool JSValToJSArrayAndLength (JSContext *ctx, jsval val,
JSObject **outObj, jsuint *outLen)
{
JSObject *obj = nsnull;
jsuint len;
if (!::JS_ValueToObject(ctx, val, &obj) ||
obj == NULL ||
!::JS_IsArrayObject(ctx, obj) ||
!::JS_GetArrayLength(ctx, obj, &len))
{
return PR_FALSE;
}
*outObj = obj;
*outLen = len;
return PR_TRUE;
}
template<class T>
static nsresult JSValToSpecificInterface(JSContext *ctx, jsval val, T **out)
{
if (JSVAL_IS_NULL(val)) {
*out = nsnull;
return NS_OK;
}
if (!JSVAL_IS_OBJECT(val))
return NS_ERROR_DOM_SYNTAX_ERR;
nsCOMPtr<nsISupports> isup;
nsresult rv = nsContentUtils::XPConnect()->WrapJS(ctx, JSVAL_TO_OBJECT(val),
NS_GET_IID(nsISupports),
getter_AddRefs(isup));
if (NS_FAILED(rv))
return NS_ERROR_DOM_SYNTAX_ERR;
nsCOMPtr<T> obj = do_QueryInterface(isup);
if (!obj)
return NS_ERROR_DOM_SYNTAX_ERR;
NS_ADDREF(*out = obj.get());
return NS_OK;
}
static inline JSObject *ArrayToJSArray (JSContext *ctx,
const PRInt32 *vals,
const PRUint32 len)
{
// XXX handle ints that are too big to fit
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = INT_TO_JSVAL(vals[i]);
return JS_NewArrayObject(ctx, len, jsvector);
}
static inline JSObject *ArrayToJSArray (JSContext *ctx,
const PRUint32 *vals,
const PRUint32 len)
{
// XXX handle ints that are too big to fit
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = INT_TO_JSVAL(vals[i]);
return JS_NewArrayObject(ctx, len, jsvector);
}
};
class JSObjectHelper {
friend class NativeJSContext;
public:
JSObjectHelper(NativeJSContext *jsctx)
: mCtx (jsctx)
{
mObject = JS_NewObject(mCtx->ctx, NULL, NULL, NULL);
if (!mObject)
return;
if (!mCtx->AddGCRoot(&mObject, "JSObjectHelperCanvas3D"))
mObject = nsnull;
}
~JSObjectHelper() {
if (mObject && mCtx)
mCtx->ReleaseGCRoot(&mObject);
}
PRBool DefineProperty(const char *name, PRInt32 val) {
// XXX handle too big ints
if (!JS_DefineProperty(mCtx->ctx, mObject, name, INT_TO_JSVAL(val), NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
PRBool DefineProperty(const char *name, PRUint32 val) {
// XXX handle too big ints
if (!JS_DefineProperty(mCtx->ctx, mObject, name, INT_TO_JSVAL((int)val), NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
PRBool DefineProperty(const char *name, double val) {
jsval dv = DOUBLE_TO_JSVAL(val);
if (!JS_DefineProperty(mCtx->ctx, mObject, name, dv, NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
PRBool DefineProperty(const char *name, JSObject *val) {
if (!JS_DefineProperty(mCtx->ctx, mObject, name, OBJECT_TO_JSVAL(val), NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
// Blah. We can't name this DefineProperty also because PRBool is the same as PRInt32
PRBool DefineBoolProperty(const char *name, PRBool val) {
if (!JS_DefineProperty(mCtx->ctx, mObject, name, val ? JSVAL_TRUE : JSVAL_FALSE, NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
// We can't use ns*Substring, because we don't have internal linkage
#if 0
PRBool DefineProperty(const char *name, const nsCSubstring& val) {
JSString *jsstr = JS_NewStringCopyN(mCtx->ctx, val.BeginReading(), val.Length());
if (!jsstr ||
!JS_DefineProperty(mCtx->ctx, mObject, name, STRING_TO_JSVAL(jsstr), NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
PRBool DefineProperty(const char *name, const nsSubstring& val) {
JSString *jsstr = JS_NewUCStringCopyN(mCtx->ctx, val.BeginReading(), val.Length());
if (!jsstr ||
!JS_DefineProperty(mCtx->ctx, mObject, name, STRING_TO_JSVAL(jsstr), NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
#endif
PRBool DefineProperty(const char *name, const char *val, PRUint32 len) {
JSString *jsstr = JS_NewStringCopyN(mCtx->ctx, val, len);
if (!jsstr ||
!JS_DefineProperty(mCtx->ctx, mObject, name, STRING_TO_JSVAL(jsstr), NULL, NULL, JSPROP_ENUMERATE))
return PR_FALSE;
return PR_TRUE;
}
JSObject *Object() {
return mObject;
}
protected:
NativeJSContext *mCtx;
JSObject *mObject;
};
inline void
NativeJSContext::SetRetVal(JSObjectHelper& objh) {
SetRetValAsJSVal(OBJECT_TO_JSVAL(objh.mObject));
}
#endif

View File

@ -52,7 +52,6 @@
#include "gfxUtils.h"
#include "CanvasUtils.h"
#include "NativeJSContext.h"
#include "GLContextProvider.h"
@ -652,6 +651,18 @@ NS_INTERFACE_MAP_BEGIN(WebGLUniformLocation)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLUniformLocation)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(WebGLActiveInfo)
NS_IMPL_RELEASE(WebGLActiveInfo)
DOMCI_DATA(WebGLActiveInfo, WebGLActiveInfo)
NS_INTERFACE_MAP_BEGIN(WebGLActiveInfo)
NS_INTERFACE_MAP_ENTRY(WebGLActiveInfo)
NS_INTERFACE_MAP_ENTRY(nsIWebGLActiveInfo)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLActiveInfo)
NS_INTERFACE_MAP_END
#define NAME_NOT_SUPPORTED(base) \
NS_IMETHODIMP base::GetName(WebGLuint *aName) \
{ return NS_ERROR_NOT_IMPLEMENTED; } \
@ -674,3 +685,24 @@ NS_IMETHODIMP WebGLUniformLocation::SetLocation(WebGLint aLocation)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute WebGLint size; */
NS_IMETHODIMP WebGLActiveInfo::GetSize(WebGLint *aSize)
{
*aSize = mSize;
return NS_OK;
}
/* readonly attribute WebGLenum type; */
NS_IMETHODIMP WebGLActiveInfo::GetType(WebGLenum *aType)
{
*aType = mType;
return NS_OK;
}
/* readonly attribute DOMString name; */
NS_IMETHODIMP WebGLActiveInfo::GetName(nsAString & aName)
{
aName = mName;
return NS_OK;
}

View File

@ -938,6 +938,42 @@ protected:
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLUniformLocation, WEBGLUNIFORMLOCATION_PRIVATE_IID)
#define WEBGLACTIVEINFO_PRIVATE_IID \
{0x90def5ec, 0xc672, 0x4ac3, {0xb8, 0x97, 0x04, 0xa2, 0x6d, 0xda, 0x66, 0xd7}}
class WebGLActiveInfo :
public nsIWebGLActiveInfo
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLACTIVEINFO_PRIVATE_IID)
WebGLActiveInfo(WebGLint size, WebGLenum type, const char *nameptr, PRUint32 namelength) :
mDeleted(PR_FALSE),
mSize(size),
mType(type)
{
mName.AssignASCII(nameptr, namelength);
}
void Delete() {
if (mDeleted)
return;
mDeleted = PR_TRUE;
}
PRBool Deleted() { return mDeleted; }
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBGLACTIVEINFO
protected:
PRBool mDeleted;
WebGLint mSize;
WebGLenum mType;
nsString mName;
};
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLActiveInfo, WEBGLACTIVEINFO_PRIVATE_IID)
/**
** Template implementations
**/

View File

@ -52,7 +52,6 @@
#include "nsLayoutUtils.h"
#include "CanvasUtils.h"
#include "NativeJSContext.h"
#include "jstypedarray.h"
@ -1111,10 +1110,6 @@ WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAct
if (!GetGLName<WebGLProgram>("getActiveAttrib: program", pobj, &progname))
return NS_OK;
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
GLint len = 0;
@ -1134,12 +1129,9 @@ WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAct
return NS_OK;
}
JSObjectHelper retobj(&js);
retobj.DefineProperty("size", attrsize);
retobj.DefineProperty("type", attrtype);
retobj.DefineProperty("name", name, len);
WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, name.get(), len);
js.SetRetVal(retobj);
NS_ADDREF(*retval = retActiveInfo);
return NS_OK;
}
@ -1169,10 +1161,6 @@ WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAc
if (!GetGLName<WebGLProgram>("getActiveUniform: program", pobj, &progname))
return NS_OK;
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
MakeContextCurrent();
GLint len = 0;
@ -1212,12 +1200,9 @@ WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAc
name[len++] = ']';
}
JSObjectHelper retobj(&js);
retobj.DefineProperty("size", attrsize);
retobj.DefineProperty("type", attrtype);
retobj.DefineProperty("name", name, len);
WebGLActiveInfo *retActiveInfo = new WebGLActiveInfo(attrsize, attrtype, name.get(), len);
js.SetRetVal(retobj.Object());
NS_ADDREF(*retval = retActiveInfo);
return NS_OK;
}
@ -2048,11 +2033,10 @@ WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, n
}
NS_IMETHODIMP
WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname)
WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **retval)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
MakeContextCurrent();
@ -2065,7 +2049,7 @@ WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname)
{
PRInt32 i = 0;
gl->fGetVertexAttribiv(index, pname, (GLint*) &i);
js.SetRetVal(i);
wrval->SetAsInt32(i);
}
break;
@ -2073,7 +2057,8 @@ WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname)
{
GLfloat fv[4] = { 0 };
gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, fv);
js.SetRetVal(fv, 4);
wrval->SetAsArray(nsIDataType::VTYPE_FLOAT, nsnull,
4, static_cast<void*>(fv));
}
break;
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
@ -2081,7 +2066,7 @@ WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname)
{
PRInt32 i = 0;
gl->fGetVertexAttribiv(index, pname, (GLint*) &i);
js.SetBoolRetVal(PRBool(i));
wrval->SetAsBool(PRBool(i));
}
break;
@ -2091,6 +2076,8 @@ WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname)
return ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);
}
*retval = wrval.forget().get();
return NS_OK;
}

View File

@ -1416,6 +1416,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLUniformLocation, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLActiveInfo, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -3994,6 +3996,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUniformLocation)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLActiveInfo, nsIWebGLActiveInfo)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLActiveInfo)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_END

View File

@ -467,6 +467,7 @@ DOMCI_CLASS(WebGLShader)
DOMCI_CLASS(WebGLFramebuffer)
DOMCI_CLASS(WebGLRenderbuffer)
DOMCI_CLASS(WebGLUniformLocation)
DOMCI_CLASS(WebGLActiveInfo)
// WebGL Buffers
DOMCI_CLASS(PaintRequest)

View File

@ -699,7 +699,7 @@ interface nsICanvasRenderingContextWebGL : nsISupports
nsIWebGLUniformLocation getUniformLocation (in nsIWebGLProgram program, in DOMString name);
void getVertexAttrib(in WebGLuint index, in WebGLenum pname);
nsIVariant getVertexAttrib(in WebGLuint index, in WebGLenum pname);
// TBD
// void glGetVertexAttribPointerv(WebGLuint index, WebGLenum pname, void** pointer);