Bug 635059 - Update WebGL test suite to version 1.0.0 from khronos.org - a=NPOTB
authorBenoit Jacob <bjacob@mozilla.com>
Thu, 03 Mar 2011 11:02:36 -0500
changeset 63319 646c6004d9d6
parent 63318 fb4921333812
child 63320 a6eb991e7f05
push idunknown
push userunknown
push dateunknown
reviewersNPOTB
bugs635059
milestone2.0b13pre
Bug 635059 - Update WebGL test suite to version 1.0.0 from khronos.org - a=NPOTB
content/canvas/test/webgl/00_test_list.txt
content/canvas/test/webgl/README.mozilla
content/canvas/test/webgl/README.txt
content/canvas/test/webgl/conformance/00_readme.txt
content/canvas/test/webgl/conformance/00_test_list.txt
content/canvas/test/webgl/conformance/array-unit-tests.html
content/canvas/test/webgl/conformance/buffer-data-array-buffer.html
content/canvas/test/webgl/conformance/buffer-preserve-test.html
content/canvas/test/webgl/conformance/canvas-test.html
content/canvas/test/webgl/conformance/constants.html
content/canvas/test/webgl/conformance/context-attributes-alpha-depth-stencil-antialias.html
content/canvas/test/webgl/conformance/context-lost-restored.html
content/canvas/test/webgl/conformance/context-lost.html
content/canvas/test/webgl/conformance/copy-tex-image-and-sub-image-2d.html
content/canvas/test/webgl/conformance/draw-elements-out-of-bounds.html
content/canvas/test/webgl/conformance/gl-bind-attrib-location-test.html
content/canvas/test/webgl/conformance/gl-drawelements.html
content/canvas/test/webgl/conformance/gl-enable-enum-test.html
content/canvas/test/webgl/conformance/gl-enum-tests.html
content/canvas/test/webgl/conformance/gl-get-calls.html
content/canvas/test/webgl/conformance/gl-getshadersource.html
content/canvas/test/webgl/conformance/gl-min-attribs.html
content/canvas/test/webgl/conformance/gl-min-textures-unroll.html
content/canvas/test/webgl/conformance/gl-min-textures.html
content/canvas/test/webgl/conformance/gl-min-uniforms.html
content/canvas/test/webgl/conformance/gl-object-get-calls.html
content/canvas/test/webgl/conformance/gl-pixelstorei.html
content/canvas/test/webgl/conformance/gl-teximage.html
content/canvas/test/webgl/conformance/gl-uniform-arrays.html
content/canvas/test/webgl/conformance/gl-uniform-bool.html
content/canvas/test/webgl/conformance/gl-uniformmatrix4fv.html
content/canvas/test/webgl/conformance/gl-vertex-attrib-zero-issues.html
content/canvas/test/webgl/conformance/gl-vertexattribpointer.html
content/canvas/test/webgl/conformance/glsl-conformance.html
content/canvas/test/webgl/conformance/include.vs
content/canvas/test/webgl/conformance/index-validation.html
content/canvas/test/webgl/conformance/instanceof-test.html
content/canvas/test/webgl/conformance/invalid-passed-params.html
content/canvas/test/webgl/conformance/more/00_test_list.txt
content/canvas/test/webgl/conformance/more/README.md
content/canvas/test/webgl/conformance/more/all_tests.html
content/canvas/test/webgl/conformance/more/all_tests_linkonly.html
content/canvas/test/webgl/conformance/more/all_tests_sequential.html
content/canvas/test/webgl/conformance/more/conformance/badArgsArityLessThanArgc.html
content/canvas/test/webgl/conformance/more/conformance/constants.html
content/canvas/test/webgl/conformance/more/conformance/fuzzTheAPI.html
content/canvas/test/webgl/conformance/more/conformance/getContext.html
content/canvas/test/webgl/conformance/more/conformance/methods.html
content/canvas/test/webgl/conformance/more/conformance/quickCheckAPI.html
content/canvas/test/webgl/conformance/more/conformance/quickCheckAPI.js
content/canvas/test/webgl/conformance/more/conformance/quickCheckAPIBadArgs.html
content/canvas/test/webgl/conformance/more/conformance/webGLArrays.html
content/canvas/test/webgl/conformance/more/demos/opengl_web.html
content/canvas/test/webgl/conformance/more/demos/video.html
content/canvas/test/webgl/conformance/more/functions/bindBuffer.html
content/canvas/test/webgl/conformance/more/functions/bindBufferBadArgs.html
content/canvas/test/webgl/conformance/more/functions/bindFramebufferLeaveNonZero.html
content/canvas/test/webgl/conformance/more/functions/bufferData.html
content/canvas/test/webgl/conformance/more/functions/bufferDataBadArgs.html
content/canvas/test/webgl/conformance/more/functions/bufferSubData.html
content/canvas/test/webgl/conformance/more/functions/bufferSubDataBadArgs.html
content/canvas/test/webgl/conformance/more/functions/copyTexImage2D.html
content/canvas/test/webgl/conformance/more/functions/copyTexImage2DBadArgs.html
content/canvas/test/webgl/conformance/more/functions/copyTexSubImage2D.html
content/canvas/test/webgl/conformance/more/functions/copyTexSubImage2DBadArgs.html
content/canvas/test/webgl/conformance/more/functions/deleteBufferBadArgs.html
content/canvas/test/webgl/conformance/more/functions/drawArrays.html
content/canvas/test/webgl/conformance/more/functions/drawArraysOutOfBounds.html
content/canvas/test/webgl/conformance/more/functions/drawElements.html
content/canvas/test/webgl/conformance/more/functions/drawElementsBadArgs.html
content/canvas/test/webgl/conformance/more/functions/isTests.html
content/canvas/test/webgl/conformance/more/functions/readPixels.html
content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html
content/canvas/test/webgl/conformance/more/functions/texImage2D.html
content/canvas/test/webgl/conformance/more/functions/texImage2DBadArgs.html
content/canvas/test/webgl/conformance/more/functions/texImage2DHTML.html
content/canvas/test/webgl/conformance/more/functions/texImage2DHTMLBadArgs.html
content/canvas/test/webgl/conformance/more/functions/texSubImage2D.html
content/canvas/test/webgl/conformance/more/functions/texSubImage2DBadArgs.html
content/canvas/test/webgl/conformance/more/functions/texSubImage2DHTML.html
content/canvas/test/webgl/conformance/more/functions/texSubImage2DHTMLBadArgs.html
content/canvas/test/webgl/conformance/more/functions/uniformMatrix.html
content/canvas/test/webgl/conformance/more/functions/uniformMatrixBadArgs.html
content/canvas/test/webgl/conformance/more/functions/uniformf.html
content/canvas/test/webgl/conformance/more/functions/uniformfArrayLen1.html
content/canvas/test/webgl/conformance/more/functions/uniformfBadArgs.html
content/canvas/test/webgl/conformance/more/functions/uniformi.html
content/canvas/test/webgl/conformance/more/functions/uniformiBadArgs.html
content/canvas/test/webgl/conformance/more/functions/vertexAttrib.html
content/canvas/test/webgl/conformance/more/functions/vertexAttribBadArgs.html
content/canvas/test/webgl/conformance/more/functions/vertexAttribPointer.html
content/canvas/test/webgl/conformance/more/functions/vertexAttribPointerBadArgs.html
content/canvas/test/webgl/conformance/more/glsl/arrayOutOfBounds.html
content/canvas/test/webgl/conformance/more/glsl/longLoops.html
content/canvas/test/webgl/conformance/more/glsl/uniformOutOfBounds.html
content/canvas/test/webgl/conformance/more/glsl/unusedAttribsUniforms.html
content/canvas/test/webgl/conformance/more/index.html
content/canvas/test/webgl/conformance/more/performance/CPUvsGPU.html
content/canvas/test/webgl/conformance/more/performance/bandwidth.html
content/canvas/test/webgl/conformance/more/performance/jsGCPause.html
content/canvas/test/webgl/conformance/more/performance/jsMatrixMult.html
content/canvas/test/webgl/conformance/more/performance/jsToGLOverhead.html
content/canvas/test/webgl/conformance/more/unit.css
content/canvas/test/webgl/conformance/more/unit.js
content/canvas/test/webgl/conformance/more/util.js
content/canvas/test/webgl/conformance/null-object-behaviour.html
content/canvas/test/webgl/conformance/object-deletion-behaviour.html
content/canvas/test/webgl/conformance/oes-standard-derivatives.html
content/canvas/test/webgl/conformance/oes-texture-float.html
content/canvas/test/webgl/conformance/oes-vertex-array-object.html
content/canvas/test/webgl/conformance/program-test.html
content/canvas/test/webgl/conformance/read-pixels-test.html
content/canvas/test/webgl/conformance/resource-sharing-test.html
content/canvas/test/webgl/conformance/resources/boolUniformShader.vert
content/canvas/test/webgl/conformance/resources/floatUniformShader.vert
content/canvas/test/webgl/conformance/resources/fragmentShader.frag
content/canvas/test/webgl/conformance/resources/gray-ramp-default-gamma.png
content/canvas/test/webgl/conformance/resources/gray-ramp-gamma0.1.png
content/canvas/test/webgl/conformance/resources/gray-ramp-gamma1.0.png
content/canvas/test/webgl/conformance/resources/gray-ramp-gamma2.0.png
content/canvas/test/webgl/conformance/resources/gray-ramp-gamma4.0.png
content/canvas/test/webgl/conformance/resources/gray-ramp-gamma9.0.png
content/canvas/test/webgl/conformance/resources/gray-ramp.png
content/canvas/test/webgl/conformance/resources/intUniformShader.vert
content/canvas/test/webgl/conformance/resources/matUniformShader.vert
content/canvas/test/webgl/conformance/resources/noopUniformShader.frag
content/canvas/test/webgl/conformance/resources/noopUniformShader.vert
content/canvas/test/webgl/conformance/resources/red-indexed.png
content/canvas/test/webgl/conformance/resources/samplerUniformShader.frag
content/canvas/test/webgl/conformance/resources/structUniformShader.vert
content/canvas/test/webgl/conformance/resources/testrunner.js
content/canvas/test/webgl/conformance/resources/vertexShader.vert
content/canvas/test/webgl/conformance/resources/webgl-test-utils.js
content/canvas/test/webgl/conformance/resources/zero-alpha.png
content/canvas/test/webgl/conformance/shaders/00_shaders.txt
content/canvas/test/webgl/conformance/shaders/misc/00_shaders.txt
content/canvas/test/webgl/conformance/shaders/misc/non-ascii-comments.vert
content/canvas/test/webgl/conformance/shaders/misc/non-ascii.vert
content/canvas/test/webgl/conformance/tex-image-and-sub-image-2d-with-image-data.html
content/canvas/test/webgl/conformance/tex-image-and-sub-image-2d-with-image.html
content/canvas/test/webgl/conformance/tex-image-and-sub-image-2d-with-video.html
content/canvas/test/webgl/conformance/tex-image-with-format-and-type.html
content/canvas/test/webgl/conformance/tex-input-validation.html
content/canvas/test/webgl/conformance/tex-sub-image-2d-bad-args.html
content/canvas/test/webgl/conformance/texture-active-bind-2.html
content/canvas/test/webgl/conformance/texture-active-bind.html
content/canvas/test/webgl/conformance/texture-complete.html
content/canvas/test/webgl/conformance/texture-formats-test.html
content/canvas/test/webgl/conformance/texture-npot.html
content/canvas/test/webgl/conformance/texture-transparent-pixels-initialized.html
content/canvas/test/webgl/conformance/uniform-location.html
content/canvas/test/webgl/conformance/uninitialized-test.html
content/canvas/test/webgl/conformance/viewport-unchanged-upon-resize.html
content/canvas/test/webgl/conformance/webgl-specific.html
content/canvas/test/webgl/delete-quickCheckAPI.patch
content/canvas/test/webgl/disable-gl-min-textures.patch
content/canvas/test/webgl/dont-load-image-from-internet.patch
content/canvas/test/webgl/extra/webgl-info.html
content/canvas/test/webgl/failing_tests_linux.txt
content/canvas/test/webgl/failing_tests_mac.txt
content/canvas/test/webgl/failing_tests_windows.txt
content/canvas/test/webgl/increase-timeout-delays.patch
content/canvas/test/webgl/more/00_testFIXME_list.txt
content/canvas/test/webgl/more/00_test_list.txt
content/canvas/test/webgl/more/README.md
content/canvas/test/webgl/more/all_tests.html
content/canvas/test/webgl/more/all_tests_linkonly.html
content/canvas/test/webgl/more/all_tests_sequential.html
content/canvas/test/webgl/more/conformance/badArgsArityLessThanArgc.html
content/canvas/test/webgl/more/conformance/constants.html
content/canvas/test/webgl/more/conformance/fuzzTheAPI.html
content/canvas/test/webgl/more/conformance/getContext.html
content/canvas/test/webgl/more/conformance/methods.html
content/canvas/test/webgl/more/conformance/quickCheckAPI.html
content/canvas/test/webgl/more/conformance/quickCheckAPI.js
content/canvas/test/webgl/more/conformance/quickCheckAPIBadArgs.html
content/canvas/test/webgl/more/conformance/webGLArrays.html
content/canvas/test/webgl/more/demos/opengl_web.html
content/canvas/test/webgl/more/demos/video.html
content/canvas/test/webgl/more/functions/bindBuffer.html
content/canvas/test/webgl/more/functions/bindBufferBadArgs.html
content/canvas/test/webgl/more/functions/bindFramebufferLeaveNonZero.html
content/canvas/test/webgl/more/functions/bufferData.html
content/canvas/test/webgl/more/functions/bufferDataBadArgs.html
content/canvas/test/webgl/more/functions/bufferSubData.html
content/canvas/test/webgl/more/functions/bufferSubDataBadArgs.html
content/canvas/test/webgl/more/functions/copyTexImage2D.html
content/canvas/test/webgl/more/functions/copyTexImage2DBadArgs.html
content/canvas/test/webgl/more/functions/copyTexSubImage2D.html
content/canvas/test/webgl/more/functions/copyTexSubImage2DBadArgs.html
content/canvas/test/webgl/more/functions/deleteBufferBadArgs.html
content/canvas/test/webgl/more/functions/drawArrays.html
content/canvas/test/webgl/more/functions/drawArraysOutOfBounds.html
content/canvas/test/webgl/more/functions/drawElements.html
content/canvas/test/webgl/more/functions/drawElementsBadArgs.html
content/canvas/test/webgl/more/functions/getImageData.html
content/canvas/test/webgl/more/functions/getImageDataBadArgs.html
content/canvas/test/webgl/more/functions/isTests.html
content/canvas/test/webgl/more/functions/linkProgramBadArgs.html
content/canvas/test/webgl/more/functions/readPixels.html
content/canvas/test/webgl/more/functions/readPixelsBadArgs.html
content/canvas/test/webgl/more/functions/texImage2D.html
content/canvas/test/webgl/more/functions/texImage2DBadArgs.html
content/canvas/test/webgl/more/functions/texImage2DHTML.html
content/canvas/test/webgl/more/functions/texImage2DHTMLBadArgs.html
content/canvas/test/webgl/more/functions/texSubImage2D.html
content/canvas/test/webgl/more/functions/texSubImage2DBadArgs.html
content/canvas/test/webgl/more/functions/texSubImage2DHTML.html
content/canvas/test/webgl/more/functions/texSubImage2DHTMLBadArgs.html
content/canvas/test/webgl/more/functions/uniformMatrix.html
content/canvas/test/webgl/more/functions/uniformMatrixBadArgs.html
content/canvas/test/webgl/more/functions/uniformf.html
content/canvas/test/webgl/more/functions/uniformfBadArgs.html
content/canvas/test/webgl/more/functions/uniformi.html
content/canvas/test/webgl/more/functions/uniformiBadArgs.html
content/canvas/test/webgl/more/functions/vertexAttrib.html
content/canvas/test/webgl/more/functions/vertexAttribBadArgs.html
content/canvas/test/webgl/more/functions/vertexAttribPointer.html
content/canvas/test/webgl/more/functions/vertexAttribPointerBadArgs.html
content/canvas/test/webgl/more/glsl/arrayOutOfBounds.html
content/canvas/test/webgl/more/glsl/longLoops.html
content/canvas/test/webgl/more/glsl/uniformOutOfBounds.html
content/canvas/test/webgl/more/glsl/unusedAttribsUniforms.html
content/canvas/test/webgl/more/index.html
content/canvas/test/webgl/more/performance/CPUvsGPU.html
content/canvas/test/webgl/more/performance/bandwidth.html
content/canvas/test/webgl/more/performance/jsGCPause.html
content/canvas/test/webgl/more/performance/jsMatrixMult.html
content/canvas/test/webgl/more/performance/jsToGLOverhead.html
content/canvas/test/webgl/more/unit.css
content/canvas/test/webgl/more/unit.js
content/canvas/test/webgl/more/util.js
content/canvas/test/webgl/resources/desktop-gl-constants.js
content/canvas/test/webgl/resources/js-test-pre.js
content/canvas/test/webgl/resources/webgl-test-harness.js
content/canvas/test/webgl/test_webgl_conformance_test_suite.html
content/canvas/test/webgl/webgl-conformance-tests.html
--- a/content/canvas/test/webgl/00_test_list.txt
+++ b/content/canvas/test/webgl/00_test_list.txt
@@ -1,5 +1,5 @@
-// files that end in .txt list other tests
-// other lines are assumed to be .html files
-
-conformance/00_test_list.txt
-
+// files that end in .txt list other tests
+// other lines are assumed to be .html files
+
+conformance/00_test_list.txt
+
--- a/content/canvas/test/webgl/README.mozilla
+++ b/content/canvas/test/webgl/README.mozilla
@@ -1,24 +1,13 @@
-This is a local copy of the WebGL conformance suite.
-
-  SVN revision: 13113
+This is a local copy of the WebGL conformance suite, version 1.0.0.
 
 The canonical location for this testsuite is:
 
-  https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/
+  https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/conformance-suites/1.0.0/webgl-conformance-tests.html
 
 All files and directories in this directory, with the exceptions listed below, come from
 upstream and should not be modified without corresponding upstream fixes and/or a
-patch file in the "patches" directory. The exceptions (the Mozilla-specific files) are:
+patch file in this directory. The exceptions (the Mozilla-specific files) are:
  * README.mozilla (this file)
- * failing_tests.txt
+ * failing_tests_*.txt
  * Makefile.in
- * the "mozilla" directory, if any
- * the "patches" directory, if any
-
-Moreover, the files named 00_test_list.txt are temporarily renamed to 00_testFIXME_list.txt to work around bug 584611, quote:
-> In mochitest, we tell people that mochitests should start with test_.  The
-> actual truth is that we match anything with a test_ in it.
-
-The "mozilla" directory contains integration of this test suite into Mozilla's
-testing system.
-
+ * *.patch files, if any
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/README.txt
@@ -0,0 +1,28 @@
+Welcome to the WebGL Conformance Test Suite
+===========================================
+
+This is the initial release of the WebGL conformance test suite.
+
+NOTE TO USERS: Unless you are a WebGL implementor, there is no need to submit
+a conformance result using this process.  Should you discover bugs in your
+browser's WebGL implementation, either via this test suite or otherwise,
+please report them to your browser vendor's bug tracking system.
+
+FOR WEBGL IMPLEMENTORS: Please follow the isntructions below to create
+a formal conformance submission.'
+
+1) Open webgl-conformance-tests.html in your target browser
+
+2) Press the "run tests" button
+
+3) At the end of the run, press "display text summary"
+
+4) Verify that the User Agent and WebGL renderer strings identify your browser and target correctly.
+
+5) Copy the contents of the text summary (starting with "WebGL Conformance Test Results") and send via email to
+   --- NEED ADDRESS HERE --- @khronos.org
+
+
+- Version 1.0.0
+- February 24, 2011
+
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/00_test_list.txt
@@ -1,17 +1,20 @@
 array-buffer-crash.html
 array-buffer-view-crash.html
 array-unit-tests.html
 bad-arguments-test.html
 buffer-bind-test.html
 buffer-data-array-buffer.html
+buffer-preserve-test.html
 canvas-test.html
 constants.html
 context-attributes-alpha-depth-stencil-antialias.html
+context-lost-restored.html
+context-lost.html
 context-type-test.html
 copy-tex-image-and-sub-image-2d.html
 draw-arrays-out-of-bounds.html
 draw-elements-out-of-bounds.html
 error-reporting.html
 framebuffer-object-attachment.html
 framebuffer-test.html
 get-active-test.html
@@ -19,66 +22,78 @@ gl-bind-attrib-location-test.html
 gl-clear.html
 gl-drawelements.html
 gl-enable-enum-test.html
 gl-enable-vertex-attrib.html
 gl-enum-tests.html
 gl-get-active-attribute.html
 gl-get-active-uniform.html
 gl-get-calls.html
+gl-getshadersource.html
 gl-getstring.html
+gl-min-attribs.html
+# gl-min-textures.html
+gl-min-uniforms.html
 gl-object-get-calls.html
 gl-pixelstorei.html
 gl-scissor-test.html
 gl-shader-test.html
 gl-teximage.html
 gl-uniform-arrays.html
 gl-uniform-bool.html
 gl-uniformmatrix4fv.html
 gl-unknown-uniform.html
 gl-vertex-attrib.html
+gl-vertex-attrib-zero-issues.html
 gl-vertexattribpointer.html
-glsl-2types-of-textures-on-same-unit.html
+#glsl-2types-of-textures-on-same-unit.html
 glsl-conformance.html
 incorrect-context-object-behaviour.html
 index-validation-copies-indices.html
 index-validation-crash-with-buffer-sub-data.html
 index-validation-verifies-too-many-indices.html
 index-validation-with-resized-buffer.html
 index-validation.html
+instanceof-test.html
 invalid-UTF-16.html
 invalid-passed-params.html
 is-object.html
 methods.html
 more-than-65536-points.html
 null-object-behaviour.html
 null-uniform-location.html
 object-deletion-behaviour.html
+oes-standard-derivatives.html
+oes-texture-float.html
+oes-vertex-array-object.html
 origin-clean-conformance.html
 point-size.html
 program-test.html
 read-pixels-pack-alignment.html
 read-pixels-test.html
 renderbuffer-initialization.html
 resource-sharing-test.html
 tex-image-and-sub-image-2d-with-array-buffer-view.html
 tex-image-and-sub-image-2d-with-image-data.html
 tex-image-and-sub-image-2d-with-image.html
 tex-image-and-sub-image-2d-with-video.html
 tex-image-and-uniform-binding-bugs.html
 tex-image-with-format-and-type.html
 tex-image-with-invalid-data.html
 tex-input-validation.html
+tex-sub-image-2d-bad-args.html
 tex-sub-image-2d.html
 texparameter-test.html
 texture-active-bind-2.html
 texture-active-bind.html
 texture-complete.html
 texture-formats-test.html
 texture-npot.html
 texture-transparent-pixels-initialized.html
 triangle.html
 type-conversion-test.html
 uniform-location.html
 uniform-samplers-test.html
 uninitialized-test.html
 viewport-unchanged-upon-resize.html
 webgl-specific.html
+more/00_test_list.txt
+
--- a/content/canvas/test/webgl/conformance/array-unit-tests.html
+++ b/content/canvas/test/webgl/conformance/array-unit-tests.html
@@ -182,16 +182,105 @@ function testConstructWithTypedArrayOfSi
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
 //
+// Test cases for integral types.
+// Some JavaScript engines need separate copies of this code in order
+// to exercise all of their optimized code paths.
+//
+
+function testIntegralArrayTruncationBehavior(type, name, unsigned) {
+  running('test integral array truncation behavior for ' + name);
+
+  var sourceData;
+  var expectedResults;
+
+  if (unsigned) {
+    sourceData = [0.6, 10.6];
+    expectedResults = [0, 10];
+  } else {
+    sourceData = [0.6, 10.6, -0.6, -10.6];
+    expectedResults = [0, 10, 0, -10];
+  }
+
+  var numIterations = 10;
+  var array = new type(numIterations);
+
+  // The code block in each of the case statements below is identical, but some
+  // JavaScript engines need separate copies in order to exercise all of
+  // their optimized code paths.
+
+  try {
+    switch (type) {
+    case Int8Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Int16Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Int32Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Uint8Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Uint16Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Uint32Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    default:
+      fail("Unhandled type");
+      break;
+    }
+
+    pass();
+  } catch (e) {
+    fail(e);
+  }
+}
+
+
+//
 // Test cases for both signed and unsigned types
 //
 
 function testGetWithOutOfRangeIndices(type, name) {
     debug('Testing ' + name + ' GetWithOutOfRangeIndices');
     // See below for declaration of this global variable
     array = new type([2, 3]);
     shouldBeUndefined("array[2]");
@@ -309,18 +398,18 @@ function negativeTestSetFromArray(type, 
     } catch (e) {
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
-function testSlice(type, name) {
-  running('test ' + name + ' Slice');
+function testSubarray(type, name) {
+  running('test ' + name + ' Subarray');
   try {
     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     var subarray = array.subarray(0, 5);
     assertEq('subarray.length', 5, subarray.length);
     for (var i = 0; i < 5; i++) {
       assertEq('Element ' + i, i, subarray[i]);
     }
     subarray = array.subarray(4, 10);
@@ -329,18 +418,18 @@ function testSlice(type, name) {
       assertEq('Element ' + i, 4 + i, subarray[i]);
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
-function negativeTestSlice(type, name) {
-  running('negativeTest ' + name + ' Slice');
+function negativeTestSubarray(type, name) {
+  running('negativeTest ' + name + ' Subarray');
   try {
     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     subarray = array.subarray(5, 11);
     if (subarray.length != 5) {
       fail();
       return;
     }
     subarray = array.subarray(10, 10);
@@ -349,27 +438,41 @@ function negativeTestSlice(type, name) {
       return;
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
-function testBoundaryConditions(type, name, lowValue, expectedLowValue, highValue, expectedHighValue) {
-  running('test ' + name + ' BoundaryConditions(' +
-          lowValue + ', ' + expectedLowValue + ', ' +
-          highValue + ', ' + expectedHighValue + ')');
+function testSetBoundaryConditions(type, name, testValues, expectedValues) {
+  running('test ' + name + ' SetBoundaryConditions');
   try {
     var array = new type(1);
     assertEq('Array length', 1, array.length);
-    array[0] = lowValue;
-    assertEq('Element 0', expectedLowValue, array[0]);
-    array[0] = highValue;
-    assertEq('Element 0', expectedHighValue, array[0]);
+    for (var ii = 0; ii < testValues.length; ++ii) {
+      for (var jj = 0; jj < 10; ++jj) {
+        array[0] = testValues[ii];
+        assertEq('Element 0', expectedValues[ii], array[0]);
+      }
+    }
+    pass();
+  } catch (e) {
+    fail(e);
+  }
+}
+
+function testConstructionBoundaryConditions(type, name, testValues, expectedValues) {
+  running('test ' + name + ' ConstructionBoundaryConditions');
+  try {
+    var array = new type(testValues);
+    assertEq('Array length', testValues.length, array.length);
+    for (var ii = 0; ii < testValues.length; ++ii) {
+      assertEq('Element ' + ii, expectedValues[ii], array[ii]);
+    }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
 function testConstructionWithNullBuffer(type, name) {
     var array;
@@ -471,18 +574,18 @@ function testConstructionWithBothArrayBu
         testFailed("Array lengths DID NOT MATCH with explicit and implicit creation of ArrayBuffer");
     }
 }
 
 // These need to be global for shouldBe to see them
 var array;
 var typeSize;
 
-function testSlicingWithOutOfRangeValues(type, name, sz) {
-    debug("Testing slicing of " + name);
+function testSubarrayWithOutOfRangeValues(type, name, sz) {
+    debug("Testing subarray of " + name);
     try {
         var buffer = new ArrayBuffer(32);
         array = new type(buffer);
         typeSize = sz;
         shouldBe("array.length", "32 / typeSize");
         try {
             shouldBe("array.subarray(4, 0x3FFFFFFF).length", "(32 / typeSize) - 4");
             shouldBe("array.subarray(4, -2147483648).length", "0");
@@ -492,37 +595,37 @@ function testSlicingWithOutOfRangeValues
                 // Full byte offset is +1 larger than the maximum unsigned long int.
                 // Make sure subarray() still handles it correctly.  Otherwise overflow would happen and
                 // offset would be 0, and array.length array.length would incorrectly be 1.
                 var start = 4294967296 / sz - 2;
                 array = array.subarray(start, start + 1);
                 shouldBe("array.length", "0");
             }
         } catch (e) {
-            testFailed("Slicing of " + name + " threw exception");
+            testFailed("Subarray of " + name + " threw exception");
         }
     } catch (e) {
         testFailed("Exception: " + e);
     }
 }
 
-function testSlicingWithDefaultValues(type, name, sz) {
-    debug("Testing slicing with default inputs of " + name);
+function testSubarrayWithDefaultValues(type, name, sz) {
+    debug("Testing subarray with default inputs of " + name);
     try {
         var buffer = new ArrayBuffer(32);
         array = new type(buffer);
         typeSize = sz;
         shouldBe("array.length", "32 / typeSize");
         try {
             shouldBe("array.subarray(0).length", "(32 / typeSize)");
             shouldBe("array.subarray(2).length", "(32 / typeSize) - 2");
             shouldBe("array.subarray(-2).length", "2");
             shouldBe("array.subarray(-2147483648).length", "(32 / typeSize)");
         } catch (e) {
-            testFailed("Slicing of " + name + " threw exception");
+            testFailed("Subarray of " + name + " threw exception");
         }
     } catch (e) {
         testFailed("Exception: " + e);
     }
 }
 
 function testSettingFromArrayWithOutOfRangeOffset(type, name) {
     var webglArray = new type(32);
@@ -579,76 +682,151 @@ function negativeTestGetAndSetMethods(ty
     var output = "array.set(0, 1) ";
     if (exceptionThrown) {
         testPassed(output + "threw exception.");
     } else {
         testFailed(output + "did not throw exception.");
     }
 }
 
+function testNaNConversion(type, name) {
+  running('test storing NaN in ' + name);
+
+  var array = new type([1, 1]);
+  var results = [];
+
+  // The code block in each of the case statements below is identical, but some
+  // JavaScript engines need separate copies in order to exercise all of
+  // their optimized code paths.
+  try {
+    switch (type) {
+    case Float32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int8Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int16Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint8Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint16Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    default:
+      fail("Unhandled type");
+      break;
+    }
+
+    // Some types preserve NaN values; all other types convert NaN to zero.
+    if (type === Float32Array) {
+      assert('initial NaN preserved', isNaN(new type([NaN])[0]));
+      for (var i = 0; i < array.length; ++i)
+        assert('NaN preserved via setter', isNaN(results[i]));
+    } else {
+      assertEq('initial NaN converted to zero', 0, new type([NaN])[0]);
+      for (var i = 0; i < array.length; ++i)
+        assertEq('NaN converted to zero by setter', 0, results[i]);
+    }
+
+    pass();
+  } catch (e) {
+      fail(e);
+  }
+}
+
 //
 // Test driver
 //
 
 function runTests() {
   allPassed = true;
 
   // The "name" attribute is a concession to browsers which don't
   // implement the "name" property on function objects
   var testCases =
     [ {name: "Float32Array",
        unsigned: false,
+       integral: false,
        elementSizeInBytes: 4,
-       low: -500.5,
-       expectedLow: -500.5,
-       high: 500.5,
-       expectedHigh: 500.5},
+       testValues:     [ -500.5, 500.5 ],
+       expectedValues: [ -500.5, 500.5 ]
+      },
       {name: "Int8Array",
        unsigned: false,
+       integral: true,
        elementSizeInBytes: 1,
-       low: -128,
-       expectedLow: -128,
-       high: 127,
-       expectedHigh: 127},
+       testValues:     [ -128, 127, -129,  128 ],
+       expectedValues: [ -128, 127,  127, -128 ]
+      },
       {name: "Int16Array",
        unsigned: false,
+       integral: true,
        elementSizeInBytes: 2,
-       low: -32768,
-       expectedLow: -32768,
-       high: 32767,
-       expectedHigh: 32767},
+       testValues:     [ -32768, 32767, -32769,  32768 ],
+       expectedValues: [ -32768, 32767,  32767, -32768 ]
+      },
       {name: "Int32Array",
        unsigned: false,
+       integral: true,
        elementSizeInBytes: 4,
-       low: -2147483648,
-       expectedLow: -2147483648,
-       high: 2147483647,
-       expectedHigh: 2147483647},
+       testValues:     [ -2147483648, 2147483647, -2147483649,  2147483648 ],
+       expectedValues: [ -2147483648, 2147483647,  2147483647, -2147483648 ]
+      },
       {name: "Uint8Array",
        unsigned: true,
+       integral: true,
        elementSizeInBytes: 1,
-       low: 0,
-       expectedLow: 0,
-       high: 255,
-       expectedHigh: 255},
+       testValues:     [ 0, 255,  -1, 256 ],
+       expectedValues: [ 0, 255, 255,   0 ]
+      },
       {name: "Uint16Array",
        unsigned: true,
+       integral: true,
        elementSizeInBytes: 2,
-       low: 0,
-       expectedLow: 0,
-       high: 65535,
-       expectedHigh: 65535},
+       testValues:     [ 0, 65535,    -1, 65536 ],
+       expectedValues: [ 0, 65535, 65535,     0 ]
+      },
       {name: "Uint32Array",
        unsigned: true,
+       integral: true,
        elementSizeInBytes: 4,
-       low: 0,
-       expectedLow: 0,
-       high: 4294967295,
-       expectedHigh: 4294967295} ];
-
+       testValues:     [ 0, 4294967295,         -1, 4294967296 ],
+       expectedValues: [ 0, 4294967295, 4294967295,          0 ]
+      }
+    ];
   for (var i = 0; i < testCases.length; i++) {
     var testCase = testCases[i];
     running(testCase.name);
     if (!(testCase.name in window)) {
         fail("does not exist");
         continue;
     }
     var type = window[testCase.name];
@@ -657,43 +835,49 @@ function runTests() {
       testSetAndGet10To1(type, name);
       testConstructWithArrayOfUnsignedValues(type, name);
       testConstructWithTypedArrayOfUnsignedValues(type, name);
     } else {
       testSetAndGetPos10ToNeg10(type, name);
       testConstructWithArrayOfSignedValues(type, name);
       testConstructWithTypedArrayOfSignedValues(type, name);
     }
+    if (testCase.integral) {
+      testIntegralArrayTruncationBehavior(type, name, testCase.unsigned);
+    }
     testGetWithOutOfRangeIndices(type, name);
     testOffsetsAndSizes(type, name, testCase.elementSizeInBytes);
     testSetFromTypedArray(type, name);
     negativeTestSetFromTypedArray(type, name);
     testSetFromArray(type, name);
     negativeTestSetFromArray(type, name);
-    testSlice(type, name);
-    negativeTestSlice(type, name);
-    testBoundaryConditions(type,
-                           name,
-                           testCase.low,
-                           testCase.expectedLow,
-                           testCase.high,
-                           testCase.expectedHigh);
+    testSubarray(type, name);
+    negativeTestSubarray(type, name);
+    testSetBoundaryConditions(type,
+                              name,
+                              testCase.testValues,
+                              testCase.expectedValues);
+    testConstructionBoundaryConditions(type,
+                                       name,
+                                       testCase.testValues,
+                                       testCase.expectedValues);
     testConstructionWithNullBuffer(type, name);
     testConstructionWithOutOfRangeValues(type, name);
     testConstructionWithNegativeOutOfRangeValues(type, name);
     testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
     testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes);
     testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);
     testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes);
-    testSlicingWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
-    testSlicingWithDefaultValues(type, name, testCase.elementSizeInBytes);
+    testSubarrayWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
+    testSubarrayWithDefaultValues(type, name, testCase.elementSizeInBytes);
     testSettingFromArrayWithOutOfRangeOffset(type, name);
     testSettingFromFakeArrayWithOutOfRangeLength(type, name);
     testSettingFromTypedArrayWithOutOfRangeOffset(type, name);
     negativeTestGetAndSetMethods(type, name);
+    testNaNConversion(type, name);
   }
 
   printSummary();
 }
 
 runTests();
 successfullyParsed = true;
 
--- a/content/canvas/test/webgl/conformance/buffer-data-array-buffer.html
+++ b/content/canvas/test/webgl/conformance/buffer-data-array-buffer.html
@@ -28,25 +28,34 @@ var buf = gl.createBuffer();
 shouldBeNonNull(buf);
 
 gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
 glErrorShouldBe(gl, gl.INVALID_OPERATION);
 
 gl.bindBuffer(gl.ARRAY_BUFFER, buf);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
+gl.bufferData(gl.ARRAY_BUFFER, -10, gl.STATIC_DRAW);
+glErrorShouldBe(gl, gl.INVALID_VALUE);
+
 // This should not crash, but the selection of the overload is ambiguous per Web IDL.
 gl.bufferData(gl.ARRAY_BUFFER, null, gl.STATIC_DRAW);
 gl.getError();
 
 gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 array = new ArrayBuffer(64);
 
+gl.bufferSubData(gl.ARRAY_BUFFER, -10, array);
+glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+gl.bufferSubData(gl.ARRAY_BUFFER, -10, new Float32Array(8));
+glErrorShouldBe(gl, gl.INVALID_VALUE);
+
 gl.bufferSubData(gl.ARRAY_BUFFER, 10, array);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 gl.bufferSubData(gl.ARRAY_BUFFER, 10, null);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 successfullyParsed = true;
 </script>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/buffer-preserve-test.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>WebGL required buffer clear behaviour test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+<style type="text/css">
+body {
+    height: 3000px;
+}
+</style>
+<script type="text/javascript">
+
+var iter = 0;
+var gl;
+
+var wtu = WebGLTestUtils;
+
+function checkPixel(gl, x, y, c) {
+    var buf = new Uint8Array(4);
+    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+    return buf[0] == c[0] &&
+	buf[1] == c[1] &&
+	buf[2] == c[2] &&
+	buf[3] == c[3];
+}
+
+function timer() {
+    if (iter == 0) {
+	// some random hacky stuff to make sure that we get a compositing step
+	window.scrollBy(0, 10);
+	window.scrollBy(0, -10);
+	iter++;
+
+	setTimeout(timer, 500);
+    } else if (iter == 1) {
+	// scissor was set earlier
+	gl.clearColor(0, 0, 1, 1);
+	gl.clear(gl.COLOR_BUFFER_BIT);
+
+	wtu.checkCanvasRect(gl, 0, 10, 10, 10, [0, 0, 255, 255], "cleared corner should be blue, stencil should be preserved");
+	wtu.checkCanvasRect(gl, 0, 0, 10, 10, [0, 0, 0, 0], "remainder of buffer should be cleared");
+
+	finishTest();
+    }
+}
+
+function go() {
+    description("This test ensures WebGL implementations correctly clear the drawing buffer on composite if preserveDrawingBuffer is false.");
+
+    debug("");
+
+    gl = create3DContext(document.getElementById("c"));
+    if (!gl) {
+	finishTest();
+	return;
+    }
+
+    shouldBeTrue('gl.getContextAttributes().preserveDrawingBuffer == false');
+
+    gl.clearColor(1, 0, 0, 1);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+    // enable scissor here, before compositing, to make sure it's correctly
+    // ignored and restored
+    gl.scissor(0, 10, 10, 10);
+    gl.enable(gl.SCISSOR_TEST);
+
+    setTimeout(timer, 500);
+}
+
+window.addEventListener("load", go, false);
+
+successfullyParsed = true;
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
+<div id="console"></div>
+</body>
+</html>
\ No newline at end of file
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/canvas-test.html
+++ b/content/canvas/test/webgl/conformance/canvas-test.html
@@ -24,16 +24,17 @@ if (window.initNonKhronosFramework) {
   window.initNonKhronosFramework(true);
 }
 
 description("This test ensures WebGL implementations interact correctly with the canvas tag.");
 
 debug("");
 debug("Canvas.getContext");
 
+var err;
 var canvas = document.getElementById("canvas");
 var canvas2d = document.getElementById("canvas2d");
 var ctx2d = canvas2d.getContext("2d");
 var gl = create3DContext(canvas);
 if (!gl) {
   testFailed("context does not exist");
 } else {
   testPassed("context exists");
@@ -153,48 +154,42 @@ if (!gl) {
       // Check that the clear color does not change.
       // Check that the color mask does not change.
       debug("");
       debug("change the actual size of the canvas and see that the viewport does not change");
       gl.clearColor(0.25, 0.5, 0.75, 1);
       gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
       checkCanvasContentIs(64, 128, 192, 255);
       gl.colorMask(0,0,0,0);
+      glErrorShouldBe(gl, gl.NO_ERROR, "No GL errors before resizing the canvas");
       canvas.width = 400;
       canvas.height = 10;
-
-      var v = gl.getParameter(gl.COLOR_CLEAR_VALUE);
-      assertMsg(isAboutEqual(v[0], 0.25) &&
-                isAboutEqual(v[1], 0.5) &&
-                isAboutEqual(v[2], 0.75) &&
-                isAboutEqual(v[3], 1),
-                "gl.clearColor should not change after canvas resize");
-      v = gl.getParameter(gl.COLOR_WRITEMASK);
-      assertMsg(isAboutEqual(v[0], 0) &&
-                isAboutEqual(v[1], 0) &&
-                isAboutEqual(v[2], 0) &&
-                isAboutEqual(v[3], 0),
-                "gl.colorMask should not change after canvas resize");
-      shouldBe('getViewport()', '"0,0,300,150"');
-      checkCanvasContentIs(0, 0, 0, 0);
+      err = gl.getError();
+      // Some implementations might lost the context when resizing
+      if (err != gl.CONTEXT_LOST_WEBGL) {
+        shouldBe("err", "gl.NO_ERROR");
+        var v = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+        assertMsg(isAboutEqual(v[0], 0.25) &&
+                  isAboutEqual(v[1], 0.5) &&
+                  isAboutEqual(v[2], 0.75) &&
+                  isAboutEqual(v[3], 1),
+                  "gl.clearColor should not change after canvas resize");
+        v = gl.getParameter(gl.COLOR_WRITEMASK);
+        assertMsg(isAboutEqual(v[0], 0) &&
+                  isAboutEqual(v[1], 0) &&
+                  isAboutEqual(v[2], 0) &&
+                  isAboutEqual(v[3], 0),
+                  "gl.colorMask should not change after canvas resize");
+        shouldBe('getViewport()', '"0,0,300,150"');
+        checkCanvasContentIs(0, 0, 0, 0);
+      }
 
       debug("");
-      successfullyParsed = true;
-      var epilogue = document.createElement("script");
-      epilogue.onload = finish;
-      epilogue.src = "../resources/js-test-post.js";
-      document.body.appendChild(epilogue);
+      finishTest();
     }
    }, 1000/30);
 }
-
-function finish() {
-  if (window.nonKhronosFrameworkNotifyDone) {
-    window.nonKhronosFrameworkNotifyDone();
-  }
-}
-
 </script>
 <script>
 </script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/constants.html
+++ b/content/canvas/test/webgl/conformance/constants.html
@@ -240,19 +240,17 @@ MAX_VERTEX_TEXTURE_IMAGE_UNITS   : 0x8B4
 MAX_TEXTURE_IMAGE_UNITS          : 0x8872,
 MAX_FRAGMENT_UNIFORM_VECTORS     : 0x8DFD,
 SHADER_TYPE                      : 0x8B4F,
 DELETE_STATUS                    : 0x8B80,
 LINK_STATUS                      : 0x8B82,
 VALIDATE_STATUS                  : 0x8B83,
 ATTACHED_SHADERS                 : 0x8B85,
 ACTIVE_UNIFORMS                  : 0x8B86,
-ACTIVE_UNIFORM_MAX_LENGTH        : 0x8B87,
 ACTIVE_ATTRIBUTES                : 0x8B89,
-ACTIVE_ATTRIBUTE_MAX_LENGTH      : 0x8B8A,
 SHADING_LANGUAGE_VERSION         : 0x8B8C,
 CURRENT_PROGRAM                  : 0x8B8D,
     
     /* StencilFunction */
 NEVER                          : 0x0200,
 LESS                           : 0x0201,
 EQUAL                          : 0x0202,
 LEQUAL                         : 0x0203,
@@ -270,17 +268,16 @@ DECR                           : 0x1E03,
 INVERT                         : 0x150A,
 INCR_WRAP                      : 0x8507,
 DECR_WRAP                      : 0x8508,
     
     /* StringName */
 VENDOR                         : 0x1F00,
 RENDERER                       : 0x1F01,
 VERSION                        : 0x1F02,
-EXTENSIONS                     : 0x1F03,
     
     /* TextureMagFilter */
 NEAREST                        : 0x2600,
 LINEAR                         : 0x2601,
     
     /* TextureMinFilter */
     /*      NEAREST */
     /*      LINEAR */
@@ -372,18 +369,16 @@ VERTEX_ATTRIB_ARRAY_SIZE           : 0x8
 VERTEX_ATTRIB_ARRAY_STRIDE         : 0x8624,
 VERTEX_ATTRIB_ARRAY_TYPE           : 0x8625,
 VERTEX_ATTRIB_ARRAY_NORMALIZED     : 0x886A,
 VERTEX_ATTRIB_ARRAY_POINTER        : 0x8645,
 VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
     
     /* Shader Source */
 COMPILE_STATUS                 : 0x8B81,
-INFO_LOG_LENGTH                : 0x8B84,
-SHADER_SOURCE_LENGTH           : 0x8B88,
 SHADER_COMPILER                : 0x8DFA,
     
     /* Shader Precision-Specified Types */
 LOW_FLOAT                      : 0x8DF0,
 MEDIUM_FLOAT                   : 0x8DF1,
 HIGH_FLOAT                     : 0x8DF2,
 LOW_INT                        : 0x8DF3,
 MEDIUM_INT                     : 0x8DF4,
--- a/content/canvas/test/webgl/conformance/context-attributes-alpha-depth-stencil-antialias.html
+++ b/content/canvas/test/webgl/conformance/context-attributes-alpha-depth-stencil-antialias.html
@@ -207,28 +207,19 @@ function runTest()
     testAlpha(false);
     testDepth(true);
     testDepth(false);
     testStencil(true);
     testStencil(false);
     testAntialias(true);
     testAntialias(false);
 
-    successfullyParsed = true;
-    var epilogue = document.createElement("script");
-    epilogue.onload = finish;
-    epilogue.src = "../resources/js-test-post.js";
-    document.body.appendChild(epilogue);
+    finishTest()
 }
 
-function finish() {
-    if (window.nonKhronosFrameworkNotifyDone) {
-        window.nonKhronosFrameworkNotifyDone();
-    }
-}
 </script>
 </head>
 <body onload="init()">
 <canvas id="alphaOn" width="1px" height="1px"></canvas>
 <canvas id="alphaOff" width="1px" height="1px"></canvas>
 <canvas id="depthOn" width="1px" height="1px"></canvas>
 <canvas id="depthOff" width="1px" height="1px"></canvas>
 <canvas id="stencilOn" width="1px" height="1px"></canvas>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/context-lost-restored.html
@@ -0,0 +1,130 @@
+<html>
+<head>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+var extension_name = "WEBKIT_lose_context";
+var extension;
+var bufferObjects;
+var program;
+var texture;
+var texColor = [255, 10, 20, 255];
+
+function init()
+{
+    if (window.initNonKhronosFramework) {
+        window.initNonKhronosFramework(true);
+    }
+
+    description("Tests behavior under a restored context");
+
+    canvas = document.getElementById("canvas");
+    canvas.addEventListener("webglcontextlost", testLostContext, false);
+    canvas.addEventListener("webglcontextrestored", testRestoredContext, false);
+
+    gl = wtu.create3DContext(canvas);
+    shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+    extension = gl.getExtension(extension_name);
+    if (!extension) {
+        debug(extension_name + " extension not found.");
+        finish();
+        return;
+    }
+
+    testOriginalContext();
+    extension.loseContext();
+}
+
+function testRendering()
+{
+    gl.clearColor(0, 0, 0, 255);
+    gl.colorMask(1, 1, 1, 0);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+    program = wtu.setupSimpleTextureProgram(gl);
+    bufferObjects = wtu.setupUnitQuad(gl);
+    texture = wtu.createColoredTexture(gl, canvas.width, canvas.height, texColor);
+
+    gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+    wtu.drawQuad(gl, [0, 0, 0, 255]);
+
+    var compare = texColor.slice(0, 3);
+    wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, compare, "shouldBe " + compare);
+
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function testOriginalContext()
+{
+    debug("Test valid context");
+    shouldBeFalse("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+    testRendering();
+    debug("");
+}
+
+function testLostContext()
+{
+    debug("Test lost context");
+    shouldBeTrue("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+    debug("");
+}
+
+function testResources(expected)
+{
+    var tests = [
+        "gl.bindTexture(gl.TEXTURE_2D, texture)",
+        "gl.useProgram(program)",
+        "gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[0])",
+    ];
+
+    for (var i = 0; i < tests.length; ++i)
+        shouldGenerateGLError(gl, expected, tests[i]);
+}
+
+function testRestoredContext()
+{
+    debug("Test restored context");
+    shouldBeFalse("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+
+    // Validate that using old resources fails.
+    testResources(gl.INVALID_OPERATION);
+
+    testRendering();
+
+    // Validate new resources created in testRendering().
+    testResources(gl.NO_ERROR);
+    debug("");
+
+    finish();
+}
+
+function finish() {
+    successfullyParsed = true;
+    var epilogue = document.createElement("script");
+    epilogue.onload = function() {
+        if (window.nonKhronosFrameworkNotifyDone)
+            window.nonKhronosFrameworkNotifyDone();
+    };
+    epilogue.src = "../resources/js-test-post.js";
+    document.body.appendChild(epilogue);
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="1px" height="1px"></canvas>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/context-lost.html
@@ -0,0 +1,318 @@
+<html>
+<head>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
+<script>
+var wtu;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+var extension_name = "WEBKIT_lose_context";
+var extension;
+
+var buffer;
+var framebuffer;
+var program;
+var renderbuffer;
+var shader;
+var texture;
+var uniformLocation;
+var arrayBuffer;
+var arrayBufferView
+var image;
+var video;
+var canvas2d;
+var ctx2d;
+var imageData;
+var float32array;
+var int32array;
+
+function init()
+{
+    wtu = WebGLTestUtils;
+    canvas = document.getElementById("canvas");
+    gl = wtu.create3DContext(canvas);
+    shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+    description("Tests behavior under a lost context");
+
+    if (window.initNonKhronosFramework) {
+        window.initNonKhronosFramework(true);
+    }
+
+    // call testValidContext() before checking for the extension, because this is where we check
+    // for the isContextLost() method, which we want to do regardless of the extension's presence.
+    testValidContext();
+
+    extension = gl.getExtension(extension_name);
+    if (!extension) {
+        debug(extension_name + " extension not found.");
+        finish();
+        return;
+    }
+
+    canvas.addEventListener("webglcontextlost", testLostContext, false);
+
+    loseContext();
+}
+
+function loseContext()
+{
+    debug("");
+    debug("Lose context");
+    shouldGenerateGLError(gl, gl.NO_ERROR, "extension.loseContext()");
+    debug("");
+}
+
+function testValidContext()
+{
+    debug("Test valid context");
+
+    shouldBeFalse("gl.isContextLost()");
+
+    arrayBuffer = new ArrayBuffer(4);
+    arrayBufferView = new Int8Array(arrayBuffer);
+
+    // Generate resources for testing.
+    buffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+    framebuffer = gl.createFramebuffer();
+    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+    program = wtu.setupSimpleTextureProgram(gl);
+    renderbuffer = gl.createRenderbuffer();
+    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+    shader = gl.createShader(gl.VERTEX_SHADER);
+    texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+
+    // Test is queries that will later be false
+    shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enable(gl.BLEND)");
+    shouldBeTrue("gl.isBuffer(buffer)");
+    shouldBeTrue("gl.isEnabled(gl.BLEND)");
+    shouldBeTrue("gl.isFramebuffer(framebuffer)");
+    shouldBeTrue("gl.isProgram(program)");
+    shouldBeTrue("gl.isRenderbuffer(renderbuffer)");
+    shouldBeTrue("gl.isShader(shader)");
+    shouldBeTrue("gl.isTexture(texture)");
+}
+
+function testLostContext()
+{
+    debug("Test lost context");
+
+    // Functions with special return values.
+    shouldBeTrue("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
+    shouldBe("gl.getAttribLocation(program, 'u_modelViewProjMatrix')", "-1");
+    shouldBe("gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)", "0");
+
+    // Test the extension itself.
+    shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.loseContext()");
+
+    image = document.createElement("image");
+    video = document.createElement("video");
+    canvas2d = document.createElement("canvas");
+    ctx2d = canvas2d.getContext("2d");
+    imageData = ctx2d.createImageData(1, 1);
+    float32array = new Float32Array(1);
+    int32array = new Int32Array(1);
+
+    // Functions returning void should return immediately.
+    // This is untestable, but we can at least be sure they cause no errors
+    // and the codepaths are exercised.
+    var voidTests = [
+        "gl.activeTexture(gl.TEXTURE0)",
+        "gl.attachShader(program, shader)",
+        "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)",
+        "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)",
+        "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)",
+        "gl.bindTexture(gl.TEXTURE_2D, texture)",
+        "gl.blendColor(1.0, 1.0, 1.0, 1.0)",
+        "gl.blendEquation(gl.FUNC_ADD)",
+        "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)",
+        "gl.blendFunc(gl.ONE)",
+        "gl.blendFuncSeparate(gl.ONE, gl.ONE)",
+        "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)",
+        "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)",
+        "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)",
+        "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)",
+        "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)",
+        "gl.clear(gl.COLOR_BUFFER_BIT)",
+        "gl.clearColor(1, 1, 1, 1)",
+        "gl.clearDepth(1)",
+        "gl.clearStencil(0)",
+        "gl.colorMask(1, 1, 1, 1)",
+        "gl.compileShader(shader)",
+        "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)",
+        "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)",
+        "gl.cullFace(gl.FRONT)",
+        "gl.deleteBuffer(buffer)",
+        "gl.deleteFramebuffer(framebuffer)",
+        "gl.deleteProgram(program)",
+        "gl.deleteRenderbuffer(renderbuffer)",
+        "gl.deleteShader(shader)",
+        "gl.deleteTexture(texture)",
+        "gl.depthFunc(gl.NEVER)",
+        "gl.depthMask(0)",
+        "gl.depthRange(0, 1)",
+        "gl.detachShader(program, shader)",
+        "gl.disable(gl.BLEND)",
+        "gl.disableVertexAttribArray(0)",
+        "gl.drawArrays(gl.POINTS, 0, 0)",
+        "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)",
+        "gl.enable(gl.BLEND)",
+        "gl.enableVertexAttribArray(0)",
+        "gl.finish()",
+        "gl.flush()",
+        "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)",
+        "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)",
+        "gl.frontFace(gl.CW)",
+        "gl.generateMipmap(gl.TEXTURE_2D)",
+        "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)",
+        "gl.lineWidth(0)",
+        "gl.linkProgram(program)",
+        "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)",
+        "gl.polygonOffset(0, 0)",
+        "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+        "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)",
+        "gl.sampleCoverage(0, 0)",
+        "gl.scissor(0, 0, 0, 0)",
+        "gl.shaderSource(shader, '')",
+        "gl.stencilFunc(gl.NEVER, 0, 0)",
+        "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)",
+        "gl.stencilMask(0)",
+        "gl.stencilMaskSeparate(gl.FRONT, 0)",
+        "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)",
+        "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video)",
+        "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
+        "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video)",
+        "gl.uniform1f(uniformLocation, 0)",
+        "gl.uniform1fv(uniformLocation, float32array)",
+        "gl.uniform1fv(uniformLocation, [0])",
+        "gl.uniform1i(uniformLocation, 0)",
+        "gl.uniform1iv(uniformLocation, int32array)",
+        "gl.uniform1iv(uniformLocation, [0])",
+        "gl.uniform2f(uniformLocation, 0, 0)",
+        "gl.uniform2fv(uniformLocation, float32array)",
+        "gl.uniform2fv(uniformLocation, [0, 0])",
+        "gl.uniform2i(uniformLocation, 0, 0)",
+        "gl.uniform2iv(uniformLocation, int32array)",
+        "gl.uniform2iv(uniformLocation, [0, 0])",
+        "gl.uniform3f(uniformLocation, 0, 0, 0)",
+        "gl.uniform3fv(uniformLocation, float32array)",
+        "gl.uniform3fv(uniformLocation, [0, 0, 0])",
+        "gl.uniform3i(uniformLocation, 0, 0, 0)",
+        "gl.uniform3iv(uniformLocation, int32array)",
+        "gl.uniform3iv(uniformLocation, [0, 0, 0])",
+        "gl.uniform4f(uniformLocation, 0, 0, 0, 0)",
+        "gl.uniform4fv(uniformLocation, float32array)",
+        "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])",
+        "gl.uniform4i(uniformLocation, 0, 0, 0, 0)",
+        "gl.uniform4iv(uniformLocation, int32array)",
+        "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])",
+        "gl.uniformMatrix2fv(uniformLocation, false, float32array)",
+        "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])",
+        "gl.uniformMatrix3fv(uniformLocation, false, float32array)",
+        "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])",
+        "gl.uniformMatrix4fv(uniformLocation, false, float32array)",
+        "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])",
+        "gl.useProgram(program)",
+        "gl.validateProgram(program)",
+        "gl.vertexAttrib1f(0, 0)",
+        "gl.vertexAttrib1fv(0, float32array)",
+        "gl.vertexAttrib1fv(0, [0])",
+        "gl.vertexAttrib2f(0, 0, 0)",
+        "gl.vertexAttrib2fv(0, float32array)",
+        "gl.vertexAttrib2fv(0, [0, 0])",
+        "gl.vertexAttrib3f(0, 0, 0, 0)",
+        "gl.vertexAttrib3fv(0, float32array)",
+        "gl.vertexAttrib3fv(0, [0, 0, 0])",
+        "gl.vertexAttrib4f(0, 0, 0, 0, 0)",
+        "gl.vertexAttrib4fv(0, float32array)",
+        "gl.vertexAttrib4fv(0, [0, 0, 0, 0])",
+        "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)",
+        "gl.viewport(0, 0, 0, 0)",
+    ];
+    for (var i = 0; i < voidTests.length; ++i) {
+        shouldGenerateGLError(gl, gl.NO_ERROR, voidTests[i]);
+    }
+
+    // Functions return nullable values should all return null.
+    var nullTests = [
+        "gl.createBuffer()",
+        "gl.createFramebuffer()",
+        "gl.createProgram()",
+        "gl.createRenderbuffer()",
+        "gl.createShader(gl.GL_VERTEX_SHADER)",
+        "gl.createTexture()",
+        "gl.getActiveAttrib(program, 0)",
+        "gl.getActiveUniform(program, 0)",
+        "gl.getAttachedShaders(program)",
+        "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)",
+        "gl.getContextAttributes()",
+        "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)",
+        "gl.getParameter(gl.CURRENT_PROGRAM)",
+        "gl.getProgramInfoLog(program)",
+        "gl.getProgramParameter(program, gl.LINK_STATUS)",
+        "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)",
+        "gl.getShaderInfoLog(shader)",
+        "gl.getShaderParameter(shader, gl.SHADER_TYPE)",
+        "gl.getShaderSource(shader)",
+        "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)",
+        "gl.getUniform(program, uniformLocation)",
+        "gl.getUniformLocation(program, 'vPosition')",
+        "gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)",
+        "gl.getSupportedExtensions()",
+        "gl.getExtension('" + extension_name + "')",
+    ];
+    for (var i = 0; i < nullTests.length; ++i) {
+        shouldBeNull(nullTests[i]);
+    }
+
+    // "Is" queries should all return false.
+    shouldBeFalse("gl.isBuffer(buffer)");
+    shouldBeFalse("gl.isEnabled(gl.BLEND)");
+    shouldBeFalse("gl.isFramebuffer(framebuffer)");
+    shouldBeFalse("gl.isProgram(program)");
+    shouldBeFalse("gl.isRenderbuffer(renderbuffer)");
+    shouldBeFalse("gl.isShader(shader)");
+    shouldBeFalse("gl.isTexture(texture)");
+
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+
+    finish();
+}
+
+function finish() {
+    successfullyParsed = true;
+    var epilogue = document.createElement("script");
+    epilogue.onload = function() {
+        if (window.nonKhronosFrameworkNotifyDone)
+            window.nonKhronosFrameworkNotifyDone();
+    };
+    epilogue.src = "../resources/js-test-post.js";
+    document.body.appendChild(epilogue);
+}
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas">
+</body>
+</html>
--- a/content/canvas/test/webgl/conformance/copy-tex-image-and-sub-image-2d.html
+++ b/content/canvas/test/webgl/conformance/copy-tex-image-and-sub-image-2d.html
@@ -3,191 +3,130 @@ Copyright (c) 2010 The Chromium Authors.
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
  -->
 <html>
 <head>
 <link rel="stylesheet" href="../resources/js-test-style.css"/>
 <script src="../resources/js-test-pre.js"></script>
 <script src="resources/webgl-test.js"></script>
-<script id="vshader" type="x-shader/x-vertex">
-attribute vec3 g_Position;
-attribute vec2 g_TexCoord0;
-
-varying vec2 texCoord;
-
-void main()
-{
-    gl_Position = vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);
-    texCoord = g_TexCoord0;
-}
-</script>
-
-<script id="fshader" type="x-shader/x-fragment">
-#ifdef GL_ES
-precision mediump float;
-#endif
-uniform sampler2D tex;
-varying vec2 texCoord;
-void main()
-{
-    gl_FragColor = texture2D(tex, texCoord);
-}
-</script>
+<script src="resources/webgl-test-utils.js"></script>
 
 <script>
 var successfullyParsed = false;
 
 function init()
 {
     if (window.initNonKhronosFramework) {
         window.initNonKhronosFramework(true);
     }
 
     description('Verify copyTexImage2D and copyTexSubImage2D');
 
     runTest();
 }
 
-// These two declarations need to be global for "shouldBe" to see them
-var pixel = [0, 0, 0];
-var correctColor = null;
 var gl = null;
+var wtu = WebGLTestUtils;
 
 function runTestIteration(antialias)
 {
-    if (antialias)
-        gl = initWebGL("antialiasOn", "vshader", "fshader", [ "g_Position", "g_TexCoord0" ], [ 0, 0, 0, 1 ], 1);
-    else
-        gl = initWebGL("antialiasOff", "vshader", "fshader", [ "g_Position", "g_TexCoord0" ], [ 0, 0, 0, 1 ], 1, { antialias: false });
-
-    var textureLoc = gl.getUniformLocation(gl.program, "tex");
+    var canvas = document.getElementById(
+        antialias ? "antialiasOn" : "antialiasOff");
+    var attribs = antialias ? { antialias: false } : undefined;
+    gl = wtu.create3DContext(canvas, attribs);
+    var program = wtu.setupTexturedQuad(gl);
+    var textureLoc = gl.getUniformLocation(program, "tex");
+    glErrorShouldBe(gl, gl.NO_ERROR, "During Initialization");
 
-    var vertices = new Float32Array([
-         1.0,  1.0, 0.0,
-        -1.0,  1.0, 0.0,
-        -1.0, -1.0, 0.0,
-         1.0,  1.0, 0.0,
-        -1.0, -1.0, 0.0,
-         1.0, -1.0, 0.0]);
-    var texCoords = new Float32Array([
-        1.0, 1.0,
-        0.0, 1.0,
-        0.0, 0.0,
-        1.0, 1.0,
-        0.0, 0.0,
-        1.0, 0.0]);
-    var texCoordOffset = vertices.byteLength;
-
-    var vbo = gl.createBuffer();
-    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
-    gl.bufferData(gl.ARRAY_BUFFER,
-                  texCoordOffset + texCoords.byteLength,
-                  gl.STATIC_DRAW);
-    gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
-    gl.bufferSubData(gl.ARRAY_BUFFER, texCoordOffset, texCoords);
-
-    gl.enableVertexAttribArray(0);
-    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
-    gl.enableVertexAttribArray(1);
-    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, texCoordOffset);
-
-    gl.colorMask(1, 1, 1, 0);
+    gl.colorMask(1, 1, 1, 1);
     gl.disable(gl.BLEND);
     debug('Testing copyTexImage2D');
 
     // Red canvas
     gl.clearColor(1, 0, 0, 1);
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
     var texture = gl.createTexture();
     // Bind the texture to texture unit 0
     gl.bindTexture(gl.TEXTURE_2D, texture);
     // Set up texture
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-
-    glErrorShouldBe(gl, gl.NO_ERROR);
-    gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 2, 2, 0);
-    glErrorShouldBe(gl, gl.NO_ERROR);
+    gl.uniform1i(textureLoc, 0);
 
-    // Green canvas
-    gl.clearColor(0, 1, 0, 1);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    // Point the uniform sampler to texture unit 0
-    gl.uniform1i(textureLoc, 0);
-    // Draw the triangles
-    gl.drawArrays(gl.TRIANGLES, 0, 6);
+    var colors = [
+      [1, 0, 0, 1],
+      [0, 1, 0, 1],
+      [0, 0, 1, 1],
+      [0.5, 0.5, 0.5, 0.5],
+    ];
+    var count = 0;
+    for (var yy = -2; yy <= 2; ++yy) {
+      for (var xx = -2; xx <= 2; ++xx) {
+         for (var ii = 0; ii < 2; ++ii) {
+          var texColor = colors[count];
+          var clearColor = colors[(count + 1) % colors.length];
+          // clear to some color
+          gl.clearColor(texColor[0], texColor[1], texColor[2], texColor[3]);
+          gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
-    // Read back the rendering results, should be red
-    var buf = new Uint8Array(2 * 2 * 4);
-    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, buf);
-    var idx = 0;
-    correctColor = [255, 0, 0];
-    for (var y = 0; y < 2; y++) {
-        for (var x = 0; x < 2; x++) {
-            idx = (y * 2 + x) * 4;
-            pixel[0] = buf[idx];
-            pixel[1] = buf[idx + 1];
-            pixel[2] = buf[idx + 2];
-            shouldBe("pixel", "correctColor");
+          // copy that color to the texture.
+          switch (ii) {
+          case 0:
+            gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, xx, yy, 2, 2, 0);
+            glErrorShouldBe(gl, gl.NO_ERROR,
+                "using copyTexImage2D: x =" + xx + ", y = " + yy);
+            break;
+          case 1:
+            gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, xx, yy, 2, 2);
+            glErrorShouldBe(gl, gl.NO_ERROR,
+                "using copyTexSubImage2D: x =" + xx + ", y = " + yy);
+            break;
+          }
+
+          // clear to some other color.
+          gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+          gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+          // Draw the triangles
+          wtu.drawQuad(gl);
+
+          // check the rendering results
+          for (var iy = 0; iy < 2; ++iy) {
+            for (var ix = 0; ix < 2; ++ix) {
+              var x = xx + ix;
+              var y = yy + iy;
+              var expectedColor = (x < 0 || y < 0 || x >= 2 || y >= 2) ?
+                  [0,0,0,0] :
+                  [Math.floor(255 * texColor[0]),
+                   Math.floor(255 * texColor[1]),
+                   Math.floor(255 * texColor[2]),
+                   Math.floor(255 * texColor[3])];
+              wtu.checkCanvasRect(gl, ix, iy, 1, 1, expectedColor,
+                  "" + ix + ", " + iy + " should render " + expectedColor + " (+/-1)", 1);
+            }
+          }
+          count = (count + 1) % colors.length;
         }
+      }
     }
 
-    debug('Testing copyTexSubImage2D');
-
-    // Green canvas
-    gl.clearColor(0, 1, 0, 1);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    glErrorShouldBe(gl, gl.NO_ERROR);
-    gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
-    glErrorShouldBe(gl, gl.NO_ERROR);
-
-    // Blue canvas
-    gl.clearColor(0, 0, 1, 1);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    // Draw the triangles
-    gl.drawArrays(gl.TRIANGLES, 0, 6);
-
-    // Read back the rendering results, should be green
-    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, buf);
-    correctColor = [0, 255, 0];
-    for (var y = 0; y < 2; y++) {
-        for (var x = 0; x < 2; x++) {
-            idx = (y * 2 + x) * 4;
-            pixel[0] = buf[idx];
-            pixel[1] = buf[idx + 1];
-            pixel[2] = buf[idx + 2];
-            shouldBe("pixel", "correctColor");
-        }
-    }
+    debug("");
 }
 
 function runTest(antialias)
 {
     debug("Testing with antialias on");
     runTestIteration(true);
     debug("Testing with antialias off");
     runTestIteration(false);
 
-    successfullyParsed = true;
-    var epilogue = document.createElement("script");
-    epilogue.onload = finish;
-    epilogue.src = "../resources/js-test-post.js";
-    document.body.appendChild(epilogue);
-}
-
-function finish() {
-    if (window.nonKhronosFrameworkNotifyDone) {
-        window.nonKhronosFrameworkNotifyDone();
-    }
+    finishTest();
 }
 </script>
 </head>
 <body onload="init()">
 <canvas id="antialiasOn" width="2px" height="2px"></canvas>
 <canvas id="antialiasOff" width="2px" height="2px"></canvas>
 <div id="description"></div>
 <div id="console"></div>
--- a/content/canvas/test/webgl/conformance/draw-elements-out-of-bounds.html
+++ b/content/canvas/test/webgl/conformance/draw-elements-out-of-bounds.html
@@ -112,23 +112,24 @@ context.vertexAttribPointer(0, 3, contex
 // bind 2 elements, starting after the first 3; same stride of 5 float elements
 context.vertexAttribPointer(1, 2, context.FLOAT, false, 5*4, 3*4);
 
 context.enableVertexAttribArray(0);
 context.enableVertexAttribArray(1);
 
 var ebo = context.createBuffer();
 context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, ebo);
-context.bufferData(context.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 0, 1, 2,
-                                                                   1, 2, 0,
-                                                                   2, 0, 1,
-                                                                   200, 200, 200,
-                                                                   0x7fff, 0x7fff, 0x7fff,
-                                                                   0xffff, 0xffff, 0xffff ]),
-                   context.STATIC_DRAW);
+context.bufferData(context.ELEMENT_ARRAY_BUFFER, new Uint16Array(
+    [ 0, 1, 2,
+      1, 2, 0,
+      2, 0, 1,
+      200, 200, 200,
+      0x7fff, 0x7fff, 0x7fff,
+      0xffff, 0xffff, 0xffff ]),
+    context.STATIC_DRAW);
 
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 9, context.UNSIGNED_SHORT, 0)");
 
 // invalid type arguments
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.drawElements(context.TRIANGLES, 9, context.FLOAT, 0)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.drawElements(context.TRIANGLES, 9, context.SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.drawElements(context.TRIANGLES, 9, context.UNSIGNED_INT, 0)");
 
@@ -139,15 +140,36 @@ shouldGenerateGLError(context, context.I
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 18, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 3, context.UNSIGNED_SHORT, 2*15)");
 
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 0xffffffff, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0x7fffffff, context.UNSIGNED_SHORT, 0)");
 
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 0, context.UNSIGNED_SHORT, 0)");
 
+// invalid operation with offset that's not a multiple of the type size
+shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 0)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 1)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
+
+// invalid operation if no buffer is bound to ELEMENT_ARRAY_BUFFER
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, null);
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 0)");
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, ebo);
+
+debug("")
+debug("Test buffer setting attrib 0 to a buffer too small and disable it.");
+var smallVBO = context.createBuffer();
+shouldBeNonNull('smallVBO');
+context.bindBuffer(context.ARRAY_BUFFER, smallVBO);
+context.bufferData(context.ARRAY_BUFFER, 1, context.STATIC_DRAW);
+context.vertexAttribPointer(0, 3, context.FLOAT, false, 0, 0x10);
+context.disableVertexAttribArray(0);
+shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, null);
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
 debug("")
 successfullyParsed = true;
 </script>
 
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-bind-attrib-location-test.html
+++ b/content/canvas/test/webgl/conformance/gl-bind-attrib-location-test.html
@@ -120,17 +120,17 @@ function setBindLocations(colorLocation,
   gl.linkProgram(program);
   gl.useProgram(program);
   var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
   assertMsg(linked, "program linked successfully");
 
   debug("vPosition:" + gl.getAttribLocation(program, "vPosition"))
   debug("vColor   :" + gl.getAttribLocation(program, "vColor"))
   assertMsg(gl.getAttribLocation(program, "vPosition") == positionLocation,
-            "location of vPositon should be " + positionLocation);
+            "location of vPosition should be " + positionLocation);
   assertMsg(gl.getAttribLocation(program, "vColor") == colorLocation,
             "location of vColor should be " + colorLocation);
 
   var ploc = gl.getAttribLocation(program, "vPosition");
   var cloc = gl.getAttribLocation(program, "vColor");
   gl.bindBuffer(gl.ARRAY_BUFFER, positions);
   gl.enableVertexAttribArray(positionLocation);
   gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
old mode 100755
new mode 100644
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-enum-tests.html
+++ b/content/canvas/test/webgl/conformance/gl-enum-tests.html
@@ -50,17 +50,16 @@ if (!gl) {
     "gl.bufferData(gl.ARRAY_BUFFER, 3, desktopGL['STATIC_READ'])",
     "gl.disable(desktopGL['CLIP_PLANE0'])",
     "gl.disable(desktopGL['POINT_SPRITE'])",
     "gl.getBufferParameter(gl.ARRAY_BUFFER, desktopGL['PIXEL_PACK_BUFFER'])",
     "gl.hint(desktopGL['PERSPECTIVE_CORRECTION_HINT'], gl.FASTEST)",
     "gl.isEnabled(desktopGL['CLIP_PLANE0'])",
     "gl.isEnabled(desktopGL['POINT_SPRITE'])",
     "gl.pixelStorei(desktopGL['PACK_SWAP_BYTES'], 1)",
-    "gl.readPixels(0, 0, 1, 1, gl.ALPHA, gl.SHORT, buf)",
   ];
   for (var ii = 0; ii < tests.length; ++ii) {
     eval(tests[ii]);
     glErrorShouldBe(gl, gl.INVALID_ENUM,
               tests[ii] + " should return INVALID_ENUM.");
   }
 
   gl.bindTexture(gl.TEXTURE_2D, tex);
--- a/content/canvas/test/webgl/conformance/gl-get-calls.html
+++ b/content/canvas/test/webgl/conformance/gl-get-calls.html
@@ -117,20 +117,33 @@ else {
     shouldBe('context.getParameter(context.STENCIL_WRITEMASK)', '0xFFFFFFFF');
 
     shouldBe('context.getParameter(context.TEXTURE_BINDING_2D)', 'null');
     shouldBe('context.getParameter(context.TEXTURE_BINDING_CUBE_MAP)', 'null');
     shouldBe('context.getParameter(context.UNPACK_ALIGNMENT)', '4');
     shouldBe('context.getParameter(context.UNPACK_FLIP_Y_WEBGL)', 'false');
     shouldBe('context.getParameter(context.UNPACK_PREMULTIPLY_ALPHA_WEBGL)', 'false');
     shouldBe('context.getParameter(context.VIEWPORT)', '[0, 0, 2, 2]');
+    shouldBe('context.getParameter(context.NUM_COMPRESSED_TEXTURE_FORMATS)', '0');
+
+    shouldBeTrue('context.getParameter(context.MAX_COMBINED_TEXTURE_IMAGE_UNITS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_CUBE_MAP_TEXTURE_SIZE) >= 16');
     shouldBeTrue('context.getParameter(context.MAX_FRAGMENT_UNIFORM_VECTORS) >= 16');
+    shouldBeTrue('context.getParameter(context.MAX_RENDERBUFFER_SIZE) >= 1');
+    shouldBeTrue('context.getParameter(context.MAX_TEXTURE_IMAGE_UNITS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_TEXTURE_SIZE) >= 64');
+    shouldBeTrue('context.getParameter(context.MAX_VARYING_VECTORS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_VERTEX_ATTRIBS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_VERTEX_TEXTURE_IMAGE_UNITS) >= 0');
     shouldBeTrue('context.getParameter(context.MAX_VERTEX_UNIFORM_VECTORS) >= 128');
-    shouldBeTrue('context.getParameter(context.MAX_VARYING_VECTORS) >= 8');
-    shouldBe('context.getParameter(context.NUM_COMPRESSED_TEXTURE_FORMATS)', '0');
+    // Note: This requirement should be removed from the spec IMO. Many impelementations
+    // will be based on FBOs and FBOs might have a restriction smaller than the current screen size.
+    // especially if there are multiple screens.
+    shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[0] >= window.screen.width');
+    shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[1] >= window.screen.height');
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-getshadersource.html
@@ -0,0 +1,45 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
+   <title>WebGL getShaderSource conformance test.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">abc//defNOTASCII</script>
+<script>
+description("Tests that the source that goes into a shader is what comes out.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var original = document.getElementById("vshader").text;
+var shader = gl.createShader(gl.VERTEX_SHADER);
+gl.shaderSource(shader, original);
+var source = gl.getShaderSource(shader);
+shouldBe("source", "original");
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+successfullyParsed = true;
+</script>
+</body>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-attribs.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of attributes are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec4 v0;
+attribute vec4 v1;
+attribute vec4 v2;
+attribute vec4 v3;
+attribute vec4 v4;
+attribute vec4 v5;
+attribute vec4 v6;
+varying vec4 color;
+void main()
+{
+    gl_Position = vPosition;
+    color = v0 + v1 + v2 + v3 + v4 + v5 + v6;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5', 'v6'],
+    [0, 1, 2, 3, 4, 5, 6, 7]);
+
+for (var ii = 0; ii < 7; ++ii) {
+  var v = (ii + 1) / 28;
+  var vertexObject = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8]), gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(ii + 1);
+  gl.vertexAttribPointer(ii + 1, 4, gl.FLOAT, false, 0, 0);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 127, 64, 32], "Should render 255,127,64,32 (+/-1)", 1);
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-textures-unroll.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#define NUM_TEXTURES 8 // See spec
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D uni[8];
+void main()
+{
+    vec4 c = vec4(0,0,0,0);
+    c += texture2D(uni[0], vec2(0.5, 0.5));
+    c += texture2D(uni[1], vec2(0.5, 0.5));
+    c += texture2D(uni[2], vec2(0.5, 0.5));
+    c += texture2D(uni[3], vec2(0.5, 0.5));
+    c += texture2D(uni[4], vec2(0.5, 0.5));
+    c += texture2D(uni[5], vec2(0.5, 0.5));
+    c += texture2D(uni[6], vec2(0.5, 0.5));
+    c += texture2D(uni[7], vec2(0.5, 0.5));
+    gl_FragColor = c;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 8; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.activeTexture(gl.TEXTURE0 + ii);
+  var tex = gl.createTexture();
+  wtu.fillTexture(gl, tex, 1, 1, [32, 16, 8, ii * 9], 0);
+  gl.uniform1i(loc, ii);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [255, 128, 64, 252],
+                "Should render using all texture units");
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-textures.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#define NUM_TEXTURES 8 // See spec
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D uni[8];
+void main()
+{
+    vec4 c = vec4(0,0,0,0);
+    for (int ii = 0; ii < NUM_TEXTURES; ++ii) {
+      c += texture2D(uni[ii], vec2(0.5, 0.5));
+    }
+    gl_FragColor = c;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 8; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.activeTexture(gl.TEXTURE0 + ii);
+  var tex = gl.createTexture();
+  wtu.fillTexture(gl, tex, 1, 1, [32, 16, 8, ii * 9], 0);
+  gl.uniform1i(loc, ii);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [255, 128, 64, 252],
+                "Should render using all texture units");
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-uniforms.html
@@ -0,0 +1,120 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+#define NUM_UNIFORMS 128 // See spec
+attribute vec4 vPosition;
+uniform vec4 uni[NUM_UNIFORMS];
+varying vec4 color;
+void main()
+{
+    gl_Position = vPosition;
+    vec4 c = vec4(0,0,0,0);
+    for (int ii = 0; ii < NUM_UNIFORMS; ++ii) {
+      c += uni[ii];
+    }
+    color = c;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script id="vshader2" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader2" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+#define NUM_UNIFORMS 16 // See spec
+uniform vec4 uni[NUM_UNIFORMS];
+void main()
+{
+    vec4 c = vec4(0,0,0,0);
+    for (int ii = 0; ii < NUM_UNIFORMS; ++ii) {
+       c += uni[ii];
+    }
+    gl_FragColor = vec4(c.r, c.g, c.b, c.a / 120.0);
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 128; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.uniform4f(loc, 2/256, 2/512, 2/1024, ii/8128);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 127, 64, 255], "Should render 255,127,64,32 (+/-1)", 1);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader2', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader2', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 16; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.uniform4f(loc, 16/2048, 16/1024, 16/512, ii);
+}
+
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [32, 64, 127, 255], "Should render 32,64,127,255 (+/-1)", 1);
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
--- a/content/canvas/test/webgl/conformance/gl-object-get-calls.html
+++ b/content/canvas/test/webgl/conformance/gl-object-get-calls.html
@@ -5,17 +5,17 @@ Redistribution and use in source and bin
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
 
-THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. AS IS AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@@ -111,22 +111,19 @@ shouldBe('gl.getFramebufferAttachmentPar
 
 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER');
 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer');
 
 // Test getProgramParameter
 shouldBe('gl.getProgramParameter(standardProgram, gl.DELETE_STATUS)', 'false');
 shouldBe('gl.getProgramParameter(standardProgram, gl.LINK_STATUS)', 'true');
 shouldBe('typeof gl.getProgramParameter(standardProgram, gl.VALIDATE_STATUS)', '"boolean"');
-shouldBe('typeof gl.getProgramParameter(standardProgram, gl.INFO_LOG_LENGTH)', '"number"');
 shouldBe('gl.getProgramParameter(standardProgram, gl.ATTACHED_SHADERS)', '2');
 shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_ATTRIBUTES)', '2');
-shouldBeNonZero('gl.getProgramParameter(standardProgram, gl.ACTIVE_ATTRIBUTE_MAX_LENGTH)');
 shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_UNIFORMS)', '1');
-shouldBeNonZero('gl.getProgramParameter(standardProgram, gl.ACTIVE_UNIFORM_MAX_LENGTH)');
 
 // Test getRenderbufferParameter
 shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)', '2');
 shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)', '2');
 // Note: we can't test the actual value of the internal format since
 // the implementation is allowed to change it.
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT)');
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE)');
@@ -139,18 +136,16 @@ shouldBeNonZero('gl.getRenderbufferParam
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE)');
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE)');
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)');
 
 // Test getShaderParameter
 shouldBe('gl.getShaderParameter(standardVert, gl.SHADER_TYPE)', 'gl.VERTEX_SHADER');
 shouldBe('gl.getShaderParameter(standardVert, gl.DELETE_STATUS)', 'false');
 shouldBe('gl.getShaderParameter(standardVert, gl.COMPILE_STATUS)', 'true');
-shouldBe('typeof gl.getShaderParameter(standardVert, gl.INFO_LOG_LENGTH)', '"number"');
-shouldBeNonZero('gl.getShaderParameter(standardVert, gl.SHADER_SOURCE_LENGTH)');
 
 // Test getTexParameter
 gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
 gl.bindTexture(gl.TEXTURE_2D, texture);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
@@ -206,16 +201,27 @@ gl.uniform1f(fvalLoc, 11);
 gl.uniform2f(fval2Loc, 12, 13);
 gl.uniform3f(fval3Loc, 14, 15, 16);
 gl.uniform4f(fval4Loc, 17, 18, 19, 20);
 glErrorShouldBe(gl, gl.NO_ERROR);
 shouldBe('gl.getUniform(floatProgram, fvalLoc)', '11');
 shouldBe('gl.getUniform(floatProgram, fval2Loc)', '[12, 13]');
 shouldBe('gl.getUniform(floatProgram, fval3Loc)', '[14, 15, 16]');
 shouldBe('gl.getUniform(floatProgram, fval4Loc)', '[17, 18, 19, 20]');
+// Sampler uniform variables
+var samplerProgram = loadProgram(gl, "resources/noopUniformShader.vert", "resources/samplerUniformShader.frag");
+shouldBe('gl.getProgramParameter(samplerProgram, gl.LINK_STATUS)', 'true');
+var s2DValLoc = gl.getUniformLocation(samplerProgram, "s2D");
+var sCubeValLoc = gl.getUniformLocation(samplerProgram, "sCube");
+gl.useProgram(samplerProgram);
+gl.uniform1i(s2DValLoc, 0);
+gl.uniform1i(sCubeValLoc, 1);
+glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(samplerProgram, s2DValLoc)', '0');
+shouldBe('gl.getUniform(samplerProgram, sCubeValLoc)', '1');
 // Matrix uniform variables
 var matProgram = loadProgram(gl, "resources/matUniformShader.vert", "resources/noopUniformShader.frag");
 shouldBe('gl.getProgramParameter(matProgram, gl.LINK_STATUS)', 'true');
 var mval2Loc = gl.getUniformLocation(matProgram, "mval2");
 var mval3Loc = gl.getUniformLocation(matProgram, "mval3");
 var mval4Loc = gl.getUniformLocation(matProgram, "mval4");
 gl.useProgram(matProgram);
 gl.uniformMatrix2fv(mval2Loc, false, [1, 2, 3, 4]);
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-teximage.html
+++ b/content/canvas/test/webgl/conformance/gl-teximage.html
@@ -34,16 +34,17 @@ var imgURLs = [
   'resources/gray-ramp-gamma1.0.png',
   'resources/gray-ramp-gamma2.0.png',
   'resources/gray-ramp-gamma4.0.png',
   'resources/gray-ramp-gamma9.0.png',
   'resources/gray-ramp.png',
   'resources/zero-alpha.png',
   'resources/3x3.png',
   'resources/blue-1x1.jpg',
+  'resources/red-indexed.png',
   'resources/green-2x2-16bit.png',
   'resources/small-square-with-colorspin-profile.jpg',
   'resources/small-square-with-colorspin-profile.png',
   'resources/small-square-with-cie-rgb-profile.png',
   'resources/small-square-with-colormatch-profile.png',
   'resources/small-square-with-e-srgb-profile.png',
   'resources/small-square-with-smpte-c-profile.png',
   'resources/small-square-with-srgb-iec61966-2.1-profile.png'];
@@ -84,29 +85,33 @@ function runTests(imgs) {
 
   function checkPixelRange(buf, x, y, color, allowedRange) {
     var off = (y * width + x) * 4;
     var msg = "pixel " + x + ", " + y + " should be within " +
               allowedRange + " units of " +
               color[0] + ", " +
               color[1] + ", " +
               color[2] + ", " +
-              color[3] + " was " +
+              color[3];
+    var subMsg = " was " +
               buf[off + 0] + ", " +
               buf[off + 1] + ", " +
               buf[off + 2] + ", " +
               buf[off + 3];
-
+    // When running in WebKit's test harness, we don't want to print the
+    // pixel value when the test passes, because different machines might
+    // have different results and we record the text output.
+    var inDumpRenderTree = window.layoutTestController;
     for (var ii = 0; ii < 4; ++ii) {
       if (Math.abs(buf[off + ii] - color[ii]) > allowedRange) {
-        testFailed(msg);
+        testFailed(msg + subMsg);
         return;
       }
     }
-    testPassed(msg);
+    testPassed(msg + (inDumpRenderTree ? "" : subMsg));
   }
 
   var tex = gl.createTexture();
   gl.bindTexture(gl.TEXTURE_2D, tex);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
@@ -202,54 +207,82 @@ function runTests(imgs) {
         break;
       }
     }
     assertMsg(same, "pixels should be same regardless of gamma settings.");
   }
 
   debug("");
   debug("check pixels are UN pre-multiplied");
-  var canvas2d = document.createElement("canvas");
-  canvas2d.width = 256;
-  canvas2d.height = 1;
-  //canvas2d.style.height = "40px";
-  //var description = document.getElementById("description");
-  //description.appendChild(canvas2d);
-  var ctx = canvas2d.getContext("2d");
-  ctx.fillRect(0, 0, 256, 1);
-  ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
-  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
-  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
-  wtu.drawQuad(gl);
-  var ref = new Uint8Array(width * height * 4);
-  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
-  var lt128Count = [0, 0, 0];
-  var ge128Count = [0, 0, 0];
-  for (var jj = 0; jj < width; ++jj) {
-    var off = jj * 4;
-    for (var cc = 0; cc < 3; ++cc) {
-      if (buf[off + cc] < 128) {
-        ++lt128Count[cc];
-      } else {
-        ++ge128Count[cc];
+  for (var ii = 0; ii < 2; ++ii) {
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+    if (ii == 0) {
+      var canvas2d = document.createElement("canvas");
+      canvas2d.width = 256;
+      canvas2d.height = 1;
+      var ctx = canvas2d.getContext("2d");
+      ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
+      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
+    } else {
+      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                    imgs['resources/gray-ramp-256-with-128-alpha.png']);
+    }
+    glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+    wtu.drawQuad(gl);
+    var buf = new Uint8Array(width * height * 4);
+    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    var lt128Count = [0, 0, 0];
+    var ge128Count = [0, 0, 0];
+    for (var jj = 0; jj < width; ++jj) {
+      var off = jj * 4;
+      for (var cc = 0; cc < 3; ++cc) {
+        if (buf[off + cc] < 128) {
+          ++lt128Count[cc];
+        } else {
+          ++ge128Count[cc];
+        }
       }
     }
+    // Not sure the exact count here because gamma does effect drawing into the
+    // canvas but it should be close to 50% so I'll pass 45%
+    for (var jj = 0; jj < 3; ++jj) {
+      assertMsg(ge128Count[jj] > 256 * 0.45,
+                "Half the pixels in channel " + jj +
+                " should be >= 128,128,128. found " +
+                ((ge128Count[jj] / 256) * 100).toFixed() + "%");
+      assertMsg(lt128Count[jj] > 256 * 0.45,
+                "Half the pixels in channel " + jj +
+                " should be < 128,128,128. found " +
+                ((lt128Count[jj] / 256) * 100).toFixed() + "%");
+    }
   }
-  // Not sure the exact count here because gamma does effect drawing into the
-  // canvas but it should be close to 50% so I'll pass 45%
-  for (var jj = 0; jj < 3; ++jj) {
-    assertMsg(ge128Count[jj] > 256 * 0.45,
-              "Half the pixels in channel " + jj +
-              " should be >= 128,128,128. found " +
-              ((ge128Count[jj] / 256) * 100).toFixed() + "%");
-    assertMsg(lt128Count[jj] > 256 * 0.45,
-              "Half the pixels in channel " + jj +
-              " should be < 128,128,128. found " +
-              ((lt128Count[jj] / 256) * 100).toFixed() + "%");
-  }
+
+  debug("");
+  debug("check canvas pixels are UN pre-multiplied");
+  var canvas2d = document.createElement("canvas");
+  canvas2d.width = 1;
+  canvas2d.height = 1;
+  var ctx = canvas2d.getContext("2d");
+  ctx.fillStyle ="rgba(255,255,255,0.5)";
+  ctx.fillRect(0, 0, 256, 1);
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+  checkPixelRange(buf, 0, 0, [255, 255, 255, 127], 4);
+
+  debug("");
+  debug("check canvas pixels are pre-multiplied");
+  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+  checkPixelRange(buf, 0, 0, [127, 127, 127, 127], 4);
+
 
   debug("");
   debug("check pixels are pre-multiplied");
   gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
   // TODO(gman): use different texture that won't pass on failure
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
                 imgs['resources/zero-alpha.png']);
   glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
@@ -351,16 +384,26 @@ function runTests(imgs) {
         same = false;
         break;
       }
     }
     assertMsg(same, "uploading PNGs with same data but various ICC profiles should generate the same results");
   }
 
   debug("");
+  debug("check uploading of indexed PNG images");
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                imgs['resources/red-indexed.png']);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  // The image should be red.
+  checkPixelRange(buf, middle, center, [ 255, 0, 0, 255 ], 10);
+
+  debug("");
   successfullyParsed = true;
   shouldBeTrue("successfullyParsed");
   debug('<br /><span class="pass">TEST COMPLETE</span>');
   notifyFinishedToHarness();
 }
 </script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/gl-uniform-arrays.html
+++ b/content/canvas/test/webgl/conformance/gl-uniform-arrays.html
@@ -103,23 +103,24 @@ var typeInfos = [
     },
     srcValueAsString: function(index, srcValues) {
       return srcValues[index].toString();
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' : value.toString();
     },
     checkType: function(value) {
-      return typeof values === 'number';
+      return typeof value === 'number';
     },
     checkValue: function(typeInfo, index, value) {
       return typeInfo.srcValues[index] == value;
     },
     srcValues: [16, 15, 14],
-    srcValuesBad: [],
+    srcValuesLess: [],
+    srcValuesNonMultiple: null,
   },
   { type: 'vec2',
     jsTypeOf: 'Float32Array',
     setter: 'uniform2fv',
     elem: '[1]',
     numSrcValues: 3,
     invalidSet: function(loc) {
       gl.uniform1fv(loc, [2]);
@@ -130,26 +131,28 @@ var typeInfos = [
     srcValueAsString: function(index, srcValues) {
       return "[" + srcValues[index * 2 + 0].toString() + ", " +
                    srcValues[index * 2 + 1].toString() + "]";
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
     },
     checkType: function(value) {
-      return typeof values.length === 'number' &&
-             values.length == 2;
+      return value &&
+             typeof value.length === 'number' &&
+             value.length == 2;
     },
     checkValue: function(typeInfo, index, value) {
       return value !== null &&
              typeInfo.srcValues[index * 2 + 0] == value[0] &&
              typeInfo.srcValues[index * 2 + 1] == value[1];
     },
     srcValues: [16, 15, 14, 13, 12, 11],
-    srcValuesBad: [16],
+    srcValuesLess: [16],
+    srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
   },
   { type: 'vec3',
     jsTypeOf: 'Float32Array',
     setter: 'uniform3fv',
     elem: '[2]',
     numSrcValues: 3,
     invalidSet: function(loc) {
       gl.uniform1fv(loc, [2]);
@@ -162,27 +165,29 @@ var typeInfos = [
                    srcValues[index * 3 + 1].toString() + ", " +
                    srcValues[index * 3 + 2].toString() + "]";
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' :
           ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
     },
     checkType: function(value) {
-      return typeof values.length === 'number' &&
-             values.length == 3;
+      return value &&
+             typeof value.length === 'number' &&
+             value.length == 3;
     },
     checkValue: function(typeInfo, index, value) {
       return value !== null &&
              typeInfo.srcValues[index * 3 + 0] == value[0] &&
              typeInfo.srcValues[index * 3 + 1] == value[1] &&
              typeInfo.srcValues[index * 3 + 2] == value[2];
     },
     srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
-    srcValuesBad: [16, 15],
+    srcValuesLess: [16, 15],
+    srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
   },
   { type: 'vec4',
     jsTypeOf: 'Float32Array',
     setter: 'uniform4fv',
     elem: '[3]',
     numSrcValues: 3,
     invalidSet: function(loc) {
       gl.uniform1fv(loc, [2]);
@@ -197,28 +202,30 @@ var typeInfos = [
                    srcValues[index * 4 + 3].toString() + "]";
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' :
           ("[" + value[0] + ", " + value[1] +
            ", " + value[2] + ", " + value[3] + "]");
     },
     checkType: function(value) {
-      return typeof values.length === 'number' &&
-             values.length == 4;
+      return value &&
+             typeof value.length === 'number' &&
+             value.length == 4;
     },
     checkValue: function(typeInfo, index, value) {
       return value !== null &&
              typeInfo.srcValues[index * 4 + 0] == value[0] &&
              typeInfo.srcValues[index * 4 + 1] == value[1] &&
              typeInfo.srcValues[index * 4 + 2] == value[2] &&
              typeInfo.srcValues[index * 4 + 3] == value[3];
     },
     srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
-    srcValuesBad: [16, 15, 14],
+    srcValuesLess: [16, 15, 14],
+    srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
   }
 ];
 
 for (var tt = 0; tt < typeInfos.length; ++tt) {
   var typeInfo = typeInfos[tt];
   debug("");
   debug("check " + typeInfo.type);
   var fSrc = fTemplate.replace(/\$type/g, typeInfo.type).
@@ -228,64 +235,70 @@ for (var tt = 0; tt < typeInfos.length; 
 
   var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
   assertMsg(numUniforms == 1, "1 uniform found");
   var info = gl.getActiveUniform(program, 0);
   assertMsg(info.name == "color[0]",
             "uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10");
   var loc = gl.getUniformLocation(program, "color[0]");
   var srcValues = typeInfo.srcValues;
-  var srcValuesBad = typeInfo.srcValuesBad;
+  var srcValuesLess = typeInfo.srcValuesLess;
+  var srcValuesNonMultiple = typeInfo.srcValuesNonMultiple;
 
   // Try setting the value before using the program
   gl[typeInfo.setter](loc, srcValues);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
-            "should fail if there is no current program");
+                  "should fail if there is no current program");
 
   gl.useProgram(program);
-  gl[typeInfo.setter](loc, srcValuesBad);
+  gl[typeInfo.setter](loc, srcValuesLess);
   glErrorShouldBe(gl, gl.INVALID_VALUE,
-            "should fail with insufficient array size with gl." + typeInfo.setter);
+                  "should fail with insufficient array size with gl." + typeInfo.setter);
+  if (srcValuesNonMultiple) {
+    gl[typeInfo.setter](loc, srcValuesNonMultiple);
+    glErrorShouldBe(gl, gl.INVALID_VALUE,
+                    "should fail with non-multiple array size with gl." + typeInfo.setter);
+  }
   gl[typeInfo.setter](loc, srcValues);
   glErrorShouldBe(gl, gl.NO_ERROR,
-            "can set an array of uniforms with gl." + typeInfo.setter);
+                  "can set an array of uniforms with gl." + typeInfo.setter);
   var values = gl.getUniform(program, loc);
   glErrorShouldBe(gl, gl.NO_ERROR,
-            "can call gl.getUniform");
+                  "can call gl.getUniform");
   assertMsg(typeInfo.checkType(values),
             "gl.getUniform returns the correct type.");
   for (var ii = 0; ii < typeInfo.numSrcValues; ++ii) {
     var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
     glErrorShouldBe(gl, gl.NO_ERROR,
-              "can get location of element " + ii +
-              " of array from gl.getUniformLocation");
+                    "can get location of element " + ii +
+                    " of array from gl.getUniformLocation");
     var value = gl.getUniform(program, elemLoc);
     glErrorShouldBe(gl, gl.NO_ERROR,
-              "can get value of element " + ii + " of array from gl.getUniform");
+                    "can get value of element " + ii + " of array from gl.getUniform");
     assertMsg(typeInfo.checkValue(typeInfo, ii, value),
               "value put in (" + typeInfo.srcValueAsString(ii, srcValues) +
               ") matches value pulled out (" +
               typeInfo.returnValueAsString(value) + ")");
   }
   typeInfo.invalidSet(loc);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
-            "using the wrong size of gl.Uniform fails");
+                  "using the wrong size of gl.Uniform fails");
   var exceptionCaught = false;
   if (typeInfo.illegalSet) {
     try {
       typeInfo.illegalSet(loc);
     } catch (e) {
       exceptionCaught = true;
     }
     assertMsg(exceptionCaught, "passing non-array to glUniform*fv should throw TypeError");
   }
 
   gl.useProgram(null);
   glErrorShouldBe(gl, gl.NO_ERROR,
-            "can call gl.useProgram(null)");
+                  "can call gl.useProgram(null)");
 }
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
 <script>
--- a/content/canvas/test/webgl/conformance/gl-uniform-bool.html
+++ b/content/canvas/test/webgl/conformance/gl-uniform-bool.html
@@ -40,17 +40,17 @@ debug("");
 debug("NOTE: Some OpenGL drivers do not handle this correctly");
 debug("");
 debug("Checking gl.uniform1f with bool.");
 
 gl = initWebGL("example", "vshader", "fshader", [ "vPosition"], [ 0, 0, 0, 1 ], 1);
 var loc = gl.getUniformLocation(gl.program, "color");
 gl.uniform1f(loc, 1);
 glErrorShouldBe(gl, gl.NO_ERROR,
-          "should be able to set bool with gl.uniform1f");
+                "should be able to set bool with gl.uniform1f");
 
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
 <script>
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-uniformmatrix4fv.html
+++ b/content/canvas/test/webgl/conformance/gl-uniformmatrix4fv.html
@@ -40,27 +40,34 @@ void main()
 description("This test ensures WebGL implementations handle uniformMatrix in a OpenGL ES 2.0 spec compliant way");
 
 debug("");
 debug("Checking gl.uniformMatrix.");
 
 gl = initWebGL("example", "vshader", "fshader", [ "vPosition"], [ 0, 0, 0, 1 ], 1);
 for (var ii = 2; ii <= 4; ++ii) {
   var loc = gl.getUniformLocation(gl.program, "world" + ii);
-  var mat = [];
+  var matLess = [];
   for (var jj = 0; jj < ii; ++jj) {
     for (var ll = 0; ll < ii; ++ll) {
       if (jj == ii - 1 && ll == ii - 1)
         continue;
-      mat[jj * ii + ll] = (jj == ll) ? 1 : 0;
+      matLess[jj * ii + ll] = (jj == ll) ? 1 : 0;
     }
   }
+  var mat = matLess.concat([1]);
+  var matMore = mat.concat([1]);
   name = "uniformMatrix" + ii + "fv";
+  gl[name](loc, false, matLess);
+  glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with insufficient array size for " + name);
   gl[name](loc, false, mat);
-  glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with insufficient array size for " + name);
+  glErrorShouldBe(gl, gl.NO_ERROR, "should succeed with correct array size for " + name);
+  gl[name](loc, false, matMore);
+  glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with more than 1 array size for " + name);
+
   mat[ii * ii - 1] = 1;
   gl[name](loc, false, mat);
   glErrorShouldBe(gl, gl.NO_ERROR, "can call " + name + "with transpose = false");
   gl[name](loc, true, mat);
   glErrorShouldBe(gl, gl.INVALID_VALUE, name + " should return INVALID_VALUE with transpose = true");
 }
 
 debug("");
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-vertex-attrib-zero-issues.html
@@ -0,0 +1,97 @@
+<!--
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<title>WebGL Enable Vertex Attrib Zero Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+    attribute vec4 vPosition;
+    void main()
+    {
+        gl_Position = vPosition;
+    }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+    void main()
+    {
+        gl_FragColor = vec4(0.0,0.0,0.0,0.0);
+    }
+</script>
+
+<script>
+description("Test some of the issues of the difference between attrib 0 on OpenGL vs WebGL");
+debug("");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+
+function setup(numVerts, attribIndex) {
+  var program = wtu.setupProgram(
+      gl,
+      [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+       wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+      ['vPosition'], [attribIndex]);
+  // draw with something on attrib zero with a small number of vertices
+  var vertexObject = gl.createBuffer();
+  g_program = program;
+  g_attribLocation = attribIndex;
+  shouldBe("g_attribLocation", "gl.getAttribLocation(g_program, 'vPosition')");
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(
+      gl.ARRAY_BUFFER, new Float32Array(numVerts * 3), gl.STATIC_DRAW);
+  gl.vertexAttribPointer(attribIndex, 3, gl.FLOAT, false, 0, 0);
+  var indices = new Uint16Array(numVerts);
+  for (var ii = 0; ii < numVerts; ++ii) {
+    indices[ii] = ii;
+  }
+  var indexBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+  return program;
+}
+
+var p1 = setup(3, 0);
+var p2 = setup(60000, 3);
+
+for (var ii = 0; ii < 5; ++ii) {
+  gl.useProgram(p1);
+  gl.enableVertexAttribArray(0);
+  gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+  glErrorShouldBe(
+      gl, gl.NO_ERROR,
+      "drawing using attrib 0 with 3 verts");
+
+  gl.useProgram(p2);
+  gl.enableVertexAttribArray(3);
+  gl.drawArrays(gl.LINES, 0, 60000);
+  glErrorShouldBe(
+      gl, gl.NO_ERROR,
+      "drawing using attrib 3 with 60000 verts");
+}
+
+wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be 0, 0, 0, 0");
+
+successfullyParsed = true;
+</script>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-vertexattribpointer.html
+++ b/content/canvas/test/webgl/conformance/gl-vertexattribpointer.html
@@ -8,49 +8,125 @@ found in the LICENSE file.
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>WebGL vertexAttribPointer Conformance Tests</title>
 <link rel="stylesheet" href="../resources/js-test-style.css"/>
 <script src="../resources/desktop-gl-constants.js" type="text/javascript"></script>
 <script src="../resources/js-test-pre.js"></script>
 <script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
 </head>
 <body>
 <div id="description"></div>
 <div id="console"></div>
 <canvas id="canvas" width="2" height="2"> </canvas>
 <script>
 description("This test checks vertexAttribPointer behaviors in WebGL.");
 
 debug("");
 debug("Canvas.getContext");
 
+var wtu = WebGLTestUtils;
 var gl = create3DContext(document.getElementById("canvas"));
 if (!gl) {
   testFailed("context does not exist");
 } else {
   testPassed("context exists");
 
   debug("");
   debug("Checking gl.vertexAttribPointer.");
 
+  if (!gl.FIXED) {
+    gl.FIXED = 0x140C;
+  }
+
   gl.vertexAttribPointer(0, 3, gl.FLOAT, 0, 0, 12);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
       "vertexAttribPointer should fail if no buffer is bound");
 
   var vertexObject = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
-  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(512), gl.STATIC_DRAW);
-  gl.vertexAttribPointer(0, 1, gl.FLOAT, 0, 256, 0);
-  glErrorShouldBe(gl, gl.INVALID_VALUE,
-      "WebGL API supports vertex attribute data strides up to 255 bytes");
-  gl.vertexAttribPointer(0, 1, gl.FLOAT, 0, 255, 0);
-  glErrorShouldBe(gl, gl.NO_ERROR,
-      "vertexAttribPointer with stride <= 255 should succeed");
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(0), gl.STATIC_DRAW);
+
+  gl.vertexAttribPointer(0, 1, gl.INT, 0, 0, 0);
+  glErrorShouldBe(gl, gl.INVALID_ENUM,
+      "vertexAttribPointer should not support INT");
+  gl.vertexAttribPointer(0, 1, gl.UNSIGNED_INT, 0, 0, 0);
+  glErrorShouldBe(gl, gl.INVALID_ENUM,
+      "vertexAttribPointer should not support UNSIGNED_INT");
+  gl.vertexAttribPointer(0, 1, gl.FIXED, 0, 0, 0);
+  glErrorShouldBe(gl, gl.INVALID_ENUM,
+      "vertexAttribPointer should not support FIXED");
+
+  function checkVertexAttribPointer(
+      gl, err, reason, size, type, normalize, stride, offset) {
+    gl.vertexAttribPointer(0, size, type, normalize, stride, offset);
+    glErrorShouldBe(gl, err,
+        "gl.vertexAttribPointer(0, " + size +
+        ", gl." + wtu.glEnumToString(gl, type) +
+        ", " + normalize +
+        ", " + stride +
+        ", " + offset +
+        ") should " + (err == gl.NO_ERROR ? "succeed " : "fail ") + reason);
+  }
+
+  var types = [
+    { type:gl.BYTE,           bytesPerComponent: 1 },
+    { type:gl.UNSIGNED_BYTE,  bytesPerComponent: 1 },
+    { type:gl.SHORT,          bytesPerComponent: 2 },
+    { type:gl.UNSIGNED_SHORT, bytesPerComponent: 2 },
+    { type:gl.FLOAT,          bytesPerComponent: 4 },
+  ];
+
+  for (var ii = 0; ii < types.length; ++ii) {
+    var info = types[ii];
+    debug("");
+    for (var size = 1; size <= 4; ++size) {
+      debug("");
+      debug("checking: " + wtu.glEnumToString(gl, info.type) + " with size " + size);
+      var bytesPerElement = size * info.bytesPerComponent;
+      var offsetSet = [
+          0,
+          1,
+          info.bytesPerComponent - 1,
+          info.bytesPerComponent,
+          info.bytesPerComponent + 1,
+          info.bytesPerComponent * 2];
+      for (var jj = 0; jj < offsetSet.length; ++jj) {
+        var offset = offsetSet[jj];
+        for (var kk = 0; kk < offsetSet.length; ++kk) {
+          var stride = offsetSet[kk];
+          var err = gl.NO_ERROR;
+          var reason = ""
+          if (offset % info.bytesPerComponent != 0) {
+            reason = "because offset is bad";
+            err = gl.INVALID_OPERATION;
+          }
+          if (stride % info.bytesPerComponent != 0) {
+            reason = "because stride is bad";
+            err = gl.INVALID_OPERATION;
+          }
+          checkVertexAttribPointer(
+              gl, err, reason, size, info.type, false, stride, offset);
+        }
+        var stride = Math.floor(255 / info.bytesPerComponent) * info.bytesPerComponent;
+
+        if (offset == 0) {
+          checkVertexAttribPointer(
+              gl, gl.NO_ERROR, "at stride limit",
+              size, info.type, false, stride, offset);
+          checkVertexAttribPointer(
+              gl, gl.INVALID_VALUE, "over stride limit",
+              size, info.type, false,
+              stride + info.bytesPerComponent, offset);
+        }
+      }
+    }
+  }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/glsl-conformance.html
+++ b/content/canvas/test/webgl/conformance/glsl-conformance.html
@@ -95,16 +95,27 @@ void main()
   void main()
   {
       gl_FragColor = vec4(0.0,0.0,0.0,1.0);
   }
 #else
   foo
 #endif
 </script>
+<script id="fshaderWithUndefinedPreprocessorSymbol" type="text/something-not-javascript">
+#if UNDEFINED_FOO
+  // according to ES GLSL spec 3.4 undefined symbols should fail.
+#else
+  precision mediump float;
+  void main()
+  {
+      gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+  }
+#endif
+</script>
 <script id="fshaderWithFragDepth" type="text/something-not-javascript">
 precision mediump float;
 void main()
 {
     gl_FragColor = vec4(0.0,0.0,0.0,1.0);
     gl_FragDepth = 1.0;
 }
 </script>
@@ -218,16 +229,26 @@ void main()
 </script>
 <script id="vshaderWithLineDirective" type="text/something-not-javascript">
 #line 123
 foo
 </script>
 <script id="vshaderWith__FILE__" type="text/something-not-javascript">
 __FILE__
 </script>
+<script id="vshaderWithIncludeDirective" type="text/something-not-javascript">
+// Sadly I can not force the current path so this could fail beacuse include.vs
+// does not exist, not because #include is disallowed.
+#include "include.vs"
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
 <script id="fshaderWithdFdx" type="text/something-not-javascript">
 #extension GL_OES_standard_derivatives:enable
 precision mediump float;
 void main()
 {
     gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
 }
 </script>
@@ -235,30 +256,62 @@ void main()
 precision mediump float;
 void main()
 {
     gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
 }
 </script>
 <script id="fshaderWith256CharacterIdentifier" type="text/something-not-javascript">
 precision mediump float;
-uniform float a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 = 2.0;
+uniform float a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345;
 void main()
 {
   gl_FragColor = vec4(a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345,0.0,0.0,1.0);
 }
 </script>
 <script id="fshaderWith257CharacterIdentifier" type="text/something-not-javascript">
 precision mediump float;
-uniform float a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456 = 2.0;
+uniform float a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456;
 void main()
 {
   gl_FragColor = vec4(a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456,0.0,0.0,1.0);
 }
 </script>
+<script id="fshaderWithLongLine" type="text/something-not-javascript">
+precision mediump float;
+uniform float fooo;
+#if defined(someSymbolNotDefined)
+#error long
+#endif
+void main()
+{
+    gl_FragColor = vec4(fooo+fooo+fooo+fooo, fooo+fooo+fooo+fooo, fooo+fooo+fooo+fooo, 1.0);
+}
+</script>
+<script id="fshaderWithErrorDirective" type="text/something-not-javascript">
+#error testing123 testing123
+void main()
+{
+    gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fshaderWithQuotedErrorDirective" type="text/something-not-javascript">
+#error "testing123 testing123" // will return INVALID_VALUE. See WebGL 6.18
+void main()
+{
+    gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fshaderWithNonASCIIErrorDirective" type="text/something-not-javascript">
+#error ͂`rbhhł͂Ȃ // will return INVALID_VALUE. See WebGL 6.18
+void main()
+{
+    gl_FragColor = vec4(0,0,0,0);
+}
+</script>
 <canvas id="canvas" width="2" height="2"> </canvas>
 <script>
 description("This test ensures WebGL implementations allow proper GLES2 shaders compile and improper ones fail.");
 
 debug("");
 debug("Canvas.getContext");
 
 var wtu = WebGLTestUtils;
@@ -331,16 +384,23 @@ if (!gl) {
       vShaderSuccess: true,
       fShaderId: 'fshaderWithVERSION100PreprocessorSymbol',
       fShaderSuccess: true,
       linkSuccess: true,
       passMsg: 'fragment shader that uses __VERSION__==100 should succeed',
     },
     { vShaderId: 'vshader',
       vShaderSuccess: true,
+      fShaderId: 'fshaderWithUndefinedPreprocessorSymbol',
+      fShaderSuccess: false,
+      linkSuccess: false,
+      passMsg: 'fragment shader undefined preprocessor symbol should fail (3.4)',
+    },
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
       fShaderId: 'fshaderWithFragDepth',
       fShaderSuccess: false,
       linkSuccess: false,
       passMsg: 'fragment shader that uses gl_FragDepth should fail',
     },
     { vShaderId: 'vshader',
       vShaderSuccess: true,
       fShaderId: 'fshaderWithdFdx',
@@ -456,33 +516,82 @@ if (!gl) {
     { vShaderId: 'vshaderWithLineDirective',
       vShaderSuccess: false,
       vShaderTest: (function() { return wtu.getLastError().indexOf("124") >= 0; }),
       fShaderId: 'fshader',
       fShaderSuccess: true,
       linkSuccess: false,
       passMsg: 'vertex shader uses #line directive should report correct line',
     },
-// TODO(zmo): adding these tests back once the limit is added to WebGL spec.
-/*
+    { vShaderId: 'vshaderWithIncludeDirective',
+      vShaderSuccess: false,
+      fShaderId: 'fshader',
+      fShaderSuccess: true,
+      linkSuccess: false,
+      passMsg: 'vertex shader uses #include should fail',
+    },
+    //{ vShaderId: 'vshader',
+    //  vShaderSuccess: true,
+    //  fShaderId: 'fshaderWith257CharacterIdentifier',
+    //  fShaderSuccess: false,
+    //  linkSuccess: false,
+    //  passMsg: 'shader that uses 257 character identifier should fail',
+    //},
     { vShaderId: 'vshader',
       vShaderSuccess: true,
       fShaderId: 'fshaderWith256CharacterIdentifier',
       fShaderSuccess: true,
       linkSuccess: true,
-      passMsg: 'shared that uses 256 character identifier should succeed',
+      passMsg: 'shader that uses 256 character identifier should succeed',
     },
     { vShaderId: 'vshader',
       vShaderSuccess: true,
-      fShaderId: 'fshaderWith257CharacterIdentifier',
+      fShaderId: 'fshaderWithLongLine',
+      fShaderSuccess: true,
+      fShaderPrep: function(str) {
+        function expand(str, re, replacement, count) {
+          for (var ii = 0; ii < count; ++ii) {
+            str = str.replace(re, replacement);
+          }
+          return str;
+        }
+        str = expand(str, new RegExp(" ", 'g'), "  ", 12);
+        str = expand(str, new RegExp("0", 'g'), "00", 8);
+        str = expand(str, new RegExp("fooo", 'g'), "fooofooo", 6);
+        str = expand(str, new RegExp("long", 'g'), "longlong", 6);
+        //debug("len:" + str.length);
+        //debug(str);
+        return str;
+      },
+      linkSuccess: true,
+      passMsg: 'shader that uses long lines should succeed',
+    },
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
+      fShaderId: 'fshaderWithErrorDirective',
+      fShaderSuccess: false,
+      fShaderTest: (function() {
+        return wtu.getLastError().indexOf("testing123 testing123") >= 0; }),
+      linkSuccess: false,
+      passMsg: "error directive returns error user's error message",
+    },
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
+      fShaderId: 'fshaderWithQuotedErrorDirective',
       fShaderSuccess: false,
       linkSuccess: false,
-      passMsg: 'shared that uses 257 character identifier should fail',
+      passMsg: "error directive using quotes fails",
     },
-*/
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
+      fShaderId: 'fshaderWithNonASCIIErrorDirective',
+      fShaderSuccess: false,
+      linkSuccess: false,
+      passMsg: "error directive using characters outside of allowed set fails",
+    }
   ];
 
   // Read in all the shader source.
   for (var ii = 0; ii < shaderInfo.length; ++ii) {
     var si = shaderInfo[ii];
     si.vShaderSource = document.getElementById(si.vShaderId).text;
     si.fShaderSource = document.getElementById(si.fShaderId).text;
   }
@@ -543,42 +652,52 @@ if (!gl) {
   addExternalShaders('shaders/00_shaders.txt');
 
   for (var ii = 0; ii < shaderInfo.length; ++ii) {
     var info = shaderInfo[ii];
     var passMsg = '[' + info.vShaderId + '/' + info.fShaderId + ']: ' +
                   info.passMsg
     log(passMsg);
     //debug(info.fShaderId);
-    var vShader = wtu.loadShader(gl, info.vShaderSource, gl.VERTEX_SHADER);
+    var vSource = info.vShaderPrep ? info.vShaderPrep(info.vShaderSource) :
+      info.vShaderSource;
+    var vShader = wtu.loadShader(gl, vSource, gl.VERTEX_SHADER);
     if (info.vShaderTest) {
       if (!info.vShaderTest(vShader)) {
         testFailed(passMsg);
         continue;
       }
     }
     if ((vShader != null) != info.vShaderSuccess) {
       testFailed(passMsg);
       continue;
     }
-    var fShader = wtu.loadShader(gl, info.fShaderSource, gl.FRAGMENT_SHADER);
+    var fSource = info.fShaderPrep ? info.fShaderPrep(info.fShaderSource) :
+      info.fShaderSource;
+    var fShader = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER);
+    if (info.fShaderTest) {
+      if (!info.fShaderTest(fShader)) {
+        testFailed(passMsg);
+        continue;
+      }
+    }
     //debug(fShader == null ? "fail" : "succeed");
     if ((fShader != null) != info.fShaderSuccess) {
       testFailed(passMsg);
       continue;
     }
 
     if (vShader && fShader) {
       var program = gl.createProgram();
       gl.attachShader(program, vShader);
       gl.attachShader(program, fShader);
       gl.linkProgram(program);
       var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
       if (!linked) {
-        var error = gl.getProgramInfoLog(shader);
+        var error = gl.getProgramInfoLog(program);
         log("*** Error linking program '"+program+"':"+error);
       }
       if (linked != info.linkSuccess) {
         testFailed(passMsg);
         continue;
       }
     } else {
       if (info.linkSuccess) {
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/include.vs
@@ -0,0 +1,4 @@
+// Do not delete!
+// Needed to help glsl-conformance tests.
+
+
--- a/content/canvas/test/webgl/conformance/index-validation.html
+++ b/content/canvas/test/webgl/conformance/index-validation.html
@@ -121,16 +121,18 @@ gl.enableVertexAttribArray(extraLoc);
 debug("Enable an extra attribute with null");
 glErrorShouldBe(gl, gl.NO_ERROR);
 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
 glErrorShouldBe(gl, gl.INVALID_OPERATION);
 debug("Enable an extra attribute with insufficient data buffer");
 gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
 glErrorShouldBe(gl, gl.NO_ERROR);
 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
 glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
 
 successfullyParsed = true;
 </script>
 
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/instanceof-test.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL instanceof test.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec2 texCoord;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+debug("Tests that instanceof works on WebGL objects.");
+debug("");
+var gl = create3DContext(document.getElementById("canvas"));
+shouldBeTrue('gl instanceof WebGLRenderingContext');
+shouldBeTrue('gl.createBuffer() instanceof WebGLBuffer');
+shouldBeTrue('gl.createFramebuffer() instanceof WebGLFramebuffer');
+shouldBeTrue('gl.createProgram() instanceof WebGLProgram');
+shouldBeTrue('gl.createRenderbuffer() instanceof WebGLRenderbuffer');
+shouldBeTrue('gl.createShader(gl.VERTEX_SHADER) instanceof WebGLShader');
+shouldBeTrue('gl.createTexture() instanceof WebGLTexture');
+
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+shouldBeTrue('gl.getUniformLocation(program, "color") instanceof WebGLUniformLocation');
+shouldBeTrue('gl.getActiveAttrib(program, 0) instanceof WebGLActiveInfo');
+shouldBeTrue('gl.getActiveUniform(program, 0) instanceof WebGLActiveInfo');
+
+debug("");
+debug("Tests that those WebGL objects can not be constructed through new operator");
+debug("");
+
+function shouldThrowWithNew(objectType, objectName)
+{
+    try {
+        new objectType;
+        testFailed('new ' + objectName + ' did not throw');
+    } catch (e) {
+        testPassed('new ' + objectName + ' threw an error');
+    }
+}
+
+shouldThrowWithNew(WebGLRenderingContext, 'WebGLRenderingContext');
+shouldThrowWithNew(WebGLActiveInfo, 'WebGLActiveInfo');
+shouldThrowWithNew(WebGLBuffer, 'WebGLBuffer');
+shouldThrowWithNew(WebGLFramebuffer, 'WebGLFramebuffer');
+shouldThrowWithNew(WebGLProgram, 'WebGLProgram');
+shouldThrowWithNew(WebGLRenderbuffer, 'WebGLRenderbuffer');
+shouldThrowWithNew(WebGLShader, 'WebGLShader');
+shouldThrowWithNew(WebGLTexture, 'WebGLTexture');
+shouldThrowWithNew(WebGLUniformLocation, 'WebGLUniformLocation');
+
+successfullyParsed = true;
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
--- a/content/canvas/test/webgl/conformance/invalid-passed-params.html
+++ b/content/canvas/test/webgl/conformance/invalid-passed-params.html
@@ -33,40 +33,156 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 <div id="description"></div>
 <div id="console"></div>
 
 <script>
 description("Test for invalid passed parameters");
 
 var context = create3DContext();
 
+debug("");
 debug("Test createShader()");
 shouldGenerateGLError(context, context.NO_ERROR, "context.createShader(context.FRAGMENT_SHADER)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.createShader(context.VERTEX_SHADER)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.createShader(0)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.createShader(context.TRIANGLES)");
 
+debug("");
 debug("Test clear()");
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'])");
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'] | context.COLOR_BUFFER_BIT)");
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'] | context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT)");
 
+debug("");
 debug("Test bufferData()");
 var buffer = context.createBuffer();
 shouldGenerateGLError(context, context.NO_ERROR, "context.bindBuffer(context.ARRAY_BUFFER, buffer)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 16, context.STREAM_DRAW)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 16, context.STATIC_DRAW)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 16, context.DYNAMIC_DRAW)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STREAM_READ'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STREAM_COPY'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STATIC_READ'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STATIC_COPY'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_READ'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_COPY'])");
 
+debug("");
+debug("Test {copy}Tex{Sub}Image2D with negative offset/width/height");
+var tex = context.createTexture();
+var pixels = new Uint8Array(2 * 2 * 4);
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindTexture(context.TEXTURE_2D, tex)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, -16, -16, 0, context.RGBA, context.UNSIGNED_BYTE, null)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 16, 16, 0, context.RGBA, context.UNSIGNED_BYTE, null)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.texSubImage2D(context.TEXTURE_2D, 0, -1, -1, 2, 2, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.texSubImage2D(context.TEXTURE_2D, 0, 0, 0, -1, -1, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.texSubImage2D(context.TEXTURE_2D, 0, 0, 0, 2, 2, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, -1, -1, 0)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, 16, 16, 0)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, -1, -1, 0, 0, 2, 2)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, -1, -1)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2)");
+
+debug("");
+debug("Test renderbufferStorage() with negative width/height");
+var renderbuffer = context.createRenderbuffer();
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindRenderbuffer(context.RENDERBUFFER, renderbuffer)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.renderbufferStorage(context.RENDERBUFFER, context.RGBA4, -2, -2)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.renderbufferStorage(context.RENDERBUFFER, context.RGBA4, 16, 16)");
+
+debug("");
+debug("Test scissor() with negative width/height");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.scissor(0, 0, -2, -2)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.scissor(0, 0, 16, 16)");
+
+debug("");
+debug("Test viewport() with negative width/height");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.viewport(0, 0, -2, -2)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.viewport(0, 0, 16, 16)");
+
+debug("");
+debug("Set up a program to test invalid characters");
+var invalidSet = ['"', '$', '`', '@', '\\', "'"];
+var validUniformName = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
+var validAttribName = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+function generateShaderSource(opt_invalidIdentifierChar, opt_invalidCommentChar) {
+  var invalidIdentifierString = "";
+  var invalidCommentString = "";
+  if (opt_invalidIdentifierChar != undefined) {
+    invalidIdentifierString += opt_invalidIdentifierChar;
+  }
+  if (opt_invalidCommentChar != undefined) {
+    invalidCommentString += opt_invalidCommentChar;
+  }
+  return "uniform float " + validUniformName + invalidIdentifierString + ";\n"
+                          + "varying float " + validAttribName + ";\n"
+                          + "void main() {\n"
+                          + validAttribName  + " = " + validUniformName + ";\n"
+                          + "gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }\n";
+                          + "//.+-/*%<>[](){}^|&~=!:;,?# " + invalidCommentString;
+}
+var vShader = context.createShader(context.VERTEX_SHADER);
+context.shaderSource(vShader, generateShaderSource());
+context.compileShader(vShader);
+shouldBe("context.getError()", "context.NO_ERROR");
+var fShader = context.createShader(context.FRAGMENT_SHADER);
+context.shaderSource(fShader, "precision highp float;\n"
+                              + "varying float " + validAttribName + ";\n"
+                              + "void main() {\n"
+                              + "gl_FragColor = vec4(" + validAttribName + ", 0.0, 0.0, 1.0); }");
+context.compileShader(fShader);
+shouldBe("context.getError()", "context.NO_ERROR");
+var program = context.createProgram();
+context.attachShader(program, vShader);
+context.attachShader(program, fShader);
+context.linkProgram(program);
+shouldBeTrue("context.getProgramParameter(program, context.LINK_STATUS)");
+shouldBe("context.getError()", "context.NO_ERROR");
+context.bindAttribLocation(program, 1, validAttribName);
+shouldBe("context.getError()", "context.NO_ERROR");
+context.getAttribLocation(program, validAttribName);
+shouldBe("context.getError()", "context.NO_ERROR");
+context.getUniformLocation(program, validUniformName);
+shouldBe("context.getError()", "context.NO_ERROR");
+
+debug("");
+debug("Test shaderSource() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var validShaderSource = generateShaderSource(undefined, invalidSet[i]);
+  context.shaderSource(vShader, validShaderSource);
+  shouldBe("context.getError()", "context.NO_ERROR");
+  var invalidShaderSource = generateShaderSource(invalidSet[i], undefined);
+  context.shaderSource(vShader, invalidShaderSource);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test bindAttribLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var invalidName = validAttribName + invalidSet[i];
+  context.bindAttribLocation(program, 1, invalidName);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test getAttribLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var invalidName = validAttribName + invalidSet[i];
+  context.getAttribLocation(program, invalidName);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test getUniformLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var invalidName = validUniformName + invalidSet[i];
+  context.getUniformLocation(program, invalidName);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
 debug("")
 successfullyParsed = true;
 </script>
 
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/00_test_list.txt
@@ -0,0 +1,48 @@
+conformance/constants.html
+conformance/getContext.html
+conformance/methods.html
+#conformance/quickCheckAPI.html
+conformance/webGLArrays.html
+functions/bindBuffer.html
+functions/bindBufferBadArgs.html
+functions/bindFramebufferLeaveNonZero.html
+functions/bufferData.html
+functions/bufferDataBadArgs.html
+functions/bufferSubData.html
+functions/bufferSubDataBadArgs.html
+functions/copyTexImage2D.html
+functions/copyTexImage2DBadArgs.html
+functions/copyTexSubImage2D.html
+functions/copyTexSubImage2DBadArgs.html
+functions/deleteBufferBadArgs.html
+functions/drawArrays.html
+functions/drawArraysOutOfBounds.html
+functions/drawElements.html
+functions/drawElementsBadArgs.html
+functions/isTests.html
+functions/readPixels.html
+functions/readPixelsBadArgs.html
+functions/texImage2D.html
+functions/texImage2DBadArgs.html
+functions/texImage2DHTML.html
+functions/texImage2DHTMLBadArgs.html
+functions/texSubImage2D.html
+functions/texSubImage2DBadArgs.html
+functions/texSubImage2DHTML.html
+functions/texSubImage2DHTMLBadArgs.html
+functions/uniformf.html
+functions/uniformfBadArgs.html
+functions/uniformfArrayLen1.html
+functions/uniformi.html
+functions/uniformiBadArgs.html
+functions/uniformMatrix.html
+functions/uniformMatrixBadArgs.html
+functions/vertexAttrib.html
+functions/vertexAttribBadArgs.html
+functions/vertexAttribPointer.html
+functions/vertexAttribPointerBadArgs.html
+glsl/arrayOutOfBounds.html
+#glsl/longLoops.html // No interactive tests.
+glsl/uniformOutOfBounds.html
+#glsl/unusedAttribsUniforms.html // No interactive tests.
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/README.md
@@ -0,0 +1,53 @@
+Tests for the WebGL canvas context
+==================================
+
+These tests are intended to serve the following purposes:
+
+  * Assert spec conformance
+  * Check the safety of the GL binding (bounds checking, same origin policy)
+  * Provide performance numbers for developers
+
+
+Running the tests
+-----------------
+
+  1. <a href="http://learningwebgl.com/blog/?p=11">Install a browser with WebGL support</a>
+  2. Run <code>ruby gen_tests.rb</code> if you have modified the tests.
+  3. Run <code>ruby test_server.rb</code> if you want to get test run output to test_server's stdout (especially useful for finding out which test crashed your browser.)
+  4. Open all_tests.html in your browser.
+
+
+Want to contribute?
+-------------------
+
+  1. Fork this repo
+  2. Run <code>gen_tests.rb</code>
+  3. Look into templates/ to see which functions lack tests (also see <a href="../raw/master/methods.txt">methods.txt</a> and <a href="http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl">nsICanvasRenderingContextWebGL.idl</a>):
+    1. copy methodName.html to functions/methodName.html and write tests that test the results of valid inputs.
+    2. copy methodNameBadArgs.html to functions/methodNameBadArgs.html and write tests to assert that invalid inputs throw exceptions.
+    3. If your test causes a segfault, add the following to the top of the script tag: <code>Tests.autorun = false; Tests.message = "Caution: this may crash your browser";</code>
+  4. For each performance test:
+    1. Write a performance/myTestName.html and set <code>Tests.autorun = false;</code>
+  5. If you have a test that you would like to run over the whole API or want to generate tests programmatically, add them to gen_tests.rb or write your own script.
+  6. Create a commit for each file. (E.g. <code>for f in $(git status | grep -e "^#\\s*functions/\\S*$" | sed "s/^#\s*//"); do git add $f; git commit -m $f; done</code>)
+  7. Send me a pull request.
+  8. Congratulations, you're now a contributor!
+
+
+For more information on WebGL:
+
+  * <a href="http://planet-webgl.org">Planet WebGL</a>
+  * <a href="http://learningwebgl.com">Learning WebGL</a>
+  * <a href="http://www.khronos.org/message_boards/viewforum.php?f=34">WebGL on Khronos Message Boards</a>
+
+Developer links:
+
+  * <a href="https://bugzilla.mozilla.org/buglist.cgi?quicksearch=webgl">WebGL on Mozilla Bugzilla</a>
+  * <a href="https://bugzilla.webkit.org/buglist.cgi?quicksearch=webgl">WebGL on WebKit Bugzilla</a>
+  * <a href="http://code.google.com/p/chromium/issues/list?q=label:3D-WebGL">WebGL on Chromium Bugzilla</a>
+
+What's the stuff in apigen?
+
+  There are some Python scripts in the apigen/ directory that generate C++ based on the API definition files (gl2.h, api_modifications.txt, valid_args.txt.) The generated code is Mozilla XPCOM functions that check their args against the valid GLES 2.0 constants (as they were written on the man pages.) There's also some wackier stuff for checking copyTexImage2D and copyTexSubImage2D image dimensions against viewport dimensions.
+
+  If you can use it to generate code for your WebGL implementation, it might save you 1500 lines of typing and testing. The last time I used it was summer 2009 to generate a patch for Canvas 3D, so it's likely somewhat out of date.
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/all_tests.html
@@ -0,0 +1,399 @@
+<html>
+<head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+  <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+  <style type="text/css">
+    h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+    iframe { display: inline; border: 1px solid black; overflow: hidden;}
+  </style>
+  <script type="text/javascript">
+    function loadTest(id, url) {
+      document.getElementById(id).src = url;
+    }
+    function seqLoader() {
+      var iframes = document.getElementsByTagName('iframe');
+      for (var i=0; i<iframes.length; i++) {
+        iframes[i].addEventListener('load', (function(j) {
+          return function() {
+            var e = document.getElementById((j+1)+'_link');
+            if (e) loadTest(j+1, e.href);
+          }
+        })(i), false);
+      }
+      var e = document.getElementById('0_link');
+      if (e) loadTest(0, e.href);
+    }
+  </script>
+</head>
+<body onload="seqLoader()">
+
+    <div>
+      <iframe src="conformance/badArgsArityLessThanArgc.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/constants.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/constants.html">conformance/constants.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/fuzzTheAPI.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/getContext.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/getContext.html">conformance/getContext.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/methods.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/methods.html">conformance/methods.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/quickCheckAPI.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/quickCheckAPIBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/webGLArrays.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bindBuffer.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bindBufferBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bindFramebufferLeaveNonZero.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferData.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferData.html">functions/bufferData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferDataBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferSubData.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferSubDataBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexSubImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexSubImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/deleteBufferBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawArrays.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawArraysOutOfBounds.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawElements.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawElements.html">functions/drawElements.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawElementsBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/getImageData.html" width="110" height="42"></iframe>
+      <h2><a href="functions/getImageData.html">functions/getImageData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/getImageDataBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/isTests.html" width="110" height="42"></iframe>
+      <h2><a href="functions/isTests.html">functions/isTests.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/linkProgramBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/readPixels.html" width="110" height="42"></iframe>
+      <h2><a href="functions/readPixels.html">functions/readPixels.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/readPixelsBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2DHTML.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2DHTMLBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2DHTML.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2DHTMLBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformMatrix.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformMatrixBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformf.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformf.html">functions/uniformf.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformfBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformi.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformi.html">functions/uniformi.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformiBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttrib.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttribBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttribPointer.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttribPointerBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/CPUvsGPU.html" width="110" height="42"></iframe>
+      <h2><a href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/bandwidth.html" width="110" height="42"></iframe>
+      <h2><a href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/jsGCPause.html" width="110" height="42"></iframe>
+      <h2><a href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/jsMatrixMult.html" width="110" height="42"></iframe>
+      <h2><a href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/jsToGLOverhead.html" width="110" height="42"></iframe>
+      <h2><a href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/arrayOutOfBounds.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/longLoops.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/uniformOutOfBounds.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/unusedAttribsUniforms.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+    </div>
+    
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/all_tests_linkonly.html
@@ -0,0 +1,399 @@
+<html>
+<head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+  <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+  <style type="text/css">
+    h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+    iframe { display: inline; border: 1px solid black; overflow: hidden;}
+  </style>
+  <script type="text/javascript">
+    function loadTest(id, url) {
+      document.getElementById(id).src = url;
+    }
+    function seqLoader() {
+      var iframes = document.getElementsByTagName('iframe');
+      for (var i=0; i<iframes.length; i++) {
+        iframes[i].addEventListener('load', (function(j) {
+          return function() {
+            var e = document.getElementById((j+1)+'_link');
+            if (e) loadTest(j+1, e.href);
+          }
+        })(i), false);
+      }
+      var e = document.getElementById('0_link');
+      if (e) loadTest(0, e.href);
+    }
+  </script>
+</head>
+<body onload="seqLoader()">
+
+    <div>
+      <iframe id="0" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(0, 'conformance/badArgsArityLessThanArgc.html');return false" href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="1" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(1, 'conformance/constants.html');return false" href="conformance/constants.html">conformance/constants.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="2" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(2, 'conformance/fuzzTheAPI.html');return false" href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="3" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(3, 'conformance/getContext.html');return false" href="conformance/getContext.html">conformance/getContext.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="4" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(4, 'conformance/methods.html');return false" href="conformance/methods.html">conformance/methods.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="5" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(5, 'conformance/quickCheckAPI.html');return false" href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="6" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(6, 'conformance/quickCheckAPIBadArgs.html');return false" href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="7" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(7, 'conformance/webGLArrays.html');return false" href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="8" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(8, 'functions/bindBuffer.html');return false" href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="9" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(9, 'functions/bindBufferBadArgs.html');return false" href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="10" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(10, 'functions/bindFramebufferLeaveNonZero.html');return false" href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="11" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(11, 'functions/bufferData.html');return false" href="functions/bufferData.html">functions/bufferData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="12" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(12, 'functions/bufferDataBadArgs.html');return false" href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="13" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(13, 'functions/bufferSubData.html');return false" href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="14" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(14, 'functions/bufferSubDataBadArgs.html');return false" href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="15" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(15, 'functions/copyTexImage2D.html');return false" href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="16" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(16, 'functions/copyTexImage2DBadArgs.html');return false" href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="17" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(17, 'functions/copyTexSubImage2D.html');return false" href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="18" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(18, 'functions/copyTexSubImage2DBadArgs.html');return false" href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="19" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(19, 'functions/deleteBufferBadArgs.html');return false" href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="20" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(20, 'functions/drawArrays.html');return false" href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="21" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(21, 'functions/drawArraysOutOfBounds.html');return false" href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="22" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(22, 'functions/drawElements.html');return false" href="functions/drawElements.html">functions/drawElements.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="23" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(23, 'functions/drawElementsBadArgs.html');return false" href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="24" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(24, 'functions/getImageData.html');return false" href="functions/getImageData.html">functions/getImageData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="25" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(25, 'functions/getImageDataBadArgs.html');return false" href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="26" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(26, 'functions/isTests.html');return false" href="functions/isTests.html">functions/isTests.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="27" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(27, 'functions/linkProgramBadArgs.html');return false" href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="28" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(28, 'functions/readPixels.html');return false" href="functions/readPixels.html">functions/readPixels.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="29" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(29, 'functions/readPixelsBadArgs.html');return false" href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="30" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(30, 'functions/texImage2D.html');return false" href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="31" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(31, 'functions/texImage2DBadArgs.html');return false" href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="32" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(32, 'functions/texImage2DHTML.html');return false" href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="33" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(33, 'functions/texImage2DHTMLBadArgs.html');return false" href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="34" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(34, 'functions/texSubImage2D.html');return false" href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="35" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(35, 'functions/texSubImage2DBadArgs.html');return false" href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="36" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(36, 'functions/texSubImage2DHTML.html');return false" href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="37" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(37, 'functions/texSubImage2DHTMLBadArgs.html');return false" href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="38" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(38, 'functions/uniformMatrix.html');return false" href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="39" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(39, 'functions/uniformMatrixBadArgs.html');return false" href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="40" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(40, 'functions/uniformf.html');return false" href="functions/uniformf.html">functions/uniformf.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="41" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(41, 'functions/uniformfBadArgs.html');return false" href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="42" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(42, 'functions/uniformi.html');return false" href="functions/uniformi.html">functions/uniformi.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="43" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(43, 'functions/uniformiBadArgs.html');return false" href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="44" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(44, 'functions/vertexAttrib.html');return false" href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="45" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(45, 'functions/vertexAttribBadArgs.html');return false" href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="46" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(46, 'functions/vertexAttribPointer.html');return false" href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="47" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(47, 'functions/vertexAttribPointerBadArgs.html');return false" href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="48" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(48, 'performance/CPUvsGPU.html');return false" href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="49" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(49, 'performance/bandwidth.html');return false" href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="50" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(50, 'performance/jsGCPause.html');return false" href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="51" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(51, 'performance/jsMatrixMult.html');return false" href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="52" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(52, 'performance/jsToGLOverhead.html');return false" href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="53" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(53, 'glsl/arrayOutOfBounds.html');return false" href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="54" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(54, 'glsl/longLoops.html');return false" href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="55" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(55, 'glsl/uniformOutOfBounds.html');return false" href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="56" width="110" height="42"></iframe>
+      <h2><a onclick="loadTest(56, 'glsl/unusedAttribsUniforms.html');return false" href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+    </div>
+    
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/all_tests_sequential.html
@@ -0,0 +1,399 @@
+<html>
+<head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+  <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+  <style type="text/css">
+    h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+    iframe { display: inline; border: 1px solid black; overflow: hidden;}
+  </style>
+  <script type="text/javascript">
+    function loadTest(id, url) {
+      document.getElementById(id).src = url;
+    }
+    function seqLoader() {
+      var iframes = document.getElementsByTagName('iframe');
+      for (var i=0; i<iframes.length; i++) {
+        iframes[i].addEventListener('load', (function(j) {
+          return function() {
+            var e = document.getElementById((j+1)+'_link');
+            if (e) loadTest(j+1, e.href);
+          }
+        })(i), false);
+      }
+      var e = document.getElementById('0_link');
+      if (e) loadTest(0, e.href);
+    }
+  </script>
+</head>
+<body onload="seqLoader()">
+
+    <div>
+      <iframe id="0" width="110" height="42"></iframe>
+      <h2><a id="0_link" href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="1" width="110" height="42"></iframe>
+      <h2><a id="1_link" href="conformance/constants.html">conformance/constants.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="2" width="110" height="42"></iframe>
+      <h2><a id="2_link" href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="3" width="110" height="42"></iframe>
+      <h2><a id="3_link" href="conformance/getContext.html">conformance/getContext.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="4" width="110" height="42"></iframe>
+      <h2><a id="4_link" href="conformance/methods.html">conformance/methods.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="5" width="110" height="42"></iframe>
+      <h2><a id="5_link" href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="6" width="110" height="42"></iframe>
+      <h2><a id="6_link" href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="7" width="110" height="42"></iframe>
+      <h2><a id="7_link" href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="8" width="110" height="42"></iframe>
+      <h2><a id="8_link" href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="9" width="110" height="42"></iframe>
+      <h2><a id="9_link" href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="10" width="110" height="42"></iframe>
+      <h2><a id="10_link" href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="11" width="110" height="42"></iframe>
+      <h2><a id="11_link" href="functions/bufferData.html">functions/bufferData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="12" width="110" height="42"></iframe>
+      <h2><a id="12_link" href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="13" width="110" height="42"></iframe>
+      <h2><a id="13_link" href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="14" width="110" height="42"></iframe>
+      <h2><a id="14_link" href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="15" width="110" height="42"></iframe>
+      <h2><a id="15_link" href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="16" width="110" height="42"></iframe>
+      <h2><a id="16_link" href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="17" width="110" height="42"></iframe>
+      <h2><a id="17_link" href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="18" width="110" height="42"></iframe>
+      <h2><a id="18_link" href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="19" width="110" height="42"></iframe>
+      <h2><a id="19_link" href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="20" width="110" height="42"></iframe>
+      <h2><a id="20_link" href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="21" width="110" height="42"></iframe>
+      <h2><a id="21_link" href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="22" width="110" height="42"></iframe>
+      <h2><a id="22_link" href="functions/drawElements.html">functions/drawElements.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="23" width="110" height="42"></iframe>
+      <h2><a id="23_link" href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="24" width="110" height="42"></iframe>
+      <h2><a id="24_link" href="functions/getImageData.html">functions/getImageData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="25" width="110" height="42"></iframe>
+      <h2><a id="25_link" href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="26" width="110" height="42"></iframe>
+      <h2><a id="26_link" href="functions/isTests.html">functions/isTests.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="27" width="110" height="42"></iframe>
+      <h2><a id="27_link" href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="28" width="110" height="42"></iframe>
+      <h2><a id="28_link" href="functions/readPixels.html">functions/readPixels.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="29" width="110" height="42"></iframe>
+      <h2><a id="29_link" href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="30" width="110" height="42"></iframe>
+      <h2><a id="30_link" href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="31" width="110" height="42"></iframe>
+      <h2><a id="31_link" href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="32" width="110" height="42"></iframe>
+      <h2><a id="32_link" href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="33" width="110" height="42"></iframe>
+      <h2><a id="33_link" href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="34" width="110" height="42"></iframe>
+      <h2><a id="34_link" href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="35" width="110" height="42"></iframe>
+      <h2><a id="35_link" href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="36" width="110" height="42"></iframe>
+      <h2><a id="36_link" href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="37" width="110" height="42"></iframe>
+      <h2><a id="37_link" href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="38" width="110" height="42"></iframe>
+      <h2><a id="38_link" href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="39" width="110" height="42"></iframe>
+      <h2><a id="39_link" href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="40" width="110" height="42"></iframe>
+      <h2><a id="40_link" href="functions/uniformf.html">functions/uniformf.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="41" width="110" height="42"></iframe>
+      <h2><a id="41_link" href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="42" width="110" height="42"></iframe>
+      <h2><a id="42_link" href="functions/uniformi.html">functions/uniformi.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="43" width="110" height="42"></iframe>
+      <h2><a id="43_link" href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="44" width="110" height="42"></iframe>
+      <h2><a id="44_link" href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="45" width="110" height="42"></iframe>
+      <h2><a id="45_link" href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="46" width="110" height="42"></iframe>
+      <h2><a id="46_link" href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="47" width="110" height="42"></iframe>
+      <h2><a id="47_link" href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="48" width="110" height="42"></iframe>
+      <h2><a id="48_link" href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="49" width="110" height="42"></iframe>
+      <h2><a id="49_link" href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="50" width="110" height="42"></iframe>
+      <h2><a id="50_link" href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="51" width="110" height="42"></iframe>
+      <h2><a id="51_link" href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="52" width="110" height="42"></iframe>
+      <h2><a id="52_link" href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="53" width="110" height="42"></iframe>
+      <h2><a id="53_link" href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="54" width="110" height="42"></iframe>
+      <h2><a id="54_link" href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="55" width="110" height="42"></iframe>
+      <h2><a id="55_link" href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe id="56" width="110" height="42"></iframe>
+      <h2><a id="56_link" href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+    </div>
+    
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/badArgsArityLessThanArgc.html
@@ -0,0 +1,598 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+<script type="application/x-javascript">
+
+/*
+  The following tests are generated from
+  http://www.khronos.org/registry/gles/api/2.0/gl2.h
+  and api_modifications.txt
+*/
+Tests.test_activeTexture = function(gl) {
+  assertFail(function(){ gl.activeTexture(); });
+}
+Tests.test_attachShader = function(gl) {
+  assertFail(function(){ gl.attachShader(); });
+  assertFail(function(){ gl.attachShader(0); });
+}
+Tests.test_bindAttribLocation = function(gl) {
+  assertFail(function(){ gl.bindAttribLocation(); });
+  assertFail(function(){ gl.bindAttribLocation(0); });
+  assertFail(function(){ gl.bindAttribLocation(0,0); });
+}
+Tests.test_bindBuffer = function(gl) {
+  assertFail(function(){ gl.bindBuffer(); });
+  assertFail(function(){ gl.bindBuffer(0); });
+}
+Tests.test_bindFramebuffer = function(gl) {
+  assertFail(function(){ gl.bindFramebuffer(); });
+  assertFail(function(){ gl.bindFramebuffer(0); });
+}
+Tests.test_bindRenderbuffer = function(gl) {
+  assertFail(function(){ gl.bindRenderbuffer(); });
+  assertFail(function(){ gl.bindRenderbuffer(0); });
+}
+Tests.test_bindTexture = function(gl) {
+  assertFail(function(){ gl.bindTexture(); });
+  assertFail(function(){ gl.bindTexture(0); });
+}
+Tests.test_blendColor = function(gl) {
+  assertFail(function(){ gl.blendColor(); });
+  assertFail(function(){ gl.blendColor(0); });
+  assertFail(function(){ gl.blendColor(0,0); });
+  assertFail(function(){ gl.blendColor(0,0,0); });
+}
+Tests.test_blendEquation = function(gl) {
+  assertFail(function(){ gl.blendEquation(); });
+}
+Tests.test_blendEquationSeparate = function(gl) {
+  assertFail(function(){ gl.blendEquationSeparate(); });
+  assertFail(function(){ gl.blendEquationSeparate(0); });
+}
+Tests.test_blendFunc = function(gl) {
+  assertFail(function(){ gl.blendFunc(); });
+  assertFail(function(){ gl.blendFunc(0); });
+}
+Tests.test_blendFuncSeparate = function(gl) {
+  assertFail(function(){ gl.blendFuncSeparate(); });
+  assertFail(function(){ gl.blendFuncSeparate(0); });
+  assertFail(function(){ gl.blendFuncSeparate(0,0); });
+  assertFail(function(){ gl.blendFuncSeparate(0,0,0); });
+}
+Tests.test_bufferData = function(gl) {
+  assertFail(function(){ gl.bufferData(); });
+  assertFail(function(){ gl.bufferData(0); });
+  assertFail(function(){ gl.bufferData(0,0); });
+}
+Tests.test_bufferSubData = function(gl) {
+  assertFail(function(){ gl.bufferSubData(); });
+  assertFail(function(){ gl.bufferSubData(0); });
+  assertFail(function(){ gl.bufferSubData(0,0); });
+}
+Tests.test_checkFramebufferStatus = function(gl) {
+  assertFail(function(){ gl.checkFramebufferStatus(); });
+}
+Tests.test_clear = function(gl) {
+  assertFail(function(){ gl.clear(); });
+}
+Tests.test_clearColor = function(gl) {
+  assertFail(function(){ gl.clearColor(); });
+  assertFail(function(){ gl.clearColor(0); });
+  assertFail(function(){ gl.clearColor(0,0); });
+  assertFail(function(){ gl.clearColor(0,0,0); });
+}
+Tests.test_clearDepth = function(gl) {
+  assertFail(function(){ gl.clearDepth(); });
+}
+Tests.test_clearStencil = function(gl) {
+  assertFail(function(){ gl.clearStencil(); });
+}
+Tests.test_colorMask = function(gl) {
+  assertFail(function(){ gl.colorMask(); });
+  assertFail(function(){ gl.colorMask(0); });
+  assertFail(function(){ gl.colorMask(0,0); });
+  assertFail(function(){ gl.colorMask(0,0,0); });
+}
+Tests.test_compileShader = function(gl) {
+  assertFail(function(){ gl.compileShader(); });
+}
+Tests.test_copyTexImage2D = function(gl) {
+  assertFail(function(){ gl.copyTexImage2D(); });
+  assertFail(function(){ gl.copyTexImage2D(0); });
+  assertFail(function(){ gl.copyTexImage2D(0,0); });
+  assertFail(function(){ gl.copyTexImage2D(0,0,0); });
+  assertFail(function(){ gl.copyTexImage2D(0,0,0,0); });
+  assertFail(function(){ gl.copyTexImage2D(0,0,0,0,0); });
+  assertFail(function(){ gl.copyTexImage2D(0,0,0,0,0,0); });
+  assertFail(function(){ gl.copyTexImage2D(0,0,0,0,0,0,0); });
+}
+Tests.test_copyTexSubImage2D = function(gl) {
+  assertFail(function(){ gl.copyTexSubImage2D(); });
+  assertFail(function(){ gl.copyTexSubImage2D(0); });
+  assertFail(function(){ gl.copyTexSubImage2D(0,0); });
+  assertFail(function(){ gl.copyTexSubImage2D(0,0,0); });
+  assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0); });
+  assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0,0); });
+  assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0,0,0); });
+  assertFail(function(){ gl.copyTexSubImage2D(0,0,0,0,0,0,0); });
+}
+Tests.test_createProgram = function(gl) {
+}
+Tests.test_createShader = function(gl) {
+  assertFail(function(){ gl.createShader(); });
+}
+Tests.test_cullFace = function(gl) {
+  assertFail(function(){ gl.cullFace(); });
+}
+Tests.test_deleteBuffer = function(gl) {
+  assertFail(function(){ gl.deleteBuffer(); });
+}
+Tests.test_deleteFramebuffer = function(gl) {
+  assertFail(function(){ gl.deleteFramebuffer(); });
+}
+Tests.test_deleteProgram = function(gl) {
+  assertFail(function(){ gl.deleteProgram(); });
+}
+Tests.test_deleteRenderbuffer = function(gl) {
+  assertFail(function(){ gl.deleteRenderbuffer(); });
+}
+Tests.test_deleteShader = function(gl) {
+  assertFail(function(){ gl.deleteShader(); });
+}
+Tests.test_deleteTexture = function(gl) {
+  assertFail(function(){ gl.deleteTexture(); });
+}
+Tests.test_depthFunc = function(gl) {
+  assertFail(function(){ gl.depthFunc(); });
+}
+Tests.test_depthMask = function(gl) {
+  assertFail(function(){ gl.depthMask(); });
+}
+Tests.test_depthRange = function(gl) {
+  assertFail(function(){ gl.depthRange(); });
+  assertFail(function(){ gl.depthRange(0); });
+}
+Tests.test_detachShader = function(gl) {
+  assertFail(function(){ gl.detachShader(); });
+  assertFail(function(){ gl.detachShader(0); });
+}
+Tests.test_disable = function(gl) {
+  assertFail(function(){ gl.disable(); });
+}
+Tests.test_disableVertexAttribArray = function(gl) {
+  assertFail(function(){ gl.disableVertexAttribArray(); });
+}
+Tests.test_drawArrays = function(gl) {
+  assertFail(function(){ gl.drawArrays(); });
+  assertFail(function(){ gl.drawArrays(0); });
+  assertFail(function(){ gl.drawArrays(0,0); });
+}
+Tests.test_drawElements = function(gl) {
+  assertFail(function(){ gl.drawElements(); });
+  assertFail(function(){ gl.drawElements(0); });
+  assertFail(function(){ gl.drawElements(0,0); });
+  assertFail(function(){ gl.drawElements(0,0,0); });
+}
+Tests.test_enable = function(gl) {
+  assertFail(function(){ gl.enable(); });
+}
+Tests.test_enableVertexAttribArray = function(gl) {
+  assertFail(function(){ gl.enableVertexAttribArray(); });
+}
+Tests.test_finish = function(gl) {
+}
+Tests.test_flush = function(gl) {
+}
+Tests.test_framebufferRenderbuffer = function(gl) {
+  assertFail(function(){ gl.framebufferRenderbuffer(); });
+  assertFail(function(){ gl.framebufferRenderbuffer(0); });
+  assertFail(function(){ gl.framebufferRenderbuffer(0,0); });
+  assertFail(function(){ gl.framebufferRenderbuffer(0,0,0); });
+}
+Tests.test_framebufferTexture2D = function(gl) {
+  assertFail(function(){ gl.framebufferTexture2D(); });
+  assertFail(function(){ gl.framebufferTexture2D(0); });
+  assertFail(function(){ gl.framebufferTexture2D(0,0); });
+  assertFail(function(){ gl.framebufferTexture2D(0,0,0); });
+  assertFail(function(){ gl.framebufferTexture2D(0,0,0,0); });
+}
+Tests.test_frontFace = function(gl) {
+  assertFail(function(){ gl.frontFace(); });
+}
+Tests.test_createBuffer = function(gl) {
+}
+Tests.test_generateMipmap = function(gl) {
+  assertFail(function(){ gl.generateMipmap(); });
+}
+Tests.test_createFramebuffer = function(gl) {
+}
+Tests.test_createRenderbuffer = function(gl) {
+}
+Tests.test_createTexture = function(gl) {
+}
+Tests.test_getActiveAttrib = function(gl) {
+  assertFail(function(){ gl.getActiveAttrib(); });
+  assertFail(function(){ gl.getActiveAttrib(0); });
+}
+Tests.test_getActiveUniform = function(gl) {
+  assertFail(function(){ gl.getActiveUniform(); });
+  assertFail(function(){ gl.getActiveUniform(0); });
+}
+Tests.test_getAttachedShaders = function(gl) {
+  assertFail(function(){ gl.getAttachedShaders(); });
+}
+Tests.test_getAttribLocation = function(gl) {
+  assertFail(function(){ gl.getAttribLocation(); });
+  assertFail(function(){ gl.getAttribLocation(0); });
+}
+Tests.test_getBufferParameteri = function(gl) {
+  assertFail(function(){ gl.getBufferParameteri(); });
+  assertFail(function(){ gl.getBufferParameteri(0); });
+}
+Tests.test_getError = function(gl) {
+}
+Tests.test_getFramebufferAttachmentParameteri = function(gl) {
+  assertFail(function(){ gl.getFramebufferAttachmentParameteri(); });
+  assertFail(function(){ gl.getFramebufferAttachmentParameteri(0); });
+  assertFail(function(){ gl.getFramebufferAttachmentParameteri(0,0); });
+}
+Tests.test_getProgramInfoLog = function(gl) {
+  assertFail(function(){ gl.getProgramInfoLog(); });
+}
+Tests.test_getRenderbufferParameteri = function(gl) {
+  assertFail(function(){ gl.getRenderbufferParameteri(); });
+  assertFail(function(){ gl.getRenderbufferParameteri(0); });
+}
+Tests.test_getShaderInfoLog = function(gl) {
+  assertFail(function(){ gl.getShaderInfoLog(); });
+}
+Tests.test_getShaderSource = function(gl) {
+  assertFail(function(){ gl.getShaderSource(); });
+}
+Tests.test_getUniformLocation = function(gl) {
+  assertFail(function(){ gl.getUniformLocation(); });
+  assertFail(function(){ gl.getUniformLocation(0); });
+}
+Tests.test_hint = function(gl) {
+  assertFail(function(){ gl.hint(); });
+  assertFail(function(){ gl.hint(0); });
+}
+Tests.test_isBuffer = function(gl) {
+  assertFail(function(){ gl.isBuffer(); });
+}
+Tests.test_isEnabled = function(gl) {
+  assertFail(function(){ gl.isEnabled(); });
+}
+Tests.test_isFramebuffer = function(gl) {
+  assertFail(function(){ gl.isFramebuffer(); });
+}
+Tests.test_isProgram = function(gl) {
+  assertFail(function(){ gl.isProgram(); });
+}
+Tests.test_isRenderbuffer = function(gl) {
+  assertFail(function(){ gl.isRenderbuffer(); });
+}
+Tests.test_isShader = function(gl) {
+  assertFail(function(){ gl.isShader(); });
+}
+Tests.test_isTexture = function(gl) {
+  assertFail(function(){ gl.isTexture(); });
+}
+Tests.test_lineWidth = function(gl) {
+  assertFail(function(){ gl.lineWidth(); });
+}
+Tests.test_linkProgram = function(gl) {
+  assertFail(function(){ gl.linkProgram(); });
+}
+Tests.test_polygonOffset = function(gl) {
+  assertFail(function(){ gl.polygonOffset(); });
+  assertFail(function(){ gl.polygonOffset(0); });
+}
+Tests.test_readPixels = function(gl) {
+  assertFail(function(){ gl.readPixels(); });
+  assertFail(function(){ gl.readPixels(0); });
+  assertFail(function(){ gl.readPixels(0,0); });
+  assertFail(function(){ gl.readPixels(0,0,0); });
+  assertFail(function(){ gl.readPixels(0,0,0,0); });
+  assertFail(function(){ gl.readPixels(0,0,0,0,0); });
+}
+Tests.test_renderbufferStorage = function(gl) {
+  assertFail(function(){ gl.renderbufferStorage(); });
+  assertFail(function(){ gl.renderbufferStorage(0); });
+  assertFail(function(){ gl.renderbufferStorage(0,0); });
+  assertFail(function(){ gl.renderbufferStorage(0,0,0); });
+}
+Tests.test_sampleCoverage = function(gl) {
+  assertFail(function(){ gl.sampleCoverage(); });
+  assertFail(function(){ gl.sampleCoverage(0); });
+}
+Tests.test_scissor = function(gl) {
+  assertFail(function(){ gl.scissor(); });
+  assertFail(function(){ gl.scissor(0); });
+  assertFail(function(){ gl.scissor(0,0); });
+  assertFail(function(){ gl.scissor(0,0,0); });
+}
+Tests.test_shaderSource = function(gl) {
+  assertFail(function(){ gl.shaderSource(); });
+  assertFail(function(){ gl.shaderSource(0); });
+}
+Tests.test_stencilFunc = function(gl) {
+  assertFail(function(){ gl.stencilFunc(); });
+  assertFail(function(){ gl.stencilFunc(0); });
+  assertFail(function(){ gl.stencilFunc(0,0); });
+}
+Tests.test_stencilFuncSeparate = function(gl) {
+  assertFail(function(){ gl.stencilFuncSeparate(); });
+  assertFail(function(){ gl.stencilFuncSeparate(0); });
+  assertFail(function(){ gl.stencilFuncSeparate(0,0); });
+  assertFail(function(){ gl.stencilFuncSeparate(0,0,0); });
+}
+Tests.test_stencilMask = function(gl) {
+  assertFail(function(){ gl.stencilMask(); });
+}
+Tests.test_stencilMaskSeparate = function(gl) {
+  assertFail(function(){ gl.stencilMaskSeparate(); });
+  assertFail(function(){ gl.stencilMaskSeparate(0); });
+}
+Tests.test_stencilOp = function(gl) {
+  assertFail(function(){ gl.stencilOp(); });
+  assertFail(function(){ gl.stencilOp(0); });
+  assertFail(function(){ gl.stencilOp(0,0); });
+}
+Tests.test_stencilOpSeparate = function(gl) {
+  assertFail(function(){ gl.stencilOpSeparate(); });
+  assertFail(function(){ gl.stencilOpSeparate(0); });
+  assertFail(function(){ gl.stencilOpSeparate(0,0); });
+  assertFail(function(){ gl.stencilOpSeparate(0,0,0); });
+}
+Tests.test_texImage2D = function(gl) {
+  assertFail(function(){ gl.texImage2D(); });
+  assertFail(function(){ gl.texImage2D(0); });
+  assertFail(function(){ gl.texImage2D(0,0); });
+}
+Tests.test_texParameteri = function(gl) {
+  assertFail(function(){ gl.texParameteri(); });
+  assertFail(function(){ gl.texParameteri(0); });
+  assertFail(function(){ gl.texParameteri(0,0); });
+}
+Tests.test_texSubImage2D = function(gl) {
+  assertFail(function(){ gl.texSubImage2D(); });
+  assertFail(function(){ gl.texSubImage2D(0); });
+  assertFail(function(){ gl.texSubImage2D(0,0); });
+  assertFail(function(){ gl.texSubImage2D(0,0,0); });
+  assertFail(function(){ gl.texSubImage2D(0,0,0,0); });
+  assertFail(function(){ gl.texSubImage2D(0,0,0,0,0); });
+  assertFail(function(){ gl.texSubImage2D(0,0,0,0,0,0); });
+  assertFail(function(){ gl.texSubImage2D(0,0,0,0,0,0,0); });
+  assertFail(function(){ gl.texSubImage2D(0,0,0,0,0,0,0,0); });
+}
+Tests.test_uniform1f = function(gl) {
+  assertFail(function(){ gl.uniform1f(); });
+  assertFail(function(){ gl.uniform1f(0); });
+}
+Tests.test_uniform1fv = function(gl) {
+  assertFail(function(){ gl.uniform1fv(); });
+  assertFail(function(){ gl.uniform1fv(0); });
+}
+Tests.test_uniform1i = function(gl) {
+  assertFail(function(){ gl.uniform1i(); });
+  assertFail(function(){ gl.uniform1i(0); });
+}
+Tests.test_uniform1iv = function(gl) {
+  assertFail(function(){ gl.uniform1iv(); });
+  assertFail(function(){ gl.uniform1iv(0); });
+}
+Tests.test_uniform2f = function(gl) {
+  assertFail(function(){ gl.uniform2f(); });
+  assertFail(function(){ gl.uniform2f(0); });
+  assertFail(function(){ gl.uniform2f(0,0); });
+}
+Tests.test_uniform2fv = function(gl) {
+  assertFail(function(){ gl.uniform2fv(); });
+  assertFail(function(){ gl.uniform2fv(0); });
+}
+Tests.test_uniform2i = function(gl) {
+  assertFail(function(){ gl.uniform2i(); });
+  assertFail(function(){ gl.uniform2i(0); });
+  assertFail(function(){ gl.uniform2i(0,0); });
+}
+Tests.test_uniform2iv = function(gl) {
+  assertFail(function(){ gl.uniform2iv(); });
+  assertFail(function(){ gl.uniform2iv(0); });
+}
+Tests.test_uniform3f = function(gl) {
+  assertFail(function(){ gl.uniform3f(); });
+  assertFail(function(){ gl.uniform3f(0); });
+  assertFail(function(){ gl.uniform3f(0,0); });
+  assertFail(function(){ gl.uniform3f(0,0,0); });
+}
+Tests.test_uniform3fv = function(gl) {
+  assertFail(function(){ gl.uniform3fv(); });
+  assertFail(function(){ gl.uniform3fv(0); });
+}
+Tests.test_uniform3i = function(gl) {
+  assertFail(function(){ gl.uniform3i(); });
+  assertFail(function(){ gl.uniform3i(0); });
+  assertFail(function(){ gl.uniform3i(0,0); });
+  assertFail(function(){ gl.uniform3i(0,0,0); });
+}
+Tests.test_uniform3iv = function(gl) {
+  assertFail(function(){ gl.uniform3iv(); });
+  assertFail(function(){ gl.uniform3iv(0); });
+}
+Tests.test_uniform4f = function(gl) {
+  assertFail(function(){ gl.uniform4f(); });
+  assertFail(function(){ gl.uniform4f(0); });
+  assertFail(function(){ gl.uniform4f(0,0); });
+  assertFail(function(){ gl.uniform4f(0,0,0); });
+  assertFail(function(){ gl.uniform4f(0,0,0,0); });
+}
+Tests.test_uniform4fv = function(gl) {
+  assertFail(function(){ gl.uniform4fv(); });
+  assertFail(function(){ gl.uniform4fv(0); });
+}
+Tests.test_uniform4i = function(gl) {
+  assertFail(function(){ gl.uniform4i(); });
+  assertFail(function(){ gl.uniform4i(0); });
+  assertFail(function(){ gl.uniform4i(0,0); });
+  assertFail(function(){ gl.uniform4i(0,0,0); });
+  assertFail(function(){ gl.uniform4i(0,0,0,0); });
+}
+Tests.test_uniform4iv = function(gl) {
+  assertFail(function(){ gl.uniform4iv(); });
+  assertFail(function(){ gl.uniform4iv(0); });
+}
+Tests.test_uniformMatrix2fv = function(gl) {
+  assertFail(function(){ gl.uniformMatrix2fv(); });
+  assertFail(function(){ gl.uniformMatrix2fv(0); });
+  assertFail(function(){ gl.uniformMatrix2fv(0,0); });
+}
+Tests.test_uniformMatrix3fv = function(gl) {
+  assertFail(function(){ gl.uniformMatrix3fv(); });
+  assertFail(function(){ gl.uniformMatrix3fv(0); });
+  assertFail(function(){ gl.uniformMatrix3fv(0,0); });
+}
+Tests.test_uniformMatrix4fv = function(gl) {
+  assertFail(function(){ gl.uniformMatrix4fv(); });
+  assertFail(function(){ gl.uniformMatrix4fv(0); });
+  assertFail(function(){ gl.uniformMatrix4fv(0,0); });
+}
+Tests.test_useProgram = function(gl) {
+  assertFail(function(){ gl.useProgram(); });
+}
+Tests.test_validateProgram = function(gl) {
+  assertFail(function(){ gl.validateProgram(); });
+}
+Tests.test_vertexAttrib1f = function(gl) {
+  assertFail(function(){ gl.vertexAttrib1f(); });
+  assertFail(function(){ gl.vertexAttrib1f(0); });
+}
+Tests.test_vertexAttrib1fv = function(gl) {
+  assertFail(function(){ gl.vertexAttrib1fv(); });
+  assertFail(function(){ gl.vertexAttrib1fv(0); });
+}
+Tests.test_vertexAttrib2f = function(gl) {
+  assertFail(function(){ gl.vertexAttrib2f(); });
+  assertFail(function(){ gl.vertexAttrib2f(0); });
+  assertFail(function(){ gl.vertexAttrib2f(0,0); });
+}
+Tests.test_vertexAttrib2fv = function(gl) {
+  assertFail(function(){ gl.vertexAttrib2fv(); });
+  assertFail(function(){ gl.vertexAttrib2fv(0); });
+}
+Tests.test_vertexAttrib3f = function(gl) {
+  assertFail(function(){ gl.vertexAttrib3f(); });
+  assertFail(function(){ gl.vertexAttrib3f(0); });
+  assertFail(function(){ gl.vertexAttrib3f(0,0); });
+  assertFail(function(){ gl.vertexAttrib3f(0,0,0); });
+}
+Tests.test_vertexAttrib3fv = function(gl) {
+  assertFail(function(){ gl.vertexAttrib3fv(); });
+  assertFail(function(){ gl.vertexAttrib3fv(0); });
+}
+Tests.test_vertexAttrib4f = function(gl) {
+  assertFail(function(){ gl.vertexAttrib4f(); });
+  assertFail(function(){ gl.vertexAttrib4f(0); });
+  assertFail(function(){ gl.vertexAttrib4f(0,0); });
+  assertFail(function(){ gl.vertexAttrib4f(0,0,0); });
+  assertFail(function(){ gl.vertexAttrib4f(0,0,0,0); });
+}
+Tests.test_vertexAttrib4fv = function(gl) {
+  assertFail(function(){ gl.vertexAttrib4fv(); });
+  assertFail(function(){ gl.vertexAttrib4fv(0); });
+}
+Tests.test_vertexAttribPointer = function(gl) {
+  assertFail(function(){ gl.vertexAttribPointer(); });
+  assertFail(function(){ gl.vertexAttribPointer(0); });
+  assertFail(function(){ gl.vertexAttribPointer(0,0); });
+  assertFail(function(){ gl.vertexAttribPointer(0,0,0); });
+  assertFail(function(){ gl.vertexAttribPointer(0,0,0,0); });
+  assertFail(function(){ gl.vertexAttribPointer(0,0,0,0,0); });
+}
+Tests.test_viewport = function(gl) {
+  assertFail(function(){ gl.viewport(); });
+  assertFail(function(){ gl.viewport(0); });
+  assertFail(function(){ gl.viewport(0,0); });
+  assertFail(function(){ gl.viewport(0,0,0); });
+}
+Tests.test_currentArrayBufferBinding = function(gl) {
+}
+Tests.test_currentElementArrayBufferBinding = function(gl) {
+}
+Tests.test_currentFramebufferBinding = function(gl) {
+}
+Tests.test_currentRenderbufferBinding = function(gl) {
+}
+Tests.test_currentTextureBinding2D = function(gl) {
+}
+Tests.test_currentTextureBindingCubeMap = function(gl) {
+}
+Tests.test_currentProgram = function(gl) {
+}
+Tests.test_getParameter = function(gl) {
+  assertFail(function(){ gl.getParameter(); });
+}
+Tests.test_getProgramParameter = function(gl) {
+  assertFail(function(){ gl.getProgramParameter(); });
+  assertFail(function(){ gl.getProgramParameter(0); });
+}
+Tests.test_getShaderParameter = function(gl) {
+  assertFail(function(){ gl.getShaderParameter(); });
+  assertFail(function(){ gl.getShaderParameter(0); });
+}
+Tests.test_getTexParameteri = function(gl) {
+  assertFail(function(){ gl.getTexParameteri(); });
+  assertFail(function(){ gl.getTexParameteri(0); });
+}
+Tests.test_getUniformi = function(gl) {
+  assertFail(function(){ gl.getUniformi(); });
+  assertFail(function(){ gl.getUniformi(0); });
+}
+Tests.test_getVertexAttribi = function(gl) {
+  assertFail(function(){ gl.getVertexAttribi(); });
+  assertFail(function(){ gl.getVertexAttribi(0); });
+}
+Tests.test_present = function(gl) {
+}
+Tests.startUnit = function() {
+  var canvas = document.getElementById('gl');
+  var gl = wrapGLContext(canvas.getContext(GL_CONTEXT_ID));
+  return [gl];
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+  <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/constants.html
@@ -0,0 +1,374 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+<script type="application/x-javascript">
+
+/*
+  The following tests are generated from
+  http://www.khronos.org/registry/gles/api/2.0/gl2.h
+  and api_modifications.txt
+*/
+var constants = {
+DEPTH_BUFFER_BIT : 0x00000100,
+STENCIL_BUFFER_BIT : 0x00000400,
+COLOR_BUFFER_BIT : 0x00004000,
+POINTS : 0x0000,
+LINES : 0x0001,
+LINE_LOOP : 0x0002,
+LINE_STRIP : 0x0003,
+TRIANGLES : 0x0004,
+TRIANGLE_STRIP : 0x0005,
+TRIANGLE_FAN : 0x0006,
+ZERO : 0,
+ONE : 1,
+SRC_COLOR : 0x0300,
+ONE_MINUS_SRC_COLOR : 0x0301,
+SRC_ALPHA : 0x0302,
+ONE_MINUS_SRC_ALPHA : 0x0303,
+DST_ALPHA : 0x0304,
+ONE_MINUS_DST_ALPHA : 0x0305,
+DST_COLOR : 0x0306,
+ONE_MINUS_DST_COLOR : 0x0307,
+SRC_ALPHA_SATURATE : 0x0308,
+FUNC_ADD : 0x8006,
+BLEND_EQUATION : 0x8009,
+BLEND_EQUATION_RGB : 0x8009,
+BLEND_EQUATION_ALPHA : 0x883D,
+FUNC_SUBTRACT : 0x800A,
+FUNC_REVERSE_SUBTRACT : 0x800B,
+BLEND_DST_RGB : 0x80C8,
+BLEND_SRC_RGB : 0x80C9,
+BLEND_DST_ALPHA : 0x80CA,
+BLEND_SRC_ALPHA : 0x80CB,
+CONSTANT_COLOR : 0x8001,
+ONE_MINUS_CONSTANT_COLOR : 0x8002,
+CONSTANT_ALPHA : 0x8003,
+ONE_MINUS_CONSTANT_ALPHA : 0x8004,
+BLEND_COLOR : 0x8005,
+ARRAY_BUFFER : 0x8892,
+ELEMENT_ARRAY_BUFFER : 0x8893,
+ARRAY_BUFFER_BINDING : 0x8894,
+ELEMENT_ARRAY_BUFFER_BINDING : 0x8895,
+STREAM_DRAW : 0x88E0,
+STATIC_DRAW : 0x88E4,
+DYNAMIC_DRAW : 0x88E8,
+BUFFER_SIZE : 0x8764,
+BUFFER_USAGE : 0x8765,
+CURRENT_VERTEX_ATTRIB : 0x8626,
+FRONT : 0x0404,
+BACK : 0x0405,
+FRONT_AND_BACK : 0x0408,
+TEXTURE_2D : 0x0DE1,
+CULL_FACE : 0x0B44,
+BLEND : 0x0BE2,
+DITHER : 0x0BD0,
+STENCIL_TEST : 0x0B90,
+DEPTH_TEST : 0x0B71,
+SCISSOR_TEST : 0x0C11,
+POLYGON_OFFSET_FILL : 0x8037,
+SAMPLE_ALPHA_TO_COVERAGE : 0x809E,
+SAMPLE_COVERAGE : 0x80A0,
+NO_ERROR : 0,
+INVALID_ENUM : 0x0500,
+INVALID_VALUE : 0x0501,
+INVALID_OPERATION : 0x0502,
+OUT_OF_MEMORY : 0x0505,
+CW : 0x0900,
+CCW : 0x0901,
+LINE_WIDTH : 0x0B21,
+ALIASED_POINT_SIZE_RANGE : 0x846D,
+ALIASED_LINE_WIDTH_RANGE : 0x846E,
+CULL_FACE_MODE : 0x0B45,
+FRONT_FACE : 0x0B46,
+DEPTH_RANGE : 0x0B70,
+DEPTH_WRITEMASK : 0x0B72,
+DEPTH_CLEAR_VALUE : 0x0B73,
+DEPTH_FUNC : 0x0B74,
+STENCIL_CLEAR_VALUE : 0x0B91,
+STENCIL_FUNC : 0x0B92,
+STENCIL_FAIL : 0x0B94,
+STENCIL_PASS_DEPTH_FAIL : 0x0B95,
+STENCIL_PASS_DEPTH_PASS : 0x0B96,
+STENCIL_REF : 0x0B97,
+STENCIL_VALUE_MASK : 0x0B93,
+STENCIL_WRITEMASK : 0x0B98,
+STENCIL_BACK_FUNC : 0x8800,
+STENCIL_BACK_FAIL : 0x8801,
+STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802,
+STENCIL_BACK_PASS_DEPTH_PASS : 0x8803,
+STENCIL_BACK_REF : 0x8CA3,
+STENCIL_BACK_VALUE_MASK : 0x8CA4,
+STENCIL_BACK_WRITEMASK : 0x8CA5,
+VIEWPORT : 0x0BA2,
+SCISSOR_BOX : 0x0C10,
+COLOR_CLEAR_VALUE : 0x0C22,
+COLOR_WRITEMASK : 0x0C23,
+UNPACK_ALIGNMENT : 0x0CF5,
+PACK_ALIGNMENT : 0x0D05,
+MAX_TEXTURE_SIZE : 0x0D33,
+MAX_VIEWPORT_DIMS : 0x0D3A,
+SUBPIXEL_BITS : 0x0D50,
+RED_BITS : 0x0D52,
+GREEN_BITS : 0x0D53,
+BLUE_BITS : 0x0D54,
+ALPHA_BITS : 0x0D55,
+DEPTH_BITS : 0x0D56,
+STENCIL_BITS : 0x0D57,
+POLYGON_OFFSET_UNITS : 0x2A00,
+POLYGON_OFFSET_FACTOR : 0x8038,
+TEXTURE_BINDING_2D : 0x8069,
+SAMPLE_BUFFERS : 0x80A8,
+SAMPLES : 0x80A9,
+SAMPLE_COVERAGE_VALUE : 0x80AA,
+SAMPLE_COVERAGE_INVERT : 0x80AB,
+NUM_COMPRESSED_TEXTURE_FORMATS : 0x86A2,
+COMPRESSED_TEXTURE_FORMATS : 0x86A3,
+DONT_CARE : 0x1100,
+FASTEST : 0x1101,
+NICEST : 0x1102,
+GENERATE_MIPMAP_HINT : 0x8192,
+BYTE : 0x1400,
+UNSIGNED_BYTE : 0x1401,
+SHORT : 0x1402,
+UNSIGNED_SHORT : 0x1403,
+INT : 0x1404,
+UNSIGNED_INT : 0x1405,
+FLOAT : 0x1406,
+//FIXED : 0x140C,
+DEPTH_COMPONENT : 0x1902,
+ALPHA : 0x1906,
+RGB : 0x1907,
+RGBA : 0x1908,
+LUMINANCE : 0x1909,
+LUMINANCE_ALPHA : 0x190A,
+UNSIGNED_SHORT_4_4_4_4 : 0x8033,
+UNSIGNED_SHORT_5_5_5_1 : 0x8034,
+UNSIGNED_SHORT_5_6_5 : 0x8363,
+FRAGMENT_SHADER : 0x8B30,
+VERTEX_SHADER : 0x8B31,
+MAX_VERTEX_ATTRIBS : 0x8869,
+MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB,
+MAX_VARYING_VECTORS : 0x8DFC,
+MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D,
+MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C,
+MAX_TEXTURE_IMAGE_UNITS : 0x8872,
+MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD,
+SHADER_TYPE : 0x8B4F,
+DELETE_STATUS : 0x8B80,
+LINK_STATUS : 0x8B82,
+VALIDATE_STATUS : 0x8B83,
+ATTACHED_SHADERS : 0x8B85,
+ACTIVE_UNIFORMS : 0x8B86,
+ACTIVE_ATTRIBUTES : 0x8B89,
+SHADING_LANGUAGE_VERSION : 0x8B8C,
+CURRENT_PROGRAM : 0x8B8D,
+NEVER : 0x0200,
+LESS : 0x0201,
+EQUAL : 0x0202,
+LEQUAL : 0x0203,
+GREATER : 0x0204,
+NOTEQUAL : 0x0205,
+GEQUAL : 0x0206,
+ALWAYS : 0x0207,
+KEEP : 0x1E00,
+REPLACE : 0x1E01,
+INCR : 0x1E02,
+DECR : 0x1E03,
+INVERT : 0x150A,
+INCR_WRAP : 0x8507,
+DECR_WRAP : 0x8508,
+VENDOR : 0x1F00,
+RENDERER : 0x1F01,
+VERSION : 0x1F02,
+//EXTENSIONS : 0x1F03,
+NEAREST : 0x2600,
+LINEAR : 0x2601,
+NEAREST_MIPMAP_NEAREST : 0x2700,
+LINEAR_MIPMAP_NEAREST : 0x2701,
+NEAREST_MIPMAP_LINEAR : 0x2702,
+LINEAR_MIPMAP_LINEAR : 0x2703,
+TEXTURE_MAG_FILTER : 0x2800,
+TEXTURE_MIN_FILTER : 0x2801,
+TEXTURE_WRAP_S : 0x2802,
+TEXTURE_WRAP_T : 0x2803,
+TEXTURE : 0x1702,
+TEXTURE_CUBE_MAP : 0x8513,
+TEXTURE_BINDING_CUBE_MAP : 0x8514,
+TEXTURE_CUBE_MAP_POSITIVE_X : 0x8515,
+TEXTURE_CUBE_MAP_NEGATIVE_X : 0x8516,
+TEXTURE_CUBE_MAP_POSITIVE_Y : 0x8517,
+TEXTURE_CUBE_MAP_NEGATIVE_Y : 0x8518,
+TEXTURE_CUBE_MAP_POSITIVE_Z : 0x8519,
+TEXTURE_CUBE_MAP_NEGATIVE_Z : 0x851A,
+MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C,
+TEXTURE0 : 0x84C0,
+TEXTURE1 : 0x84C1,
+TEXTURE2 : 0x84C2,
+TEXTURE3 : 0x84C3,
+TEXTURE4 : 0x84C4,
+TEXTURE5 : 0x84C5,
+TEXTURE6 : 0x84C6,
+TEXTURE7 : 0x84C7,
+TEXTURE8 : 0x84C8,
+TEXTURE9 : 0x84C9,
+TEXTURE10 : 0x84CA,
+TEXTURE11 : 0x84CB,
+TEXTURE12 : 0x84CC,
+TEXTURE13 : 0x84CD,
+TEXTURE14 : 0x84CE,
+TEXTURE15 : 0x84CF,
+TEXTURE16 : 0x84D0,
+TEXTURE17 : 0x84D1,
+TEXTURE18 : 0x84D2,
+TEXTURE19 : 0x84D3,
+TEXTURE20 : 0x84D4,
+TEXTURE21 : 0x84D5,
+TEXTURE22 : 0x84D6,
+TEXTURE23 : 0x84D7,
+TEXTURE24 : 0x84D8,
+TEXTURE25 : 0x84D9,
+TEXTURE26 : 0x84DA,
+TEXTURE27 : 0x84DB,
+TEXTURE28 : 0x84DC,
+TEXTURE29 : 0x84DD,
+TEXTURE30 : 0x84DE,
+TEXTURE31 : 0x84DF,
+ACTIVE_TEXTURE : 0x84E0,
+REPEAT : 0x2901,
+CLAMP_TO_EDGE : 0x812F,
+MIRRORED_REPEAT : 0x8370,
+FLOAT_VEC2 : 0x8B50,
+FLOAT_VEC3 : 0x8B51,
+FLOAT_VEC4 : 0x8B52,
+INT_VEC2 : 0x8B53,
+INT_VEC3 : 0x8B54,
+INT_VEC4 : 0x8B55,
+BOOL : 0x8B56,
+BOOL_VEC2 : 0x8B57,
+BOOL_VEC3 : 0x8B58,
+BOOL_VEC4 : 0x8B59,
+FLOAT_MAT2 : 0x8B5A,
+FLOAT_MAT3 : 0x8B5B,
+FLOAT_MAT4 : 0x8B5C,
+SAMPLER_2D : 0x8B5E,
+SAMPLER_CUBE : 0x8B60,
+VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622,
+VERTEX_ATTRIB_ARRAY_SIZE : 0x8623,
+VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624,
+VERTEX_ATTRIB_ARRAY_TYPE : 0x8625,
+VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A,
+VERTEX_ATTRIB_ARRAY_POINTER : 0x8645,
+VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
+//IMPLEMENTATION_COLOR_READ_TYPE : 0x8B9A,
+//IMPLEMENTATION_COLOR_READ_FORMAT : 0x8B9B,
+COMPILE_STATUS : 0x8B81,
+SHADER_COMPILER : 0x8DFA,
+LOW_FLOAT : 0x8DF0,
+MEDIUM_FLOAT : 0x8DF1,
+HIGH_FLOAT : 0x8DF2,
+LOW_INT : 0x8DF3,
+MEDIUM_INT : 0x8DF4,
+HIGH_INT : 0x8DF5,
+FRAMEBUFFER : 0x8D40,
+RENDERBUFFER : 0x8D41,
+RGBA4 : 0x8056,
+RGB5_A1 : 0x8057,
+RGB565 : 0x8D62,
+DEPTH_COMPONENT16 : 0x81A5,
+STENCIL_INDEX : 0x1901,
+STENCIL_INDEX8 : 0x8D48,
+DEPTH_STENCIL : 0x84F9,
+RENDERBUFFER_WIDTH : 0x8D42,
+RENDERBUFFER_HEIGHT : 0x8D43,
+RENDERBUFFER_INTERNAL_FORMAT : 0x8D44,
+RENDERBUFFER_RED_SIZE : 0x8D50,
+RENDERBUFFER_GREEN_SIZE : 0x8D51,
+RENDERBUFFER_BLUE_SIZE : 0x8D52,
+RENDERBUFFER_ALPHA_SIZE : 0x8D53,
+RENDERBUFFER_DEPTH_SIZE : 0x8D54,
+RENDERBUFFER_STENCIL_SIZE : 0x8D55,
+FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE : 0x8CD0,
+FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2,
+FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3,
+COLOR_ATTACHMENT0 : 0x8CE0,
+DEPTH_ATTACHMENT : 0x8D00,
+STENCIL_ATTACHMENT : 0x8D20,
+DEPTH_STENCIL_ATTACHMENT : 0x821A,
+NONE : 0,
+FRAMEBUFFER_COMPLETE : 0x8CD5,
+FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6,
+FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7,
+FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9,
+FRAMEBUFFER_UNSUPPORTED : 0x8CDD,
+FRAMEBUFFER_BINDING : 0x8CA6,
+RENDERBUFFER_BINDING : 0x8CA7,
+MAX_RENDERBUFFER_SIZE : 0x84E8,
+INVALID_FRAMEBUFFER_OPERATION : 0x0506,
+//FALSE : 0,
+//TRUE : 1,
+UNPACK_FLIP_Y_WEBGL : 0x9240,
+UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241
+}
+
+Tests.testOES20Constants = function(gl) {
+  for (var i in constants) {
+    assertProperty(gl, i) &&
+    assertEquals(i, gl[i], constants[i]);
+  }
+  var extended = false;
+  for (var i in gl) {
+    if (i.match(/^[A-Z_]+$/) && constants[i] == null) {
+      if (!extended) {
+        extended = true;
+        var h = document.createElement('h3');
+        h.textContent = "Also found the following extra constants";
+        __testLog__.appendChild(h);
+      }
+      log(i);
+    }
+  }
+}
+
+Tests.startUnit = function() {
+  var canvas = document.getElementById('gl');
+  var gl = wrapGLContext(canvas.getContext(GL_CONTEXT_ID));
+  return [gl];
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+  <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/fuzzTheAPI.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+
+<script type="application/x-javascript">
+
+Tests.autorun = false;
+Tests.message = "This will fuzz the API with random inputs for a [long] while."
+
+
+function randomCall(testProgress, gl, m, arities) {
+    doTestNotify(m);
+    var argcs = {};
+    var foundArity = false;
+    if (arities == null) {
+        testProgress.textContent += "            500 random arity calls on " + m + "\n";
+        for (var i=0; i<50; i++) {
+            for (var j=0; j<10; j++) {
+                var args = generateRandomArgs(j);
+//                 doTestNotify(m + ": " + args.toSource());
+                try {
+                    gl[m].apply(gl, args);
+                    argcs[j] = true;
+                    foundArity = true;
+                } catch (e) {
+                }
+            }
+        }
+        for (var j in argcs) {
+            testProgress.textContent += "200 arity " + j + " calls on " + m + "\n";
+            for (var i=0; i<200; i++) {
+                var args = generateRandomArgs(j);
+//                 doTestNotify(m + ": " + args.toSource());
+                try {
+                    gl[m].apply(gl, args);
+                    argcs[j] = true;
+                } catch (e) {
+                }
+            }
+        }
+    } else {
+        for (var k=0; k<arities.length; k++) {
+            var j = arities[k];
+            testProgress.textContent += "500 arity " + j + " calls on " + m + "\n";
+            for (var i=0; i<500; i++) {
+                var args = generateRandomArgs(j);
+//                 doTestNotify(m + ": " + args.toSource());
+                try {
+                    gl[m].apply(gl, args);
+                } catch (e) {
+                }
+            }
+        }
+    }
+//     doTestNotify(m+"--OK");
+}
+
+Tests.testGetGLWeb20 = function() {
+    var testProgress = document.getElementById('testProgress');
+    var funcnames = document.getElementById('funcnames').value.split(",");
+    var canvas = document.getElementById('glweb20');
+    var gl;
+    assertOk(function(){gl = canvas.getContext(GL_CONTEXT_ID);});
+    var funcs = [];
+    for (var i=0; i<funcnames.length; i++) {
+        var fn = funcnames[i];
+        fn = fn.replace(/^\s+|\s+$/g, '');
+        if (fn.length > 0)
+            funcs.push(fn);
+    }
+    if (funcs.length == 0) {
+        for (var m in gl)
+            try{if (typeof gl[m] == 'function')
+                funcs.push(m);}catch(e){}
+    }
+    var idx = 0;
+    var count = 0;
+    var limit = 1000;
+    var iv1;
+    var iv2;
+    iv1 = setInterval(function(){
+        if (idx >= funcs.length) {
+            iv2 = setInterval(function(){
+                if (count >= limit) {
+                    clearInterval(iv2);
+                    return false;
+                }
+                count++;
+                var f = Math.floor(Math.random() * funcs.length);
+                randomCall(testProgress, gl, funcs[f]);
+            }, 50);
+            clearInterval(iv1);
+            return false;
+        }
+        randomCall(testProgress, gl, funcs[idx]);
+        idx++;
+    }, 50);
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+  <canvas id="glweb20" width="16" height="16"></canvas>
+  <p>Optional: Enter a comma-separated list of functions to fuzz (leave blank for full API)</p>
+  <input type="text" size="40" id="funcnames" value="">
+  <pre id="testProgress"></pre>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/getContext.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+
+<script type="application/x-javascript">
+
+Tests.testGetWebGL = function() {
+  var canvas = document.getElementById('webgl');
+  var gl;
+  assertOk(function(){gl = canvas.getContext(GL_CONTEXT_ID)});
+  assertEquals("ctx.canvas === canvas", gl.canvas, canvas);
+  assertOk(function(){g2d = canvas.getContext('2d')});
+  assert("Should get a null 2d context after getting webgl context", g2d === null);
+}
+
+Tests.testGet2D = function() {
+  var canvas = document.getElementById('2d');
+  var g2d;
+  var gl;
+  assertOk(function(){g2d = canvas.getContext('2d')});
+  assertOk(function(){gl = canvas.getContext(GL_CONTEXT_ID)});
+  assert("Should get a null WebGL context after getting 2D context", gl === null);
+}
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+  <canvas id="2d" width="1" height="1"></canvas>
+  <canvas id="webgl" width="1" height="1"></canvas>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/methods.html
@@ -0,0 +1,202 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+<script type="application/x-javascript">
+
+/*
+  The following tests are generated from
+  http://www.khronos.org/registry/gles/api/2.0/gl2.h
+  and api_modifications.txt
+*/
+var methods = ['canvas',
+"activeTexture",
+"attachShader",
+"bindAttribLocation",
+"bindBuffer",
+"bindFramebuffer",
+"bindRenderbuffer",
+"bindTexture",
+"blendColor",
+"blendEquation",
+"blendEquationSeparate",
+"blendFunc",
+"blendFuncSeparate",
+"bufferData",
+"bufferSubData",
+"checkFramebufferStatus",
+"clear",
+"clearColor",
+"clearDepth",
+"clearStencil",
+"colorMask",
+"compileShader",
+"copyTexImage2D",
+"copyTexSubImage2D",
+"createProgram",
+"createShader",
+"cullFace",
+"deleteBuffer",
+"deleteFramebuffer",
+"deleteProgram",
+"deleteRenderbuffer",
+"deleteShader",
+"deleteTexture",
+"depthFunc",
+"depthMask",
+"depthRange",
+"detachShader",
+"disable",
+"disableVertexAttribArray",
+"drawArrays",
+"drawElements",
+"enable",
+"enableVertexAttribArray",
+"finish",
+"flush",
+"framebufferRenderbuffer",
+"framebufferTexture2D",
+"frontFace",
+"createBuffer",
+"generateMipmap",
+"createFramebuffer",
+"createRenderbuffer",
+"createTexture",
+"getActiveAttrib",
+"getActiveUniform",
+"getAttachedShaders",
+"getAttribLocation",
+"getBufferParameter",
+"getError",
+"getExtension",
+"getSupportedExtensions",
+"getFramebufferAttachmentParameter",
+"getProgramInfoLog",
+"getRenderbufferParameter",
+"getShaderInfoLog",
+"getShaderSource",
+"getUniformLocation",
+"hint",
+"isBuffer",
+"isContextLost",
+"isEnabled",
+"isFramebuffer",
+"isProgram",
+"isRenderbuffer",
+"isShader",
+"isTexture",
+"lineWidth",
+"linkProgram",
+"polygonOffset",
+"readPixels",
+"renderbufferStorage",
+"sampleCoverage",
+"scissor",
+"shaderSource",
+"stencilFunc",
+"stencilFuncSeparate",
+"stencilMask",
+"stencilMaskSeparate",
+"stencilOp",
+"stencilOpSeparate",
+"texImage2D",
+"texParameteri",
+"texSubImage2D",
+"uniform1f",
+"uniform1fv",
+"uniform1i",
+"uniform1iv",
+"uniform2f",
+"uniform2fv",
+"uniform2i",
+"uniform2iv",
+"uniform3f",
+"uniform3fv",
+"uniform3i",
+"uniform3iv",
+"uniform4f",
+"uniform4fv",
+"uniform4i",
+"uniform4iv",
+"uniformMatrix2fv",
+"uniformMatrix3fv",
+"uniformMatrix4fv",
+"useProgram",
+"validateProgram",
+"vertexAttrib1f",
+"vertexAttrib1fv",
+"vertexAttrib2f",
+"vertexAttrib2fv",
+"vertexAttrib3f",
+"vertexAttrib3fv",
+"vertexAttrib4f",
+"vertexAttrib4fv",
+"vertexAttribPointer",
+"viewport",
+"getParameter",
+"getProgramParameter",
+"getShaderParameter",
+"getTexParameter",
+"getUniform",
+"getVertexAttrib"
+]
+
+Tests.testOES20Methods = function(gl) {
+  for (var i=0; i<methods.length; i++) {
+    assertProperty(gl, methods[i]);
+  }
+  var extended = false;
+  for (var i in gl) {
+    if (i.match(/^[a-z_]+$/) && methods.indexOf(i) == -1) {
+      if (!extended) {
+        extended = true;
+        var h = document.createElement('h3');
+        h.textContent = "Also found the following extra properties";
+        __testLog__.appendChild(h);
+      }
+      log(i);
+    }
+  }
+}
+
+Tests.startUnit = function() {
+  var canvas = document.getElementById('gl');
+  var gl = wrapGLContext(canvas.getContext(GL_CONTEXT_ID));
+  return [gl];
+}
+
+</script>
+<style>canvas{ position:absolute; }</style>
+</head><body>
+  <canvas id="gl" width="1" height="1"></canvas>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/quickCheckAPI.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+<script type="application/x-javascript" src="quickCheckAPI.js"></script>
+
+<script type="application/x-javascript">
+
+// Test that all GL functions specified in ArgGenerators work
+// when called with randomly generated valid arguments
+Tests.testValidArgs = function() {
+  var randomTestCount = 100;
+  for (var name in ArgGenerators) {
+    try {
+      if (!GL[name])
+        throw (new Error(name + " is missing from the WebGL context"));
+      var argGen = ArgGenerators[name];
+      var alreadyTriedArgs = {};
+      if (!argGen.generate) continue;
+      // test each GL function with randomTestCount randomly generated valid args
+      argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+        if (!gen.noAlreadyTriedCheck) {
+          var src = Object.toSource(args);
+          if (alreadyTriedArgs[src])
+            return true;
+
+          alreadyTriedArgs[src] = true;
+        }
+        var ok = false;
+        // if we have an validity checker, assert that the generated args are valid
+        if (gen.checkArgValidity)
+          assert("Valid args: "+name+"("+args.map(function(a){return Object.toSource(a)}).join(",")+")",
+                gen.checkArgValidity.apply(gen, args));
+        var rv;
+        // assert that GL function works when called with valid args
+        assertOk("This should work: "+name+"("+args.map(function(a){return Object.toSource(a)}).join(",")+")",
+                function(){rv = GL[name].apply(GL, args); ok = true;});
+        // if we need to cleanup the return value, do it here
+        // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+        if (gen.returnValueCleanup)
+          assertOk("Cleaning up return value after "+name+"("+args.map(function(a){return Object.toSource(a)}).join(",")+")",
+                   function() { gen.returnValueCleanup(rv); });
+        return ok;
+      }, argGen.testCount || randomTestCount);
+    } catch(e) {
+      testFailed(name, e.name, formatError(e));
+    }
+  }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/quickCheckAPI.js
@@ -0,0 +1,1191 @@
+/*
+  QuickCheck tests for WebGL:
+
+    1. Write a valid arg generator for each function
+      1.1. Write valid arg predicates to use with random generator:
+            if value passes generator, accept it as valid.
+      1.2. Often needs initializing and cleanup:
+            setup - generate - cleanup
+            gl.createBuffer - test(bindBufferGenerator) - gl.deleteBuffer
+
+    2. Write an invalid arg generator
+      2.1. Take valid args, modify an arg until the args no longer pass
+            checkArgValidity.
+      2.2. Repeat for all args.
+
+    3. Test functions using the generators
+      3.1. Args generated with the valid arg generator should pass
+            assertOk(f(args))
+      3.2. Args generated with the invalid arg generator should pass
+            assertFail(f(args))
+*/
+var GLcanvas = document.createElement('canvas');
+var canvas2D = document.createElement('canvas');
+GLcanvas.width = GLcanvas.height = 256;
+GL = GLcanvas.getContext(GL_CONTEXT_ID);
+Array.from = function(o) {
+  var a = [];
+  for (var i=0; i<o.length; i++)
+    a.push(o[i]);
+  return a;
+}
+Array.prototype.has = function(v) { return this.indexOf(v) != -1; }
+Array.prototype.random = function() { return this[randomInt(this.length)]; }
+
+castToInt = function(o) {
+  if (typeof o == 'number')
+    return isNaN(o) ? 0 : Math.floor(o);
+  if (o == true) return 1;
+  return 0;
+};
+
+// Creates a constant checker / generator from its arguments.
+//
+// E.g. if you want a constant checker for the constants 1, 2, and 3, you
+// would do the following:
+//
+//   var cc = constCheck(1,2,3);
+//   var randomConst = cc.random();
+//   if (cc.has(randomConst))
+//     console.log("randomConst is included in cc's constants");
+//
+constCheck = function() {
+  var a = Array.from(arguments);
+  a.has = function(v) { return this.indexOf(castToInt(v)) != -1; };
+  return a;
+}
+
+bindTextureTarget = constCheck(GL.TEXTURE_2D, GL.TEXTURE_CUBE_MAP);
+blendEquationMode = constCheck(GL.FUNC_ADD, GL.FUNC_SUBTRACT, GL.FUNC_REVERSE_SUBTRACT);
+blendFuncSfactor = constCheck(
+  GL.ZERO, GL.ONE, GL.SRC_COLOR, GL.ONE_MINUS_SRC_COLOR, GL.DST_COLOR,
+  GL.ONE_MINUS_DST_COLOR, GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.DST_ALPHA,
+  GL.ONE_MINUS_DST_ALPHA, GL.CONSTANT_COLOR, GL.ONE_MINUS_CONSTANT_COLOR,
+  GL.CONSTANT_ALPHA, GL.ONE_MINUS_CONSTANT_ALPHA, GL.SRC_ALPHA_SATURATE
+);
+blendFuncDfactor = constCheck(
+  GL.ZERO, GL.ONE, GL.SRC_COLOR, GL.ONE_MINUS_SRC_COLOR, GL.DST_COLOR,
+  GL.ONE_MINUS_DST_COLOR, GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.DST_ALPHA,
+  GL.ONE_MINUS_DST_ALPHA, GL.CONSTANT_COLOR, GL.ONE_MINUS_CONSTANT_COLOR,
+  GL.CONSTANT_ALPHA, GL.ONE_MINUS_CONSTANT_ALPHA
+);
+bufferTarget = constCheck(GL.ARRAY_BUFFER, GL.ELEMENT_ARRAY_BUFFER);
+bufferMode = constCheck(GL.STREAM_DRAW, GL.STATIC_DRAW, GL.DYNAMIC_DRAW);
+clearMask = constCheck(
+  GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT | GL.STENCIL_BUFFER_BIT,
+  GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT,
+  GL.COLOR_BUFFER_BIT | GL.STENCIL_BUFFER_BIT,
+  GL.DEPTH_BUFFER_BIT | GL.STENCIL_BUFFER_BIT,
+  GL.COLOR_BUFFER_BIT, GL.DEPTH_BUFFER_BIT, GL.STENCIL_BUFFER_BIT, 0
+);
+cullFace = constCheck(GL.FRONT, GL.BACK, GL.FRONT_AND_BACK);
+depthFuncFunc = constCheck(
+  GL.NEVER, GL.LESS, GL.EQUAL, GL.LEQUAL, GL.GREATER, GL.NOTEQUAL,
+  GL.GEQUAL, GL.ALWAYS
+);
+stencilFuncFunc = depthFuncFunc;
+enableCap = constCheck(
+  GL.BLEND, GL.CULL_FACE, GL.DEPTH_TEST, GL.DITHER, GL.POLYGON_OFFSET_FILL,
+  GL.SAMPLE_ALPHA_TO_COVERAGE, GL.SAMPLE_COVERAGE, GL.SCISSOR_TEST,
+  GL.STENCIL_TEST
+);
+frontFaceMode = constCheck(GL.CCW, GL.CW);
+getParameterPname = constCheck(
+  GL.ACTIVE_TEXTURE || "GL.ACTIVE_TEXTURE",
+  GL.ALIASED_LINE_WIDTH_RANGE || "GL.ALIASED_LINE_WIDTH_RANGE",
+  GL.ALIASED_POINT_SIZE_RANGE || "GL.ALIASED_POINT_SIZE_RANGE",
+  GL.ALPHA_BITS || "GL.ALPHA_BITS",
+  GL.ARRAY_BUFFER_BINDING || "GL.ARRAY_BUFFER_BINDING",
+  GL.BLEND || "GL.BLEND",
+  GL.BLEND_COLOR || "GL.BLEND_COLOR",
+  GL.BLEND_DST_ALPHA || "GL.BLEND_DST_ALPHA",
+  GL.BLEND_DST_RGB || "GL.BLEND_DST_RGB",
+  GL.BLEND_EQUATION_ALPHA || "GL.BLEND_EQUATION_ALPHA",
+  GL.BLEND_EQUATION_RGB || "GL.BLEND_EQUATION_RGB",
+  GL.BLEND_SRC_ALPHA || "GL.BLEND_SRC_ALPHA",
+  GL.BLEND_SRC_RGB || "GL.BLEND_SRC_RGB",
+  GL.BLUE_BITS || "GL.BLUE_BITS",
+  GL.COLOR_CLEAR_VALUE || "GL.COLOR_CLEAR_VALUE",
+  GL.COLOR_WRITEMASK || "GL.COLOR_WRITEMASK",
+  GL.COMPRESSED_TEXTURE_FORMATS || "GL.COMPRESSED_TEXTURE_FORMATS",
+  GL.CULL_FACE || "GL.CULL_FACE",
+  GL.CULL_FACE_MODE || "GL.CULL_FACE_MODE",
+  GL.CURRENT_PROGRAM || "GL.CURRENT_PROGRAM",
+  GL.DEPTH_BITS || "GL.DEPTH_BITS",
+  GL.DEPTH_CLEAR_VALUE || "GL.DEPTH_CLEAR_VALUE",
+  GL.DEPTH_FUNC || "GL.DEPTH_FUNC",
+  GL.DEPTH_RANGE || "GL.DEPTH_RANGE",
+  GL.DEPTH_TEST || "GL.DEPTH_TEST",
+  GL.DEPTH_WRITEMASK || "GL.DEPTH_WRITEMASK",
+  GL.DITHER || "GL.DITHER",
+  GL.ELEMENT_ARRAY_BUFFER_BINDING || "GL.ELEMENT_ARRAY_BUFFER_BINDING",
+  GL.FRAMEBUFFER_BINDING || "GL.FRAMEBUFFER_BINDING",
+  GL.FRONT_FACE || "GL.FRONT_FACE",
+  GL.GENERATE_MIPMAP_HINT || "GL.GENERATE_MIPMAP_HINT",
+  GL.GREEN_BITS || "GL.GREEN_BITS",
+  GL.LINE_WIDTH || "GL.LINE_WIDTH",
+  GL.MAX_COMBINED_TEXTURE_IMAGE_UNITS || "GL.MAX_COMBINED_TEXTURE_IMAGE_UNITS",
+  GL.MAX_CUBE_MAP_TEXTURE_SIZE || "GL.MAX_CUBE_MAP_TEXTURE_SIZE",
+  GL.MAX_FRAGMENT_UNIFORM_VECTORS || "GL.MAX_FRAGMENT_UNIFORM_VECTORS",
+  GL.MAX_RENDERBUFFER_SIZE || "GL.MAX_RENDERBUFFER_SIZE",
+  GL.MAX_TEXTURE_IMAGE_UNITS || "GL.MAX_TEXTURE_IMAGE_UNITS",
+  GL.MAX_TEXTURE_SIZE || "GL.MAX_TEXTURE_SIZE",
+  GL.MAX_VARYING_VECTORS || "GL.MAX_VARYING_VECTORS",
+  GL.MAX_VERTEX_ATTRIBS || "GL.MAX_VERTEX_ATTRIBS",
+  GL.MAX_VERTEX_TEXTURE_IMAGE_UNITS || "GL.MAX_VERTEX_TEXTURE_IMAGE_UNITS",
+  GL.MAX_VERTEX_UNIFORM_VECTORS || "GL.MAX_VERTEX_UNIFORM_VECTORS",
+  GL.MAX_VIEWPORT_DIMS || "GL.MAX_VIEWPORT_DIMS",
+  GL.NUM_COMPRESSED_TEXTURE_FORMATS || "GL.NUM_COMPRESSED_TEXTURE_FORMATS",
+  GL.PACK_ALIGNMENT || "GL.PACK_ALIGNMENT",
+  GL.POLYGON_OFFSET_FACTOR || "GL.POLYGON_OFFSET_FACTOR",
+  GL.POLYGON_OFFSET_FILL || "GL.POLYGON_OFFSET_FILL",
+  GL.POLYGON_OFFSET_UNITS || "GL.POLYGON_OFFSET_UNITS",
+  GL.RED_BITS || "GL.RED_BITS",
+  GL.RENDERBUFFER_BINDING || "GL.RENDERBUFFER_BINDING",
+  GL.SAMPLE_BUFFERS || "GL.SAMPLE_BUFFERS",
+  GL.SAMPLE_COVERAGE_INVERT || "GL.SAMPLE_COVERAGE_INVERT",
+  GL.SAMPLE_COVERAGE_VALUE || "GL.SAMPLE_COVERAGE_VALUE",
+  GL.SAMPLES || "GL.SAMPLES",
+  GL.SCISSOR_BOX || "GL.SCISSOR_BOX",
+  GL.SCISSOR_TEST || "GL.SCISSOR_TEST",
+  GL.STENCIL_BACK_FAIL || "GL.STENCIL_BACK_FAIL",
+  GL.STENCIL_BACK_FUNC || "GL.STENCIL_BACK_FUNC",
+  GL.STENCIL_BACK_PASS_DEPTH_FAIL || "GL.STENCIL_BACK_PASS_DEPTH_FAIL",
+  GL.STENCIL_BACK_PASS_DEPTH_PASS || "GL.STENCIL_BACK_PASS_DEPTH_PASS",
+  GL.STENCIL_BACK_REF || "GL.STENCIL_BACK_REF",
+  GL.STENCIL_BACK_VALUE_MASK || "GL.STENCIL_BACK_VALUE_MASK",
+  GL.STENCIL_BACK_WRITEMASK || "GL.STENCIL_BACK_WRITEMASK",
+  GL.STENCIL_BITS || "GL.STENCIL_BITS",
+  GL.STENCIL_CLEAR_VALUE || "GL.STENCIL_CLEAR_VALUE",
+  GL.STENCIL_FAIL || "GL.STENCIL_FAIL",
+  GL.STENCIL_FUNC || "GL.STENCIL_FUNC",
+  GL.STENCIL_PASS_DEPTH_FAIL || "GL.STENCIL_PASS_DEPTH_FAIL",
+  GL.STENCIL_PASS_DEPTH_PASS || "GL.STENCIL_PASS_DEPTH_PASS",
+  GL.STENCIL_REF || "GL.STENCIL_REF",
+  GL.STENCIL_TEST || "GL.STENCIL_TEST",
+  GL.STENCIL_VALUE_MASK || "GL.STENCIL_VALUE_MASK",
+  GL.STENCIL_WRITEMASK || "GL.STENCIL_WRITEMASK",
+  GL.SUBPIXEL_BITS || "GL.SUBPIXEL_BITS",
+  GL.TEXTURE_BINDING_2D || "GL.TEXTURE_BINDING_2D",
+  GL.TEXTURE_BINDING_CUBE_MAP || "GL.TEXTURE_BINDING_CUBE_MAP",
+  GL.UNPACK_ALIGNMENT || "GL.UNPACK_ALIGNMENT",
+  GL.VIEWPORT || "GL.VIEWPORT"
+);
+mipmapHint = constCheck(GL.FASTEST, GL.NICEST, GL.DONT_CARE);
+pixelStoreiPname = constCheck(GL.PACK_ALIGNMENT, GL.UNPACK_ALIGNMENT);
+pixelStoreiParam = constCheck(1,2,4,8);
+shaderType = constCheck(GL.VERTEX_SHADER, GL.FRAGMENT_SHADER);
+stencilOp = constCheck(GL.KEEP, GL.ZERO, GL.REPLACE, GL.INCR, GL.INCR_WRAP,
+                        GL.DECR, GL.DECR_WRAP, GL.INVERT);
+texImageTarget = constCheck(
+  GL.TEXTURE_2D,
+  GL.TEXTURE_CUBE_MAP_POSITIVE_X,
+  GL.TEXTURE_CUBE_MAP_NEGATIVE_X,
+  GL.TEXTURE_CUBE_MAP_POSITIVE_Y,
+  GL.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+  GL.TEXTURE_CUBE_MAP_POSITIVE_Z,
+  GL.TEXTURE_CUBE_MAP_NEGATIVE_Z
+);
+texImageInternalFormat = constCheck(
+  GL.ALPHA,
+  GL.LUMINANCE,
+  GL.LUMINANCE_ALPHA,
+  GL.RGB,
+  GL.RGBA
+);
+texImageFormat = constCheck(
+  GL.ALPHA,
+  GL.LUMINANCE,
+  GL.LUMINANCE_ALPHA,
+  GL.RGB,
+  GL.RGBA
+);
+texImageType = constCheck(GL.UNSIGNED_BYTE);
+texParameterPname = constCheck(
+  GL.TEXTURE_MIN_FILTER, GL.TEXTURE_MAG_FILTER,
+  GL.TEXTURE_WRAP_S, GL.TEXTURE_WRAP_T);
+texParameterParam = {};
+texParameterParam[GL.TEXTURE_MIN_FILTER] = constCheck(
+  GL.NEAREST, GL.LINEAR, GL.NEAREST_MIPMAP_NEAREST, GL.LINEAR_MIPMAP_NEAREST,
+  GL.NEAREST_MIPMAP_LINEAR, GL.LINEAR_MIPMAP_LINEAR);
+texParameterParam[GL.TEXTURE_MAG_FILTER] = constCheck(GL.NEAREST, GL.LINEAR);
+texParameterParam[GL.TEXTURE_WRAP_S] = constCheck(
+  GL.CLAMP_TO_EDGE, GL.MIRRORED_REPEAT, GL.REPEAT);
+texParameterParam[GL.TEXTURE_WRAP_T] = texParameterParam[GL.TEXTURE_WRAP_S];
+textureUnit = constCheck.apply(this, (function(){
+  var textureUnits = [];
+  var texUnits = GL.getParameter(GL.MAX_TEXTURE_IMAGE_UNITS);
+  for (var i=0; i<texUnits; i++) textureUnits.push(GL['TEXTURE'+i]);
+  return textureUnits;
+})());
+
+var StencilBits = GL.getParameter(GL.STENCIL_BITS);
+var MaxStencilValue = 1 << StencilBits;
+
+var MaxVertexAttribs = GL.getParameter(GL.MAX_VERTEX_ATTRIBS);
+var LineWidthRange = GL.getParameter(GL.ALIASED_LINE_WIDTH_RANGE);
+
+// Returns true if bufData can be passed to GL.bufferData
+isBufferData = function(bufData) {
+  if (typeof bufData == 'number')
+    return bufData >= 0;
+  if (bufData instanceof ArrayBuffer)
+    return true;
+  return WebGLArrayTypes.some(function(t) {
+    return bufData instanceof t;
+  });
+};
+
+isVertexAttribute = function(idx) {
+  if (typeof idx != 'number') return false;
+  return idx >= 0 && idx < MaxVertexAttribs;
+};
+
+isValidName = function(name) {
+  if (typeof name != 'string') return false;
+  for (var i=0; i<name.length; i++) {
+    var c = name.charCodeAt(i);
+    if (c & 0x00FF == 0 || c & 0xFF00 == 0) {
+      return false;
+    }
+  }
+  return true;
+};
+
+WebGLArrayTypes = [
+  Float32Array,
+  Int32Array,
+  Int16Array,
+  Int8Array,
+  Uint32Array,
+  Uint16Array,
+  Uint8Array
+];
+webGLArrayContentGenerators = [randomLength, randomSmallIntArray];
+randomWebGLArray = function() {
+  var t = WebGLArrayTypes.random();
+  return new t(webGLArrayContentGenerators.random()());
+};
+
+randomArrayBuffer = function(buflen) {
+  if (buflen == null) buflen = 256;
+  var len = randomInt(buflen)+1;
+  var rv;
+  try {
+    rv = new ArrayBuffer(len);
+  } catch(e) {
+    log("Error creating ArrayBuffer with length " + len);
+    throw(e);
+  }
+  return rv;
+};
+
+bufferDataGenerators = [randomLength, randomWebGLArray, randomArrayBuffer];
+randomBufferData = function() {
+  return bufferDataGenerators.random()();
+};
+
+randomSmallWebGLArray = function(buflen) {
+  var t = WebGLArrayTypes.random();
+  return new t(randomInt(buflen/4)+1);
+};
+
+bufferSubDataGenerators = [randomSmallWebGLArray, randomArrayBuffer];
+randomBufferSubData = function(buflen) {
+  var data = bufferSubDataGenerators.random()(buflen);
+  var offset = randomInt(buflen - data.byteLength);
+  return {data:data, offset:offset};
+};
+
+randomColor = function() {
+  return [Math.random(), Math.random(), Math.random(), Math.random()];
+};
+
+randomName = function() {
+  var arr = [];
+  var len = randomLength()+1;
+  for (var i=0; i<len; i++) {
+    var l = randomInt(255)+1;
+    var h = randomInt(255)+1;
+    var c = (h << 8) | l;
+    arr.push(String.fromCharCode(c));
+  }
+  return arr.join('');
+};
+randomVertexAttribute = function() {
+  return randomInt(MaxVertexAttribs);
+};
+
+randomBool = function() { return Math.random() > 0.5; };
+
+randomStencil = function() {
+  return randomInt(MaxStencilValue);
+};
+
+randomLineWidth = function() {
+  var lo = LineWidthRange[0],
+      hi = LineWidthRange[1];
+  return randomFloatFromRange(lo, hi);
+};
+
+randomImage = function(w,h) {
+  var img;
+  var r = Math.random();
+  if (r < 0.5) {
+    img = document.createElement('canvas');
+    img.width = w; img.height = h;
+    img.getContext('2d').fillRect(0,0,w,h);
+  } else if (r < 0.5) {
+    img = document.createElement('video');
+    img.width = w; img.height = h;
+  } else if (r < 0.75) {
+    img = document.createElement('img');
+    img.width = w; img.height = h;
+  } else {
+    img = canvas2D.getContext('2d').createImageData(w,h);
+  }
+  return img
+};
+
+// ArgGenerators contains argument generators for WebGL functions.
+// The argument generators are used for running random tests against the WebGL
+// functions.
+//
+// ArgGenerators is an object consisting of functionName : argGen -properties.
+//
+// functionName is a WebGL context function name and the argGen is an argument
+// generator object that encapsulates the requirements to run
+// randomly generated tests on the WebGL function.
+//
+// An argGen object has the following methods:
+//   - setup    -- set up state for testing the GL function, returns values
+//                 that need cleanup in teardown. Run once before entering a
+//                 test loop.
+//   - teardown -- do cleanup on setup's return values after testing is complete
+//   - generate -- generate a valid set of random arguments for the GL function
+//   - returnValueCleanup -- do cleanup on value returned by the tested GL function
+//   - cleanup  -- do cleanup on generated arguments from generate
+//   - checkArgValidity -- check if passed args are valid. Has a call signature
+//                         that matches generate's return value. Returns true
+//                         if args are valid, false if not.
+//
+//   Example test loop that demonstrates how the function args and return
+//   values flow together:
+//
+//   var setupArgs = argGen.setup();
+//   for (var i=0; i<numberOfTests; i++) {
+//     var generatedArgs = argGen.generate.apply(argGen, setupArgs);
+//     var validArgs = argGen.checkArgValidity.apply(argGen, generatedArgs);
+//     var rv = call the GL function with generatedArgs;
+//     argGen.returnValueCleanup(rv);
+//     argGen.cleanup.apply(argGen, generatedArgs);
+//   }
+//   argGen.teardown.apply(argGen, setupArgs);
+//
+ArgGenerators = {
+
+// GL functions in alphabetical order
+
+// A
+
+  activeTexture : {
+    generate : function() { return [textureUnit.random()]; },
+    checkArgValidity : function(t) { return textureUnit.has(t); },
+    teardown : function() { GL.activeTexture(GL.TEXTURE0); }
+  },
+  attachShader : {
+    generate : function() {
+      var p = GL.createProgram();
+      var sh = GL.createShader(shaderType.random());
+      return [p, sh];
+    },
+    checkArgValidity : function(p, sh) {
+      return GL.isProgram(p) && GL.isShader(sh) && !GL.getAttachedShaders(p).has(sh);
+    },
+    cleanup : function(p, sh) {
+      try {GL.detachShader(p,sh);} catch(e) {}
+      try {GL.deleteProgram(p);} catch(e) {}
+      try {GL.deleteShader(sh);} catch(e) {}
+    }
+  },
+
+// B
+
+  bindAttribLocation : {
+    generate : function() {
+      var program = GL.createProgram();
+      return [program, randomVertexAttribute(), randomName()];
+    },
+    checkArgValidity : function(program, index, name) {
+      return GL.isProgram(program) && isVertexAttribute(index) && isValidName(name);
+    },
+    cleanup : function(program, index, name) {
+      try { GL.deleteProgram(program); } catch(e) {}
+    }
+  },
+  bindBuffer : {
+    generate : function(buf) {
+      return [bufferTarget.random(), GL.createBuffer()];
+    },
+    checkArgValidity : function(target, buf) {
+      if (!bufferTarget.has(target))
+        return false;
+      GL.bindBuffer(target, buf);
+      return GL.isBuffer(buf);
+    },
+    cleanup : function(t, buf, m) {
+      GL.deleteBuffer(buf);
+    }
+  },
+  bindFramebuffer : {
+    generate : function() {
+      return [GL.FRAMEBUFFER, Math.random() > 0.5 ? null : GL.createFramebuffer()];
+    },
+    checkArgValidity : function(target, fbo) {
+      if (target != GL.FRAMEBUFFER)
+        return false;
+      if (fbo != null)
+          GL.bindFramebuffer(target, fbo);
+      return (fbo == null || GL.isFramebuffer(fbo));
+    },
+    cleanup : function(target, fbo) {
+      GL.bindFramebuffer(target, null);
+      if (fbo)
+        GL.deleteFramebuffer(fbo);
+    }
+  },
+  bindRenderbuffer : {
+    generate : function() {
+      return [GL.RENDERBUFFER, Math.random() > 0.5 ? null : GL.createRenderbuffer()];
+    },
+    checkArgValidity : function(target, rbo) {
+      if (target != GL.RENDERBUFFER)
+        return false;
+      if (rbo != null)
+        GL.bindRenderbuffer(target, rbo);
+      return (rbo == null || GL.isRenderbuffer(rbo));
+    },
+    cleanup : function(target, rbo) {
+      GL.bindRenderbuffer(target, null);
+      if (rbo)
+        GL.deleteRenderbuffer(rbo);
+    }
+  },
+  bindTexture : {
+    generate : function() {
+      return [bindTextureTarget.random(), Math.random() > 0.5 ? null : GL.createTexture()];
+    },
+    checkArgValidity : function(target, o) {
+      if (!bindTextureTarget.has(target))
+        return false;
+      if (o != null)
+        GL.bindTexture(target, o);
+      return (o == null || GL.isTexture(o));
+    },
+    cleanup : function(target, o) {
+      GL.bindTexture(target, null);
+      if (o)
+        GL.deleteTexture(o);
+    }
+  },
+  blendColor : {
+    generate : function() { return randomColor(); },
+    teardown : function() { GL.blendColor(0,0,0,0); }
+  },
+  blendEquation : {
+    generate : function() { return [blendEquationMode.random()]; },
+    checkArgValidity : function(o) { return blendEquationMode.has(o); },
+    teardown : function() { GL.blendEquation(GL.FUNC_ADD); }
+  },
+  blendEquationSeparate : {
+    generate : function() {
+      return [blendEquationMode.random(), blendEquationMode.random()];
+    },
+    checkArgValidity : function(o,p) {
+      return blendEquationMode.has(o) && blendEquationMode.has(p);
+    },
+    teardown : function() { GL.blendEquationSeparate(GL.FUNC_ADD, GL.FUNC_ADD); }
+  },
+  blendFunc : {
+    generate : function() {
+      return [blendFuncSfactor.random(), blendFuncDfactor.random()];
+    },
+    checkArgValidity : function(s,d) {
+      return blendFuncSfactor.has(s) && blendFuncDfactor.has(d);
+    },
+    teardown : function() { GL.blendFunc(GL.ONE, GL.ZERO); }
+  },
+  blendFuncSeparate : {
+    generate : function() {
+      return [blendFuncSfactor.random(), blendFuncDfactor.random(),
+              blendFuncSfactor.random(), blendFuncDfactor.random()];
+    },
+    checkArgValidity : function(s,d,as,ad) {
+      return blendFuncSfactor.has(s) && blendFuncDfactor.has(d) &&
+              blendFuncSfactor.has(as) && blendFuncDfactor.has(ad) ;
+    },
+    teardown : function() {
+      GL.blendFuncSeparate(GL.ONE, GL.ZERO, GL.ONE, GL.ZERO);
+    }
+  },
+  bufferData : {
+    setup : function() {
+      var buf = GL.createBuffer();
+      var ebuf = GL.createBuffer();
+      GL.bindBuffer(GL.ARRAY_BUFFER, buf);
+      GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ebuf);
+      return [buf, ebuf];
+    },
+    generate : function(buf, ebuf) {
+      return [bufferTarget.random(), randomBufferData(), bufferMode.random()];
+    },
+    checkArgValidity : function(target, bufData, mode) {
+      return bufferTarget.has(target) && isBufferData(bufData) && bufferMode.has(mode);
+    },
+    teardown : function(buf, ebuf) {
+      GL.deleteBuffer(buf);
+      GL.deleteBuffer(ebuf);
+    },
+  },
+  bufferSubData : {
+    setup : function() {
+      var buf = GL.createBuffer();
+      var ebuf = GL.createBuffer();
+      GL.bindBuffer(GL.ARRAY_BUFFER, buf);
+      GL.bufferData(GL.ARRAY_BUFFER, 256, GL.STATIC_DRAW);
+      GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ebuf);
+      GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, 256, GL.STATIC_DRAW);
+      return [buf, ebuf];
+    },
+    generate : function(buf, ebuf) {
+      var d = randomBufferSubData(256);
+      return [bufferTarget.random(), d.offset, d.data];
+    },
+    checkArgValidity : function(target, offset, data) {
+      return bufferTarget.has(target) && offset >= 0 && data.byteLength >= 0 && offset + data.byteLength <= 256;
+    },
+    teardown : function(buf, ebuf) {
+      GL.deleteBuffer(buf);
+      GL.deleteBuffer(ebuf);
+    },
+  },
+
+// C
+
+  checkFramebufferStatus : {
+    generate : function() {
+      return [Math.random() > 0.5 ? null : GL.createFramebuffer()];
+    },
+    checkArgValidity : function(fbo) {
+      if (fbo != null)
+        GL.bindFramebuffer(GL.FRAMEBUFFER, fbo);
+      return fbo == null || GL.isFramebuffer(fbo);
+    },
+    cleanup : function(fbo){
+      GL.bindFramebuffer(GL.FRAMEBUFFER, null);
+      if (fbo != null)
+        try{ GL.deleteFramebuffer(fbo); } catch(e) {}
+    }
+  },
+  clear : {
+    generate : function() { return [clearMask.random()]; },
+    checkArgValidity : function(mask) { return clearMask.has(mask); }
+  },
+  clearColor : {
+    generate : function() { return randomColor(); },
+    teardown : function() { GL.clearColor(0,0,0,0); }
+  },
+  clearDepth : {
+    generate : function() { return [Math.random()]; },
+    teardown : function() { GL.clearDepth(1); }
+  },
+  clearStencil : {
+    generate : function() { return [randomStencil()]; },
+    teardown : function() { GL.clearStencil(0); }
+  },
+  colorMask : {
+    generate : function() {
+      return [randomBool(), randomBool(), randomBool(), randomBool()];
+    },
+    teardown : function() { GL.colorMask(true, true, true, true); }
+  },
+  compileShader : {}, // FIXME
+  copyTexImage2D : {}, // FIXME
+  copyTexSubImage2D : {}, // FIXME
+  createBuffer : {
+    generate : function() { return []; },
+    returnValueCleanup : function(o) { GL.deleteBuffer(o); }
+  },
+  createFramebuffer : {
+    generate : function() { return []; },
+    returnValueCleanup : function(o) { GL.deleteFramebuffer(o); }
+  },
+  createProgram : {
+    generate : function() { return []; },
+    returnValueCleanup : function(o) { GL.deleteProgram(o); }
+  },
+  createRenderbuffer : {
+    generate : function() { return []; },
+    returnValueCleanup : function(o) { GL.deleteRenderbuffer(o); }
+  },
+  createShader : {
+    generate : function() { return [shaderType.random()]; },
+    checkArgValidity : function(t) { return shaderType.has(t); },
+    returnValueCleanup : function(o) { GL.deleteShader(o); }
+  },
+  createTexture : {
+    generate : function() { return []; },
+    returnValueCleanup : function(o) { GL.deleteTexture(o); }
+  },
+  cullFace : {
+    generate : function() { return [cullFace.random()]; },
+    checkArgValidity : function(f) { return cullFace.has(f); },
+    teardown : function() { GL.cullFace(GL.BACK); }
+  },
+
+// D
+
+  deleteBuffer : {
+    generate : function() { return [GL.createBuffer()]; },
+    checkArgValidity : function(o) {
+      GL.bindBuffer(GL.ARRAY_BUFFER, o);
+      return GL.isBuffer(o);
+    },
+    cleanup : function(o) {
+      GL.bindBuffer(GL.ARRAY_BUFFER, null);
+      try { GL.deleteBuffer(o); } catch(e) {}
+    }
+  },
+  deleteFramebuffer : {
+    generate : function() { return [GL.createFramebuffer()]; },
+    checkArgValidity : function(o) {
+      GL.bindFramebuffer(GL.FRAMEBUFFER, o);
+      return GL.isFramebuffer(o);
+    },
+    cleanup : function(o) {
+      GL.bindFramebuffer(GL.FRAMEBUFFER, null);
+      try { GL.deleteFramebuffer(o); } catch(e) {}
+    }
+  },
+  deleteProgram : {
+    generate : function() { return [GL.createProgram()]; },
+    checkArgValidity : function(o) { return GL.isProgram(o); },
+    cleanup : function(o) { try { GL.deleteProgram(o); } catch(e) {} }
+  },
+  deleteRenderbuffer : {
+    generate : function() { return [GL.createRenderbuffer()]; },
+    checkArgValidity : function(o) {
+      GL.bindRenderbuffer(GL.RENDERBUFFER, o);
+      return GL.isRenderbuffer(o);
+    },
+    cleanup : function(o) {
+      GL.bindRenderbuffer(GL.RENDERBUFFER, null);
+      try { GL.deleteRenderbuffer(o); } catch(e) {}
+    }
+  },
+  deleteShader : {
+    generate : function() { return [GL.createShader(shaderType.random())]; },
+    checkArgValidity : function(o) { return GL.isShader(o); },
+    cleanup : function(o) { try { GL.deleteShader(o); } catch(e) {} }
+  },
+  deleteTexture : {
+    generate : function() { return [GL.createTexture()]; },
+    checkArgValidity : function(o) {
+      GL.bindTexture(GL.TEXTURE_2D, o);
+      return GL.isTexture(o);
+    },
+    cleanup : function(o) {
+      GL.bindTexture(GL.TEXTURE_2D, null);
+      try { GL.deleteTexture(o); } catch(e) {}
+    }
+  },
+  depthFunc : {
+    generate : function() { return [depthFuncFunc.random()]; },
+    checkArgValidity : function(f) { return depthFuncFunc.has(f); },
+    teardown : function() { GL.depthFunc(GL.LESS); }
+  },
+  depthMask : {
+    generate : function() { return [randomBool()]; },
+    teardown : function() { GL.depthFunc(GL.TRUE); }
+  },
+  depthRange : {
+    generate : function() { return [Math.random(), Math.random()]; },
+    teardown : function() { GL.depthRange(0, 1); }
+  },
+  detachShader : {
+    generate : function() {
+      var p = GL.createProgram();
+      var sh = GL.createShader(shaderType.random());
+      GL.attachShader(p, sh);
+      return [p, sh];
+    },
+    checkArgValidity : function(p, sh) {
+      return GL.isProgram(p) && GL.isShader(sh) && GL.getAttachedShaders(p).has(sh);
+    },
+    cleanup : function(p, sh) {
+      try {GL.deleteProgram(p);} catch(e) {}
+      try {GL.deleteShader(sh);} catch(e) {}
+    }
+  },
+  disable : {
+    generate : function() { return [enableCap.random()]; },
+    checkArgValidity : function(c) { return enableCap.has(c); },
+    cleanup : function(c) { if (c == GL.DITHER) GL.enable(c); }
+  },
+  disableVertexAttribArray : {
+    generate : function() { return [randomVertexAttribute()]; },
+    checkArgValidity : function(v) { return isVertexAttribute(v); }
+  },
+  drawArrays : {}, // FIXME
+  drawElements : {}, // FIXME
+
+// E
+
+  enable : {
+    generate : function() { return [enableCap.random()]; },
+    checkArgValidity : function(c) { return enableCap.has(c); },
+    cleanup : function(c) { if (c != GL.DITHER) GL.disable(c); }
+  },
+  enableVertexAttribArray : {
+    generate : function() { return [randomVertexAttribute()]; },
+    checkArgValidity : function(v) { return isVertexAttribute(castToInt(v)); },
+    cleanup : function(v) { GL.disableVertexAttribArray(v); }
+  },
+
+// F
+
+  finish : {
+    generate : function() { return []; }
+  },
+  flush : {
+    generate : function() { return []; }
+  },
+  framebufferRenderbuffer : {}, // FIXME
+  framebufferTexture2D : {}, // FIXME
+  frontFace : {
+    generate : function() { return [frontFaceMode.random()]; },
+    checkArgValidity : function(c) { return frontFaceMode.has(c); },
+    cleanup : function(c) { GL.frontFace(GL.CCW); }
+  },
+
+// G
+
+  generateMipmap : {
+    setup : function() {
+      var tex = GL.createTexture();
+      var tex2 = GL.createTexture();
+      GL.bindTexture(GL.TEXTURE_2D, tex);
+      GL.bindTexture(GL.TEXTURE_CUBE_MAP, tex2);
+      var pix = new Uint8Array(16*16*4);
+      GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+      GL.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+      GL.texImage2D(GL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+      GL.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+      GL.texImage2D(GL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+      GL.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+      GL.texImage2D(GL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL.RGBA, 16, 16, 0, GL.RGBA, GL.UNSIGNED_BYTE, pix);
+    },
+    generate : function() { return [bindTextureTarget.random()]; },
+    checkArgValidity : function(t) { return bindTextureTarget.has(t); },
+    teardown : function(tex, tex2) {
+      GL.bindTexture(GL.TEXTURE_2D, null);
+      GL.bindTexture(GL.TEXTURE_CUBE_MAP, null);
+      GL.deleteTexture(tex);
+      GL.deleteTexture(tex2);
+    }
+  },
+  getActiveAttrib : {
+  /* FIXME the queried attrib needs to be an active one
+    generate : function() {
+      var program = GL.createProgram();
+      return [program, randomVertexAttribute()];
+    },
+    checkArgValidity : function(program, index) {
+      return GL.isProgram(program) && isVertexAttribute(index);
+    },
+    cleanup : function(program, index) {
+      GL.deleteProgram(program);
+    }
+  */
+  },
+  getActiveUniform : {}, // FIXME
+  getAttachedShaders : {
+    setup : function() {
+      var program = GL.createProgram();
+      var s1 = GL.createShader(GL.VERTEX_SHADER);
+      var s2 = GL.createShader(GL.FRAGMENT_SHADER);
+      GL.attachShader(program, s1);
+      GL.attachShader(program, s2);
+      return [program, s1, s2];
+    },
+    generate : function(program, s1, s2) {
+      return [program]
+    },
+    checkArgValidity : function(program) {
+      return GL.isProgram(program);
+    },
+    teardown : function(program, s1, s2) {
+      GL.deleteProgram(program);
+      GL.deleteShader(s1);
+      GL.deleteShader(s2);
+    }
+  },
+  getAttribLocation : {
+    generate : function() {
+      var program = GL.createProgram();
+      var name = randomName();
+      GL.bindAttribLocation(program, randomVertexAttribute(), name);
+      return [program, name];
+    },
+    checkArgValidity : function(program, name) {
+      return GL.isProgram(program) && isValidName(name);
+    },
+    cleanup : function(program, name) {
+      try { GL.deleteProgram(program); } catch(e) {}
+    }
+  },
+  getParameter : {
+    generate : function() { return [getParameterPname.random()]; },
+    checkArgValidity : function(p) { return getParameterPname.has(p); }
+  },
+  getBufferParameter : {}, // FIXME
+  getError : {
+    generate : function() { return []; }
+  },
+  getFramebufferAttachmentParameter : {}, // FIXME
+  getProgramParameter : {}, // FIXME
+  getProgramInfoLog : {}, // FIXME
+  getRenderbufferParameter : {}, // FIXME
+  getShaderParameter : {}, // FIXME
+  getShaderInfoLog : {}, // FIXME
+  getShaderSource : {}, // FIXME
+  getTexParameter : {}, // FIXME
+  getUniform : {}, // FIXME
+  getUniformLocation : {}, // FIXME
+  getVertexAttrib : {}, // FIXME
+  getVertexAttribOffset : {}, // FIXME
+
+// H
+
+  hint : {
+    generate : function() { return [GL.GENERATE_MIPMAP_HINT, mipmapHint.random()]; },
+    checkValidArgs : function(h, m) {
+      return h == GL.GENERATE_MIPMAP_HINT && mipmapHint.has(m);
+    },
+    teardown : function(){ GL.hint(GL.GENERATE_MIPMAP_HINT, GL.DONT_CARE); }
+  },
+
+// I
+
+  isBuffer : {
+    generate : function() { return [GL.createBuffer()]; },
+    cleanup : function(o) { try { GL.deleteBuffer(o); } catch(e) {} }
+  },
+  isEnabled : {
+    generate : function() { return [enableCap.random()]; },
+    checkArgValidity : function(c) { return enableCap.has(c); }
+  },
+  isFramebuffer : {
+    generate : function() { return [GL.createFramebuffer()]; },
+    cleanup : function(o) { try { GL.deleteFramebuffer(o); } catch(e) {} }
+  },
+  isProgram : {
+    generate : function() { return [GL.createProgram()]; },
+    cleanup : function(o) { try { GL.deleteProgram(o); } catch(e) {} }
+  },
+  isRenderbuffer : {
+    generate : function() { return [GL.createRenderbuffer()]; },
+    cleanup : function(o) { try { GL.deleteRenderbuffer(o); } catch(e) {} }
+  },
+  isShader : {
+    generate : function() { return [GL.createShader(shaderType.random())]; },
+    cleanup : function(o) { try { GL.deleteShader(o); } catch(e) {} }
+  },
+  isTexture : {
+    generate : function() { return [GL.createTexture()]; },
+    cleanup : function(o) { try { GL.deleteTexture(o); } catch(e) {} }
+  },
+
+// L
+
+  lineWidth : {
+    generate : function() { return [randomLineWidth()]; },
+    teardown : function() { GL.lineWidth(1); }
+  },
+  linkProgram : {}, // FIXME
+
+// P
+  pixelStorei : {
+    generate : function() {
+      return [pixelStoreiPname.random(), pixelStoreiParam.random()];
+    },
+    checkArgValidity : function(pname, param) {
+      return pixelStoreiPname.has(pname) && pixelStoreiParam.has(param);
+    },
+    teardown : function() {
+      GL.pixelStorei(GL.PACK_ALIGNMENT, 4);
+      GL.pixelStorei(GL.UNPACK_ALIGNMENT, 4);
+    }
+  },
+  polygonOffset : {
+    generate : function() { return [randomFloat(), randomFloat()]; },
+    teardown : function() { GL.polygonOffset(0,0); }
+  },
+
+// R
+
+  readPixels : {}, // FIXME
+  renderbufferStorage : {}, // FIXME
+
+// S
+
+  sampleCoverage : {
+    generate : function() { return [randomFloatFromRange(0,1), randomBool()] },
+    teardown : function() { GL.sampleCoverage(1, false); }
+  },
+  scissor : {
+    generate : function() {
+      return [randomInt(3000)-1500, randomInt(3000)-1500, randomIntFromRange(0,3000), randomIntFromRange(0,3000)];
+    },
+    checkArgValidity : function(x,y,w,h) {
+      return castToInt(w) >= 0 && castToInt(h) >= 0;
+    },
+    teardown : function() {
+      GL.scissor(0,0,GL.canvas.width, GL.canvas.height);
+    }
+  },
+  shaderSource : {}, // FIXME
+  stencilFunc : {
+    generate : function(){
+      return [stencilFuncFunc.random(), randomInt(MaxStencilValue), randomInt(0xffffffff)];
+    },
+    checkArgValidity : function(func, ref, mask) {
+      return stencilFuncFunc.has(func) && castToInt(ref) >= 0 && castToInt(ref) < MaxStencilValue;
+    },
+    teardown : function() {
+      GL.stencilFunc(GL.ALWAYS, 0, 0xffffffff);
+    }
+  },
+  stencilFuncSeparate : {
+    generate : function(){
+      return [cullFace.random(), stencilFuncFunc.random(), randomInt(MaxStencilValue), randomInt(0xffffffff)];
+    },
+    checkArgValidity : function(face, func, ref, mask) {
+      return cullFace.has(face) && stencilFuncFunc.has(func) && castToInt(ref) >= 0 && castToInt(ref) < MaxStencilValue;
+    },
+    teardown : function() {
+      GL.stencilFunc(GL.ALWAYS, 0, 0xffffffff);
+    }
+  },
+  stencilMask : {
+    generate : function() { return [randomInt(0xffffffff)]; },
+    teardown : function() { GL.stencilMask(0xffffffff); }
+  },
+  stencilMaskSeparate : {
+    generate : function() { return [cullFace.random(), randomInt(0xffffffff)]; },
+    checkArgValidity : function(face, mask) {
+      return cullFace.has(face);
+    },
+    teardown : function() { GL.stencilMask(0xffffffff); }
+  },
+  stencilOp : {
+    generate : function() {
+      return [stencilOp.random(), stencilOp.random(), stencilOp.random()];
+    },
+    checkArgValidity : function(sfail, dpfail, dppass) {
+      return stencilOp.has(sfail) && stencilOp.has(dpfail) && stencilOp.has(dppass);
+    },
+    teardown : function() { GL.stencilOp(GL.KEEP, GL.KEEP, GL.KEEP); }
+  },
+  stencilOpSeparate : {
+    generate : function() {
+      return [cullFace.random(), stencilOp.random(), stencilOp.random(), stencilOp.random()];
+    },
+    checkArgValidity : function(face, sfail, dpfail, dppass) {
+      return cullFace.has(face) && stencilOp.has(sfail) &&
+              stencilOp.has(dpfail) && stencilOp.has(dppass);
+    },
+    teardown : function() { GL.stencilOp(GL.KEEP, GL.KEEP, GL.KEEP); }
+  },
+
+// T
+  texImage2D : {
+    noAlreadyTriedCheck : true, // Object.toSource is very slow here
+    setup : function() {
+      var tex = GL.createTexture();
+      var tex2 = GL.createTexture();
+      GL.bindTexture(GL.TEXTURE_2D, tex);
+      GL.bindTexture(GL.TEXTURE_CUBE_MAP, tex2);
+      return [tex, tex2];
+    },
+    generate : function() {
+      var format = texImageFormat.random();
+      if (Math.random() < 0.5) {
+        var img = randomImage(16,16);
+        var a = [ texImageTarget.random(), 0, format, format, GL.UNSIGNED_BYTE, img ];
+        return a;
+      } else {
+        var pix = null;
+        if (Math.random > 0.5) {
+          pix = new Uint8Array(16*16*4);
+        }
+        return [
+          texImageTarget.random(), 0,
+          format, 16, 16, 0,
+          format, GL.UNSIGNED_BYTE, pix
+        ];
+      }
+    },
+    checkArgValidity : function(target, level, internalformat, width, height, border, format, type, data) {
+               // or : function(target, level, internalformat, format, type, image)
+      if (!texImageTarget.has(target) || castToInt(level) < 0)
+        return false;
+      if (arguments.length <= 6) {
+        var xformat = width;
+        var xtype = height;
+        var ximage = border;
+        if ((ximage instanceof HTMLImageElement ||
+             ximage instanceof HTMLVideoElement ||
+             ximage instanceof HTMLCanvasElement ||
+             ximage instanceof ImageData) &&
+            texImageInternalFormat.has(internalformat) &&
+            texImageFormat.has(xformat) &&
+            texImageType.has(xtype) &&
+            internalformat == xformat)
+          return true;
+        return false;
+      }
+      var w = castToInt(width), h = castToInt(height), b = castToInt(border);
+      return texImageInternalFormat.has(internalformat) && w >= 0 && h >= 0 &&
+            b == 0 && (data == null || data.byteLength == w*h*4) &&
+            texImageFormat.has(format) && texImageType.has(type)
+            && internalformat == format;
+    },
+    teardown : function(tex, tex2) {
+      GL.bindTexture(GL.TEXTURE_2D, null);
+      GL.bindTexture(GL.TEXTURE_CUBE_MAP, null);
+      GL.deleteTexture(tex);
+      GL.deleteTexture(tex2);
+    }
+  },
+  texParameterf : {
+    generate : function() {
+      var pname = texParameterPname.random();
+      var param = texParameterParam[pname].random();
+      return [bindTextureTarget.random(), pname, param];
+    },
+    checkArgValidity : function(target, pname, param) {
+      if (!bindTextureTarget.has(target))
+        return false;
+      if (!texParameterPname.has(pname))
+        return false;
+      return texParameterParam[pname].has(param);
+    }
+  },
+  texParameteri : {
+    generate : function() {
+      var pname = texParameterPname.random();
+      var param = texParameterParam[pname].random();
+      return [bindTextureTarget.random(), pname, param];
+    },
+    checkArgValidity : function(target, pname, param) {
+      if (!bindTextureTarget.has(target))
+        return false;
+      if (!texParameterPname.has(pname))
+        return false;
+      return texParameterParam[pname].has(param);
+    }
+  },
+  texSubImage2D : {}, // FIXME
+
+// U
+
+  uniform1f : {}, // FIXME
+  uniform1fv : {}, // FIXME
+  uniform1i : {}, // FIXME
+  uniform1iv : {}, // FIXME
+  uniform2f : {}, // FIXME
+  uniform2fv : {}, // FIXME
+  uniform2i : {}, // FIXME
+  uniform2iv : {}, // FIXME
+  uniform3f : {}, // FIXME
+  uniform3fv : {}, // FIXME
+  uniform3i : {}, // FIXME
+  uniform3iv : {}, // FIXME
+  uniform4f : {}, // FIXME
+  uniform4fv : {}, // FIXME
+  uniform4i : {}, // FIXME
+  uniform4iv : {}, // FIXME
+  uniformMatrix2fv : {}, // FIXME
+  uniformMatrix3fv : {}, // FIXME
+  uniformMatrix4fv : {}, // FIXME
+  useProgram : {}, // FIXME
+
+// V
+
+  validateProgram : {}, // FIXME
+  vertexAttrib1f : {}, // FIXME
+  vertexAttrib1fv : {}, // FIXME
+  vertexAttrib2f : {}, // FIXME
+  vertexAttrib2fv : {}, // FIXME
+  vertexAttrib3f : {}, // FIXME
+  vertexAttrib3fv : {}, // FIXME
+  vertexAttrib4f : {}, // FIXME
+  vertexAttrib4fv : {}, // FIXME
+  vertexAttribPointer : {}, // FIXME
+  viewport : {
+    generate : function() {
+      return [randomInt(3000)-1500, randomInt(3000)-1500, randomIntFromRange(0,3000), randomIntFromRange(0,3000)];
+    },
+    checkArgValidity : function(x,y,w,h) {
+      return castToInt(w) >= 0 && castToInt(h) >= 0;
+    },
+    teardown : function() {
+      GL.viewport(0,0,GL.canvas.width, GL.canvas.height);
+    }
+  }
+
+};
+
+mutateArgs = function(args) {
+  var mutateCount = randomIntFromRange(1, args.length);
+  var newArgs = Array.from(args);
+  for (var i=0; i<mutateCount; i++) {
+    var idx = randomInt(args.length);
+    newArgs[idx] = generateRandomArg(idx, args.length);
+  }
+  return newArgs;
+};
+
+// Calls testFunction numberOfTests times with arguments generated by
+// argGen.generate() (or empty arguments if no generate present).
+//
+// The arguments testFunction is called with are the generated args,
+// the argGen, and what argGen.setup() returned or [] if argGen has not setup
+// method. I.e. testFunction(generatedArgs, argGen, setupVars).
+//
+argGeneratorTestRunner = function(argGen, testFunction, numberOfTests) {
+  // do argument generator setup if needed
+  var setupVars = argGen.setup ? argGen.setup() : [];
+  var error;
+  for (var i=0; i<numberOfTests; i++) {
+    var failed = false;
+    // generate arguments if argGen has a generate method
+    var generatedArgs = argGen.generate ? argGen.generate.apply(argGen, setupVars) : [];
+    try {
+      // call testFunction with the generated args
+      testFunction.call(this, generatedArgs, argGen, setupVars);
+    } catch (e) {
+      failed = true;
+      error = e;
+    }
+    // if argGen needs cleanup for generated args, do it here
+    if (argGen.cleanup)
+      argGen.cleanup.apply(argGen, generatedArgs);
+    if (failed) break;
+  }
+  // if argGen needs to do a final cleanup for setupVars, do it here
+  if (argGen.teardown)
+    argGen.teardown.apply(argGen, setupVars);
+  if (error) throw(error);
+}
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/quickCheckAPIBadArgs.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+<script type="application/x-javascript" src="quickCheckAPI.js"></script>
+
+<script type="application/x-javascript">
+
+// Test that all GL functions specified in ArgGenerators fail
+// when called with randomly generated invalid arguments
+// Works only on tests with checkArgValidity defined
+Tests.testInvalidArgs = function() {
+  var randomTestCount = 100;
+  for (var name in ArgGenerators) {
+    try {
+      if (!GL[name])
+        throw (new Error(name + " is missing from the WebGL context"));
+      var argGen = ArgGenerators[name];
+      var alreadyTriedArgs = {};
+      if (!argGen.generate || !argGen.checkArgValidity) continue;
+      // test each GL function with randomTestCount randomly generated valid args
+      argGeneratorTestRunner(argGen, function(args, gen, setupVars) {
+        var mutatedArgs;
+        var foundArgs = false;
+        for (var j=0; j<100; j++) {
+          mutatedArgs = mutateArgs(args);
+          var validArgs = false;
+          try {
+            validArgs = gen.checkArgValidity.apply(gen, mutatedArgs);
+          } catch(e) {}
+          if (!validArgs) {
+            if (gen.noAlreadyTriedCheck) {
+              foundArgs = true;
+              break; // found new invalid args
+            }
+            var src = Object.toSource(mutatedArgs);
+            if (!alreadyTriedArgs[src]) {
+              alreadyTriedArgs[src] = true;
+              foundArgs = true;
+              break; // found new invalid args
+            }
+          }
+        }
+        if (!foundArgs)
+          return true;
+        var ok = false;
+        var rv;
+        // assert that GL function fails when called with invalid args
+        assertFail("This should fail: "+name+"("+mutatedArgs.map(function(a){return Object.toSource(a)}).join(",")+")",
+          function(){
+            GL.getError(); // clear off existing error
+            rv = GL[name].apply(GL, mutatedArgs);
+            throwError(GL, name);
+            ok = true;
+          });
+        // if we need to cleanup the return value, do it here
+        // e.g. calling gl.deleteBuffer(rv) after testing gl.createBuffer() above
+        if (gen.returnValueCleanup && rv != null) {
+          assertOk("Cleaning up return value after "+name+"("+mutatedArgs.map(function(a){return Object.toSource(a)}).join(",")+")",
+                   function() { gen.returnValueCleanup(rv); });
+        }
+        GL.getError();
+        return !ok;
+      }, argGen.testCount || randomTestCount);
+    } catch(e) {
+      testFailed(name, e.name, formatError(e));
+    }
+  }
+}
+
+</script>
+<style>canvas{position:absolute;}</style>
+</head><body>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/conformance/webGLArrays.html
@@ -0,0 +1,160 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<link rel="stylesheet" type="text/css" href="../unit.css" />
+<script type="application/x-javascript" src="../unit.js"></script>
+<script type="application/x-javascript" src="../util.js"></script>
+
+<script type="application/x-javascript">
+
+function assertIdxs(name, arr, length) {
+//   assertOk(name+": Read with negative idx should work", function(){ return arr[-1] });
+//   assertOk(name+": Read with too large idx should work", function(){ return arr[length] });
+//   assertOk(name+": Write with negative idx should work", function(){ arr[-1] = 0 });
+//   assertOk(name+": Write with too large idx should work", function(){ arr[length] = 0 });
+//   arr[0] = 2;
+//   assertEquals(name+": Test that write worked", 2, arr[0]);
+//   assertOk(name+": Write with bad value should work", function(){ arr[0] = {x:"foo"} });
+//   assertEquals(name+": Test that bad write didn't work", 2, arr[0]);
+  assertOk(name+": Read and writes with OK idxs should work", function(){
+    for (var i=0; i<length; i++) arr[i] = i + 1;
+    for (var i=0; i<length; i++) arr[i] = arr[i] + 1;
+    for (var i=0; i<length; i++) assertEquals(name+": Test that reads and writes work", i+2, arr[i]);
+  });
+}
+
+Tests.startUnit = function () {
+  var canvas = document.getElementById('gl');
+  var gl = wrapGLContext(canvas.getContext(GL_CONTEXT_ID));
+  prog = new Shader(gl, 'vert', 'frag');
+  prog.use();
+  prog.uniform4f('c', 255, 0, 0, 255);
+  va = prog.attrib('Vertex');
+  buffer = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+  return [gl];
+}
+
+Tests.endUnit = function() {
+  prog.destroy();
+}
+
+Tests.testCreateFromArray = function() {
+  var a = new Float32Array([1,2,3,4,5,6]);
+  assertIdxs('Float', a, 6);
+  var a = new Int32Array([1,2,3,4,5,6]);
+  assertIdxs('Int', a, 6);
+  var a = new Int16Array([1,2,3,4,5,6]);
+  assertIdxs('Short', a, 6);
+  var a = new Int8Array([1,2,3,4,5,6]);
+  assertIdxs('Byte', a, 6);
+  var a = new Uint32Array([1,2,3,4,5,6]);
+  assertIdxs('UInt', a, 6);
+  var a = new Uint16Array([1,2,3,4,5,6]);
+  assertIdxs('UShort', a, 6);
+  var a = new Uint8Array([1,2,3,4,5,6]);
+  assertIdxs('UByte', a, 6);
+}
+Tests.testCreateFromCount = function() {
+  var a = new Float32Array(6);
+  assertIdxs('Float', a, 6);
+  var a = new Int32Array(6);
+  assertIdxs('Int', a, 6);
+  var a = new Int16Array(6);
+  assertIdxs('Short', a, 6);
+  var a = new Int8Array(6);
+  assertIdxs('Byte', a, 6);
+  var a = new Uint32Array(6);
+  assertIdxs('UInt', a, 6);
+  var a = new Uint16Array(6);
+  assertIdxs('UShort', a, 6);
+  var a = new Uint8Array(6);
+  assertIdxs('UByte', a, 6);
+}
+Tests.testCreateFromBuffer = function() {
+  var sz = 24;
+  var b = new ArrayBuffer(sz);
+  var a = new Float32Array(b);
+  assertIdxs('Float', a, sz/4);
+  var a = new Int32Array(b);
+  assertIdxs('Int', a, sz/4);
+  var a = new Int16Array(b);
+  assertIdxs('Short', a, sz/2);
+  var a = new Int8Array(b);
+  assertIdxs('Byte', a, sz/1);
+  var a = new Uint32Array(b);
+  assertIdxs('UInt', a, sz/4);
+  var a = new Uint16Array(b);
+  assertIdxs('UShort', a, sz/2);
+  var a = new Uint8Array(b);
+  assertIdxs('UByte', a, sz/1);
+}
+
+Tests.testThatWritesChangeDrawing = function(gl) {
+  var verts = [
+    0,0,
+    1,0,
+    1,1,
+
+    0,0,
+    1,1,
+    0,1
+  ];
+  var a = new Float32Array(verts);
+  var arr = [];
+  for (var i=0; i<12; i++)
+    arr[i] = a[i];
+  assertEquals("Test that reads work from an array-initialized Float32Array", arr, verts);
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW);
+  gl.vertexAttribPointer(va, 2, gl.FLOAT, false, 0, 0);
+  gl.enableVertexAttribArray(va);
+
+  var id = new Uint8Array(4);
+  gl.readPixels(8,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+  assertEquals([0, 0, 0, 0], [id[0], id[1], id[2], id[3]]);
+
+  gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+  gl.readPixels(8,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+  assertEquals([255, 0, 0, 255], [id[0], id[1], id[2], id[3]]);
+  gl.readPixels(0,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+  assertEquals([0, 0, 0, 0], [id[0], id[1], id[2], id[3]]);
+
+  a[0] = a[6] = a[10] = -1;
+  gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW);
+  gl.vertexAttribPointer(va, 2, gl.FLOAT, false, 0, 0);
+
+  gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+  gl.readPixels(8,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+  assertEquals([255, 0, 0, 255], [id[0], id[1], id[2], id[3]]);
+  gl.readPixels(0,8,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+  assertEquals("Test that Float32Array#[]= worked and drawArrays drew a full-width rectangle",
+               [255, 0, 0, 255], [id[0], id[1], id[2], id[3]]);
+  gl.readPixels(0,0,1,1,gl.RGBA, gl.UNSIGNED_BYTE, id);
+  assertEquals([0, 0, 0, 0], [id[0], id[1], id[2], id[3]]);
+}
+
+</script>
+<script id="vert" type="x-shader/x-vertex">
+  attribute vec2 Vertex;
+  void main()
+  {
+    gl_Position = vec4(Vertex, 0.0, 1.0);
+  }
+</script>
+<script id="frag" type="x-shader/x-fragment">
+  #ifdef GL_ES
+precision highp float;
+#endif
+  uniform vec4 c;
+  void main()
+  {
+    gl_FragColor = c;
+  }
+</script>
+<style>canvas{border: 1px solid black}</style>
+</head><body>
+<canvas id="gl" width="16" height="16"></canvas>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/demos/opengl_web.html
@@ -0,0 +1,589 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+
+<title>OpenGL for the web</title>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+
+<script type="application/x-javascript" src="../util.js"></script>
+
+    <script type="application/x-javascript">
+
+function log(msg) {
+  document.getElementById('note').textContent += "\n"+msg;
+}
+
+
+
+
+function init(ev) {
+    var canvas = document.getElementById('canvas');
+    var gl = canvas.getContext(GL_CONTEXT_ID);
+
+    var shader = new Shader(gl, "ppix-vert", "ppix-frag");
+    shader.compile();
+    var fbo = new FBO(gl, canvas.width, canvas.height);
+    var fbo2 = new FBO(gl, canvas.width, canvas.height);
+    var fbo3 = new FBO(gl, canvas.width, canvas.height);
+    var depth = new Shader(gl, "depth-vert", "depth-frag");
+    var identity = new Filter(gl, "identity-vert", "identity-frag");
+    var unpremult = new Filter(gl, "identity-vert", "unpremult-frag");
+    var hblur = new Filter(gl, "identity-vert", "hblur-frag");
+    var vblur = new Filter(gl, "identity-vert", "vblur-frag");
+    var hdof = new Filter(gl, "identity-vert", "hdof-frag");
+    var vdof = new Filter(gl, "identity-vert", "vdof-frag");
+