tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

canvas-tests-utils.js (30012B)


      1 /*
      2 Copyright (c) 2019 The Khronos Group Inc.
      3 Use of this source code is governed by an MIT-style license that can be
      4 found in the LICENSE.txt file.
      5 */
      6 
      7 // Some variables that will be used in this file
      8 var canvas;
      9 var gl;
     10 var OES_vertex_array_object;
     11 var uniformLocation;
     12 var WEBGL_lose_context;
     13 var buffer;
     14 var framebuffer;
     15 var program;
     16 var renderbuffer;
     17 var shader;
     18 var texture;
     19 var arrayBuffer;
     20 var arrayBufferView;
     21 var vertexArrayObject;
     22 var imageData;
     23 var float32array;
     24 var int32array;
     25 
     26 var OES_texture_float;
     27 var new_WEBGL_lose_context;
     28 var allowRestore;
     29 var contextLostEventFired;
     30 var contextRestoredEventFired;
     31 var newExtension;
     32 
     33 function compareGLError(glError, evalStr) {
     34    var exception;
     35    try {
     36        eval(evalStr);
     37    } catch (e) {
     38        exception = e;
     39    }
     40    if (exception) {
     41        return false;
     42    } else {
     43        if (gl.getError() == glError)
     44            return true;
     45        return false;
     46    }
     47 }
     48 
     49 function contextCreation(contextType) {
     50    canvas = new OffscreenCanvas(10, 10);
     51    gl = canvas.getContext(contextType);
     52 
     53    if (contextType == 'webgl') {
     54        if (gl instanceof WebGLRenderingContext)
     55            return true;
     56        return false;
     57    } else if (contextType == 'webgl2') {
     58        if (gl instanceof WebGL2RenderingContext)
     59            return true;
     60        return false;
     61    } else {
     62        return false;
     63    }
     64 }
     65 
     66 function transferredOffscreenCanvasCreation(placeholder, width, height) {
     67  placeholder.width = width;
     68  placeholder.height = height;
     69  return placeholder.transferControlToOffscreen();
     70 }
     71 
     72 function assertWidthAndHeight(entity, entityName, width, height) {
     73 if (entity.width == width && entity.height == height) {
     74   testPassed("The width and height of " + entityName + " are correct.");
     75   return;
     76 }
     77 var errMsg = "";
     78 if (entity.width != width) {
     79   errMsg += "The width of " + entityName + " is " + entity.width + " while expected value is " + width + ". ";
     80 }
     81 if (entity.height != height) {
     82   errMsg += "The height of " + entityName + " is " + entity.height + " while expected value is " + height + ". ";
     83 }
     84 testFailed(errMsg);
     85 }
     86 
     87 var webgl1Methods = [
     88  "getContextAttributes",
     89  "activeTexture",
     90  "attachShader",
     91  "bindAttribLocation",
     92  "bindBuffer",
     93  "bindFramebuffer",
     94  "bindRenderbuffer",
     95  "bindTexture",
     96  "blendColor",
     97  "blendEquation",
     98  "blendEquationSeparate",
     99  "blendFunc",
    100  "blendFuncSeparate",
    101  "bufferData",
    102  "bufferSubData",
    103  "checkFramebufferStatus",
    104  "clear",
    105  "clearColor",
    106  "clearDepth",
    107  "clearStencil",
    108  "colorMask",
    109  "compileShader",
    110  "compressedTexImage2D",
    111  "compressedTexSubImage2D",
    112  "copyTexImage2D",
    113  "copyTexSubImage2D",
    114  "createBuffer",
    115  "createFramebuffer",
    116  "createProgram",
    117  "createRenderbuffer",
    118  "createShader",
    119  "createTexture",
    120  "cullFace",
    121  "deleteBuffer",
    122  "deleteFramebuffer",
    123  "deleteProgram",
    124  "deleteRenderbuffer",
    125  "deleteShader",
    126  "deleteTexture",
    127  "depthFunc",
    128  "depthMask",
    129  "depthRange",
    130  "detachShader",
    131  "disable",
    132  "disableVertexAttribArray",
    133  "drawArrays",
    134  "drawElements",
    135  "enable",
    136  "enableVertexAttribArray",
    137  "finish",
    138  "flush",
    139  "framebufferRenderbuffer",
    140  "framebufferTexture2D",
    141  "frontFace",
    142  "generateMipmap",
    143  "getActiveAttrib",
    144  "getActiveUniform",
    145  "getAttachedShaders",
    146  "getAttribLocation",
    147  "getParameter",
    148  "getBufferParameter",
    149  "getError",
    150  "getExtension",
    151  "getFramebufferAttachmentParameter",
    152  "getProgramParameter",
    153  "getProgramInfoLog",
    154  "getRenderbufferParameter",
    155  "getShaderParameter",
    156  "getShaderInfoLog",
    157  "getShaderPrecisionFormat",
    158  "getShaderSource",
    159  "getSupportedExtensions",
    160  "getTexParameter",
    161  "getUniform",
    162  "getUniformLocation",
    163  "getVertexAttrib",
    164  "getVertexAttribOffset",
    165  "hint",
    166  "isBuffer",
    167  "isContextLost",
    168  "isEnabled",
    169  "isFramebuffer",
    170  "isProgram",
    171  "isRenderbuffer",
    172  "isShader",
    173  "isTexture",
    174  "lineWidth",
    175  "linkProgram",
    176  "pixelStorei",
    177  "polygonOffset",
    178  "readPixels",
    179  "renderbufferStorage",
    180  "sampleCoverage",
    181  "scissor",
    182  "shaderSource",
    183  "stencilFunc",
    184  "stencilFuncSeparate",
    185  "stencilMask",
    186  "stencilMaskSeparate",
    187  "stencilOp",
    188  "stencilOpSeparate",
    189  "texImage2D",
    190  "texParameterf",
    191  "texParameteri",
    192  "texSubImage2D",
    193  "uniform1f",
    194  "uniform1fv",
    195  "uniform1i",
    196  "uniform1iv",
    197  "uniform2f",
    198  "uniform2fv",
    199  "uniform2i",
    200  "uniform2iv",
    201  "uniform3f",
    202  "uniform3fv",
    203  "uniform3i",
    204  "uniform3iv",
    205  "uniform4f",
    206  "uniform4fv",
    207  "uniform4i",
    208  "uniform4iv",
    209  "uniformMatrix2fv",
    210  "uniformMatrix3fv",
    211  "uniformMatrix4fv",
    212  "useProgram",
    213  "validateProgram",
    214  "vertexAttrib1f",
    215  "vertexAttrib1fv",
    216  "vertexAttrib2f",
    217  "vertexAttrib2fv",
    218  "vertexAttrib3f",
    219  "vertexAttrib3fv",
    220  "vertexAttrib4f",
    221  "vertexAttrib4fv",
    222  "vertexAttribPointer",
    223  "viewport",
    224 ];
    225 
    226 var webgl2Methods = [
    227  "getBufferSubData",
    228  "copyBufferSubData",
    229  "blitFramebuffer",
    230  "framebufferTextureLayer",
    231  "getInternalformatParameter",
    232  "invalidateFramebuffer",
    233  "invalidateSubFramebuffer",
    234  "readBuffer",
    235  "renderbufferStorageMultisample",
    236  "texImage3D",
    237  "texStorage2D",
    238  "texStorage3D",
    239  "texSubImage3D",
    240  "copyTexSubImage3D",
    241  "compressedTexImage3D",
    242  "compressedTexSubImage3D",
    243  "getFragDataLocation",
    244  "uniform1ui",
    245  "uniform2ui",
    246  "uniform3ui",
    247  "uniform4ui",
    248  "uniform1uiv",
    249  "uniform2uiv",
    250  "uniform3uiv",
    251  "uniform4uiv",
    252  "uniformMatrix2x3fv",
    253  "uniformMatrix3x2fv",
    254  "uniformMatrix2x4fv",
    255  "uniformMatrix4x2fv",
    256  "uniformMatrix3x4fv",
    257  "uniformMatrix4x3fv",
    258  "vertexAttribI4i",
    259  "vertexAttribI4iv",
    260  "vertexAttribI4ui",
    261  "vertexAttribI4uiv",
    262  "vertexAttribIPointer",
    263  "vertexAttribDivisor",
    264  "drawArraysInstanced",
    265  "drawElementsInstanced",
    266  "drawRangeElements",
    267  "drawBuffers",
    268  "clearBufferiv",
    269  "clearBufferuiv",
    270  "clearBufferfv",
    271  "clearBufferfi",
    272  "createQuery",
    273  "deleteQuery",
    274  "isQuery",
    275  "beginQuery",
    276  "endQuery",
    277  "getQuery",
    278  "getQueryParameter",
    279  "createSampler",
    280  "deleteSampler",
    281  "isSampler",
    282  "bindSampler",
    283  "samplerParameteri",
    284  "samplerParameterf",
    285  "getSamplerParameter",
    286  "fenceSync",
    287  "isSync",
    288  "deleteSync",
    289  "clientWaitSync",
    290  "waitSync",
    291  "getSyncParameter",
    292  "createTransformFeedback",
    293  "deleteTransformFeedback",
    294  "isTransformFeedback",
    295  "bindTransformFeedback",
    296  "beginTransformFeedback",
    297  "endTransformFeedback",
    298  "transformFeedbackVaryings",
    299  "getTransformFeedbackVarying",
    300  "pauseTransformFeedback",
    301  "resumeTransformFeedback",
    302  "bindBufferBase",
    303  "bindBufferRange",
    304  "getIndexedParameter",
    305  "getUniformIndices",
    306  "getActiveUniforms",
    307  "getUniformBlockIndex",
    308  "getActiveUniformBlockParameter",
    309  "getActiveUniformBlockName",
    310  "uniformBlockBinding",
    311  "createVertexArray",
    312  "deleteVertexArray",
    313  "isVertexArray",
    314  "bindVertexArray",
    315 ];
    316 
    317 function assertFunction(v, f) {
    318    try {
    319        if (typeof v[f] != "function") {
    320            return false;
    321        } else {
    322            return true;
    323        }
    324    } catch(e) {
    325        return false;
    326    }
    327 }
    328 
    329 function testAPIs(contextType) {
    330    canvas = new OffscreenCanvas(10, 10);
    331    gl = canvas.getContext(contextType);
    332    var passed = true;
    333    var methods;
    334    if (contextType == 'webgl')
    335        methods = webgl1Methods;
    336    else
    337        methods = webgl1Methods.concat(webgl2Methods);
    338    for (var i=0; i<methods.length; i++) {
    339      var r = assertFunction(gl, methods[i]);
    340      passed = passed && r;
    341    }
    342 
    343    methods.push(...["makeXRCompatible"]);
    344    var extended = false;
    345    for (var i in gl) {
    346      if (typeof gl[i] == "function" && methods.indexOf(i) == -1) {
    347        if (!extended) {
    348          extended = true;
    349        }
    350      }
    351    }
    352 
    353    if (!passed || extended)
    354        return false;
    355    return true;
    356 }
    357 
    358 var simpleTextureVertexShader = [
    359  'attribute vec4 vPosition;',
    360  'attribute vec2 texCoord0;',
    361  'varying vec2 texCoord;',
    362  'void main() {',
    363  '    gl_Position = vPosition;',
    364  '    texCoord = texCoord0;',
    365  '}'].join('\n');
    366 
    367 var simpleTextureFragmentShader = [
    368  'precision mediump float;',
    369  'uniform sampler2D tex;',
    370  'varying vec2 texCoord;',
    371  'void main() {',
    372  '    gl_FragData[0] = texture2D(tex, texCoord);',
    373  '}'].join('\n');
    374 
    375 function getShader(gl, shaderStr, type)
    376 {
    377  var shader = gl.createShader(type);
    378  gl.shaderSource(shader, shaderStr);
    379  gl.compileShader(shader);
    380 
    381  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
    382    return null;
    383  return shader;
    384 }
    385 
    386 function setupProgram(gl, shaders, opt_attribs, opt_locations)
    387 {
    388  var vertexShader = getShader(gl, simpleTextureVertexShader, gl.VERTEX_SHADER);
    389  var fragmentShader = getShader(gl, simpleTextureFragmentShader, gl.FRAGMENT_SHADER);
    390  var program = gl.createProgram();
    391  gl.attachShader(program, vertexShader);
    392  gl.attachShader(program, fragmentShader);
    393 
    394  if (opt_attribs) {
    395    for (var ii = 0; ii < opt_attribs.length; ++ii) {
    396      gl.bindAttribLocation(
    397          program,
    398          opt_locations ? opt_locations[ii] : ii,
    399          opt_attribs[ii]);
    400    }
    401  }
    402  gl.linkProgram(program);
    403 
    404  // Check the link status
    405  var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
    406  if (!linked) {
    407      // something went wrong with the link
    408      gl.deleteProgram(program);
    409      return null;
    410  }
    411  gl.useProgram(program);
    412  return program;
    413 }
    414 
    415 function setupSimpleTextureProgram(gl, opt_positionLocation, opt_texcoordLocation)
    416 {
    417  opt_positionLocation = opt_positionLocation || 0;
    418  opt_texcoordLocation = opt_texcoordLocation || 1;
    419  return setupProgram(gl,
    420                      [simpleTextureVertexShader, simpleTextureFragmentShader],
    421                      ['vPosition', 'texCoord0'],
    422                      [opt_positionLocation, opt_texcoordLocation]);
    423 }
    424 
    425 function testLostContextWithoutRestore()
    426 {
    427    // Functions with special return values.
    428    if (!gl.isContextLost())
    429        return false;
    430 
    431    if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
    432        return false;
    433    if (gl.getError() != gl.NO_ERROR)
    434        return false;
    435 
    436    if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_UNSUPPORTED ||
    437        gl.getAttribLocation(program, 'u_modelViewProjMatrix') != -1 ||
    438        gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER) != 0)
    439        return false;
    440 
    441    // Test the extension itself.
    442    if (!compareGLError(gl.INVALID_OPERATION, "WEBGL_lose_context.loseContext()"))
    443        return false;
    444 
    445    imageData = new ImageData(1, 1);
    446    float32array = new Float32Array(1);
    447    int32array = new Int32Array(1);
    448 
    449    // Functions returning void should return immediately.
    450    // This is untestable, but we can at least be sure they cause no errors
    451    // and the codepaths are exercised.
    452    if (!compareGLError(gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)") ||
    453        !compareGLError(gl.NO_ERROR, "gl.attachShader(program, shader)") ||
    454        !compareGLError(gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)") ||
    455        !compareGLError(gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)") ||
    456        !compareGLError(gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)") ||
    457        !compareGLError(gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, texture)") ||
    458        !compareGLError(gl.NO_ERROR, "gl.blendColor(1.0, 1.0, 1.0, 1.0)") ||
    459        !compareGLError(gl.NO_ERROR, "gl.blendEquation(gl.FUNC_ADD)") ||
    460        !compareGLError(gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)") ||
    461        !compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.ONE, gl.ONE)") ||
    462        !compareGLError(gl.NO_ERROR, "gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE)") ||
    463        !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)") ||
    464        !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)") ||
    465        !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)") ||
    466        !compareGLError(gl.NO_ERROR, "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)") ||
    467        !compareGLError(gl.NO_ERROR, "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)") ||
    468        !compareGLError(gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)") ||
    469        !compareGLError(gl.NO_ERROR, "gl.clearColor(1, 1, 1, 1)") ||
    470        !compareGLError(gl.NO_ERROR, "gl.clearDepth(1)") ||
    471        !compareGLError(gl.NO_ERROR, "gl.clearStencil(0)") ||
    472        !compareGLError(gl.NO_ERROR, "gl.colorMask(1, 1, 1, 1)") ||
    473        !compareGLError(gl.NO_ERROR, "gl.compileShader(shader)") ||
    474        !compareGLError(gl.NO_ERROR, "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)") ||
    475        !compareGLError(gl.NO_ERROR, "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)") ||
    476        !compareGLError(gl.NO_ERROR, "gl.cullFace(gl.FRONT)") ||
    477        !compareGLError(gl.NO_ERROR, "gl.deleteBuffer(buffer)") ||
    478        !compareGLError(gl.NO_ERROR, "gl.deleteFramebuffer(framebuffer)") ||
    479        !compareGLError(gl.NO_ERROR, "gl.deleteProgram(program)") ||
    480        !compareGLError(gl.NO_ERROR, "gl.deleteRenderbuffer(renderbuffer)") ||
    481        !compareGLError(gl.NO_ERROR, "gl.deleteShader(shader)") ||
    482        !compareGLError(gl.NO_ERROR, "gl.deleteTexture(texture)") ||
    483        !compareGLError(gl.NO_ERROR, "gl.depthFunc(gl.NEVER)") ||
    484        !compareGLError(gl.NO_ERROR, "gl.depthMask(0)") ||
    485        !compareGLError(gl.NO_ERROR, "gl.depthRange(0, 1)") ||
    486        !compareGLError(gl.NO_ERROR, "gl.detachShader(program, shader)") ||
    487        !compareGLError(gl.NO_ERROR, "gl.disable(gl.BLEND)") ||
    488        !compareGLError(gl.NO_ERROR, "gl.disableVertexAttribArray(0)") ||
    489        !compareGLError(gl.NO_ERROR, "gl.drawArrays(gl.POINTS, 0, 0)") ||
    490        !compareGLError(gl.NO_ERROR, "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)") ||
    491        !compareGLError(gl.NO_ERROR, "gl.enable(gl.BLEND)") ||
    492        !compareGLError(gl.NO_ERROR, "gl.enableVertexAttribArray(0)") ||
    493        !compareGLError(gl.NO_ERROR, "gl.finish()") ||
    494        !compareGLError(gl.NO_ERROR, "gl.flush()") ||
    495        !compareGLError(gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)") ||
    496        !compareGLError(gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)") ||
    497        !compareGLError(gl.NO_ERROR, "gl.frontFace(gl.CW)") ||
    498        !compareGLError(gl.NO_ERROR, "gl.generateMipmap(gl.TEXTURE_2D)") ||
    499        !compareGLError(gl.NO_ERROR, "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)") ||
    500        !compareGLError(gl.NO_ERROR, "gl.lineWidth(0)") ||
    501        !compareGLError(gl.NO_ERROR, "gl.linkProgram(program)") ||
    502        !compareGLError(gl.NO_ERROR, "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)") ||
    503        !compareGLError(gl.NO_ERROR, "gl.polygonOffset(0, 0)") ||
    504        !compareGLError(gl.NO_ERROR, "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
    505        !compareGLError(gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)") ||
    506        !compareGLError(gl.NO_ERROR, "gl.sampleCoverage(0, 0)") ||
    507        !compareGLError(gl.NO_ERROR, "gl.scissor(0, 0, 0, 0)") ||
    508        !compareGLError(gl.NO_ERROR, "gl.shaderSource(shader, '')") ||
    509        !compareGLError(gl.NO_ERROR, "gl.stencilFunc(gl.NEVER, 0, 0)") ||
    510        !compareGLError(gl.NO_ERROR, "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)") ||
    511        !compareGLError(gl.NO_ERROR, "gl.stencilMask(0)") ||
    512        !compareGLError(gl.NO_ERROR, "gl.stencilMaskSeparate(gl.FRONT, 0)") ||
    513        !compareGLError(gl.NO_ERROR, "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)") ||
    514        !compareGLError(gl.NO_ERROR, "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)") ||
    515        !compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
    516        !compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)") ||
    517        !compareGLError(gl.NO_ERROR, "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)") ||
    518        !compareGLError(gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)") ||
    519        !compareGLError(gl.NO_ERROR, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
    520        !compareGLError(gl.NO_ERROR, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)") ||
    521        !compareGLError(gl.NO_ERROR, "gl.uniform1f(uniformLocation, 0)") ||
    522        !compareGLError(gl.NO_ERROR, "gl.uniform1fv(uniformLocation, float32array)") ||
    523        !compareGLError(gl.NO_ERROR, "gl.uniform1fv(uniformLocation, [0])") ||
    524        !compareGLError(gl.NO_ERROR, "gl.uniform1i(uniformLocation, 0)") ||
    525        !compareGLError(gl.NO_ERROR, "gl.uniform1iv(uniformLocation, int32array)") ||
    526        !compareGLError(gl.NO_ERROR, "gl.uniform1iv(uniformLocation, [0])") ||
    527        !compareGLError(gl.NO_ERROR, "gl.uniform2f(uniformLocation, 0, 0)") ||
    528        !compareGLError(gl.NO_ERROR, "gl.uniform2fv(uniformLocation, float32array)") ||
    529        !compareGLError(gl.NO_ERROR, "gl.uniform2fv(uniformLocation, [0, 0])") ||
    530        !compareGLError(gl.NO_ERROR, "gl.uniform2i(uniformLocation, 0, 0)") ||
    531        !compareGLError(gl.NO_ERROR, "gl.uniform2iv(uniformLocation, int32array)") ||
    532        !compareGLError(gl.NO_ERROR, "gl.uniform2iv(uniformLocation, [0, 0])") ||
    533        !compareGLError(gl.NO_ERROR, "gl.uniform3f(uniformLocation, 0, 0, 0)") ||
    534        !compareGLError(gl.NO_ERROR, "gl.uniform3fv(uniformLocation, float32array)") ||
    535        !compareGLError(gl.NO_ERROR, "gl.uniform3fv(uniformLocation, [0, 0, 0])") ||
    536        !compareGLError(gl.NO_ERROR, "gl.uniform3i(uniformLocation, 0, 0, 0)") ||
    537        !compareGLError(gl.NO_ERROR, "gl.uniform3iv(uniformLocation, int32array)") ||
    538        !compareGLError(gl.NO_ERROR, "gl.uniform3iv(uniformLocation, [0, 0, 0])") ||
    539        !compareGLError(gl.NO_ERROR, "gl.uniform4f(uniformLocation, 0, 0, 0, 0)") ||
    540        !compareGLError(gl.NO_ERROR, "gl.uniform4fv(uniformLocation, float32array)") ||
    541        !compareGLError(gl.NO_ERROR, "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])") ||
    542        !compareGLError(gl.NO_ERROR, "gl.uniform4i(uniformLocation, 0, 0, 0, 0)") ||
    543        !compareGLError(gl.NO_ERROR, "gl.uniform4iv(uniformLocation, int32array)") ||
    544        !compareGLError(gl.NO_ERROR, "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])") ||
    545        !compareGLError(gl.NO_ERROR, "gl.uniformMatrix2fv(uniformLocation, false, float32array)") ||
    546        !compareGLError(gl.NO_ERROR, "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])") ||
    547        !compareGLError(gl.NO_ERROR, "gl.uniformMatrix3fv(uniformLocation, false, float32array)") ||
    548        !compareGLError(gl.NO_ERROR, "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])") ||
    549        !compareGLError(gl.NO_ERROR, "gl.uniformMatrix4fv(uniformLocation, false, float32array)") ||
    550        !compareGLError(gl.NO_ERROR, "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])") ||
    551        !compareGLError(gl.NO_ERROR, "gl.useProgram(program)") ||
    552        !compareGLError(gl.NO_ERROR, "gl.validateProgram(program)") ||
    553        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1f(0, 0)") ||
    554        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1fv(0, float32array)") ||
    555        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1fv(0, [0])") ||
    556        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2f(0, 0, 0)") ||
    557        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2fv(0, float32array)") ||
    558        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2fv(0, [0, 0])") ||
    559        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3f(0, 0, 0, 0)") ||
    560        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3fv(0, float32array)") ||
    561        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3fv(0, [0, 0, 0])") ||
    562        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4f(0, 0, 0, 0, 0)") ||
    563        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4fv(0, float32array)") ||
    564        !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4fv(0, [0, 0, 0, 0])") ||
    565        !compareGLError(gl.NO_ERROR, "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)") ||
    566        !compareGLError(gl.NO_ERROR, "gl.viewport(0, 0, 0, 0)"))
    567        return false;
    568 
    569    // Functions return nullable values should all return null.
    570    if (gl.getActiveAttrib(program, 0) != null ||
    571        gl.getActiveUniform(program, 0) != null ||
    572        gl.getAttachedShaders(program) != null ||
    573        gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE) != null ||
    574        gl.getContextAttributes() != null ||
    575        gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) != null ||
    576        gl.getParameter(gl.CURRENT_PROGRAM) != null ||
    577        gl.getProgramInfoLog(program) != null ||
    578        gl.getProgramParameter(program, gl.LINK_STATUS) != null ||
    579        gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) != null ||
    580        gl.getShaderInfoLog(shader) != null ||
    581        gl.getShaderParameter(shader, gl.SHADER_TYPE) != null ||
    582        gl.getShaderSource(shader) != null ||
    583        gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S) != null ||
    584        gl.getUniform(program, uniformLocation) != null ||
    585        gl.getUniformLocation(program, 'vPosition') != null ||
    586        gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) != null ||
    587        gl.getSupportedExtensions() != null ||
    588        gl.getExtension("WEBGL_lose_context") != null)
    589        return false;
    590 
    591    const failedTests = [
    592        "gl.createBuffer()",
    593        "gl.createFramebuffer()",
    594        "gl.createProgram()",
    595        "gl.createRenderbuffer()",
    596        "gl.createShader(gl.VERTEX_SHADER)",
    597        "gl.createTexture()",
    598    ].reduce(s => {
    599        const v = eval(s);
    600        return !v;
    601    });
    602    if (failedTests.length) {
    603        console.log({failedTests});
    604        return false;
    605    }
    606 
    607    // "Is" queries should all return false.
    608    if (gl.isBuffer(buffer) || gl.isEnabled(gl.BLEND) || gl.isFramebuffer(framebuffer) ||
    609        gl.isProgram(program) || gl.isRenderbuffer(renderbuffer) || gl.isShader(shader) ||
    610        gl.isTexture(texture))
    611        return false;
    612 
    613    if (gl.getError() != gl.NO_ERROR)
    614        return false;
    615 
    616    // test extensions
    617    if (OES_vertex_array_object) {
    618        if (!compareGLError(gl.NO_ERROR, "OES_vertex_array_object.bindVertexArrayOES(vertexArrayObject)") ||
    619            !compareGLError(gl.NO_ERROR, "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)") ||
    620            !compareGLError(gl.NO_ERROR, "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)"))
    621            return false;
    622        if (!OES_vertex_array_object.createVertexArrayOES())
    623            return false;
    624    }
    625    return true;
    626 }
    627 function testValidContext()
    628 {
    629    if (gl.isContextLost())
    630        return false;
    631 
    632    arrayBuffer = new ArrayBuffer(4);
    633    arrayBufferView = new Int8Array(arrayBuffer);
    634 
    635    // Generate resources for testing.
    636    buffer = gl.createBuffer();
    637    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    638    framebuffer = gl.createFramebuffer();
    639    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    640    program = setupSimpleTextureProgram(gl);
    641    renderbuffer = gl.createRenderbuffer();
    642    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
    643    shader = gl.createShader(gl.VERTEX_SHADER);
    644    texture = gl.createTexture();
    645    gl.bindTexture(gl.TEXTURE_2D, texture);
    646    if (gl.getError() != gl.NO_ERROR)
    647        return false;
    648 
    649    // Test is queries that will later be false
    650    if (!compareGLError(gl.NO_ERROR, "gl.enable(gl.BLEND)"))
    651        return false;
    652    if (!gl.isBuffer(buffer) || !gl.isEnabled(gl.BLEND) || !gl.isFramebuffer(framebuffer) ||
    653        !gl.isProgram(program) || !gl.isRenderbuffer(renderbuffer) || !gl.isShader(shader) ||
    654        !gl.isTexture(texture))
    655        return false;
    656 
    657    if (OES_vertex_array_object) {
    658        vertexArrayObject = OES_vertex_array_object.createVertexArrayOES();
    659        if (gl.getError() != gl.NO_ERROR)
    660            return false;
    661        if (!OES_vertex_array_object.isVertexArrayOES(vertexArrayObject))
    662            return false;
    663    }
    664    return true;
    665 }
    666 
    667 function setupTest()
    668 {
    669    canvas = new OffscreenCanvas(10, 10);
    670    gl = canvas.getContext('webgl');
    671    WEBGL_lose_context = gl.getExtension("WEBGL_lose_context");
    672    if (!WEBGL_lose_context)
    673        return false;
    674 
    675    // Try to get a few extensions
    676    OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
    677    OES_texture_float = gl.getExtension("OES_texture_float");
    678 
    679    return true;
    680 }
    681 
    682 function testOriginalContext()
    683 {
    684    if (gl.isContextLost())
    685        return false;
    686    if (gl.getError() != gl.NO_ERROR)
    687        return false;
    688    return true;
    689 }
    690 
    691 function testLostContext(e)
    692 {
    693    if (contextLostEventFired)
    694        return false;
    695    contextLostEventFired = true;
    696    if (!gl.isContextLost())
    697        return false;
    698    if (gl.getError() != gl.NO_ERROR)
    699        return false;
    700    if (allowRestore)
    701      e.preventDefault();
    702    return true;
    703 }
    704 
    705 function testLosingAndRestoringContext()
    706 {
    707    return new Promise(function(resolve, reject) {
    708        if (!setupTest())
    709            reject("Test failed");
    710 
    711        canvas.addEventListener("webglcontextlost", function(e) {
    712            if (!testLostContext(e))
    713              reject("Test failed");
    714            // restore the context after this event has exited.
    715            setTimeout(function() {
    716                if (!compareGLError(gl.NO_ERROR, "WEBGL_lose_context.restoreContext()"))
    717                    reject("Test failed");
    718                // The context should still be lost. It will not get restored until the
    719                // webglrestorecontext event is fired.
    720                if (!gl.isContextLost())
    721                    reject("Test failed");
    722                if (gl.getError() != gl.NO_ERROR)
    723                    reject("Test failed");
    724                // gl methods should still be no-ops
    725                if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
    726                    reject("Test failed");
    727            }, 0);
    728        });
    729        canvas.addEventListener("webglcontextrestored", function() {
    730            if (!testRestoredContext())
    731                reject("Test failed: !testRestoredContext()");
    732            else
    733                resolve("Test passed");
    734        });
    735        allowRestore = true;
    736        contextLostEventFired = false;
    737        contextRestoredEventFired = false;
    738 
    739        if (!testOriginalContext())
    740            reject("Test failed");
    741        WEBGL_lose_context.loseContext();
    742        // The context should be lost immediately.
    743        if (!gl.isContextLost())
    744            reject("Test failed");
    745        if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
    746            reject("Test failed");
    747        if (gl.getError() != gl.NO_ERROR)
    748            reject("Test failed");
    749        // gl methods should be no-ops
    750        if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
    751            reject("Test failed");
    752        // but the event should not have been fired.
    753        if (contextLostEventFired)
    754            reject("Test failed");
    755    });
    756 }
    757 
    758 function reGetExtensionAndTestForProperty(gl, name, expectProperty) {
    759    var newExtension = gl.getExtension(name);
    760    // NOTE: while getting a extension after context lost/restored is allowed to fail
    761    // for the purpose the conformance tests it is not.
    762    //
    763    // Hypothetically the user can switch GPUs live. For example on Windows, install 2 GPUs,
    764    // then in the control panen enable 1, disable the others and visa versa. Since the GPUs
    765    // have different capabilities one or the other may not support a particlar extension.
    766    //
    767    // But, for the purpose of the conformance tests the context is expected to restore
    768    // on the same GPU and therefore the extensions that succeeded previously should
    769    // succeed on restore.
    770    if (newExtension == null)
    771        return false;
    772    if (expectProperty) {
    773        if (!(newExtension.webglTestProperty === true))
    774            return false;
    775    } else {
    776        if (!(newExtension.webglTestProperty === undefined))
    777            return false;
    778    }
    779    return newExtension;
    780 }
    781 
    782 
    783 function testOESTextureFloat() {
    784  if (OES_texture_float) {
    785    // Extension must still be lost.
    786    var tex = gl.createTexture();
    787    gl.bindTexture(gl.TEXTURE_2D, tex);
    788    if (!compareGLError(gl.INVALID_ENUM, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"))
    789        return false;
    790    // Try re-enabling extension
    791    OES_texture_float = reGetExtensionAndTestForProperty(gl, "OES_texture_float", false);
    792    if (!compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"))
    793        return false;
    794    return true;
    795  }
    796 }
    797 
    798 function testOESVertexArrayObject() {
    799  if (OES_vertex_array_object) {
    800    // Extension must still be lost.
    801    if (!OES_vertex_array_object.createVertexArrayOES()) {
    802        console.error("!OES_vertex_array_object.createVertexArrayOES()");
    803        return false;
    804    }
    805    // Try re-enabling extension
    806 
    807    var old_OES_vertex_array_object = OES_vertex_array_object;
    808    OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false);
    809    if (!OES_vertex_array_object.createVertexArrayOES()) {
    810        console.error("!OES_vertex_array_object.createVertexArrayOES() 2");
    811        return false;
    812    }
    813    if (!old_OES_vertex_array_object.createVertexArrayOES()) {
    814        console.error("!old_OES_vertex_array_object.createVertexArrayOES()");
    815        return false;
    816    }
    817    return true;
    818  }
    819 }
    820 
    821 function testExtensions() {
    822  if (!testOESTextureFloat() || !testOESVertexArrayObject())
    823    return false;
    824  return true;
    825 }
    826 
    827 function testRestoredContext()
    828 {
    829    if (contextRestoredEventFired)
    830        return false;
    831    contextRestoredEventFired = true;
    832    if (gl.isContextLost())
    833        return false;
    834    if (gl.getError() != gl.NO_ERROR)
    835        return false;
    836 
    837    if (!testExtensions())
    838        return false;
    839    return true;
    840 }