tor-browser

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

oes-texture-half-float.html (20406B)


      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 <!DOCTYPE html>
      8 <html>
      9 <head>
     10 <meta charset="utf-8">
     11 <title>WebGL OES_texture_half_float Conformance Tests</title>
     12 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
     13 <script src="../../js/js-test-pre.js"></script>
     14 <script src="../../js/webgl-test-utils.js"></script>
     15 </head>
     16 <body>
     17 <div id="description"></div>
     18 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
     19 <canvas id="canvas2d" style="width: 50px; height: 50px;"> </canvas>
     20 <div id="console"></div>
     21 <script id="testFragmentShader" type="x-shader/x-fragment">
     22 precision mediump float;
     23 uniform sampler2D tex;
     24 uniform vec4 subtractor;
     25 varying vec2 texCoord;
     26 void main()
     27 {
     28    vec4 color = texture2D(tex, texCoord);
     29    if (abs(color.r - subtractor.r) +
     30        abs(color.g - subtractor.g) +
     31        abs(color.b - subtractor.b) +
     32        abs(color.a - subtractor.a) < 8.0) {
     33        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
     34    } else {
     35        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
     36    }
     37 }
     38 </script>
     39 <!-- Shaders for testing half-floating-point render targets -->
     40 <script id="floatingPointFragmentShader" type="x-shader/x-fragment">
     41 void main()
     42 {
     43    gl_FragColor = vec4(10000.0, 10000.0, 10000.0, 10000.0);
     44 }
     45 </script>
     46 <script>
     47 "use strict"
     48 description("This test verifies the functionality of OES_texture_half_float with null/non-null ArrayBufferView");
     49 
     50 debug("");
     51 var wtu = WebGLTestUtils;
     52 var canvas = document.getElementById("canvas");
     53 var colorCanvas = document.getElementById("canvas2d");
     54 colorCanvas.width = 2;
     55 colorCanvas.height = 2;
     56 var ctx = colorCanvas.getContext("2d");
     57 ctx.fillStyle = "rgb(255,0,0)";
     58 ctx.fillRect(0, 0, 2, 2);
     59 var gl = wtu.create3DContext(canvas);
     60 // This constant must be defined in order to run the texture creation test without the extension enabled.
     61 var halfFloatOESEnum = 0x8D61;
     62 var ext = null;
     63 
     64 
     65 if (!gl) {
     66    testFailed("WebGL context does not exists");
     67 } else {
     68    testPassed("WebGL context exists");
     69 
     70    // Verify that allocation of texture fails if extension is not enabled
     71    runTextureCreationTest(false);
     72    ext = gl.getExtension("OES_texture_half_float")
     73    if (!ext) {
     74        testPassed("No OES_texture_half_float support. This is legal");
     75    } else {
     76        testPassed("Successfully enabled OES_texture_half_float extension");
     77 
     78        var program = wtu.setupTexturedQuad(gl);
     79 
     80        // Check if creation of texture succeed's with various formats and null ArrayBufferView
     81        var formats = [
     82          { format: gl.RGBA,            expected: [255,   0,   0, 255], },
     83          { format: gl.RGB,             expected: [255,   0,   0, 255], },
     84          { format: gl.LUMINANCE,       expected: [255, 255, 255, 255], },
     85          { format: gl.ALPHA,           expected: [  0,   0,   0, 255], },
     86          { format: gl.LUMINANCE_ALPHA, expected: [255, 255, 255, 255], },
     87        ];
     88        formats.forEach(function(f) {
     89            runTextureCreationTest(true, f.format, null, f.expected);
     90        });
     91 
     92        // Texture creation should fail when passed with non-null, non-Uint16 ArrayBufferView
     93        formats.forEach(function(f) {
     94            var width = 2;
     95            var height = 2;
     96            var format = f.format;
     97 
     98            // Float32Array
     99            var float32Data = new Float32Array(width * height * getNumberOfChannels(format));
    100            for (var ii = 0; ii < float32Data.length; ii++) {
    101                float32Data[ii] = 1000;
    102            }
    103            runTextureCreationTest(true, format, float32Data, null);
    104 
    105            // Int16Array
    106            var int16Data = new Int16Array(width * height * getNumberOfChannels(format));
    107            for (var ii = 0; ii <  int16Data.length; ii++) {
    108                int16Data[ii] = 1000;
    109            }
    110            runTextureCreationTest(true, format, int16Data, null);
    111        });
    112 
    113        // Test that Uint16 encoded half float values can be used as texture data.
    114 
    115        // First test that values in the 0-1 range can be written and read.
    116        var halfFloatOneThird = 0x3555; // Half float 1/3
    117        var uint16Formats = [
    118          { format: gl.RGBA,            expected: [85, 85, 85,  85], },
    119          { format: gl.RGB,             expected: [85, 85, 85, 255], },
    120          { format: gl.LUMINANCE,       expected: [85, 85, 85, 255], },
    121          { format: gl.ALPHA,           expected: [ 0,  0,  0,  85], },
    122          { format: gl.LUMINANCE_ALPHA, expected: [85, 85, 85,  85], },
    123        ];
    124 
    125        uint16Formats.forEach(function(f) {
    126            var width = 2;
    127            var height = 2;
    128            var format = f.format;
    129 
    130            var uint16Data = new Uint16Array(width * height * getNumberOfChannels(format));
    131            for (var ii = 0; ii <  uint16Data.length; ii++) {
    132                uint16Data[ii] = halfFloatOneThird;
    133            }
    134            runTextureCreationTest(true, format, uint16Data, f.expected);
    135        });
    136 
    137        // Next check that values outside the 0-1 range can be written.
    138        var halfFloatTenK = 0x70E2; // Half float 10000
    139        var uint16Formats2 = [
    140          { format: gl.RGBA, subtractor: [10000, 10000, 10000, 10000], requireRenderable: true},
    141          { format: gl.RGB,  subtractor: [10000, 10000, 10000, 1], requireRenderable: false},
    142        ];
    143 
    144        uint16Formats2.forEach(function(f) {
    145            var width = 2;
    146            var height = 2;
    147            var format = f.format;
    148 
    149            var uint16Data = new Uint16Array(width * height * getNumberOfChannels(format));
    150            for (var ii = 0; ii <  uint16Data.length; ii++) {
    151                uint16Data[ii] = halfFloatTenK;
    152            }
    153            runRenderTest(format, f.subtractor, uint16Data, f.requireRenderable);
    154        });
    155 
    156        (function() {
    157            debug("");
    158            var renderable = isRenderable(gl, ext);
    159            var renderableExtName = "EXT_color_buffer_half_float";
    160            var supported = gl.getSupportedExtensions().includes(renderableExtName);
    161            if (renderable && !supported) {
    162                testFailed("RGBA/HALF_FLOAT_OES is color renderable but " + renderableExtName + " not exposed");
    163            } else if (supported && !renderable) {
    164                testFailed(renderableExtName + " is exposed but RGBA/HALF_FLOAT_OES is not color renderable");
    165            }
    166            if (supported) {
    167                runRenderTest(gl.RGBA, [10000, 10000, 10000, 10000], null, true);
    168                runRenderTest(gl.RGB, [10000, 10000, 10000, 1], null, false);
    169                runFramebufferTest();
    170            }
    171        })();
    172 
    173        // Check of getExtension() returns same object
    174        runUniqueObjectTest();
    175    }
    176 }
    177 
    178 function isRenderable(gl, ext) {
    179    var tex = gl.createTexture();
    180    gl.bindTexture(gl.TEXTURE_2D, tex);
    181    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, ext.HALF_FLOAT_OES, null);
    182 
    183    var fb = gl.createFramebuffer();
    184    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    185    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
    186 
    187    var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
    188    gl.deleteFramebuffer(fb);
    189    gl.deleteTexture(tex);
    190 
    191    return status == gl.FRAMEBUFFER_COMPLETE;
    192 }
    193 
    194 function getNumberOfChannels(format)
    195 {
    196    if (format == gl.RGBA)
    197        return 4;
    198    else if (format == gl.RGB)
    199        return 3;
    200    else if (format == gl.LUMINANCE || format == gl.ALPHA)
    201        return 1;
    202    else if (format == gl.LUMINANCE_ALPHA)
    203        return 2;
    204 }
    205 
    206 function allocateTexture()
    207 {
    208    var texture = gl.createTexture();
    209    gl.bindTexture(gl.TEXTURE_2D, texture);
    210    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    211    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    212    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    213    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    214    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
    215    return texture;
    216 }
    217 
    218 function runTextureCreationTest(extensionEnabled, opt_format, opt_data, opt_expected)
    219 {
    220    var format = opt_format || gl.RGBA;
    221    var data = opt_data || null;
    222    var expectSuccess = true;
    223 
    224    if (!extensionEnabled || !opt_expected)
    225        expectSuccess = false;
    226    debug("Testing texture creation with extension " + (extensionEnabled ? "enabled" : "disabled") +
    227          ", format " + wtu.glEnumToString(gl, format) + ", and data " + (data ? "non-null" : "null") +
    228          ". Expect " + (expectSuccess ? "Success" : "Failure"));
    229 
    230    var texture = allocateTexture();
    231    var width = 2;
    232    var height = 2;
    233    gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, halfFloatOESEnum, data);
    234    if(!extensionEnabled) {
    235        wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Half floating point texture must be disallowed if OES_texture_half_float isn't enabled");
    236        return;
    237    } else if (!opt_expected) {
    238        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Half floating point texture allocation must be disallowed when ArrayBufferView is not-null and not-Uint16");
    239        return;
    240    } else {
    241        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Half floating point texture allocation should succeed if OES_texture_half_float is enabled");
    242 
    243        if (!data) {
    244            gl.texImage2D(gl.TEXTURE_2D, 0, format, format, halfFloatOESEnum, colorCanvas);
    245        }
    246        wtu.clearAndDrawUnitQuad(gl);
    247        wtu.checkCanvas(gl, opt_expected);
    248        // Check that linear fails.
    249        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    250        wtu.clearAndDrawUnitQuad(gl);
    251        wtu.checkCanvas(gl, [0, 0, 0, 255], "should be black");
    252    }
    253 
    254 }
    255 
    256 function checkRenderingResults()
    257 {
    258    wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
    259 }
    260 
    261 function runRenderTest(format, subtractor, data, requireRenderable)
    262 {
    263    var formatString = wtu.glEnumToString(gl, format);
    264 
    265    debug("");
    266 
    267    if (!data) {
    268        debug("Testing half floating point " + formatString + " render target");
    269    } else {
    270        debug("Testing half floating point " + formatString + " from a Uint16Array");
    271    }
    272 
    273    var texture = allocateTexture();
    274    var width = 2;
    275    var height = 2;
    276 
    277    gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, ext.HALF_FLOAT_OES, data);
    278    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Half floating point texture allocation should succeed if OES_texture_half_float is enabled");
    279 
    280    if (!data) {
    281        // Try to use this texture as render target
    282        var fbo = gl.createFramebuffer();
    283        gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    284        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
    285        gl.bindTexture(gl.TEXTURE_2D, null);
    286 
    287        // It is legal for a WebGL implementation exposing the OES_texture_half_float extension to
    288        // support half floating point textures but not as attachments to framebuffer objects.
    289        if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
    290            if (requireRenderable) {
    291                testFailed(formatString + " render targets not supported.");
    292            } else {
    293                debug(formatString + " render targets not supported -- this is legal");
    294            }
    295            return;
    296        }
    297 
    298        var renderProgram =
    299            wtu.setupProgram(gl,
    300                             [wtu.simpleVertexShader, "floatingPointFragmentShader"],
    301                             ['vPosition'],
    302                             [0]);
    303        wtu.drawUnitQuad(gl);
    304        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Rendering to half floating point texture should succeed");
    305    }
    306 
    307    // Now sample from the half floating-point texture and verify we got the correct values.
    308    var texturedShaders = [
    309          wtu.simpleTextureVertexShader,
    310          "testFragmentShader"
    311      ];
    312    var testProgram =
    313        wtu.setupProgram(gl,
    314                        [wtu.simpleTextureVertexShader, "testFragmentShader"],
    315                        ['vPosition', 'texCoord0'],
    316                        [0, 1]);
    317    var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
    318    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    319    gl.bindTexture(gl.TEXTURE_2D, texture);
    320    gl.useProgram(testProgram);
    321    gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
    322    wtu.drawUnitQuad(gl);
    323    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from half floating point texture should succeed");
    324    checkRenderingResults();
    325 }
    326 
    327 function runUniqueObjectTest()
    328 {
    329    debug("");
    330    debug("Testing that getExtension() returns the same object each time");
    331    ext = null;
    332    gl.getExtension("OES_texture_half_float").myProperty = 2;
    333    webglHarnessCollectGarbage();
    334    shouldBe('gl.getExtension("OES_texture_half_float").myProperty', '2');
    335 }
    336 
    337 // Make sure we can call readPixels with the passed in arrayBufferConstructor and that the color
    338 // channels are the ones we expect. If there is a mismatch between the glType and arrayBuffer type,
    339 // fail the test.
    340 function verifyReadPixelsColors(red, green, blue, alpha, alphaRGB, glFormat, glType, arrayBufferConstructor) {
    341    var typeName = wtu.glEnumToString(gl, glType);
    342 
    343    debug(wtu.glEnumToString(gl, glFormat) + " framebuffer with " + typeName + " readback.");
    344 
    345    var arrayBuffer = new arrayBufferConstructor(4);
    346    gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
    347    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should return NO_ERROR when reading " + typeName + " data.");
    348 
    349    assertMsg(arrayBuffer[0] === red, "Red channel should be " + red + " for " + typeName + " readPixels. Received: " + arrayBuffer[0]);
    350    assertMsg(arrayBuffer[1] === green, "Green channel should be " + green + " for " + typeName + " readPixels. Received: " + arrayBuffer[1]);
    351    assertMsg(arrayBuffer[2] === blue, "Blue channel should be " + blue + " for " + typeName + " readPixels. Received: " + arrayBuffer[2]);
    352    if (glFormat === gl.RGBA) {
    353        assertMsg(arrayBuffer[3] === alpha, "Alpha channel should be " + alpha + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]);
    354    } else if (glFormat === gl.RGB) {
    355        assertMsg(arrayBuffer[3] === alphaRGB, "Alpha channel should be " + alphaRGB + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]);
    356    }
    357 
    358    // Make sure any arrayBuffer types that are not equal to arrayBufferConstructor fail readPixels.
    359    if (arrayBufferConstructor !== Uint8Array) {
    360        arrayBuffer = new Uint8Array(4);
    361        gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
    362        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint8Array.toString());
    363    }
    364    if (arrayBufferConstructor !== Float32Array) {
    365        arrayBuffer = new Float32Array(4);
    366        gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
    367        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Float32Array.toString());
    368    }
    369    if (arrayBufferConstructor !== Uint16Array) {
    370        arrayBuffer = new Uint16Array(4);
    371        gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
    372        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint16Array.toString());
    373    }
    374 }
    375 
    376 // Verify that half float textures attached to frame buffers function correctly with regard to framebuffer
    377 // completness, IMPLEMENTATION_COLOR_READ_FORMAT/TYPE and readPixels
    378 function runFramebufferTest() {
    379    debug("");
    380    debug("Framebuffer Tests");
    381 
    382    var texture = allocateTexture();
    383    gl.bindTexture(gl.TEXTURE_2D, texture);
    384 
    385    var fbo = gl.createFramebuffer();
    386    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    387    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
    388 
    389    debug("Ensure non-color-renderable formats [LUMINANCE, LUMINANCE_ALPHA, ALPHA] fail.");
    390    var arrayBufferFloatOutput = new Float32Array(4); // 4 color channels
    391    [gl.LUMINANCE, gl.LUMINANCE_ALPHA, gl.ALPHA].forEach(function(badFormat) {
    392        debug(wtu.glEnumToString(gl, badFormat) + " framebuffer");
    393 
    394        gl.texImage2D(gl.TEXTURE_2D, 0, badFormat, 1, 1, 0, badFormat, ext.HALF_FLOAT_OES, null);
    395        shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
    396 
    397        shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT)");
    398        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_FORMAT should fail for incomplete framebuffers.");
    399 
    400        shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE)");
    401        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_TYPE should fail for incomplete framebuffers.");
    402 
    403        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, arrayBufferFloatOutput);
    404        wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION , "readPixels should fail on incomplete framebuffers.");
    405        debug("");
    406    });
    407 
    408    debug("Ensure color renderable formats [RGBA, RGB] succeed.");
    409    var arrayBufferHalfFloatInput = new Uint16Array(4); // 4 color channels
    410    arrayBufferHalfFloatInput[0] = 0;      // 0 in half float
    411    arrayBufferHalfFloatInput[1] = 0x3400; // 0.25 in half float
    412    arrayBufferHalfFloatInput[2] = 0x3800; // 0.50 in half float
    413    arrayBufferHalfFloatInput[3] = 0x3A00; // 0.75 in half float
    414 
    415    [gl.RGBA, gl.RGB].forEach(function(goodFormat) {
    416        debug(wtu.glEnumToString(gl, goodFormat) + " framebuffer tests");
    417        debug("");
    418 
    419        gl.texImage2D(gl.TEXTURE_2D, 0, goodFormat, 1, 1, 0, goodFormat, ext.HALF_FLOAT_OES, arrayBufferHalfFloatInput);
    420        if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
    421            // Per the OES_color_buffer_half_float, RGBA/FLOAT should always succeed for readPixels
    422            verifyReadPixelsColors(
    423                0.00, // red
    424                0.25, // green
    425                0.50, // blue
    426                0.75, // alpha
    427                1.0,  // alphaRGB
    428                goodFormat,
    429                gl.FLOAT,
    430                Float32Array);
    431 
    432            var implementationColorReadFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
    433            assertMsg(implementationColorReadFormat === gl.RGBA || implementationColorReadFormat === gl.RGB,
    434                "IMPLEMENTATION_COLOR_READ_FORMAT should be color renderable: RGBA or RGB. Received: " + wtu.glEnumToString(gl, implementationColorReadFormat));
    435 
    436            var implementationColorReadType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
    437 
    438            // There is nothing in the specifications that keeps the
    439            // implementation color read format and type from being the
    440            // same as the implicitly supported one. For this reason, keep
    441            // gl.FLOAT as one of the valid options.
    442            assertMsg(implementationColorReadType === gl.UNSIGNED_BYTE ||
    443                      implementationColorReadType === gl.FLOAT ||
    444                      implementationColorReadType === ext.HALF_FLOAT_OES ||
    445                      implementationColorReadType === gl.UNSIGNED_SHORT_4_4_4_4 ||
    446                      implementationColorReadType === gl.UNSIGNED_SHORT_5_5_5_1 ||
    447                      implementationColorReadType === gl.UNSIGNED_SHORT_5_6_5,
    448                      "IMPLEMENTATION_COLOR_READ_TYPE must be one of UNSIGNED_BYTE, UNSIGNED_SHORT_4_4_4_4, UNSIGNED_SHORT_5_5_5_1, UNSIGNED_SHORT_5_6_5, FLOAT, or HALF_FLOAT_OES. " +
    449                      "Received: " + wtu.glEnumToString(gl, implementationColorReadType));
    450 
    451            // Test the RGBA/HALF_FLOAT_OES combination
    452            if (implementationColorReadFormat === gl.RGBA && implementationColorReadType === ext.HALF_FLOAT_OES) {
    453                verifyReadPixelsColors(
    454                    0,      // red
    455                    0x3400, // green
    456                    0x3800, // blue
    457                    0x3A00, // alpha
    458                    0x3C00, // alphaRGB
    459                    goodFormat,
    460                    ext.HALF_FLOAT_OES,
    461                    Uint16Array);
    462            }
    463        }
    464        debug("");
    465    });
    466 }
    467 
    468 debug("");
    469 var successfullyParsed = true;
    470 </script>
    471 <script src="../../js/js-test-post.js"></script>
    472 
    473 </body>
    474 </html>