This commit is contained in:
2025-01-04 00:34:03 +01:00
parent 41829408dc
commit 0ca14bbc19
18111 changed files with 1871397 additions and 0 deletions

19
resources/app/node_modules/rope-sequence/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (C) 2016 by Marijn Haverbeke <marijn@haverbeke.berlin>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

209
resources/app/node_modules/rope-sequence/dist/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,209 @@
'use strict';
var GOOD_LEAF_SIZE = 200;
// :: class<T> A rope sequence is a persistent sequence data structure
// that supports appending, prepending, and slicing without doing a
// full copy. It is represented as a mostly-balanced tree.
var RopeSequence = function RopeSequence () {};
RopeSequence.prototype.append = function append (other) {
if (!other.length) { return this }
other = RopeSequence.from(other);
return (!this.length && other) ||
(other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) ||
(this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) ||
this.appendInner(other)
};
// :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
// Prepend an array or other rope to this one, returning a new rope.
RopeSequence.prototype.prepend = function prepend (other) {
if (!other.length) { return this }
return RopeSequence.from(other).append(this)
};
RopeSequence.prototype.appendInner = function appendInner (other) {
return new Append(this, other)
};
// :: (?number, ?number) → RopeSequence<T>
// Create a rope repesenting a sub-sequence of this rope.
RopeSequence.prototype.slice = function slice (from, to) {
if ( from === void 0 ) from = 0;
if ( to === void 0 ) to = this.length;
if (from >= to) { return RopeSequence.empty }
return this.sliceInner(Math.max(0, from), Math.min(this.length, to))
};
// :: (number) → T
// Retrieve the element at the given position from this rope.
RopeSequence.prototype.get = function get (i) {
if (i < 0 || i >= this.length) { return undefined }
return this.getInner(i)
};
// :: ((element: T, index: number) → ?bool, ?number, ?number)
// Call the given function for each element between the given
// indices. This tends to be more efficient than looping over the
// indices and calling `get`, because it doesn't have to descend the
// tree for every element.
RopeSequence.prototype.forEach = function forEach (f, from, to) {
if ( from === void 0 ) from = 0;
if ( to === void 0 ) to = this.length;
if (from <= to)
{ this.forEachInner(f, from, to, 0); }
else
{ this.forEachInvertedInner(f, from, to, 0); }
};
// :: ((element: T, index: number) → U, ?number, ?number) → [U]
// Map the given functions over the elements of the rope, producing
// a flat array.
RopeSequence.prototype.map = function map (f, from, to) {
if ( from === void 0 ) from = 0;
if ( to === void 0 ) to = this.length;
var result = [];
this.forEach(function (elt, i) { return result.push(f(elt, i)); }, from, to);
return result
};
// :: (?union<[T], RopeSequence<T>>) → RopeSequence<T>
// Create a rope representing the given array, or return the rope
// itself if a rope was given.
RopeSequence.from = function from (values) {
if (values instanceof RopeSequence) { return values }
return values && values.length ? new Leaf(values) : RopeSequence.empty
};
var Leaf = /*@__PURE__*/(function (RopeSequence) {
function Leaf(values) {
RopeSequence.call(this);
this.values = values;
}
if ( RopeSequence ) Leaf.__proto__ = RopeSequence;
Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype );
Leaf.prototype.constructor = Leaf;
var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } };
Leaf.prototype.flatten = function flatten () {
return this.values
};
Leaf.prototype.sliceInner = function sliceInner (from, to) {
if (from == 0 && to == this.length) { return this }
return new Leaf(this.values.slice(from, to))
};
Leaf.prototype.getInner = function getInner (i) {
return this.values[i]
};
Leaf.prototype.forEachInner = function forEachInner (f, from, to, start) {
for (var i = from; i < to; i++)
{ if (f(this.values[i], start + i) === false) { return false } }
};
Leaf.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
for (var i = from - 1; i >= to; i--)
{ if (f(this.values[i], start + i) === false) { return false } }
};
Leaf.prototype.leafAppend = function leafAppend (other) {
if (this.length + other.length <= GOOD_LEAF_SIZE)
{ return new Leaf(this.values.concat(other.flatten())) }
};
Leaf.prototype.leafPrepend = function leafPrepend (other) {
if (this.length + other.length <= GOOD_LEAF_SIZE)
{ return new Leaf(other.flatten().concat(this.values)) }
};
prototypeAccessors.length.get = function () { return this.values.length };
prototypeAccessors.depth.get = function () { return 0 };
Object.defineProperties( Leaf.prototype, prototypeAccessors );
return Leaf;
}(RopeSequence));
// :: RopeSequence
// The empty rope sequence.
RopeSequence.empty = new Leaf([]);
var Append = /*@__PURE__*/(function (RopeSequence) {
function Append(left, right) {
RopeSequence.call(this);
this.left = left;
this.right = right;
this.length = left.length + right.length;
this.depth = Math.max(left.depth, right.depth) + 1;
}
if ( RopeSequence ) Append.__proto__ = RopeSequence;
Append.prototype = Object.create( RopeSequence && RopeSequence.prototype );
Append.prototype.constructor = Append;
Append.prototype.flatten = function flatten () {
return this.left.flatten().concat(this.right.flatten())
};
Append.prototype.getInner = function getInner (i) {
return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length)
};
Append.prototype.forEachInner = function forEachInner (f, from, to, start) {
var leftLen = this.left.length;
if (from < leftLen &&
this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false)
{ return false }
if (to > leftLen &&
this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false)
{ return false }
};
Append.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
var leftLen = this.left.length;
if (from > leftLen &&
this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false)
{ return false }
if (to < leftLen &&
this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false)
{ return false }
};
Append.prototype.sliceInner = function sliceInner (from, to) {
if (from == 0 && to == this.length) { return this }
var leftLen = this.left.length;
if (to <= leftLen) { return this.left.slice(from, to) }
if (from >= leftLen) { return this.right.slice(from - leftLen, to - leftLen) }
return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen))
};
Append.prototype.leafAppend = function leafAppend (other) {
var inner = this.right.leafAppend(other);
if (inner) { return new Append(this.left, inner) }
};
Append.prototype.leafPrepend = function leafPrepend (other) {
var inner = this.left.leafPrepend(other);
if (inner) { return new Append(inner, this.right) }
};
Append.prototype.appendInner = function appendInner (other) {
if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1)
{ return new Append(this.left, new Append(this.right, other)) }
return new Append(this, other)
};
return Append;
}(RopeSequence));
module.exports = RopeSequence;

View File

@@ -0,0 +1,11 @@
export default class RopeSequence<T> {
length: number
prepend(other: RopeSequence<T> | readonly T[]): RopeSequence<T>
append(other: RopeSequence<T> | readonly T[]): RopeSequence<T>
slice(from: number, to?: number): RopeSequence<T>
get(i: number): T
forEach(f: (elt: T, index: number) => boolean | void, from?: number, to?: number): void
map<U>(f: (elt: T, index: number) => U, from?: number, to?: number): U[]
static from<T>(value: readonly T[] | RopeSequence<T>): RopeSequence<T>
static empty: RopeSequence<any>
}

207
resources/app/node_modules/rope-sequence/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,207 @@
var GOOD_LEAF_SIZE = 200;
// :: class<T> A rope sequence is a persistent sequence data structure
// that supports appending, prepending, and slicing without doing a
// full copy. It is represented as a mostly-balanced tree.
var RopeSequence = function RopeSequence () {};
RopeSequence.prototype.append = function append (other) {
if (!other.length) { return this }
other = RopeSequence.from(other);
return (!this.length && other) ||
(other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) ||
(this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) ||
this.appendInner(other)
};
// :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
// Prepend an array or other rope to this one, returning a new rope.
RopeSequence.prototype.prepend = function prepend (other) {
if (!other.length) { return this }
return RopeSequence.from(other).append(this)
};
RopeSequence.prototype.appendInner = function appendInner (other) {
return new Append(this, other)
};
// :: (?number, ?number) → RopeSequence<T>
// Create a rope repesenting a sub-sequence of this rope.
RopeSequence.prototype.slice = function slice (from, to) {
if ( from === void 0 ) from = 0;
if ( to === void 0 ) to = this.length;
if (from >= to) { return RopeSequence.empty }
return this.sliceInner(Math.max(0, from), Math.min(this.length, to))
};
// :: (number) → T
// Retrieve the element at the given position from this rope.
RopeSequence.prototype.get = function get (i) {
if (i < 0 || i >= this.length) { return undefined }
return this.getInner(i)
};
// :: ((element: T, index: number) → ?bool, ?number, ?number)
// Call the given function for each element between the given
// indices. This tends to be more efficient than looping over the
// indices and calling `get`, because it doesn't have to descend the
// tree for every element.
RopeSequence.prototype.forEach = function forEach (f, from, to) {
if ( from === void 0 ) from = 0;
if ( to === void 0 ) to = this.length;
if (from <= to)
{ this.forEachInner(f, from, to, 0); }
else
{ this.forEachInvertedInner(f, from, to, 0); }
};
// :: ((element: T, index: number) → U, ?number, ?number) → [U]
// Map the given functions over the elements of the rope, producing
// a flat array.
RopeSequence.prototype.map = function map (f, from, to) {
if ( from === void 0 ) from = 0;
if ( to === void 0 ) to = this.length;
var result = [];
this.forEach(function (elt, i) { return result.push(f(elt, i)); }, from, to);
return result
};
// :: (?union<[T], RopeSequence<T>>) → RopeSequence<T>
// Create a rope representing the given array, or return the rope
// itself if a rope was given.
RopeSequence.from = function from (values) {
if (values instanceof RopeSequence) { return values }
return values && values.length ? new Leaf(values) : RopeSequence.empty
};
var Leaf = /*@__PURE__*/(function (RopeSequence) {
function Leaf(values) {
RopeSequence.call(this);
this.values = values;
}
if ( RopeSequence ) Leaf.__proto__ = RopeSequence;
Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype );
Leaf.prototype.constructor = Leaf;
var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } };
Leaf.prototype.flatten = function flatten () {
return this.values
};
Leaf.prototype.sliceInner = function sliceInner (from, to) {
if (from == 0 && to == this.length) { return this }
return new Leaf(this.values.slice(from, to))
};
Leaf.prototype.getInner = function getInner (i) {
return this.values[i]
};
Leaf.prototype.forEachInner = function forEachInner (f, from, to, start) {
for (var i = from; i < to; i++)
{ if (f(this.values[i], start + i) === false) { return false } }
};
Leaf.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
for (var i = from - 1; i >= to; i--)
{ if (f(this.values[i], start + i) === false) { return false } }
};
Leaf.prototype.leafAppend = function leafAppend (other) {
if (this.length + other.length <= GOOD_LEAF_SIZE)
{ return new Leaf(this.values.concat(other.flatten())) }
};
Leaf.prototype.leafPrepend = function leafPrepend (other) {
if (this.length + other.length <= GOOD_LEAF_SIZE)
{ return new Leaf(other.flatten().concat(this.values)) }
};
prototypeAccessors.length.get = function () { return this.values.length };
prototypeAccessors.depth.get = function () { return 0 };
Object.defineProperties( Leaf.prototype, prototypeAccessors );
return Leaf;
}(RopeSequence));
// :: RopeSequence
// The empty rope sequence.
RopeSequence.empty = new Leaf([]);
var Append = /*@__PURE__*/(function (RopeSequence) {
function Append(left, right) {
RopeSequence.call(this);
this.left = left;
this.right = right;
this.length = left.length + right.length;
this.depth = Math.max(left.depth, right.depth) + 1;
}
if ( RopeSequence ) Append.__proto__ = RopeSequence;
Append.prototype = Object.create( RopeSequence && RopeSequence.prototype );
Append.prototype.constructor = Append;
Append.prototype.flatten = function flatten () {
return this.left.flatten().concat(this.right.flatten())
};
Append.prototype.getInner = function getInner (i) {
return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length)
};
Append.prototype.forEachInner = function forEachInner (f, from, to, start) {
var leftLen = this.left.length;
if (from < leftLen &&
this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false)
{ return false }
if (to > leftLen &&
this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false)
{ return false }
};
Append.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
var leftLen = this.left.length;
if (from > leftLen &&
this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false)
{ return false }
if (to < leftLen &&
this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false)
{ return false }
};
Append.prototype.sliceInner = function sliceInner (from, to) {
if (from == 0 && to == this.length) { return this }
var leftLen = this.left.length;
if (to <= leftLen) { return this.left.slice(from, to) }
if (from >= leftLen) { return this.right.slice(from - leftLen, to - leftLen) }
return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen))
};
Append.prototype.leafAppend = function leafAppend (other) {
var inner = this.right.leafAppend(other);
if (inner) { return new Append(this.left, inner) }
};
Append.prototype.leafPrepend = function leafPrepend (other) {
var inner = this.left.leafPrepend(other);
if (inner) { return new Append(inner, this.right) }
};
Append.prototype.appendInner = function appendInner (other) {
if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1)
{ return new Append(this.left, new Append(this.right, other)) }
return new Append(this, other)
};
return Append;
}(RopeSequence));
export default RopeSequence;

190
resources/app/node_modules/rope-sequence/index.js generated vendored Normal file
View File

@@ -0,0 +1,190 @@
const GOOD_LEAF_SIZE = 200
// :: class<T> A rope sequence is a persistent sequence data structure
// that supports appending, prepending, and slicing without doing a
// full copy. It is represented as a mostly-balanced tree.
class RopeSequence {
// length:: number
// The length of the rope.
// :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
// Append an array or other rope to this one, returning a new rope.
append(other) {
if (!other.length) return this
other = RopeSequence.from(other)
return (!this.length && other) ||
(other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) ||
(this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) ||
this.appendInner(other)
}
// :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
// Prepend an array or other rope to this one, returning a new rope.
prepend(other) {
if (!other.length) return this
return RopeSequence.from(other).append(this)
}
appendInner(other) {
return new Append(this, other)
}
// :: (?number, ?number) → RopeSequence<T>
// Create a rope repesenting a sub-sequence of this rope.
slice(from = 0, to = this.length) {
if (from >= to) return RopeSequence.empty
return this.sliceInner(Math.max(0, from), Math.min(this.length, to))
}
// :: (number) → T
// Retrieve the element at the given position from this rope.
get(i) {
if (i < 0 || i >= this.length) return undefined
return this.getInner(i)
}
// :: ((element: T, index: number) → ?bool, ?number, ?number)
// Call the given function for each element between the given
// indices. This tends to be more efficient than looping over the
// indices and calling `get`, because it doesn't have to descend the
// tree for every element.
forEach(f, from = 0, to = this.length) {
if (from <= to)
this.forEachInner(f, from, to, 0)
else
this.forEachInvertedInner(f, from, to, 0)
}
// :: ((element: T, index: number) → U, ?number, ?number) → [U]
// Map the given functions over the elements of the rope, producing
// a flat array.
map(f, from = 0, to = this.length) {
let result = []
this.forEach((elt, i) => result.push(f(elt, i)), from, to)
return result
}
// :: (?union<[T], RopeSequence<T>>) → RopeSequence<T>
// Create a rope representing the given array, or return the rope
// itself if a rope was given.
static from(values) {
if (values instanceof RopeSequence) return values
return values && values.length ? new Leaf(values) : RopeSequence.empty
}
// flatten:: () → [T]
// Return the content of this rope as an array.
}
class Leaf extends RopeSequence {
constructor(values) {
super()
this.values = values
}
flatten() {
return this.values
}
sliceInner(from, to) {
if (from == 0 && to == this.length) return this
return new Leaf(this.values.slice(from, to))
}
getInner(i) {
return this.values[i]
}
forEachInner(f, from, to, start) {
for (let i = from; i < to; i++)
if (f(this.values[i], start + i) === false) return false
}
forEachInvertedInner(f, from, to, start) {
for (let i = from - 1; i >= to; i--)
if (f(this.values[i], start + i) === false) return false
}
leafAppend(other) {
if (this.length + other.length <= GOOD_LEAF_SIZE)
return new Leaf(this.values.concat(other.flatten()))
}
leafPrepend(other) {
if (this.length + other.length <= GOOD_LEAF_SIZE)
return new Leaf(other.flatten().concat(this.values))
}
get length() { return this.values.length }
get depth() { return 0 }
}
// :: RopeSequence
// The empty rope sequence.
RopeSequence.empty = new Leaf([])
class Append extends RopeSequence {
constructor(left, right) {
super()
this.left = left
this.right = right
this.length = left.length + right.length
this.depth = Math.max(left.depth, right.depth) + 1
}
flatten() {
return this.left.flatten().concat(this.right.flatten())
}
getInner(i) {
return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length)
}
forEachInner(f, from, to, start) {
let leftLen = this.left.length
if (from < leftLen &&
this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false)
return false
if (to > leftLen &&
this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false)
return false
}
forEachInvertedInner(f, from, to, start) {
let leftLen = this.left.length
if (from > leftLen &&
this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false)
return false
if (to < leftLen &&
this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false)
return false
}
sliceInner(from, to) {
if (from == 0 && to == this.length) return this
let leftLen = this.left.length
if (to <= leftLen) return this.left.slice(from, to)
if (from >= leftLen) return this.right.slice(from - leftLen, to - leftLen)
return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen))
}
leafAppend(other) {
let inner = this.right.leafAppend(other)
if (inner) return new Append(this.left, inner)
}
leafPrepend(other) {
let inner = this.left.leafPrepend(other)
if (inner) return new Append(inner, this.right)
}
appendInner(other) {
if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1)
return new Append(this.left, new Append(this.right, other))
return new Append(this, other)
}
}
export default RopeSequence

22
resources/app/node_modules/rope-sequence/package.json generated vendored Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "rope-sequence",
"version": "1.3.4",
"description": "Rope-based persistent sequence type",
"main": "dist/index.cjs",
"type": "module",
"module": "dist/index.js",
"exports": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"repository": {
"type": "git",
"url": "git+https://github.com/marijnh/rope-sequence.git"
},
"author": "Marijn Haverbeke <marijn@haverbeke.berlin>",
"license": "MIT",
"devDependencies": {
"@rollup/plugin-buble": "^0.20.0",
"rollup": "^1.26.3"
}
}

78
resources/app/node_modules/rope-sequence/test.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
import RopeSequence from "./index.js"
import assert from "assert"
function describe(rope) {
if (rope.left) return "(" + describe(rope.left) + ", " + describe(rope.right) + ")"
else return rope.length
}
function appendBuild(n) {
var rope = RopeSequence.empty
for (var i = 0; i < n; i++)
rope = rope.append([i])
return rope
}
function dequeBuild(n) {
var mid = n >> 1, rope = RopeSequence.empty
for (var from = mid - 1, to = mid; to < n; from--, to++) {
rope = rope.append([to])
if (from >= 0) rope = RopeSequence.from([from]).append(rope)
}
return rope
}
function flatBuild(n) {
var arr = []
for (var i = 0; i < n; i++) arr.push(i)
return RopeSequence.from(arr)
}
var SIZE = 10000
function checkForEach(rope, name, start, end, offset) {
var cur = start
rope.forEach(function(elt, i) {
assert.equal(elt, cur + offset, "Proper element at " + cur + " in " + name)
assert.equal(cur, i, "Accurate index passed")
cur++
}, start, end)
assert.equal(cur, end, "Enough elements iterated in " + name)
rope.forEach(function(elt, i) {
cur--
assert.equal(elt, cur + offset, "Proper element during reverse iter at " + cur + " in " + name)
assert.equal(cur, i, "Accurate index passed by reverse iter")
}, end, start)
assert.equal(cur, start, "Enough elements reverse-iterated in " + name + " -- " + cur + " " + start)
}
function check(rope, size, name, offset) {
if (!offset) offset = 0
assert.equal(rope.length, size, "Size of " + name)
for (var i = 0; i < rope.length; i++)
assert.equal(rope.get(i), offset + i, "Field at " + i + " in " + name)
checkForEach(rope, name, 0, rope.length, offset)
for (var i = 0, e = Math.min(10, Math.floor(size / 100)); i < e; i++) {
var start = Math.floor(Math.random() * size), end = start + Math.ceil(Math.random() * (size - start))
checkForEach(rope, name + "-" + start + "-" + end, start, end, offset)
check(rope.slice(start, end), end - start, name + "-sliced-" + start + "-" + end, offset + start)
}
}
check(appendBuild(SIZE), SIZE, "appended")
check(dequeBuild(SIZE), SIZE, "dequed")
check(flatBuild(SIZE), SIZE, "flat")
var small = RopeSequence.from([1, 2, 4]), empty = RopeSequence.empty
assert.equal(small.append(empty), small, "ID append")
assert.equal(small.prepend(empty), small, "ID prepend")
assert.equal(empty.append(empty), empty, "empty append")
assert.equal(small.slice(0, 0), empty, "empty slice")
var sum = 0
small.forEach(function(v) { if (v == 2) return false; sum += v })
assert.equal(sum, 1, "abort iteration")
assert.deepEqual(small.map(function(x) { return x + 1 }), [2, 3, 5], "mapping")
console.log("All passed")