Bug 1450839 - Update with cherry-pick to fix timeouts in rgb10_a2 tests. draft
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 06 Apr 2018 20:01:40 -0700
changeset 779427 24a2fa7c1603c038f1c13970a016c3b383a99cc5
parent 779426 26a1135c738c34cf872905f257b4da55cc037067
child 779428 b4ca2689c1ce60a16c2b32e12dae8a70271107f7
push id105767
push userbmo:jgilbert@mozilla.com
push dateMon, 09 Apr 2018 21:22:42 +0000
bugs1450839
milestone61.0a1
Bug 1450839 - Update with cherry-pick to fix timeouts in rgb10_a2 tests. MozReview-Commit-ID: KbJmXtRxN25
dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html
dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html
dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html
dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html
dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html
dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js
dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
dom/canvas/test/webgl-conf/cherry_picks.txt
dom/canvas/test/webgl-conf/generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html
dom/canvas/test/webgl-conf/generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html
dom/canvas/test/webgl-conf/generated/test_2_conformance__buffers__buffer-data-dynamic-delay.html
dom/canvas/test/webgl-conf/generated/test_conformance__buffers__buffer-data-dynamic-delay.html
--- a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html
@@ -24,16 +24,17 @@
 -->
 <!DOCTYPE html>
 <html>
 <head>
 <meta charset="utf-8">
 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
 <script src="../../js/js-test-pre.js"></script>
 <script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/gl-bindattriblocation-aliasing.js"></script>
 <title>bindAttribLocation with aliasing</title>
 </head>
 <body>
 <div id="description"></div>
 <div id="console"></div>
 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
 <script id="vertexShader" type="text/something-not-javascript">
 precision mediump float;
@@ -45,46 +46,16 @@ void main() {
 </script>
 <script>
 "use strict";
 description("This test verifies combinations of valid, active attribute types cannot be bound to the same location with bindAttribLocation.");
 var wtu = WebGLTestUtils;
 var canvas = document.getElementById("canvas");
 var gl = wtu.create3DContext(canvas, {antialias: false});
 var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);
-var typeInfo = [
-    { type: 'float',    asVec4: 'vec4(0.0, $(var), 0.0, 1.0)' },
-    { type: 'vec2',     asVec4: 'vec4($(var), 0.0, 1.0)' },
-    { type: 'vec3',     asVec4: 'vec4($(var), 1.0)' },
-    { type: 'vec4',     asVec4: '$(var)' },
-];
-var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
-// Test all type combinations of a_1 and a_2.
-typeInfo.forEach(function(typeInfo1) {
-    typeInfo.forEach(function(typeInfo2) {
-        debug('attribute_1: ' + typeInfo1.type + ' attribute_2: ' + typeInfo2.type);
-        var replaceParams = {
-            type_1: typeInfo1.type,
-            type_2: typeInfo2.type,
-            gl_Position_1: wtu.replaceParams(typeInfo1.asVec4, {var: 'a_1'}),
-            gl_Position_2: wtu.replaceParams(typeInfo2.asVec4, {var: 'a_2'})
-        };
-        var strVertexShader = wtu.replaceParams(wtu.getScript('vertexShader'), replaceParams);
-        var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
-        assertMsg(glVertexShader != null, "Vertex shader compiled successfully.");
-        // Bind both a_1 and a_2 to the same position and verify the link fails.
-        // Do so for all valid positions available.
-        for (var l = 0; l < maxAttributes; l++) {
-            var glProgram = gl.createProgram();
-            gl.bindAttribLocation(glProgram, l, 'a_1');
-            gl.bindAttribLocation(glProgram, l, 'a_2');
-            gl.attachShader(glProgram, glVertexShader);
-            gl.attachShader(glProgram, glFragmentShader);
-            gl.linkProgram(glProgram);
-            assertMsg(!gl.getProgramParameter(glProgram, gl.LINK_STATUS), "Link should fail when both types are aliased to location " + l);
-        }
-    });
-});
+
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShader'));
+
 var successfullyParsed = true;
 </script>
 <script src="../../js/js-test-post.js"></script>
 </body>
 </html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
@@ -1,11 +1,12 @@
 buffer-bind-test.html
 buffer-data-and-buffer-sub-data.html
 --min-version 1.0.3 buffer-data-array-buffer-delete.html
+--min-version 1.0.4 buffer-data-dynamic-delay.html
 --min-version 1.0.4 buffer-uninitialized.html
 --min-version 1.0.2 element-array-buffer-delete-recreate.html
 index-validation-copies-indices.html
 index-validation-crash-with-buffer-sub-data.html
 --min-version 1.0.2 index-validation-large-buffer.html
 index-validation-verifies-too-many-indices.html
 index-validation-with-resized-buffer.html
 index-validation.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html
@@ -0,0 +1,133 @@
+<!--
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>bufferData with DYNAMIC_DRAW and delay between updating data</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">
+    attribute vec2 a_position;
+    attribute vec2 a_color;
+    varying vec2 v_color;
+    void main()
+    {
+        gl_Position = vec4(a_position, 0.0, 1.0);
+        v_color = a_color;
+    }
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+    precision mediump float;
+    varying vec2 v_color;
+    void main()
+    {
+        gl_FragColor = vec4(v_color, 0.0, 1.0);
+    }
+</script>
+
+<script>
+"use strict";
+description("Verifies that bufferData with DYNAMIC_DRAW updates the vertex attribute when there is a significant delay between updating the buffer.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+
+// Initialize position vertex attribute to draw a square covering the entire canvas.
+var positionBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+    -1.0,  1.0,
+     1.0,  1.0,
+    -1.0, -1.0,
+     1.0, -1.0
+    ]), gl.DYNAMIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+// Initialize color vertex attribute to red.
+var colorBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+    1.0, 0.0,
+    1.0, 0.0,
+    1.0, 0.0,
+    1.0, 0.0,
+    ]), gl.DYNAMIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after setup");
+
+// Fill the canvas with red
+gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after first drawArrays");
+
+wtu.checkCanvasRect(gl, 0, 0, 50, 50, [255, 0, 0, 255], "Canvas should be red after the first drawArrays");
+
+// With the buffer set to DYNAMIC_DRAW, Angle internally changes the storage type of the vertex attribute from DYNAMIC to DIRECT
+// if the buffer has not been updated after ~4-5 draw calls. When the buffer is eventually updated, the vertex attribute
+// is updated back to DYNAMIC, but there was a bug in Angle where the data is not marked as dirty. The result is that the
+// vertex data is not updated with the new buffer data. This test verifies that the vertex data is updated.
+var iteration = 0;
+function draw() {
+    // Draw 10 times to ensure that the vertex attribute storage type is changed.
+    if (iteration < 10) {
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 2);
+        requestAnimationFrame(draw);
+    }
+    else {
+        // Update the buffer bound to the color vertex attribute to green and draw.
+        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+            0.0, 1.0,
+            0.0, 1.0,
+            0.0, 1.0,
+            0.0, 1.0,
+            ]), gl.DYNAMIC_DRAW);
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after last drawArrays");
+
+        wtu.checkCanvasRect(gl, 0, 0, 50, 50, [0, 255, 0, 255], "Canvas should be green after 10 frames");
+
+        finishTest();
+    }
+
+    iteration++;
+}
+
+requestAnimationFrame(draw);
+
+</script>
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
@@ -152,16 +152,18 @@ function testLosingAndRestoringContext()
     debug("");
     debug("Test losing and restoring a context.");
 
     canvas.addEventListener("webglcontextlost", function(e) {
       testLostContext(e);
       // restore the context after this event has exited.
       setTimeout(function() {
         shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()");
+        // Calling restoreContext() twice should not cause error or crash
+        shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()");
         // The context should still be lost. It will not get restored until the
         // webglrestorecontext event is fired.
         shouldBeTrue("gl.isContextLost()");
         shouldBe("gl.getError()", "gl.NO_ERROR");
         // gl methods should still be no-ops
         shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
       }, 0);
     });
--- a/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
@@ -106,17 +106,17 @@ gl.framebufferRenderbuffer(gl.FRAMEBUFFE
 
 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "initial framebuffer setup")
 
 function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, errIfMismatch) {
     debug("");
     debug("With depthbuffer=" + haveDepthBuffer +
             ", stencilbuffer=" + haveStencilBuffer +
             ", stencilTest=" + enableStencilTest +
-            ", expecting error=" + wtu.glEnumToString(errIfMismatch) +
+            ", expecting error=" + wtu.glEnumToString(gl, errIfMismatch) +
             " for mismatching mask or func settings.");
 
     let rbo = null;
     let attachment;
     if (haveDepthBuffer || haveStencilBuffer) {
         rbo = gl.createRenderbuffer();
         gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
 
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
@@ -1,5 +1,6 @@
+--min-version 2.0.1 gl-bindAttribLocation-aliasing-inactive.html
 gl-vertex-attrib.html
 gl-vertex-attrib-i-render.html
 --min-version 2.0.1 gl-vertex-attrib-normalized-int.html
 gl-vertexattribipointer.html
 gl-vertexattribipointer-offsets.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html
@@ -0,0 +1,74 @@
+<!--
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/tests/gl-bindattriblocation-aliasing.js"></script>
+<title>bindAttribLocation with aliasing - inactive attributes</title>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<script id="vertexShaderStaticallyUsedButInactive" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+in $(type_1) a_1;
+in $(type_2) a_2;
+void main() {
+    gl_Position = true ? $(gl_Position_1) : $(gl_Position_2);
+}
+</script>
+<script id="vertexShaderUnused" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+in $(type_1) a_1;
+in $(type_2) a_2;
+void main() {
+    gl_Position = vec4(0.0);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies combinations of valid inactive attributes cannot be bound to the same location with bindAttribLocation. GLSL ES 3.00.6 section 12.46.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false}, 2);
+var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShaderESSL300, gl.FRAGMENT_SHADER);
+
+debug("Testing with shader that has statically used but inactive attributes.");
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShaderStaticallyUsedButInactive'));
+
+debug("");
+debug("Testing with shader that has entirely unused attributes.");
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShaderUnused'));
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
@@ -29,16 +29,17 @@ shader-linking.html
 shader-with-1024-character-define.html
 shader-with-1024-character-identifier.frag.html
 shader-with-1025-character-define.html
 shader-with-1025-character-identifier.frag.html
 shader-with-invalid-characters.html
 shader-with-mis-matching-uniform-block.html
 short-circuiting-in-loop-condition.html
 --min-version 2.0.1 switch-case.html
+--min-version 2.0.1 texture-offset-non-constant-offset.html
 texture-offset-out-of-range.html
 --min-version 2.0.1 texture-offset-uniform-texture-coordinate.html
 --min-version 2.0.1 tricky-loop-conditions.html
 --min-version 2.0.1 unary-minus-operator-in-dynamic-loop.html
 uniform-block-layouts.html
 uniform-block-layout-match.html
 uniform-location-length-limits.html
 --min-version 2.0.1 uniform-struct-with-non-square-matrix.html
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
@@ -197,16 +197,39 @@ void main()
     switch(u_zero)
     {
         case 0:
             ;
     }
     my_FragColor = vec4(0, 1, 0, 1);
 }
 </script>
+<script id="fshaderCaseInsideBlock" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+    // Case statements must not be nested in blocks.
+    // GLSL ES 3.00 spec is a bit vague on this but GLSL ES 3.10 section 6.2 is clearer.
+    switch(u_zero)
+    {
+        case 1:
+        {
+            case 0:
+                my_FragColor = vec4(1, 0, 0, 1);
+        }
+    }
+    my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
 <script type="application/javascript">
 "use strict";
 description();
 
 // Covers bugs:
 // http://anglebug.com/2177
 // http://anglebug.com/2178
 // http://anglebug.com/2179
@@ -257,14 +280,19 @@ GLSLConformanceTester.runTests([
   linkSuccess: true,
   passMsg: 'Constant statement should count as a statement for the purposes of switch statement validation.'
 },
 {
   fShaderId: 'fshaderLastCaseHasEmptyStatement',
   fShaderSuccess: true,
   linkSuccess: true,
   passMsg: 'Empty statement should count as a statement for the purposes of switch statement validation.'
+},
+{
+  fShaderId: 'fshaderCaseInsideBlock',
+  fShaderSuccess: false,
+  passMsg: 'Case statements must not be nested inside blocks.'
 }
 ], 2);
 </script>
 </body>
 </html>
 
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html
@@ -0,0 +1,191 @@
+<!--
+
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL texture offset with non-constant offset test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+<script src="../../js/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderTextureOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = textureOffset(u_sampler, u_texCoord, offset);
+}
+</script>
+<script id="fshaderTextureProjOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = textureProjOffset(u_sampler, u_texCoord, offset);
+}
+</script>
+<script id="fshaderTextureLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform float u_lod;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = textureLodOffset(u_sampler, u_texCoord, u_lod, offset);
+}
+</script>
+<script id="fshaderTextureProjLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform float u_lod;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = textureProjLodOffset(u_sampler, u_texCoord, u_lod, offset);
+}
+</script>
+<script id="fshaderTextureGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = textureGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, offset);
+}
+</script>
+<script id="fshaderTextureProjGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = textureProjGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, offset);
+}
+</script>
+<script id="fshaderTexelFetchOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_lod;
+
+void main() {
+    ivec2 offset = ivec2(0);
+    my_FragColor = texelFetchOffset(u_sampler, ivec2(u_texCoord), int(u_lod), offset);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("A non-constant offset is not valid in texture offset functions.");
+
+var wtu = WebGLTestUtils;
+
+var shaderTextureOffsetSrc = wtu.getScript('fshaderTextureOffset');
+var shaderTextureLodOffsetSrc = wtu.getScript('fshaderTextureLodOffset');
+var shaderTextureGradOffsetSrc = wtu.getScript('fshaderTextureGradOffset');
+var shaderTextureProjOffsetSrc = wtu.getScript('fshaderTextureProjOffset');
+var shaderTextureProjLodOffsetSrc = wtu.getScript('fshaderTextureProjLodOffset');
+var shaderTextureProjGradOffsetSrc = wtu.getScript('fshaderTextureProjGradOffset');
+var shaderTexelFetchOffsetSrc = wtu.getScript('fshaderTexelFetchOffset');
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+if (!gl) {
+    testFailed("Unable to initialize WebGL 2.0 context.");
+} else {
+    GLSLConformanceTester.runTests([
+    {
+        fShaderSource: shaderTextureOffsetSrc,
+        fShaderSuccess: false,
+        passMsg: 'textureOffset with non-constant offset is invalid'
+    },
+    {
+        fShaderSource: shaderTextureLodOffsetSrc,
+        fShaderSuccess: false,
+        passMsg: 'textureLodOffset with non-constant offset is invalid'
+    },
+    {
+        fShaderSource: shaderTextureGradOffsetSrc,
+        fShaderSuccess: false,
+        passMsg: 'textureGradOffset with non-constant offset is invalid'
+    },
+    {
+        fShaderSource: shaderTextureProjOffsetSrc,
+        fShaderSuccess: false,
+        passMsg: 'textureProjOffset with non-constant offset is invalid'
+    },
+    {
+        fShaderSource: shaderTextureProjLodOffsetSrc,
+        fShaderSuccess: false,
+         passMsg: 'textureProjLodOffset with non-constant offset is invalid'
+    },
+    {
+        fShaderSource: shaderTextureProjGradOffsetSrc,
+        fShaderSuccess: false,
+        passMsg: 'textureProjGradOffset with non-constant offset is invalid'
+    },
+    {
+        fShaderSource: shaderTexelFetchOffsetSrc,
+        fShaderSuccess: false,
+        passMsg: 'texelFetchOffset with non-constant offset is invalid'
+    }
+    ], 2);
+}
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html
@@ -0,0 +1,181 @@
+<!--
+
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test clearBuffer with drawing</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+</head>
+<body onload="runTest()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<script>
+"use strict";
+description("This tests the operation of clearBuffer followed by a draw call.");
+
+debug("Verifies that these combined with preserveDrawingBuffer's implicit clears work properly together.");
+debug("Regression test for <a href='http://crbug.com/828262'>Chromium bug 828262</a>.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl;
+var testIndex = 0;
+var iterations = 0;
+var maxIterations = 10;
+var prog;
+var tests;
+var blackUint8 = [0, 0, 0, 255];
+var redFloat = [1.0, 0.0, 0.0, 0.0];
+var redUint8 = [255, 0, 0, 255];
+var greenFloat = [0.0, 1.0, 0.0, 0.0];
+var greenUint8 = [0, 255, 0, 255];
+
+function verifyOnePixel(kind, x, y, readFormat, readType, arrayType, expectedColor) {
+  var buffer = new arrayType(4);
+  gl.readPixels(Math.floor(x), Math.floor(y), 1, 1, readFormat, readType, buffer);
+  if (buffer[0] == expectedColor[0] &&
+      buffer[1] == expectedColor[1] &&
+      buffer[2] == expectedColor[2] &&
+      buffer[3] == expectedColor[3]) {
+    testPassed(kind + " succeeded");
+  } else {
+    testFailed(kind + " failed. Expected: " + expectedColor + ", got: " + buffer);
+  }
+}
+
+function testClearBufferAndDraw(test) {
+  test['clear']();
+  wtu.setFloatDrawColor(gl, greenFloat);
+  wtu.drawUnitQuad(gl);
+  // Back buffer has no alpha channel.
+  let readFormat = gl.RGBA;
+  let readType = gl.UNSIGNED_BYTE;
+  verifyOnePixel("Clearing", 0, 0, readFormat, readType, Uint8Array, test['bgColor']);
+  verifyOnePixel("Drawing", canvas.width / 2, canvas.height / 2,
+                 readFormat, readType, Uint8Array, test['drawColor']);
+}
+
+function runNextTest() {
+  if (testIndex >= tests.length) {
+    finishTest();
+    return;
+  }
+
+
+  let test = tests[testIndex];
+  if (iterations == 0) {
+    debug('');
+    debug('Testing: ' + test['desc'])
+  }
+  testClearBufferAndDraw(test);
+
+  if (++iterations == maxIterations) {
+    iterations = 0;
+    ++testIndex;
+  }
+
+  wtu.waitForComposite(runNextTest);
+}
+
+function runTest() {
+  gl = wtu.create3DContext(canvas, { alpha:false }, 2);
+
+  if (!gl) {
+    testFailed("context does not exist");
+    return;
+  } else {
+    testPassed("context exists");
+  }
+
+  prog = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
+
+  tests = [
+    {
+      desc: 'Implicit clear',
+      clear: function() {},
+      bgColor: blackUint8,
+      // The implicit clear clears depth to 1.0, and since the quad is
+      // drawn at a depth of 0.0, it's always discarded.
+      drawColor: blackUint8,
+    },
+    {
+      desc: 'clearBufferfi only',
+      clear: function() {
+        gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 0);
+      },
+      bgColor: blackUint8,
+      drawColor: greenUint8,
+    },
+    {
+      desc: 'clearBufferfv and clear',
+      clear: function() {
+        gl.clearBufferfv(gl.COLOR, 0, redFloat),
+        gl.clearDepth(0.0);
+        gl.clear(gl.DEPTH_BUFFER_BIT);
+      },
+      bgColor: redUint8,
+      drawColor: greenUint8,
+    },
+    {
+      desc: 'clearBuffer{fv} and {fi}',
+      clear: function() {
+        gl.clearBufferfv(gl.COLOR, 0, redFloat),
+        gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 0);
+      },
+      bgColor: redUint8,
+      drawColor: greenUint8,
+    },
+  ];
+
+  // Clear canvas to something other than black to start.
+  gl.clearColor(0.0, 0.0, 1.0, 1.0);
+  gl.clear(gl.COLOR_BUFFER_BIT);
+
+  gl.enable(gl.DEPTH_TEST);
+  // Unreal Engine's depth test is reversed from the
+  // default. Including the clear of the depth buffer in this test
+  // case highlights the rendering error more clearly, since neither
+  // the background nor any rendered object show up.
+  gl.depthFunc(gl.GEQUAL);
+
+  // Must run in a requestAnimationFrame loop to provoke implicit
+  // clears of the canvas.
+  wtu.waitForComposite(runNextTest);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
@@ -43,16 +43,17 @@
 description("This test checks WebGL2 specific sync object behaviors");
 
 debug("");
 debug("Canvas.getContext");
 
 var wtu = WebGLTestUtils;
 var gl = wtu.create3DContext("canvas", null, 2);
 var sync = null;
+var pixel = new Uint8Array(4);
 
 if (!gl) {
   testFailed("context does not exist");
   finishTest();
 } else {
   testPassed("context exists");
 
   debug("");
@@ -77,102 +78,100 @@ if (!gl) {
   gl.clientWaitSync(sync, 0, max);
   shouldBe("gl.getError()", "gl.NO_ERROR");
   gl.clientWaitSync(sync, 0, max + 1);
   shouldBe("gl.getError()", "gl.INVALID_OPERATION");
 
   requestAnimationFrame(runGetSyncParameterTest);
 }
 
-var signaling_retry_ms = 1000;
+var numRetries = 20000;
+var iteration = 0;
+
+function syncWithGLServer() {
+  gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+}
 
 function runGetSyncParameterTest() {
   debug("");
   debug("Verifying sync object isn't signaled too early");
   sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
   // Verify as best as possible that the implementation doesn't allow a sync
   // object to become signaled until returning control to the event loop, by
   // spin-looping for some time.
-  var startTime = Date.now();
-  while (Date.now() - startTime < signaling_retry_ms) {
-    gl.flush();
-    gl.finish();
+  var iter = numRetries;
+  while (--iter > 0) {
+    syncWithGLServer();
     if (gl.getSyncParameter(sync, gl.SYNC_STATUS) == gl.SYNC_SIGNALED) {
       testFailed("Sync object was signaled too early");
       finishTest();
       return;
     }
   }
   testPassed("Sync object wasn't signaled too early");
-  startTimeOfFinish = Date.now();
+  iteration = numRetries;
   requestAnimationFrame(finishSyncParameterTest);
 }
 
-var startTimeOfFinish = 0;
 
 function finishSyncParameterTest() {
-  if (startTimeOfFinish == 0) {
-    startTimeOfFinish = Date.now();
-  }
-  if (Date.now() - startTimeOfFinish > signaling_retry_ms) {
-    testFailed("Sync object wasn't signaled in a reasonable timeframe (" + (Date.now() - startTimeOfFinish) + " ms)");
+  if (--iteration == 0) {
+    testFailed("Sync object wasn't signaled in a reasonable timeframe (" + numRetries + " iterations)");
     finishTest();
     return;
   }
   var res = gl.getSyncParameter(sync, gl.SYNC_STATUS);
   if (res == gl.SIGNALED) {
     testPassed("Sync object was signaled");
     requestAnimationFrame(runClientWaitSyncTest);
     return;
   }
   // Try again.
+  syncWithGLServer();
   requestAnimationFrame(finishSyncParameterTest);
 }
 
 function runClientWaitSyncTest() {
   debug("");
   debug("Verifying clientWaitSync doesn't complete too early");
 
   sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
   // Verify as best as possible that the implementation doesn't allow
   // clientWaitSync to return CONDITION_SATISFIED or ALREADY_SIGNALED until
   // returning control to the event loop, by spin-looping for some time.
-  var startTime = Date.now();
-  while (Date.now() - startTime < signaling_retry_ms) {
-    gl.flush();
-    gl.finish();
+  var iter = numRetries;
+  while (--iter > 0) {
+    syncWithGLServer();
     var res = gl.clientWaitSync(sync, 0, 0);
     if (res == gl.CONDITION_SATISFIED || res == gl.ALREADY_SIGNALED) {
       testFailed("clientWaitSync completed successfully too early");
       finishTest();
       return;
     }
   }
   testPassed("clientWaitSync didn't complete successfully too early");
-  startTimeOfFinish = 0;
+  iteration = numRetries;
   requestAnimationFrame(finishClientWaitSyncTest);
 }
 
 function finishClientWaitSyncTest() {
-  if (startTimeOfFinish == 0) {
-    startTimeOfFinish = Date.now();
-  }
-  if (Date.now() - startTimeOfFinish > signaling_retry_ms) {
-    testFailed("clientWaitSync didn't complete in a reasonable timeframe");
+  if (--iteration == 0) {
+    testFailed("clientWaitSync didn't complete in a reasonable timeframe (" + numRetries + " iterations)");
     finishTest();
     return;
   }
   var res = gl.clientWaitSync(sync, 0, 0);
   if (res == gl.CONDITION_SATISFIED || res == gl.ALREADY_SIGNALED) {
     testPassed("clientWaitSync completed successfully");
     // This is the last test right now.
     finishTest();
     return;
   }
   // Try again.
+  syncWithGLServer();
   requestAnimationFrame(finishClientWaitSyncTest);
 }
 
 debug("");
 var successfullyParsed = true;
 </script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js
@@ -0,0 +1,61 @@
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+"use strict";
+
+var runBindAttribLocationAliasingTest = function(wtu, gl, glFragmentShader, vertexShaderTemplate) {
+    var typeInfo = [
+        { type: 'float',    asVec4: 'vec4(0.0, $(var), 0.0, 1.0)' },
+        { type: 'vec2',     asVec4: 'vec4($(var), 0.0, 1.0)' },
+        { type: 'vec3',     asVec4: 'vec4($(var), 1.0)' },
+        { type: 'vec4',     asVec4: '$(var)' },
+    ];
+    var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+    // Test all type combinations of a_1 and a_2.
+    typeInfo.forEach(function(typeInfo1) {
+        typeInfo.forEach(function(typeInfo2) {
+            debug('attribute_1: ' + typeInfo1.type + ' attribute_2: ' + typeInfo2.type);
+            var replaceParams = {
+                type_1: typeInfo1.type,
+                type_2: typeInfo2.type,
+                gl_Position_1: wtu.replaceParams(typeInfo1.asVec4, {var: 'a_1'}),
+                gl_Position_2: wtu.replaceParams(typeInfo2.asVec4, {var: 'a_2'})
+            };
+            var strVertexShader = wtu.replaceParams(vertexShaderTemplate, replaceParams);
+            var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
+            assertMsg(glVertexShader != null, "Vertex shader compiled successfully.");
+            // Bind both a_1 and a_2 to the same position and verify the link fails.
+            // Do so for all valid positions available.
+            for (var l = 0; l < maxAttributes; l++) {
+                var glProgram = gl.createProgram();
+                gl.bindAttribLocation(glProgram, l, 'a_1');
+                gl.bindAttribLocation(glProgram, l, 'a_2');
+                gl.attachShader(glProgram, glVertexShader);
+                gl.attachShader(glProgram, glFragmentShader);
+                gl.linkProgram(glProgram);
+                var linkStatus = gl.getProgramParameter(glProgram, gl.LINK_STATUS);
+                assertMsg(!linkStatus, "Link should fail when both attributes are aliased to location " + l);
+            }
+        });
+    });
+};
\ No newline at end of file
--- a/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
+++ b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
@@ -52,16 +52,20 @@ var loggingOff = function() {
 
 /**
  * Converts a WebGL enum to a string.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {number} value The enum value.
  * @return {string} The enum as a string.
  */
 var glEnumToString = function(gl, value) {
+  // Avoid returning "NO_ERROR" if the arguments are totally wrong.
+  if (gl.NO_ERROR === undefined || value === undefined) {
+    return undefined;
+  }
   // Optimization for the most common enum:
   if (value === gl.NO_ERROR) {
     return "NO_ERROR";
   }
   for (var p in gl) {
     if (gl[p] == value) {
       if (p == 'drawingBufferWidth' || p == 'drawingBufferHeight') {
         continue;
@@ -186,16 +190,29 @@ var simpleVertexShader = [
 var simpleColorFragmentShader = [
   'precision mediump float;',
   'uniform vec4 u_color;',
   'void main() {',
   '    gl_FragData[0] = u_color;',
   '}'].join('\n');
 
 /**
+ * A fragment shader for a uniform color.
+ * @type {string}
+ */
+var simpleColorFragmentShaderESSL300 = [
+  '#version 300 es',
+  'precision mediump float;',
+  'out vec4 out_color;',
+  'uniform vec4 u_color;',
+  'void main() {',
+  '    out_color = u_color;',
+  '}'].join('\n');
+
+/**
  * A vertex shader for vertex colors.
  * @type {string}
  */
 var simpleVertexColorVertexShader = [
   'attribute vec4 vPosition;',
   'attribute vec4 a_color;',
   'varying vec4 v_color;',
   'void main() {',
@@ -436,53 +453,62 @@ var setupSimpleColorProgram = function(g
                       [opt_positionLocation]);
 };
 
 /**
  * Creates buffers for a textured unit quad and attaches them to vertex attribs.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {number} opt_positionLocation The attrib location for position.
  * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @param {!Object} various options. See setupQuad for details.
  * @return {!Array.<WebGLBuffer>} The buffer objects that were
  *      created.
  */
-var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation) {
-  return setupUnitQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
-                                    opt_positionLocation, opt_texcoordLocation);
+var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation, options) {
+  return setupQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
+                                opt_positionLocation, opt_texcoordLocation,
+                                options);
 };
 
 /**
- * Creates buffers for a textured unit quad with specified lower left
+ * Creates buffers for a textured quad with specified lower left
  * and upper right texture coordinates, and attaches them to vertex
  * attribs.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
  * @param {!Array.<number>} upperRightTexCoords The texture coordinates for the upper right corner.
  * @param {number} opt_positionLocation The attrib location for position.
  * @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @param {!Object} various options. See setupQuad for details.
  * @return {!Array.<WebGLBuffer>} The buffer objects that were
  *      created.
  */
-var setupUnitQuadWithTexCoords = function(
+var setupQuadWithTexCoords = function(
     gl, lowerLeftTexCoords, upperRightTexCoords,
-    opt_positionLocation, opt_texcoordLocation) {
-  return setupQuad(gl, {
+    opt_positionLocation, opt_texcoordLocation, options) {
+  var defaultOptions = {
     positionLocation: opt_positionLocation || 0,
     texcoordLocation: opt_texcoordLocation || 1,
     lowerLeftTexCoords: lowerLeftTexCoords,
     upperRightTexCoords: upperRightTexCoords
-  });
+  };
+  if (options) {
+    for (var prop in options) {
+      defaultOptions[prop] = options[prop]
+    }
+  }
+  return setupQuad(gl, defaultOptions);
 };
 
 /**
  * Makes a quad with various options.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {!Object} options
  *
- * scale: scale to multiple unit quad values by. default 1.0.
+ * scale: scale to multiply unit quad values by. default 1.0.
  * positionLocation: attribute location for position.
  * texcoordLocation: attribute location for texcoords.
  *     If this does not exist no texture coords are created.
  * lowerLeftTexCoords: an array of 2 values for the
  *     lowerLeftTexCoords.
  * upperRightTexCoords: an array of 2 values for the
  *     upperRightTexCoords.
  */
@@ -530,36 +556,38 @@ var setupQuad = function(gl, options) {
 
 /**
  * Creates a program and buffers for rendering a textured quad.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {number} opt_positionLocation The attrib location for
  *        position. Default = 0.
  * @param {number} opt_texcoordLocation The attrib location for
  *        texture coords. Default = 1.
+ * @param {!Object} various options. See setupQuad for details.
  * @return {!WebGLProgram}
  */
 var setupTexturedQuad = function(
-    gl, opt_positionLocation, opt_texcoordLocation) {
+    gl, opt_positionLocation, opt_texcoordLocation, options) {
   var program = setupSimpleTextureProgram(
       gl, opt_positionLocation, opt_texcoordLocation);
-  setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+  setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation, options);
   return program;
 };
 
 /**
  * Creates a program and buffers for rendering a color quad.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {number} opt_positionLocation The attrib location for position.
+ * @param {!Object} various options. See setupQuad for details.
  * @return {!WebGLProgram}
  */
-var setupColorQuad = function(gl, opt_positionLocation) {
+var setupColorQuad = function(gl, opt_positionLocation, options) {
   opt_positionLocation = opt_positionLocation || 0;
   var program = setupSimpleColorProgram(gl, opt_positionLocation);
-  setupUnitQuad(gl, opt_positionLocation);
+  setupUnitQuad(gl, opt_positionLocation, 0, options);
   return program;
 };
 
 /**
  * Creates a program and buffers for rendering a textured quad with
  * specified lower left and upper right texture coordinates.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
@@ -568,18 +596,18 @@ var setupColorQuad = function(gl, opt_po
  * @param {number} opt_texcoordLocation The attrib location for texture coords.
  * @return {!WebGLProgram}
  */
 var setupTexturedQuadWithTexCoords = function(
     gl, lowerLeftTexCoords, upperRightTexCoords,
     opt_positionLocation, opt_texcoordLocation) {
   var program = setupSimpleTextureProgram(
       gl, opt_positionLocation, opt_texcoordLocation);
-  setupUnitQuadWithTexCoords(gl, lowerLeftTexCoords, upperRightTexCoords,
-                             opt_positionLocation, opt_texcoordLocation);
+  setupQuadWithTexCoords(gl, lowerLeftTexCoords, upperRightTexCoords,
+                         opt_positionLocation, opt_texcoordLocation);
   return program;
 };
 
 /**
  * Creates a program and buffers for rendering a textured quad with
  * a cube map texture.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {number} opt_positionLocation The attrib location for
@@ -587,17 +615,17 @@ var setupTexturedQuadWithTexCoords = fun
  * @param {number} opt_texcoordLocation The attrib location for
  *        texture coords. Default = 1.
  * @return {!WebGLProgram}
  */
 var setupTexturedQuadWithCubeMap = function(
     gl, opt_positionLocation, opt_texcoordLocation) {
   var program = setupSimpleCubeMapTextureProgram(
       gl, opt_positionLocation, opt_texcoordLocation);
-  setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+  setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation, undefined);
   return program;
 };
 
 /**
  * Creates a unit quad with only positions of a given resolution.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {number} gridRes The resolution of the mesh grid,
  *     expressed in the number of quads across and down.
@@ -948,23 +976,26 @@ var drawUByteColorQuad = function(gl, co
 /**
  * Draws a previously setupUnitQuad.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  */
 var drawUnitQuad = function(gl) {
   gl.drawArrays(gl.TRIANGLES, 0, 6);
 };
 
-var noopProgram = null;
+var dummyProgram = null;
 var dummySetProgramAndDrawNothing = function(gl) {
-  if (!noopProgram) {
-    noopProgram = setupProgram(gl, ["void main() {}", "void main() {}"], [], []);
+  if (!dummyProgram) {
+    dummyProgram = setupProgram(gl, [
+      "void main() { gl_Position = vec4(0.0); }",
+      "void main() { gl_FragColor = vec4(0.0); }"
+    ], [], []);
   }
-  gl.useProgram(noopProgram);
-  gl.drawArrays(gl.TRIANGLES, 0, 0);
+  gl.useProgram(dummyProgram);
+  gl.drawArrays(gl.TRIANGLES, 0, 3);
 };
 
 /**
  * Clears then Draws a previously setupUnitQuad.
  * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
  * @param {!Array.<number>} opt_color The color to fill clear with before
  *        drawing. A 4 element array where each element is in the range 0 to
  *        255. Default [255, 255, 255, 255]
@@ -1886,21 +1917,16 @@ var loadShader = function(
   var shader = gl.createShader(shaderType);
   if (shader == null) {
     errFn("*** Error: unable to create shader '"+shaderSource+"'");
     return null;
   }
 
   // Load the shader source
   gl.shaderSource(shader, shaderSource);
-  var err = gl.getError();
-  if (err != gl.NO_ERROR) {
-    errFn("*** Error loading shader '" + shader + "':" + glEnumToString(gl, err));
-    return null;
-  }
 
   // Compile the shader
   gl.compileShader(shader);
 
   if (opt_logShaders) {
     var label = shaderType == gl.VERTEX_SHADER ? 'vertex shader' : 'fragment_shader';
     if (opt_shaderLabel) {
       label = opt_shaderLabel + ' ' + label;
@@ -3171,28 +3197,28 @@ var API = {
   makeVideo: makeVideo,
   error: error,
   shallowCopyObject: shallowCopyObject,
   setDefault3DContextVersion: setDefault3DContextVersion,
   setupColorQuad: setupColorQuad,
   setupProgram: setupProgram,
   setupTransformFeedbackProgram: setupTransformFeedbackProgram,
   setupQuad: setupQuad,
+  setupQuadWithTexCoords: setupQuadWithTexCoords,
   setupIndexedQuad: setupIndexedQuad,
   setupIndexedQuadWithOptions: setupIndexedQuadWithOptions,
   setupSimpleColorProgram: setupSimpleColorProgram,
   setupSimpleTextureProgram: setupSimpleTextureProgram,
   setupSimpleCubeMapTextureProgram: setupSimpleCubeMapTextureProgram,
   setupSimpleVertexColorProgram: setupSimpleVertexColorProgram,
   setupNoTexCoordTextureProgram: setupNoTexCoordTextureProgram,
   setupTexturedQuad: setupTexturedQuad,
   setupTexturedQuadWithTexCoords: setupTexturedQuadWithTexCoords,
   setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
   setupUnitQuad: setupUnitQuad,
-  setupUnitQuadWithTexCoords: setupUnitQuadWithTexCoords,
   setFloatDrawColor: setFloatDrawColor,
   setUByteDrawColor: setUByteDrawColor,
   startPlayingAndWaitForVideo: startPlayingAndWaitForVideo,
   startsWith: startsWith,
   shouldGenerateGLError: shouldGenerateGLError,
   readFile: readFile,
   readFileList: readFileList,
   replaceParams: replaceParams,
@@ -3216,16 +3242,17 @@ var API = {
 
   none: false
 };
 
 Object.defineProperties(API, {
   noTexCoordTextureVertexShader: { value: noTexCoordTextureVertexShader, writable: false },
   simpleTextureVertexShader: { value: simpleTextureVertexShader, writable: false },
   simpleColorFragmentShader: { value: simpleColorFragmentShader, writable: false },
+  simpleColorFragmentShaderESSL300: { value: simpleColorFragmentShaderESSL300, writable: false },
   simpleVertexShader: { value: simpleVertexShader, writable: false },
   simpleTextureFragmentShader: { value: simpleTextureFragmentShader, writable: false },
   simpleCubeMapTextureFragmentShader: { value: simpleCubeMapTextureFragmentShader, writable: false },
   simpleVertexColorFragmentShader: { value: simpleVertexColorFragmentShader, writable: false },
   simpleVertexColorVertexShader: { value: simpleVertexColorVertexShader, writable: false }
 });
 
 return API;
--- a/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
+++ b/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
@@ -236,17 +236,17 @@ function start() {
     this.folder = folder;
     this.url = url;
     this.totalTests = 0;
     this.totalSuccessful = 0;
     this.totalTimeouts = 0;
     this.totalSkipped = 0;
     this.totalFailed = 0;
     this.testIndex = testIndex;
-    this.startTime = 0;
+    this.startTime = new Date();
     this.totalTime = 0;
     var that = this;
 
     this.elementId = "page" + pageCount++;
     var li = reporter.localDoc.createElement('li');
     li.id = this.elementId;
     var div = reporter.localDoc.createElement('div');
     div.classList.add('pageHeader');
@@ -300,25 +300,27 @@ function start() {
 
   Page.prototype.addResult = function(msg, success, skipped) {
     ++this.totalTests;
     if (success === undefined) {
       ++this.totalTimeouts;
       var result = "timeout";
       var css = "timeout";
     } else if (success) {
-      if(skipped) {
-        ++this.totalSkipped;
-      } else {
-        ++this.totalSuccessful;
-      }
+      ++this.totalSuccessful;
       // don't report success.
       return;
     } else {
       ++this.totalFailed;
+      if (skipped) {
+        // Skipped tests are counted as both skips and failures (because we
+        // don't want to accidentally accept a conformance submission with
+        // skipped tests).
+        ++this.totalSkipped;
+      }
       var result = "failed";
       var css = "fail";
     }
 
     var node = this.reporter.localDoc.createTextNode(result + ': ' + msg);
     var li = this.reporter.localDoc.createElement('li');
     li.appendChild(node);
     li.setAttribute('class', css);
@@ -406,16 +408,28 @@ function start() {
   };
 
   Page.prototype.disableTest = function(re) {
     if (this.url.match(re)) {
       this.check.checked = false;
     }
   };
 
+  Page.prototype.toJSON = function() {
+    return {
+      'subtests': this.totalTests,
+      'successful': this.totalSuccessful,
+      'skipped': this.totalSkipped,
+      'failed': this.totalFailed,
+      'timedOut': this.totalTimeouts,
+      'totalTime': this.totalTime,
+    };
+  };
+
+
   var Folder = function(reporter, folder, depth, opt_name) {
     this.reporter = reporter;
     this.depth = depth;
     this.name = opt_name || "";
     this.displayName = this.name;
     if (folder && folder.displayName) {
       this.displayName = folder.displayName + '/' + this.displayName;
     }
@@ -723,17 +737,17 @@ function start() {
     }
 
     this.noWebGL = !ctx;
 
     this.contextInfo = {};
     this.root = new Folder(this, null, 0, "all");
     this.resultElem.appendChild(this.root.elem);
     this.callbacks = { };
-    this.startTime = 0;
+    this.startTime = new Date();
 
     if (ctx) {
       this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR);
       this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION);
       this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER);
       this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS);
       this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS);
       this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS);
@@ -810,103 +824,149 @@ function start() {
       xhr.open('POST', "/finishIndividualTest", true);
       xhr.send(null);
     }
   };
 
   Reporter.prototype.displayFinalResults = function(msg, success) {
     if (success) {
       var totalTests = 0;
-      var totalSuccessful = 0;
-      var totalTimeouts = 0;
-      var totalSkipped = 0;
-      var totalFailed = 0;
+      var testsSucceeded = 0;
+      var testsFailed = 0;
+      var testsSkipped = 0;
+      var testsTimedOut = 0;
+
+      var subtestsHit = 0;
+      var subtestsSucceeded = 0;
+      var subtestsTimedOut = 0;
+      var subtestsSkipped = 0;
+      var subtestsFailed = 0;
+
       var totalTime = Date.now() - this.startTime;
+
       for (var url in this.pagesByURL) {
         var page = this.pagesByURL[url];
-        totalTests += page.totalTests;
-        totalSuccessful += page.totalSuccessful;
-        totalTimeouts += page.totalTimeouts;
-        totalSkipped += page.totalSkipped;
-        totalFailed += page.totalFailed;
+        totalTests += 1;
+        if (page.totalSkipped) {
+          testsSkipped += 1;
+        }
+        if (page.totalFailed) {
+          testsFailed += 1;
+        } else if (page.totalTimeouts) {
+          testsTimedOut += 1;
+        } else if (page.totalSuccessful) {
+          if (page.totalSuccessful != page.totalTests)
+            throw successes_not_equal_total;
+          testsSucceeded += 1;
+        }
+
+        subtestsHit += page.totalTests;
+        subtestsSucceeded += page.totalSuccessful;
+        subtestsTimedOut += page.totalTimeouts;
+        subtestsSkipped += page.totalSkipped;
+        subtestsFailed += page.totalFailed;
       }
-      var passedMsg = 'Passed ' + totalSuccessful + '/' + totalTests + ' (' + (totalSuccessful * 100.0 / totalTests).toFixed(2) + '%)';
-      var timeout = '';
-      if (totalTimeouts > 0) {
-        timeout = ', ' + totalTimeouts + ' timed out';
+
+      function ratio_str(x, y, name) {
+        return x + '/' + y + ' ' + name + ' (' + (x / y * 100).toFixed(2) + '%)';
       }
+      var testsSucceededRatio = ratio_str(testsSucceeded, totalTests, 'tests');
+      var passedMsg = 'Passed ' + testsSucceededRatio + ', ' +
+                      ratio_str(subtestsSucceeded, subtestsHit, 'subtests');
       var skippedMsg = '';
-      if (totalSkipped > 0) {
-        skippedMsg = ' Skipped ' + totalSkipped + '/' + totalTests + ' (' + (totalSkipped * 100.0 / totalTests).toFixed(2) + '%)';
+      if (testsSkipped > 0) {
+        skippedMsg = ' Skipped ' + ratio_str(testsSkipped, totalTests, 'tests');
       }
       var failedMsg = '';
-      if (totalFailed > 0) {
-        failedMsg = ' Failed ' + totalFailed + '/' + totalTests + ' (' + (totalFailed * 100.0 / totalTests).toFixed(2) + '%)';
+      if (testsFailed > 0) {
+        failedMsg = ' Failed ' + ratio_str(testsFailed, totalTests, 'tests') + ', ' +
+                    ratio_str(subtestsFailed, subtestsHit, 'subtests');
       }
       var timeoutMsg = '';
-      if (totalTimeouts > 0) {
-        timeoutMsg = ' Timeout ' + totalTimeouts + '/' + totalTests + ' (' + (totalTimeouts * 100.0 / totalTests).toFixed(2) + '%)';
+      if (testsTimedOut > 0) {
+        timeoutMsg = ' Timeout ' + ratio_str(testsTimedOut, totalTests, 'tests');
       }
       var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg;
       this.fullResultsNode.textContent = msg;
 
       // generate a text summary
       var tx = "";
       tx += "WebGL Conformance Test Results\n";
       tx += "Version " + OPTIONS.version + "\n";
+      tx += "Generated on: " + (new Date()).toString() + "\n";
       tx += "\n";
       tx += "-------------------\n\n";
       tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n";
       tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n";
       tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n";
       tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n";
       tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n";
       tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n";
       tx += "WebGL R/G/B/A/Depth/Stencil bits (default config): " + this.contextInfo["RED_BITS"] + "/" + this.contextInfo["GREEN_BITS"] + "/" + this.contextInfo["BLUE_BITS"] + "/" + this.contextInfo["ALPHA_BITS"] + "/" + this.contextInfo["DEPTH_BITS"] + "/" + this.contextInfo["STENCIL_BITS"] + "\n";
-      tx += "\n";
-      tx += "-------------------\n\n";
-      tx += "Test Summary (" + totalTests + " total tests):\n";
-      tx += "Tests ran in " + (totalTime / 1000.0).toFixed(2) + " seconds\n";
-      tx += "Tests PASSED: " + totalSuccessful + "\n";
-      tx += "Tests FAILED: " + (totalTests - totalSuccessful - totalSkipped) + "\n";
-      tx += "Tests TIMED OUT: " + totalTimeouts + "\n";
-      tx += "Tests SKIPPED: " + totalSkipped + "\n";
-      tx += "\n";
-      tx += "-------------------\n\n";
-      if (totalSuccessful < totalTests) {
-        tx += "Failures:\n\n";
-        for (var url in this.pagesByURL) {
-            var page = this.pagesByURL[url];
-            var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
-            if (!(page.totalTests == 0 && page.totalTimeouts == 0) &&
-                pageTotalFail > 0)
-            {
-            tx += url + ": " + pageTotalFail + " tests failed";
-            if (page.totalTimeouts)
-                tx += " (" + page.totalTimeouts + " timed out)";
-            tx += "\n";
-            }
-        }
+      tx += "\n-------------------\n\n";
+
+      var result;
+      if (totalTests && testsSucceeded == totalTests) {
+        result = 'PASS';
       } else {
-        tx += "All tests PASSED\n\n";
+        result = 'FAIL';
+      }
+      tx += "Test Summary: " + result + " (" + totalTests + " tests):\n";
+      tx += subtestsHit + " subtests ran in " + (totalTime / 1000.0).toFixed(2) + " seconds\n";
+      function record(what, tests, subtests) {
+        tx += what + ": " + tests + " tests, " + subtests + " subtests\n";
       }
-      tx += "\n";
-      tx += "-------------------\n\n";
-      tx += "Complete Test Results (total / pass / fail / timeout / skipped):\n\n";
+      record('PASSED', testsSucceeded, subtestsSucceeded);
+      record('NOT PASSED', totalTests - testsSucceeded, subtestsHit - subtestsSucceeded);
+
+      record('FAILED', testsFailed, subtestsFailed);
+      record('TIMED OUT', testsTimedOut, subtestsTimedOut);
+      record('SKIPPED', testsSkipped, subtestsSkipped);
+
+      tx += "\n-------------------\n\n";
+
+      const failureLines = [];
+      const timeoutLines = [];
+      const resultLines = [];
+
       for (var url in this.pagesByURL) {
         var page = this.pagesByURL[url];
-        var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
-        if (!(page.totalTests == 0 && page.totalTimeouts == 0)) {
-          tx += url + ": " + page.totalTests + " / " +
-              page.totalSuccessful + " / " + pageTotalFail + " / " + page.totalTimeouts + " / " + page.totalSkipped + "\n";
+        resultLines.push('    "' + url + '":' + JSON.stringify(page.toJSON()));
+
+        if (page.totalFailed) {
+          failureLines.push('    "' + url + '",');
+        }
+        if (page.totalTimeouts) {
+          timeoutLines.push('    "' + url + '",');
         }
       }
-      tx += "\n";
-      tx += "-------------------\n\n";
-      tx += "Generated on: " + (new Date()).toString() + "\n";
+
+      const lines = [].concat(
+        [
+          '{',
+          '  "failures": [',
+        ],
+        failureLines,
+        [
+          '  ],',
+          '  "timeouts": [',
+        ],
+        timeoutLines,
+        [
+          '  ],',
+          '  "results": {',
+        ],
+        resultLines,
+        [
+        '  },',
+        '}',
+        ]
+      );
+
+      tx += lines.join('\n');
 
       var r = document.getElementById("testResultsAsText");
       while (r.firstChild) r.removeChild(r.firstChild);
       r.appendChild(document.createTextNode(tx));
       document.getElementById("showTextSummary").style.visibility = "visible";
       document.getElementById("dlTextSummary").style.visibility = "visible";
 
       this.postResultsToServer(tx);
--- a/dom/canvas/test/webgl-conf/cherry_picks.txt
+++ b/dom/canvas/test/webgl-conf/cherry_picks.txt
@@ -1,10 +1,19 @@
+commit bce0801d759def1b8c75b049150049aaadc7a6ff
+Author: Jeff Gilbert <jdashg@gmail.com>
+Date:   Fri Apr 6 19:52:35 2018 -0700
+
+    wtu.loadShader's gl.shaderSource should be treated as infallible.
 
 Cherries picked
 ================================================================================
 Merge base
 
-commit e899c531173da8ba956df8de6dd74fb7d9b1fa9c
-Author: Patrick To <patrto@microsoft.com>
-Date:   Fri Mar 30 13:18:38 2018 -0700
+commit fefa32a950127f6e01a5cdd1536d639a949cd82b
+Author: Olli Etuaho <olli.etuaho@gmail.com>
+Date:   Fri Apr 6 20:00:43 2018 +0300
 
-    Add unpack flip y test for depth textures (#2609)
+    Add a test for having a case statement inside a block (#2630)
+    
+    This was not being validated correctly by ANGLE until recently, though
+    this would not cause issues if the native drivers were working
+    correctly.
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html?webglVersion=2'></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance2/glsl3/texture-offset-non-constant-offset.html?webglVersion=2'></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance__buffers__buffer-data-dynamic-delay.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance/buffers/buffer-data-dynamic-delay.html?webglVersion=2'></iframe>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_conformance__buffers__buffer-data-dynamic-delay.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'/>
+    <title>
+      Mochitest wrapper for WebGL Conformance Test Suite tests
+    </title>
+    <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+    <script src='/tests/SimpleTest/SimpleTest.js'></script>
+    <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+  </head>
+  <body>
+    <iframe src='../mochi-single.html?checkout/conformance/buffers/buffer-data-dynamic-delay.html'></iframe>
+  </body>
+</html>