tor-browser

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

extend.js (7294B)


      1 "use strict";
      2 
      3 // Also test a selection with no ranges
      4 testRanges.unshift("[]");
      5 
      6 // Run a subset of all of extend tests.
      7 // Huge number of tests in a single file causes problems. Each of
      8 // extend-NN.html runs a part of them.
      9 //
     10 // startIndex - Start index in testRanges array
     11 // optionalEndIndex - End index in testRanges array + 1. If this argument is
     12 //     omitted, testRanges.length is applied.
     13 function testExtendSubSet(startIndex, optionalEndIndex) {
     14    var endIndex = optionalEndIndex === undefined ? testRanges.length : optionalEndIndex;
     15    if (startIndex < 0 || startIndex >= testRanges.length)
     16        throw "Sanity check: Specified index is invalid.";
     17    if (endIndex < 0 || endIndex > testRanges.length)
     18        throw "Sanity check: Specified index is invalid.";
     19 
     20    // We test Selections that go both forwards and backwards here.  In the
     21    // latter case we need to use extend() to force it to go backwards, which is
     22    // fair enough, since that's what we're testing.  We test collapsed
     23    // selections only once.
     24    for (var i = startIndex; i < endIndex; i++) {
     25        var endpoints = eval(testRanges[i]);
     26        // We can't test extend() with unselectable endpoints.
     27        if (!isSelectableNode(endpoints[0]) || !isSelectableNode(endpoints[2]))
     28            continue;
     29        for (var j = 0; j < testPoints.length; j++) {
     30            if (endpoints[0] == endpoints[2]
     31            && endpoints[1] == endpoints[3]) {
     32                // Test collapsed selections only once
     33                test(function() {
     34                    setSelectionForwards(endpoints);
     35                    testExtend(endpoints, eval(testPoints[j]));
     36                }, "extend() with range " + i + " " + testRanges[i]
     37                + " and point " + j + " " + testPoints[j]);
     38            } else {
     39                test(function() {
     40                    setSelectionForwards(endpoints);
     41                    testExtend(endpoints, eval(testPoints[j]));
     42                }, "extend() forwards with range " + i + " " + testRanges[i]
     43                + " and point " + j + " " + testPoints[j]);
     44 
     45                test(function() {
     46                    setSelectionBackwards(endpoints);
     47                    testExtend(endpoints, eval(testPoints[j]));
     48                }, "extend() backwards with range " + i + " " + testRanges[i]
     49                + " and point " + j + " " + testPoints[j]);
     50            }
     51        }
     52    }
     53 }
     54 
     55 function testExtend(endpoints, target) {
     56    assert_equals(getSelection().rangeCount, endpoints.length/4,
     57        "Sanity check: rangeCount must be correct");
     58 
     59    var node = target[0];
     60    var offset = target[1];
     61 
     62    // "If node's root is not the document associated with the context object,
     63    // abort these steps."
     64    if (!document.contains(node)) {
     65        assertSelectionNoChange(function() {
     66            selection.extend(node, offset);
     67        });
     68        return;
     69    }
     70 
     71    // "If the context object's range is null, throw an InvalidStateError
     72    // exception and abort these steps."
     73    if (getSelection().rangeCount == 0) {
     74        assert_throws_dom("INVALID_STATE_ERR", function() {
     75            selection.extend(node, offset);
     76        }, "extend() when rangeCount is 0 must throw InvalidStateError");
     77        return;
     78    }
     79 
     80    assert_equals(getSelection().getRangeAt(0).startContainer, endpoints[0],
     81        "Sanity check: startContainer must be correct");
     82    assert_equals(getSelection().getRangeAt(0).startOffset, endpoints[1],
     83        "Sanity check: startOffset must be correct");
     84    assert_equals(getSelection().getRangeAt(0).endContainer, endpoints[2],
     85        "Sanity check: endContainer must be correct");
     86    assert_equals(getSelection().getRangeAt(0).endOffset, endpoints[3],
     87        "Sanity check: endOffset must be correct");
     88 
     89    // "Let anchor and focus be the context object's anchor and focus, and let
     90    // new focus be the boundary point (node, offset)."
     91    var anchorNode = getSelection().anchorNode;
     92    var anchorOffset = getSelection().anchorOffset;
     93    var focusNode = getSelection().focusNode;
     94    var focusOffset = getSelection().focusOffset;
     95 
     96    // "Let new range be a new range."
     97    //
     98    // We'll always be setting either new range's start or its end to new
     99    // focus, so we'll always throw at some point.  Test that now.
    100    //
    101    // From DOM4's "set the start or end of a range": "If node is a doctype,
    102    // throw an "InvalidNodeTypeError" exception and terminate these steps."
    103    if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
    104        assert_throws_dom("INVALID_NODE_TYPE_ERR", function() {
    105            selection.extend(node, offset);
    106        }, "extend() to a doctype must throw InvalidNodeTypeError");
    107        return;
    108    }
    109 
    110    // From DOM4's "set the start or end of a range": "If offset is greater
    111    // than node's length, throw an "IndexSizeError" exception and terminate
    112    // these steps."
    113    //
    114    // FIXME: We should be casting offset to an unsigned int per WebIDL.  Until
    115    // we do, we need the offset < 0 check too.
    116    if (offset < 0 || offset > getNodeLength(node)) {
    117        assert_throws_dom("INDEX_SIZE_ERR", function() {
    118            selection.extend(node, offset);
    119        }, "extend() to an offset that's greater than node length (" + getNodeLength(node) + ") must throw IndexSizeError");
    120        return;
    121    }
    122 
    123    // Now back to the editing spec.
    124    var originalRange = getSelection().getRangeAt(0);
    125 
    126    // "If node's root is not the same as the context object's range's root,
    127    // set new range's start and end to (node, offset)."
    128    //
    129    // "Otherwise, if anchor is before or equal to new focus, set new range's
    130    // start to anchor, then set its end to new focus."
    131    //
    132    // "Otherwise, set new range's start to new focus, then set its end to
    133    // anchor."
    134    //
    135    // "Set the context object's range to new range."
    136    //
    137    // "If new focus is before anchor, set the context object's direction to
    138    // backwards. Otherwise, set it to forwards."
    139    //
    140    // The upshot of all these is summed up by just testing the anchor and
    141    // offset.
    142    getSelection().extend(node, offset);
    143 
    144    if (furthestAncestor(anchorNode) == furthestAncestor(node)) {
    145        assert_equals(getSelection().anchorNode, anchorNode,
    146            "anchorNode must not change if the node passed to extend() has the same root as the original range");
    147        assert_equals(getSelection().anchorOffset, anchorOffset,
    148            "anchorOffset must not change if the node passed to extend() has the same root as the original range");
    149    } else {
    150        assert_equals(getSelection().anchorNode, node,
    151            "anchorNode must be the node passed to extend() if it has a different root from the original range");
    152        assert_equals(getSelection().anchorOffset, offset,
    153            "anchorOffset must be the offset passed to extend() if the node has a different root from the original range");
    154    }
    155    assert_equals(getSelection().focusNode, node,
    156        "focusNode must be the node passed to extend()");
    157    assert_equals(getSelection().focusOffset, offset,
    158        "focusOffset must be the offset passed to extend()");
    159    assert_not_equals(getSelection().getRangeAt(0), originalRange,
    160        "extend() must replace any existing range with a new one, not mutate the existing one");
    161 }