Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test.html   Sprache: HTML

 
 products/Sources/formale Sprachen/C/Firefox/testing/web-platform/tests/acid/acid3/test.html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html class="reftest-wait">
 <title>The Acid3 Test</title>
 <link rel="match" href="reference.sub.html">
 <script type="text/javascript">
  var startTime = new Date();
 </script>
 <style type="text/css">

  /* set some basic styles so that we can get reliably exact results */
  * { margin: 0; border: 1px blue; padding: 0; border-spacing: 0; font: inherit; line-height: 1.2; color: inherit; background: transparent; }
  :link, :visited { color: blue; }

  /* header and general layout */
  html { font: 20px Arial, sans-serif; border: 2cm solid gray; width: 32em; margin: 1em; }
  :root { background: silver; color: black; border-width: 0 0.2em 0.2em 0; } /* left and top content edges: 1*20px = 20px */
  body { padding: 2em 2em 0; background: url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAAK%2FINwWK6QAAAAlwSFlzAAAASAAAAEgARslrPgAAABtJREFUOMtj%2FM9APmCiQO%2Bo5lHNo5pHNVNBMwAinAEnIWw89gAAACJ6VFh0U29mdHdhcmUAAHjac0zJT0pV8MxNTE8NSk1MqQQAL5wF1K4MqU0AAAAASUVORK5CYII%3D) no-repeat 99.8392283% 1px white; border: solid 1px black; margin: -0.2em 0 0 -0.2em; } /* left and top content edges: 20px-0.2*20px+1px+2*20px = 57px */
  h1:first-child { cursor: help; font-size: 5em; font-weight: bolder; margin-bottom: -0.4em; text-shadow: rgba(192, 192, 192, 1.0) 3px 3px; } /* (left:57px, top:57px) */
  #result { font-weight: bolder; width: 5.68em; text-align: right; }
  #result { font-size: 5em; margin: -2.19em 0 0; } /* (right:57px+5.2*5*20px = 577px, top:57px+1.2*5*20px-0.4*5*20px+1px+1*40px+1*40px+1px+2*40px+150px-2.19*5*20px = 230px) */
  .hidden { visibility: hidden; }
  #slash { color: red; color: hsla(0, 0%, 0%, 1.0); }
  #instructions { margin-top: 0; font-size: 0.8em; color: gray; color: -acid3-bogus; height: 6.125em; } /* (left:57px, top:230px+1.2*5*20+0 = 350px) */
  #instructions { margin-right: -20px; padding-right: 20px; background: url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAAK%2FINwWK6QAAAAlwSFlzAAAASAAAAEgARslrPgAAABtJREFUOMtj%2FM9APmCiQO%2Bo5lHNo5pHNVNBMwAinAEnIWw89gAAACJ6VFh0U29mdHdhcmUAAHjac0zJT0pV8MxNTE8NSk1MqQQAL5wF1K4MqU0AAAAASUVORK5CYII%3D) no-repeat top right; }
  #instructions span { float: right; width: 20px; margin-right: -20px; background: white; height: 20px; }
  @font-face { font-family: "AcidAhemTest"; src: url(/fonts/Ahem.ttf); }
  map::after { position: absolute; top: 18px; left: 638px; content: "X"; background: fuchsia; color: white; font: 20px/1 AcidAhemTest; }
  iframe { float: left; height: 0; width: 0; } /* hide iframes but don't make them display: none */
  object { position: fixed; left: 130.5px; top: 84.3px; background: transparent; } /* show objects if they have content */
  .removed { position: absolute; top: 80px; left: 380px; height: 100px; width: 100px; opacity: 0; }

  /* set the line height of the line of coloured boxes so we can add them without the layout changing height */
  .buckets { font: 0/0 Arial, sans-serif; }
  .buckets { padding: 0 0 150px 3px; }

  /* the next two rules give the six coloured blocks their default styles (they match the same elements); the third hides them */
  :first-child + * .buckets p { display: inline-block; vertical-align: 2em; border: 2em dotted red; padding: 1.0em 0 1.0em 2em; }
  * + * > * > p { margin: 0; border: 1px solid ! important; }
  .z { visibility: hidden; } /* only matches the buckets with no score */

  /* sizes for the six buckets */
  #bucket1 { font-size: 20px; margin-left: 0.2em; padding-left: 1.3em; padding-right: 1.3em; margin-right: 0.0001px; }
  #bucket2 { font-size: 24px; margin-left: 0.375em; padding-left: 30px; padding-right: 32px; margin-right: 2px; }
  #bucket3 { font-size: 28px; margin-left: 8.9999px; padding-left: 17px; padding-right: 55px; margin-right: 12px; }
  #bucket4 { font-size: 32px; margin-left: 0; padding-left: 84px; padding-right: 0; margin-right: 0; }
  #bucket5 { font-size: 36px; margin-left: 13px; padding-left: 0; padding-right: 94px; margin-right: 25px; }
  #bucket6 { font-size: 40px; margin-left: -10px; padding-left: 104px; padding-right: -10px; }

  /* colours for them */
  .z, .zP, .zPP, .zPPP, .zPPPP, .zPPPPP { background: black; }
  .zPPPPPP, .zPPPPPPP, .zPPPPPPPP, .zPPPPPPPP, .zPPPPPPPPP,
  .zPPPPPPPPPP { background: grey; }
  .zPPPPPPPPPPP, .zPPPPPPPPPPPP, .zPPPPPPPPPPPPP,
  .zPPPPPPPPPPPPPP, .zPPPPPPPPPPPPPPP { background: silver; }
  #bucket1.zPPPPPPPPPPPPPPPP { background: red; }
  #bucket2.zPPPPPPPPPPPPPPPP { background: orange; }
  #bucket3.zPPPPPPPPPPPPPPPP { background: yellow; }
  #bucket4.zPPPPPPPPPPPPPPPP { background: lime; }
  #bucket5.zPPPPPPPPPPPPPPPP { background: blue; }
  #bucket6.zPPPPPPPPPPPPPPPP { background: purple; }

  /* The line-height for the .bucket div is worked out as follows:
   *
   * The div.bucket element has a line box with a few
   * inline-blocks. Each inline-block consists of:
   *
   *     2.0em vertical-align from baseline to bottom of inline-block
   *     1px bottom border
   *     1.0em bottom padding
   *     1.0em top padding
   *     1px top border
   *
   * The biggest inline-block has font-size: 40px.
   *
   * Thus the distance from the baseline to the top of the biggest
   * inline-block is (2em+1em+1em)*2em*20px+2px = 162px.
   *
   * The line box itself has no other contents, and its strut has zero
   * height and there is no half-leading, so the height of the
   * div.bucket is 162px.
   *
   * (Why use line-height:0 and font-size:0? Well:
   *
   * The div.bucket line box would have a height that is the maximum
   * of the following two sums:
   *
   *  1: half-leading + font descent at 1em + font ascent at 1em + half-leading
   *  2: half-leading + font descent at 1em + 162px
   *
   * Now the half-leading is (line-height - (font-ascent + font-descent))/2, so that is really:
   *
   *  1: (line-height - (font-ascent + font-descent))/2 + font descent + font ascent + (line-height - (font-ascent + font-descent))/2
   *  2: (line-height - (font-ascent + font-descent))/2 + font descent + 162px
   *
   * Which simplify to:
   *
   *  1: line-height
   *  2: line-height/2 + (font descent - font-ascent)/2 + 162px
   *
   * So if the following expression is true:
   *
   *    line-height > line-height/2 + (font descent - font-ascent)/2 + 162px
   *
   * That is, if this is true:
   *
   *    line-height > font descent - font-ascent + 324px
   *
   * ...then the line-height matters, otherwise the font does. Note
   * that font descent - font-ascent will be in the region of
   * 10px-30px (with Ahem, exactly 12px). However, if we make the
   * line-height big, then the _positioning_ of the inline-blocks will
   * depend on the font descent, since that is what will decide the
   * distance from the bottom of the line box to the baseline of the
   * block (since the baseline is set by the strut).
   *
   * However, in Acid2 a dependency on the font metrics was introduced
   * and this caused all kinds of problems. And we can't require Ahem
   * in the Acid tests, since it's unlikely most people will have it
   * installed.
   *
   * What we want is for the font to not matter, and the baseline to
   * be as high as possible. We can do that by saying that the font
   * and the line-height are zero.
   *
   * One word of warning. If your browser has a minimum font size feature
   * that forces font sizes up even when there is no text, you will need
   * to disable it before running this test.
   *
   */

  /* rules specific to the tests below */
  #instructions:last-child { white-space: pre-wrap; white-space: x-bogus; }
  /* replaced for http://dbaron.org/mozilla/visited-privacy with the three rules after it:
     #linktest:link { display: block; color: red; text-align: center; text-decoration: none; }
     #linktest.pending, #linktest:visited { display: none; } */
  #linktest { position: absolute; left: 17px; top: 18px; color: red; width: 80px; text-decoration: none; font: 900 small-caps 10px sans-serif; }
  #linktest:link { color: red; }
  #linktest.pending, #linktest:visited { color: white; }
  #\ { color: transparent; color: hsla(0, 0, 0, 1); position: fixed; top: 10px; left: 10px; font40px Arial, sans-serif; }
  #\  #result, #\  #score { position: fixed; top: 10%; left: 10%; width: 4em; z-index: 1; color: yellow; font-size: 50px; background: fuchsia; border: solid 1em purple; }
 </style>

 <!-- part of the HTTP tests -->
 <link rel="stylesheet" href="empty.css"><!-- text/html file (should be ignored, <h1> will go red if it isn't) -->

 <!-- the next five script blocks are part of one of the tests -->
 <script type="text/javascript">
  var d1 = "fail";
  var d2 = "fail";
  var d3 = "fail";
  var d4 = "fail";
  var d5 = "fail";
 </script>
 <script type="text/javascript" src="data:text/javascript,d1%20%3D%20'one'%3B"></script>
 <script type="text/javascript" src="data:text/javascript;base64,ZDIgPSAndHdvJzs%3D"></script>
 <script type="text/javascript" src="data:text/javascript;base64,%5a%44%4d%67%50%53%41%6e%64%47%68%79%5a%57%55%6e%4f%77%3D%3D"></script>
 <script type="text/javascript" src="data:text/javascript;base64,%20ZD%20Qg%0D%0APS%20An%20Zm91cic%0D%0A%207%20"></script>
 <script type="text/javascript" src="data:text/javascript,d5%20%3D%20'five%5Cu0027s'%3B"></script>

 <!-- part of the JS regexp and \0 value tests test -->
 <script type="text/javascript">
  var nullInRegexpArgumentResult = 0 < /script/.test('\0script') ? "passed" : "failed";
 </script>

 <!-- main test body -->
 <script type="text/javascript">
  var notifications = {};
  function notify(file) {
    // used in cross-file tests
    notifications[file] = 1;
  }
  function fail(message) {
    throw { message: message };
  }
  function assert(condition, message) {
    if (!condition)
      fail(message);
  }
  function assertEquals(expression, value, message) {
    if (expression != value) {
      expression = (""+expression).replace(/[\r\n]+/g, "\\n");
      value = (""+value).replace(/\r?\n/g, "\\n");
      fail("expected '" + value + "' but got '" + expression + "' - " + message);
    }
  }
  function getTestDocument() {
    var iframe = document.getElementById("selectors");
    var doc = iframe.contentDocument;
    for (var i = doc.documentElement.childNodes.length-1; i >= 0; i -= 1)
      doc.documentElement.removeChild(doc.documentElement.childNodes[i]);
    doc.documentElement.appendChild(doc.createElement('head'));
    doc.documentElement.firstChild.appendChild(doc.createElement('title'));
    doc.documentElement.appendChild(doc.createElement('body'));
    return doc;
  }
  function selectorTest(tester) {
    var doc = getTestDocument();
    var style = doc.createElement('style');
    style.appendChild(doc.createTextNode("* { z-index: 0; position: absolute; }\n"));
    doc.documentElement.firstChild.appendChild(style);
    var ruleCount = 0;
    tester(doc, function (selector) {
        ruleCount += 1;
        style.appendChild(doc.createTextNode(selector + " { z-index: " + ruleCount + "; }\n"));
        return ruleCount;
      }, function(node, rule, message) {
        var value = doc.defaultView.getComputedStyle(node, "").zIndex;
        assert(value != 'auto'"underlying problems prevent this test from running properly");
        assertEquals(value, rule, message);
    });
  }
  var kungFuDeathGrip = null; // used to hold things from test to test
  var tests = [

    // there are 6 buckets with 16 tests each, plus four special tests (0, 97, 98, and 99).

    // Remove the "JS required" message and the <script> element in the <body>
    function () {
      // test 0: whether removing an element that is the last child correctly recomputes styles for the new last child
      // also tests support for getComputedStyle, :last-child, pre-wrap, removing a <script> element
      // removing script:
      var scripts = document.getElementsByTagName('script');
      document.body.removeChild(scripts[scripts.length-1]);
      // removing last child:
      var last = document.getElementById('remove-last-child-test');
      var penultimate = last.previousSibling; // this should be the whitespace node
      penultimate = penultimate.previousSibling; // this should now be the actual penultimate element
      last.parentNode.removeChild(last);
      assertEquals(document.defaultView.getComputedStyle(penultimate, '').whiteSpace, 'pre-wrap'"found unexpected computed style");
      return 7;
    },

    // bucket 1: DOM Traversal, DOM Range, HTTP
    // DOM Traversal
    function () {
      // test 1: NodeFilters and Exceptions
      var doc = getTestDocument(); // looks like <!DOCTYPE><html><head><title/><\head><body/><\html>     (the '\'s are to avoid validation errors)
      var iteration = 0;
      var exception = "Roses";
      var test = function(node) {
        iteration += 1;
        switch (iteration) {
          case 1: case 3: case 4: case 6: case 7: case 8: case 9: case 14: case 15: throw exception;
          case 2: case 5: case 10: case 11: case 12: case 13: return true; // ToNumber(true) => 1
          default: throw 0;
        };
      };
      var check = function(o, method) {
        var ok = false;
        try {
          o[method]();
        } catch (e) {
          if (e === exception)
            ok = true;
        }
        assert(ok, "method " + o + "." + method + "() didn't forward exception");
      };
      var i = doc.createNodeIterator(doc.documentElement, 0xFFFFFFFF, test, true);
      check(i, "nextNode"); // 1
      assertEquals(i.nextNode(), doc.documentElement, "i.nextNode() didn't return the right node"); // 2
      check(i, "previousNode"); // 3
      var w = document.createTreeWalker(doc.documentElement, 0xFFFFFFFF, test, true);
      check(w, "nextNode"); // 4
      assertEquals(w.nextNode(), doc.documentElement.firstChild, "w.nextNode() didn't return the right node"); // 5
      check(w, "previousNode"); // 6
      check(w, "firstChild"); // 7
      check(w, "lastChild"); // 8
      check(w, "nextSibling"); // 9
      assertEquals(iteration, 9, "iterations went wrong");
      assertEquals(w.previousSibling(), null, "w.previousSibling() didn't return the right node"); // doesn't call filter
      assertEquals(iteration, 9, "filter called incorrectly for previousSibling()");
      assertEquals(w.lastChild(), doc.getElementsByTagName('title')[0], "w.lastChild() didn't return the right node"); // 10
      assertEquals(w.nextSibling(), null, "w.nextSibling() didn't return the right node"); // 11 (filter called on parent, to see if it's included, otherwise it could skip that and find a nextsibling elsewhere)
      assertEquals(iteration, 11, "filter called incorrectly for nextSibling()");
      assertEquals(w.parentNode(), doc.documentElement.firstChild, "w.parentNode() didn't return the right node"); // 12
      assertEquals(w.nextSibling(), doc.documentElement.lastChild, "w.nextSibling() didn't return the right node"); // 13
      check(w, "previousSibling"); // 14
      check(w, "parentNode"); // 15
      return 1;
    },
    function () {
      // test 2: Removing nodes during iteration
      var count = 0;
      var expect = function(n, node1, node2) {
        count += 1;
        assert(n == count, "reached expectation " + n + " when expecting expectation " + count);
        assertEquals(node1, node2, "expectation " + count + " failed");
      };
      var doc = getTestDocument();
      var t1 = doc.body.appendChild(doc.createElement('t1'));
      var t2 = doc.body.appendChild(doc.createElement('t2'));
      var t3 = doc.body.appendChild(doc.createElement('t3'));
      var t4 = doc.body.appendChild(doc.createElement('t4'));
      var callCount = 0;
      var filterFunctions = [
        function (node) { expect(1, node, doc.body); return true; }, // filter 0
        function (node) { expect(3, node, t1); return true; }, // filter 1
        function (node) { expect(5, node, t2); return true; }, // filter 2
        function (node) { expect(7, node, t3); doc.body.removeChild(t4); return true; }, // filter 3
        function (node) { expect(9, node, t4); return true; }, // filter 4
        function (node) { expect(11, node, t4); doc.body.removeChild(t4); return 2 /* REJECT */; }, // filter 5
        function (node) { expect(12, node, t3); return true; }, // filter 6
        function (node) { expect(14, node, t2); doc.body.removeChild(t2); return true; }, // filter 7
        function (node) { expect(16, node, t1); return true; }, // filter 8
      ];
      var i = doc.createNodeIterator(doc.documentElement.lastChild, 0xFFFFFFFF, function (node) { return filterFunctions[callCount++](node); }, true);
      // * B 1 2 3 4
      expect(2, i.nextNode(), doc.body); // filter 0
      // [B] * 1 2 3 4
      expect(4, i.nextNode(), t1); // filter 1
      // B [1] * 2 3 4
      expect(6, i.nextNode(), t2); // filter 2
      // B 1 [2] * 3 4
      expect(8, i.nextNode(), t3); // filter 3
      // B 1 2 [3] *
      doc.body.appendChild(t4);
      // B 1 2 [3] * 4
      expect(10, i.nextNode(), t4); // filter 4
      // B 1 2 3 [4] *
      expect(13, i.previousNode(), t3); // filters 5, 6
        // B 1 2 3 * (4) // filter 5
        // B 1 2 [3] *   // between 5 and 6
        // B 1 2 * (3)   // filter 6
      // B 1 2 * [3]
      expect(15, i.previousNode(), t2); // filter 7
        // B 1 * (2) [3]
        // -- spec says "For instance, if a NodeFilter removes a node
        //    from a document, it can still accept the node, which
        //    means that the node may be returned by the NodeIterator
        //    or TreeWalker even though it is no longer in the subtree
        //    being traversed."
        // -- but it also says "If changes to the iterated list do not
        //    remove the reference node, they do not affect the state
        //    of the NodeIterator."
      // B 1 * [3]
      expect(17, i.previousNode(), t1); // filter 8
      // B [1] * 3
      return 1;
    },
    function () {
      // test 3: the infinite iterator
      var doc = getTestDocument();
      for (var i = 0; i < 5; i += 1) {
        doc.body.appendChild(doc.createElement('section'));
        doc.body.lastChild.title = i;
      }
      var count = 0;
      var test = function() {
        if (count > 3 && count < 12)
          doc.body.appendChild(doc.body.firstChild);
        count += 1;
        return (count % 2 == 0) ? 1 : 2;
      };
      var i = doc.createNodeIterator(doc.body, 0xFFFFFFFF, test, true);
      assertEquals(i.nextNode().title"0""failure 1");
      assertEquals(i.nextNode().title"2""failure 2");
      assertEquals(i.nextNode().title"4""failure 3");
      assertEquals(i.nextNode().title"1""failure 4");
      assertEquals(i.nextNode().title"3""failure 5");
      assertEquals(i.nextNode().title"0""failure 6");
      assertEquals(i.nextNode().title"2""failure 7");
      assertEquals(i.nextNode(), null, "failure 8");
      return 1;
    },
    function () {
      // test 4: ignoring whitespace text nodes with node iterators
      var count = 0;
      var expect = function(node1, node2) {
        count += 1;
        assertEquals(node1, node2, "expectation " + count + " failed");
      };
      var allButWS = function (node) {
        if (node.nodeType == 3 && node.data.match(/^\s*$/))
          return 2;
        return 1;
      };
      var i = document.createNodeIterator(document.body, 0x01 | 0x04 | 0x08 | 0x10 | 0x20, allButWS, true);
      // now walk the document body and make sure everything is in the right place
      expect(i.nextNode(), document.body); // 1
      expect(i.nextNode(), document.getElementsByTagName('h1')[0]);
      expect(i.nextNode(), document.getElementsByTagName('h1')[0].firstChild);
      expect(i.nextNode(), document.getElementsByTagName('div')[0]);
      expect(i.nextNode(), document.getElementById('bucket1'));
      expect(i.nextNode(), document.getElementById('bucket2'));
      expect(i.nextNode(), document.getElementById('bucket3'));
      expect(i.nextNode(), document.getElementById('bucket4'));
      expect(i.nextNode(), document.getElementById('bucket5'));
      expect(i.nextNode(), document.getElementById('bucket6')); // 10
      expect(i.nextNode(), document.getElementById('result'));
      expect(i.nextNode(), document.getElementById('score'));
      expect(i.nextNode(), document.getElementById('score').firstChild);
      expect(i.nextNode(), document.getElementById('slash'));
      expect(i.nextNode(), document.getElementById('slash').firstChild);
      expect(i.nextNode(), document.getElementById('slash').nextSibling);
      expect(i.nextNode(), document.getElementById('slash').nextSibling.firstChild);
      expect(i.nextNode(), document.getElementsByTagName('map')[0]);
      expect(i.nextNode(), document.getElementsByTagName('area')[0]);
      expect(i.nextNode(), document.getElementsByTagName('iframe')[0]); // 20
      expect(i.nextNode(), document.getElementsByTagName('iframe')[0].firstChild);
      expect(i.nextNode(), document.getElementsByTagName('iframe')[1]);
      expect(i.nextNode(), document.getElementsByTagName('iframe')[1].firstChild);
      expect(i.nextNode(), document.getElementsByTagName('iframe')[2]);
      expect(i.nextNode(), document.forms[0]);
      expect(i.nextNode(), document.forms.form.elements[0]);
      expect(i.nextNode(), document.getElementsByTagName('table')[0]);
      expect(i.nextNode(), document.getElementsByTagName('tbody')[0]);
      expect(i.nextNode(), document.getElementsByTagName('tr')[0]);
      expect(i.nextNode(), document.getElementsByTagName('td')[0]);
      expect(i.nextNode(), document.getElementsByTagName('td')[0].getElementsByTagName('p')[0]);
      expect(i.nextNode(), document.getElementById('instructions'));
      expect(i.nextNode(), document.getElementById('instructions').firstChild);
      expect(i.nextNode().nodeName, "SPAN");
      expect(i.nextNode().nodeName, "#text");
      expect(i.nextNode(), document.links[1]);
      expect(i.nextNode(), document.links[1].firstChild);
      expect(i.nextNode(), document.getElementById('instructions').lastChild);
      expect(i.nextNode(), null);
      // walk it backwards for good measure
      expect(i.previousNode(), document.getElementById('instructions').lastChild);
      expect(i.previousNode(), document.links[1].firstChild);
      expect(i.previousNode(), document.links[1]);
      expect(i.previousNode().nodeName, "#text");
      expect(i.previousNode().nodeName, "SPAN");
      expect(i.previousNode(), document.getElementById('instructions').firstChild);
      expect(i.previousNode(), document.getElementById('instructions'));
      expect(i.previousNode(), document.getElementsByTagName('td')[0].getElementsByTagName('p')[0]);
      expect(i.previousNode(), document.getElementsByTagName('td')[0]);
      expect(i.previousNode(), document.getElementsByTagName('tr')[0]);
      expect(i.previousNode(), document.getElementsByTagName('tbody')[0]);
      expect(i.previousNode(), document.getElementsByTagName('table')[0]);
      expect(i.previousNode(), document.forms.form.elements[0]);
      expect(i.previousNode(), document.forms[0]);
      expect(i.previousNode(), document.getElementsByTagName('iframe')[2]);
      expect(i.previousNode(), document.getElementsByTagName('iframe')[1].firstChild);
      expect(i.previousNode(), document.getElementsByTagName('iframe')[1]);
      expect(i.previousNode(), document.getElementsByTagName('iframe')[0].firstChild);
      expect(i.previousNode(), document.getElementsByTagName('iframe')[0]); // 20
      expect(i.previousNode(), document.getElementsByTagName('area')[0]);
      expect(i.previousNode(), document.getElementsByTagName('map')[0]);
      expect(i.previousNode(), document.getElementById('slash').nextSibling.firstChild);
      expect(i.previousNode(), document.getElementById('slash').nextSibling);
      expect(i.previousNode(), document.getElementById('slash').firstChild);
      expect(i.previousNode(), document.getElementById('slash'));
      expect(i.previousNode(), document.getElementById('score').firstChild);
      expect(i.previousNode(), document.getElementById('score'));
      expect(i.previousNode(), document.getElementById('result'));
      expect(i.previousNode(), document.getElementById('bucket6'));
      expect(i.previousNode(), document.getElementById('bucket5'));
      expect(i.previousNode(), document.getElementById('bucket4'));
      expect(i.previousNode(), document.getElementById('bucket3'));
      expect(i.previousNode(), document.getElementById('bucket2'));
      expect(i.previousNode(), document.getElementById('bucket1'));
      expect(i.previousNode(), document.getElementsByTagName('div')[0]);
      expect(i.previousNode(), document.getElementsByTagName('h1')[0].firstChild);
      expect(i.previousNode(), document.getElementsByTagName('h1')[0]);
      expect(i.previousNode(), document.body);
      expect(i.previousNode(), null);
      return 1;
    },
    function () {
      // test 5: ignoring whitespace text nodes with tree walkers
      var count = 0;
      var expect = function(node1, node2) {
        count += 1;
        assertEquals(node1, node2, "expectation " + count + " failed");
      };
      var allButWS = function (node) {
        if (node.nodeType == 3 && node.data.match(/^\s*$/))
          return 3;
        return 1;
      };
      var w = document.createTreeWalker(document.body, 0x01 | 0x04 | 0x08 | 0x10 | 0x20, allButWS, true);
      expect(w.currentNode, document.body);
      expect(w.parentNode(), null);
      expect(w.currentNode, document.body);
      expect(w.firstChild(), document.getElementsByTagName('h1')[0]);
      expect(w.firstChild().nodeType, 3);
      expect(w.parentNode(), document.getElementsByTagName('h1')[0]);
      expect(w.nextSibling().previousSibling.nodeType, 3);
      expect(w.nextSibling(), document.getElementsByTagName('p')[6]);
      expect(w.nextSibling(), document.getElementsByTagName('map')[0]);
      expect(w.lastChild(), document.getElementsByTagName('table')[0]);
      expect(w.lastChild(), document.getElementsByTagName('tbody')[0]);
      expect(w.nextNode(), document.getElementsByTagName('tr')[0]);
      expect(w.nextNode(), document.getElementsByTagName('td')[0]);
      expect(w.nextNode(), document.getElementsByTagName('p')[7]);
      expect(w.nextNode(), document.getElementsByTagName('p')[8]); // instructions.inc paragraph
      expect(w.previousSibling(), document.getElementsByTagName('map')[0]);
      expect(w.previousNode().data, "100");
      expect(w.parentNode().tagName, "SPAN");
      expect(w.parentNode(), document.getElementById('result'));
      expect(w.parentNode(), document.body);
      expect(w.lastChild().id, "instructions");
      expect(w.lastChild().data.substr(0,1), ".");
      expect(w.previousNode(), document.links[1].firstChild);
      return 1;
    },
    function () {
      // test 6: walking outside a tree
      var doc = getTestDocument();
      var p = doc.createElement('p');
      doc.body.appendChild(p);
      var b = doc.body;
      var w = document.createTreeWalker(b, 0xFFFFFFFF, null, true);
      assertEquals(w.currentNode, b, "basic use of TreeWalker failed: currentNode");
      assertEquals(w.lastChild(), p, "basic use of TreeWalker failed: lastChild()");
      assertEquals(w.previousNode(), b, "basic use of TreeWalker failed: previousNode()");
      doc.documentElement.removeChild(b);
      assertEquals(w.lastChild(), p, "TreeWalker failed after removing the current node from the tree");
      assertEquals(w.nextNode(), null, "failed to walk into the end of a subtree");
      doc.documentElement.appendChild(p);
      assertEquals(w.previousNode(), doc.getElementsByTagName('title')[0], "failed to handle regrafting correctly");
      p.appendChild(b);
      assertEquals(w.nextNode(), p, "couldn't retrace steps");
      assertEquals(w.nextNode(), b, "couldn't step back into root");
      assertEquals(w.previousNode(), null, "root didn't retake its rootish position");
      return 1;
    },

    // DOM Range
    function () {
      // test 7: basic ranges tests
      var r = document.createRange();
      assert(r, "range not created");
      assert(r.collapsed, "new range wasn't collapsed");
      assertEquals(r.commonAncestorContainer, document, "new range's common ancestor wasn't the document");
      assertEquals(r.startContainer, document, "new range's start container wasn't the document");
      assertEquals(r.startOffset, 0, "new range's start offset wasn't zero");
      assertEquals(r.endContainer, document, "new range's end container wasn't the document");
      assertEquals(r.endOffset, 0, "new range's end offset wasn't zero");
      assert(r.cloneContents(), "cloneContents() didn't return an object");
      assertEquals(r.cloneContents().childNodes.length, 0, "nothing cloned was more than nothing");
      assertEquals(r.cloneRange().toString(), """nothing cloned stringifed to more than nothing");
      r.collapse(true); // no effect
      assertEquals(r.compareBoundaryPoints(r.START_TO_END, r.cloneRange()), 0, "starting boundary point of range wasn't the same as the end boundary point of the clone range");
      r.deleteContents(); // no effect
      assertEquals(r.extractContents().childNodes.length, 0, "nothing removed was more than nothing");
      var endOffset = r.endOffset;
      r.insertNode(document.createComment("commented inserted to test ranges"));
      r.setEnd(r.endContainer, endOffset + 1); // added to work around spec bug that smaug is blocking the errata for
      try {
        assert(!r.collapsed, "range with inserted comment is collapsed");
        assertEquals(r.commonAncestorContainer, document, "range with inserted comment has common ancestor that isn't the document");
        assertEquals(r.startContainer, document, "range with inserted comment has start container that isn't the document");
        assertEquals(r.startOffset, 0, "range with inserted comment has start offset that isn't zero");
        assertEquals(r.endContainer, document, "range with inserted comment has end container that isn't the document");
        assertEquals(r.endOffset, 1, "range with inserted comment has end offset that isn't after the comment");
      } finally {
        document.removeChild(document.firstChild);
      }
      return 1;
    },
    function () {
      // test 8: moving boundary points
      var doc = document.implementation.createDocument(null, null, null);
      var root = doc.createElement("root");
      doc.appendChild(root);
      var e1 = doc.createElement("e");
      root.appendChild(e1);
      var e2 = doc.createElement("e");
      root.appendChild(e2);
      var e3 = doc.createElement("e");
      root.appendChild(e3);
      var r = doc.createRange();
      r.setStart(e2, 0);
      r.setEnd(e3, 0);
      assert(!r.collapsed, "non-empty range claims to be collapsed");
      r.setEnd(e1, 0);
      assert(r.collapsed, "setEnd() didn't collapse the range");
      assertEquals(r.startContainer, e1, "startContainer is wrong after setEnd()");
      assertEquals(r.startOffset, 0, "startOffset is wrong after setEnd()");
      assertEquals(r.endContainer, e1, "endContainer is wrong after setEnd()");
      assertEquals(r.endOffset, 0, "endOffset is wrong after setEnd()");
      r.setStartBefore(e3);
      assert(r.collapsed, "setStartBefore() didn't collapse the range");
      assertEquals(r.startContainer, root, "startContainer is wrong after setStartBefore()");
      assertEquals(r.startOffset, 2, "startOffset is wrong after setStartBefore()");
      assertEquals(r.endContainer, root, "endContainer is wrong after setStartBefore()");
      assertEquals(r.endOffset, 2, "endOffset is wrong after setStartBefore()");
      r.setEndAfter(root);
      assert(!r.collapsed, "setEndAfter() didn't uncollapse the range");
      assertEquals(r.startContainer, root, "startContainer is wrong after setEndAfter()");
      assertEquals(r.startOffset, 2, "startOffset is wrong after setEndAfter()");
      assertEquals(r.endContainer, doc, "endContainer is wrong after setEndAfter()");
      assertEquals(r.endOffset, 1, "endOffset is wrong after setEndAfter()");
      r.setStartAfter(e2);
      assert(!r.collapsed, "setStartAfter() collapsed the range");
      assertEquals(r.startContainer, root, "startContainer is wrong after setStartAfter()");
      assertEquals(r.startOffset, 2, "startOffset is wrong after setStartAfter()");
      assertEquals(r.endContainer, doc, "endContainer is wrong after setStartAfter()");
      assertEquals(r.endOffset, 1, "endOffset is wrong after setStartAfter()");
      var msg = '';
      try {
        r.setEndBefore(doc);
        msg = "no exception thrown for setEndBefore() the document itself";
      } catch (e) {
// COMMENTED OUT FOR 2011 UPDATE - we may want to merge RangeException and DOMException
//        if (e.BAD_BOUNDARYPOINTS_ERR != 1)
//          msg = 'not a RangeException';
//        else
//        if (e.INVALID_NODE_TYPE_ERR != 2)
//          msg = 'RangeException has no INVALID_NODE_TYPE_ERR';
//        else
//        if ("INVALID_ACCESS_ERR" in e)
//          msg = 'RangeException has DOMException constants';
//        else
        if (e.code != e.INVALID_NODE_TYPE_ERR)
          msg = 'wrong exception raised from setEndBefore()';
      }
      assert(msg == "", msg);
      assert(!r.collapsed, "setEndBefore() collapsed the range");
      assertEquals(r.startContainer, root, "startContainer is wrong after setEndBefore()");
      assertEquals(r.startOffset, 2, "startOffset is wrong after setEndBefore()");
      assertEquals(r.endContainer, doc, "endContainer is wrong after setEndBefore()");
      assertEquals(r.endOffset, 1, "endOffset is wrong after setEndBefore()");
      r.collapse(false);
      assert(r.collapsed, "collapse() collapsed the range");
      assertEquals(r.startContainer, doc, "startContainer is wrong after collapse()");
      assertEquals(r.startOffset, 1, "startOffset is wrong after collapse()");
      assertEquals(r.endContainer, doc, "endContainer is wrong after collapse()");
      assertEquals(r.endOffset, 1, "endOffset is wrong after collapse()");
      r.selectNodeContents(root);
      assert(!r.collapsed, "collapsed is wrong after selectNodeContents()");
      assertEquals(r.startContainer, root, "startContainer is wrong after selectNodeContents()");
      assertEquals(r.startOffset, 0, "startOffset is wrong after selectNodeContents()");
      assertEquals(r.endContainer, root, "endContainer is wrong after selectNodeContents()");
      assertEquals(r.endOffset, 3, "endOffset is wrong after selectNodeContents()");
      r.selectNode(e2);
      assert(!r.collapsed, "collapsed is wrong after selectNode()");
      assertEquals(r.startContainer, root, "startContainer is wrong after selectNode()");
      assertEquals(r.startOffset, 1, "startOffset is wrong after selectNode()");
      assertEquals(r.endContainer, root, "endContainer is wrong after selectNode()");
      assertEquals(r.endOffset, 2, "endOffset is wrong after selectNode()");
      return 1;
    },
    function () {
      // test 9: extractContents() in a Document
      var doc = getTestDocument();
      var h1 = doc.createElement('h1');
      var t1 = doc.createTextNode('Hello ');
      h1.appendChild(t1);
      var em = doc.createElement('em');
      var t2 = doc.createTextNode('Wonderful');
      em.appendChild(t2);
      h1.appendChild(em);
      var t3 = doc.createTextNode(' Kitty');
      h1.appendChild(t3);
      doc.body.appendChild(h1);
      var p = doc.createElement('p');
      var t4 = doc.createTextNode('How are you?');
      p.appendChild(t4);
      doc.body.appendChild(p);
      var r = doc.createRange();
      r.selectNodeContents(doc);
      assertEquals(r.toString(), "Hello Wonderful KittyHow are you?""toString() on range selecting Document gave wrong output");
      r.setStart(t2, 6);
      r.setEnd(p, 0);
      // <body><h1>Hello <em>Wonder ful<\em> Kitty<\h1><p> How are you?<\p><\body>     (the '\'s are to avoid validation errors)
      //                           ^----------------------^
      assertEquals(r.toString(), "ful Kitty""toString() on range crossing text nodes gave wrong output");
      var f = r.extractContents();
      // <h1><em>ful<\em> Kitty<\h1><p><\p>
      // ccccccccccccccccMMMMMMcccccccccccc
      assertEquals(f.nodeType, 11, "failure 1");
      assert(f.childNodes.length == 2, "expected two children in the result, got " + f.childNodes.length);
      assertEquals(f.childNodes[0].tagName, "H1""failure 3");
      assert(f.childNodes[0] != h1"failure 4");
      assertEquals(f.childNodes[0].childNodes.length, 2, "failure 5");
      assertEquals(f.childNodes[0].childNodes[0].tagName, "EM""failure 6");
      assert(f.childNodes[0].childNodes[0] != em"failure 7");
      assertEquals(f.childNodes[0].childNodes[0].childNodes.length, 1, "failure 8");
      assertEquals(f.childNodes[0].childNodes[0].childNodes[0].data, "ful""failure 9");
      assert(f.childNodes[0].childNodes[0].childNodes[0] != t2, "failure 10");
      assertEquals(f.childNodes[0].childNodes[1], t3, "failure 11");
      assert(f.childNodes[0].childNodes[1] != em"failure 12");
      assertEquals(f.childNodes[1].tagName, "P""failure 13");
      assertEquals(f.childNodes[1].childNodes.length, 0, "failure 14");
      assert(f.childNodes[1] != p, "failure 15");
      return 1;
    },
    function () {
      // test 10: Ranges and Attribute Nodes
// COMMENTED OUT FOR 2011 UPDATE - turns out instead of dropping Attr entirely, as Acid3 originally expected, the API is just being refactored
//      var e = document.getElementById('result');
//      if (!e.getAttributeNode)
//        return 1; // support for attribute nodes is optional in Acid3, because attribute nodes might be removed from DOM Core in the future.
//      // however, if they're supported, they'd better work:
//      var a = e.getAttributeNode('id');
//      var r = document.createRange();
//      r.selectNodeContents(a);
//      assertEquals(r.toString(), "result""toString() didn't work for attribute node");
//      var t = a.firstChild;
//      var f = r.extractContents();
//      assertEquals(f.childNodes.length, 1, "extracted contents were the wrong length");
//      assertEquals(f.childNodes[0], t, "extracted contents were the wrong node");
//      assertEquals(t.textContent, 'result'"extracted contents didn't match old attribute value");
//      assertEquals(r.toString(), ''"extracting contents didn't empty attribute value; instead equals '" + r.toString() + "'");
//      assertEquals(e.getAttribute('id'), ''"extracting contents didn't change 'id' attribute to empty string");
//      e.id = 'result';
      return 1;
    },
    function () {
      // test 11: Ranges and Comments
      var msg;
      var doc = getTestDocument();
      var c1 = doc.createComment("11111");
      doc.appendChild(c1);
      var r = doc.createRange();
      r.selectNode(c1);
      msg = 'wrong exception raised';
      try {
        r.surroundContents(doc.createElement('a'));
        msg = 'no exception raised';
      } catch (e) {
        if ('code' in e)
          msg += '; code = ' + e.code;
        if (e.code == 3) // HIERARCHY_REQUEST_ERR
          msg = '';
      }
      assert(msg == ''"when inserting into Document with another child: " + msg);
      var c2 = doc.createComment("22222");
      doc.body.appendChild(c2);
      var c3 = doc.createComment("33333");
      doc.body.appendChild(c3);
      r.setStart(c2, 2);
      r.setEnd(c3, 3);
      var msg = 'wrong exception raised';
      try {
        r.surroundContents(doc.createElement('a'));
        msg = 'no exception raised';
      } catch (e) {
// COMMENTED OUT FOR 2011 UPDATE - DOM Core changes the exception from RangeException.BAD_BOUNDARYPOINTS_ERR (1) to DOMException.INVALID_STATE_ERR (11)
//        if ('code' in e)
//          msg += '; code = ' + e.code;
//        if (e.code == 1)
          msg = '';
      }
      assert(msg == ''"when trying to surround two halves of comment: " + msg);
      assertEquals(r.toString(), """comments returned text");
      return 1;
    },
    function () {
      // test 12: Ranges under mutations: insertion into text nodes
      var doc = getTestDocument();
      var p = doc.createElement('p');
      var t1 = doc.createTextNode('12345');
      p.appendChild(t1);
      var t2 = doc.createTextNode('ABCDE');
      p.appendChild(t2);
      doc.body.appendChild(p);
      var r = doc.createRange();
      r.setStart(p.firstChild, 2);
      r.setEnd(p.firstChild, 3);
      assert(!r.collapsed, "collapsed is wrong at start");
      assertEquals(r.commonAncestorContainer, p.firstChild, "commonAncestorContainer is wrong at start");
      assertEquals(r.startContainer, p.firstChild, "startContainer is wrong at start");
      assertEquals(r.startOffset, 2, "startOffset is wrong at start");
      assertEquals(r.endContainer, p.firstChild, "endContainer is wrong at start");
      assertEquals(r.endOffset, 3, "endOffset is wrong at start");
      assertEquals(r.toString(), "3""range in text node stringification failed");
      r.insertNode(p.lastChild);
      assertEquals(p.childNodes.length, 3, "insertion of node made wrong number of child nodes");
      assertEquals(p.childNodes[0], t1, "unexpected first text node");
      assertEquals(p.childNodes[0].data, "12""unexpected first text node contents");
      assertEquals(p.childNodes[1], t2, "unexpected second text node");
      assertEquals(p.childNodes[1].data, "ABCDE""unexpected second text node");
      assertEquals(p.childNodes[2].data, "345""unexpected third text node contents");
      // The spec is very vague about what exactly should be in the range afterwards:
      // the insertion results in a splitText(), which it says is equivalent to a truncation
      // followed by an insertion, but it doesn't say what to do when you have a truncation,
      // so we don't know where either the start or the end boundary points end up.
      // The spec really should be clarified for how to handle splitText() and
      // text node truncation in general
      // The only thing that seems very clear is that the inserted text node should
      // be in the range, and it has to be at the start, since insertion always puts it at
      // the start.
      assert(!r.collapsed, "collapsed is wrong after insertion");
      assert(r.toString().match(/^ABCDE/), "range didn't start with the expected text; range stringified to '" + r.toString() + "'");
      return 1;
    },
    function () {
      // test 13: Ranges under mutations: deletion
      var doc = getTestDocument();
      var p = doc.createElement('p');
      p.appendChild(doc.createTextNode("12345"));
      doc.body.appendChild(p);
      var r = doc.createRange();
      r.setEnd(doc.body, 1);
      r.setStart(p.firstChild, 2);
      assert(!r.collapsed, "collapsed is wrong at start");
      assertEquals(r.commonAncestorContainer, doc.body"commonAncestorContainer is wrong at start");
      assertEquals(r.startContainer, p.firstChild, "startContainer is wrong at start");
      assertEquals(r.startOffset, 2, "startOffset is wrong at start");
      assertEquals(r.endContainer, doc.body"endContainer is wrong at start");
      assertEquals(r.endOffset, 1, "endOffset is wrong at start");
      doc.body.removeChild(p);
      assert(r.collapsed, "collapsed is wrong after deletion");
      assertEquals(r.commonAncestorContainer, doc.body"commonAncestorContainer is wrong after deletion");
      assertEquals(r.startContainer, doc.body"startContainer is wrong after deletion");
      assertEquals(r.startOffset, 0, "startOffset is wrong after deletion");
      assertEquals(r.endContainer, doc.body"endContainer is wrong after deletion");
      assertEquals(r.endOffset, 0, "endOffset is wrong after deletion");
      return 1;
    },

    // HTTP
    function () {
      // test 14: HTTP - Content-Type: image/png
      assert(!notifications['empty.png'], "privilege escalation security bug: PNG ran script");
      var iframe = document.getElementsByTagName('iframe')[0];
      assert(iframe"no