Subversion Repositories JSX

Compare Revisions

Last modification

Ignore whitespace Rev 498 → Rev 499

/trunk/test/array.js
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
Index: trunk/test/array-test.js
===================================================================
--- trunk/test/array-test.js (nonexistent)
+++ trunk/test/array-test.js (revision 499)
@@ -0,0 +1,309 @@
+function runTests()
+{
+ var _test = jsx.test;
+ var assert = _test.assert;
+ var assertArrayEquals = _test.assertArrayEquals;
+ var _createComparator = jsx.array.createComparator;
+ var BigArray = jsx.array.BigArray;
+
+ _test.runner.run({
+ file: "array.js",
+ tests: [
+ {
+ feature: 'jsx.array.BigArray()',
+ description: 'Return new instance (factory)',
+ code: function () {
+ assert(BigArray() instanceof BigArray);
+ }
+ },
+ {
+ feature: 'new jsx.array.BigArray()',
+ description: 'Return new empty instance (constructor)',
+ code: function () {
+ assert(new BigArray() instanceof BigArray);
+ }
+ },
+ {
+ feature: 'new BigArray(BigArray)',
+ description: 'Clone instance',
+ code: function () {
+ var s = (new BigArray(new BigArray("x"))).toString();
+ assert(s === "x");
+ }
+ },
+ {
+ feature: 'new BigArray("")',
+ description: 'Return one-element array',
+ code: function () {
+ assertArrayEquals([""], new BigArray("").toArray());
+ }
+ },
+ {
+ feature: 'new BigArray("x")',
+ description: 'Convert to <code>BigArray("x")</code>',
+ code: function () {
+ assertArrayEquals(["x"], new BigArray("x").toArray());
+ }
+ },
+ {
+ feature: 'new BigArray(int)',
+ description: 'Create <code>BigArray</code> of specified length',
+ code: function () {
+ var a = [];
+ a.length = 42;
+ assertArrayEquals(a, new BigArray(42).toArray());
+ }
+ },
+
+ {
+ feature: 'BigArray.prototype.toArray()',
+ description: 'Return the correct value',
+ code: function () {
+ assertArrayEquals([], new BigArray().toArray());
+ assertArrayEquals([""], new BigArray("").toArray());
+ assertArrayEquals(["x"], new BigArray("x").toArray());
+ assertArrayEquals([23, 42], new BigArray(23, 42).toArray());
+ }
+ },
+ {
+ feature: 'BigArray.length',
+ description: 'Getter works',
+ code: function () {
+ var i = Math.pow(2, 53);
+ assert(new BigArray(i).length == i);
+ }
+ },
+
+ {
+ feature: 'BigArray.getLength()',
+ description: 'Return the correct value',
+ code: function () {
+ assert(new BigArray().getLength() === 0);
+ assert(new BigArray(42).getLength() === 42);
+ assert(new BigArray("").getLength() === 1);
+ assert(new BigArray("x").getLength() === 1);
+ assert(new BigArray("x", "y").getLength() === 2);
+ }
+ },
+
+ {
+ feature: 'BigArray.prototype.get()',
+ description: 'Throw <code>jsx.InvalidArgumentError</code>',
+ code: function () {
+ var failure = jsx.tryThis(
+ function () {
+ new BigArray().get();
+ return false;
+ },
+ function (e) {
+ return (e instanceof jsx.InvalidArgumentError);
+ });
+ assert(failure);
+ }
+ },
+ {
+ feature: 'BigArray.prototype.get(…)',
+ description: 'Return the correct value',
+ code: function () {
+ assert(new BigArray("x").get(0) === "x");
+ assert(typeof new BigArray("x").get(1) == "undefined");
+
+ assert(new BigArray("x", "y").get(-2) === "x");
+ assert(new BigArray("x", "y").get(-1) === "y");
+ assert(typeof new BigArray("x", "y").get(-4) == "undefined");
+ }
+ },
+
+ /* TODO: Override and test Array methods that are not MAX_LENGTH-safe */
+
+ {
+ feature: 'BigArray.prototype.toString(…)',
+ description: 'Return the correct value',
+ code: function () {
+ assert(new BigArray().toString() === "");
+ assert(new BigArray(0).toString() === "");
+ assert(new BigArray(1).toString() === "");
+ assert(new BigArray(2).toString() === ",");
+ }
+ },
+
+ {
+ feature: 'BigArray.prototype.valueOf(…)',
+ description: 'Return the correct value',
+ code: function () {
+ var a = new BigArray("x\uD834\uDD1Ey");
+ var v = a.valueOf();
+ assert(v === a);
+ }
+ },
+
+ {
+ feature: 'jsx.array.createComparator(aKeys)',
+ description: 'Sort <code>Array</code> as specified',
+ code: function () {
+ var o1 = {x: 2};
+ var o2 = {x: 1};
+ var a = [o1, o2];
+ a.sort(_createComparator(["x"]));
+ assertArrayEquals([o2, o1], a);
+ }
+ },
+ {
+ feature: 'jsx.array.createComparator(aKeys, oOptions)',
+ description: 'Sort <code>Array</code> as specified',
+ code: function () {
+ var o1 = {x: 1};
+ var o2 = {x: 2};
+ var a = [o1, o2];
+ a.sort(_createComparator(["x"], {descending: true}));
+ assertArrayEquals([o2, o1], a);
+
+ o1 = {x: "1 "};
+ o2 = {x: 1};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {strict: true}));
+ assertArrayEquals([o2, o1], a);
+
+ o1 = {x: 1};
+ o2 = {x: "1 "};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {descending: true, strict: true}));
+ assertArrayEquals([o2, o1], a);
+
+ o1 = {x: "20"};
+ o2 = {x: "1"};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {numeric: true}));
+ assertArrayEquals([o2, o1], a);
+
+ o1 = {x: "1"};
+ o2 = {x: "1"};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {numeric: true, strict: true}));
+ assertArrayEquals([o1, o2], a);
+
+ o1 = {x: 1};
+ o2 = {x: "1"};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {numeric: true}));
+ assertArrayEquals([o1, o2], a);
+
+ o1 = {x: "1 "};
+ o2 = {x: 1};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {numeric: true, strict: true}));
+ assertArrayEquals([o1, o2], a);
+
+ o1 = {x: 2};
+ o2 = {x: "12"};
+ a = [o1, o2];
+ a.sort(_createComparator(["x"], {
+ descending: true,
+ numeric: true,
+ strict: true
+ }));
+ assertArrayEquals([o2, o1], a);
+ }
+ },
+ {
+ feature: 'jsx.array.createComparator([{key: …, callback: …}])',
+ description: 'Sort <code>Array</code> as specified',
+ code: function () {
+ var o1 = {
+ x: "10"
+ };
+ var o2 = {
+ x: "2"
+ };
+ var a = [o1, o2];
+ a.sort(_createComparator([
+ {
+ key: "x",
+ callback: Number
+ }
+ ]));
+ assertArrayEquals([o2, o1], a);
+ }
+ },
+ {
+ feature: 'jsx.array.createComparator([{key: …, constructor: …}])',
+ description: 'Sort <code>Array</code> as specified',
+ code: function () {
+ var o1 = {
+ x: "10"
+ };
+ var o2 = {
+ x: "2"
+ };
+ var a = [o1, o2];
+ a.sort(_createComparator([
+ {
+ key: "x",
+ constructor: Number
+ }
+ ]));
+ assertArrayEquals([o2, o1], a);
+ }
+ },
+ {
+ feature: 'jsx.array.createComparator([{key: …, comparator: …}])',
+ description: 'Sort <code>Array</code> as specified',
+ code: function () {
+ var o1 = {
+ engine: {
+ liters: 4.0,
+ cylinders: 4
+ },
+ };
+ var o2 = {
+ engine: {
+ liters: 3.0,
+ cylinders: 4
+ },
+ };
+ var a = [o1, o2];
+ a.sort(_createComparator([
+ {
+ key: "engine",
+ comparator: _createComparator(["cylinders", "liters"])
+ }
+ ]));
+ assertArrayEquals([o2, o1], a);
+ }
+ },
+
+ {
+ feature: 'jsx.array.createComparator("…", {callback: …, constructor: …, comparator: …})',
+ description: 'Sort <code>Array</code> as specified',
+ code: function () {
+ function Bar (baz)
+ {
+ this.baz = String(baz);
+ }
+
+ Bar.prototype.toString = function () {
+ return this.baz;
+ };
+
+ function Baz (bla)
+ {
+ this.length = bla.length;
+ }
+
+ var o1 = {"bar": new Bar("burpbarbazbla")};
+ var o2 = {"bar": new Bar("foo")};
+
+ var foo = [o1, o2];
+
+ foo.sort(_createComparator(["bar"], {
+ callback: String,
+ constructor: Baz,
+ comparator: _createComparator(["length"], {numeric: true})
+ }));
+
+ assertArrayEquals([o2, o1], foo);
+ }
+ }
+ ]
+ });
+}
\ No newline at end of file
/trunk/test/array-test.js
Property changes:
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: trunk/array.js
===================================================================
--- trunk/array.js (revision 498)
+++ trunk/array.js (revision 499)
@@ -40,10 +40,20 @@
*/
jsx.array = (/** @constructor */ function () {
/* Imports */
- var _jsx_object = jsx.object;
+ var _jsx = jsx;
+ var _tryThis = _jsx.tryThis;
+ var _jsx_object = _jsx.object;
+ var _defineProperty = _jsx_object.defineProperty;
+ var _getClass = _jsx_object.getClass;
var _getKeys = _jsx_object.getKeys;
var _hasOwnProperty = _jsx_object._hasOwnProperty;
+ var _getKeys = _jsx_object.getKeys;
+ var _hasOwnProperty = _jsx_object._hasOwnProperty;
var _isArray = _jsx_object.isArray;
+ var _isNativeObject = _jsx_object.isNativeObject;
+
+ /* Constant-like variables */
+ var _MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1;
var _isNativeMethod = _jsx_object.isNativeMethod;
/**
@@ -123,7 +133,327 @@
return [];
}
+ /**
+ * Array index out of range
+ *
+ * @type jsx.array.RangeError
+ * @extends RangeError|jsx.InvalidArgumentError
+ * @constructor
+ */
+ var _RangeError = (
+ function (sReason, sGot, sExpected) {
+ _jsx.InvalidArgumentError.apply(this, arguments);
+ }
+ ).extend(
+ typeof RangeError == "function"
+ ? RangeError
+ : _jsx.InvalidArgumentError,
+ {
+ name: "jsx.array.RangeError"
+ });
+
+ /**
+ * Array-like object which can hold up to 2<sup>53</sup> elements
+ *
+ * @function
+ * @type jsx.array.BigArray
+ * @extends Array
+ * @constructor
+ */
+ var _BigArray = jsx.object.extend(
+ /**
+ * @type __jsx.array.BigArray
+ * @param {Array|Object} src (optional)
+ * Array-like object to be converted
+ * @return {jsx.arrayBigArray}
+ */
+ function jsx_array_BigArray (src) {
+ if (!(this instanceof jsx_array_BigArray))
+ {
+ return jsx_array_BigArray.construct(arguments);
+ }
+
+ /**
+ * @memberOf __jsx.array.BigArray
+ * @private
+ */
+ var _length = 0;
+
+ /**
+ * Removes all elements from the array
+ *
+ * @memberOf jsx.array.BigArray
+ */
+ this.clear = function () {
+ for (var i in this)
+ {
+ if (_BigArray.isIndex(i))
+ {
+ delete this[i];
+ }
+ }
+
+ this.setLength(0);
+ };
+
+ /**
+ * Sets the real length of this array
+ *
+ * @param {int} value
+ * @throws jsx.array.RangeError
+ * if the value is less than <code>0</code> or
+ * greater than {@link BigArray.MAX_LENGTH}
+ */
+ this.setLength = function BigArray_setLength (value) {
+ if (value < 0 || value > _BigArray.MAX_LENGTH)
+ {
+ return _jsx.throwThis(_RangeError,
+ ["Invalid length", value,
+ "0.." + _BigArray.MAX_LENGTH
+ + " (2^" + Math.floor(Math.log(_BigArray.MAX_LENGTH) / Math.log(2)) + ")"],
+ BigArray_setLength);
+ }
+
+ _length = Math.floor(value);
+
+ return this;
+ };
+
+ /**
+ * Returns the real length of this array
+ *
+ * @return {int}
+ */
+ this.getLength = function () {
+ return _length;
+ };
+
+ _defineProperty(this, "length", {
+ /**
+ * @memberOf jsx.array.BigArray
+ */
+ "get": this.getLength,
+ "set": this.setLength
+ }, "jsx.array.BigArray");
+
+ /**
+ * Sets the element at <var>index</var> to <var>value</var>
+ *
+ * @param {int} index
+ * @param {any} value
+ */
+ this.set = function (index, value) {
+ if (index < 0)
+ {
+ index = this.getLength() + Math.ceil(index);
+ }
+ else
+ {
+ index = Math.floor(index);
+ }
+
+ if (this.getLength() < index + 1)
+ {
+ this.setLength(index + 1);
+ }
+
+ this[index] = value;
+
+ return this;
+ };
+
+ /**
+ * @param {int} index
+ * @return {any} the element of this array at <var>index</var>
+ */
+ this.get = function BigArray_get (index) {
+ if (arguments.length < 1)
+ {
+ return jsx.throwThis(jsx.InvalidArgumentError,
+ ["Not enough arguments", "", "(int)"],
+ BigArray_get);
+ }
+
+ if (index < 0)
+ {
+ index = this.getLength() + Math.ceil(index);
+ }
+ else
+ {
+ index = Math.floor(index);
+ }
+
+ return this[index];
+ };
+
+ this.clear();
+
+ var arglen = arguments.length;
+ if (arglen > 1)
+ {
+ for (var i = arglen; i--;)
+ {
+ this.set(i, arguments[i]);
+ }
+ }
+ else if (arglen == 1)
+ {
+ var t = typeof src;
+ if (t == "number")
+ {
+ this.setLength(src);
+ }
+ else
+ {
+ if (!_isArray(src) && _isNativeObject(src)
+ && _getClass(src) != "Object")
+ {
+ this.set(0, src);
+ }
+ else
+ {
+ this.setAll(src);
+ }
+ }
+ }
+ },
+ {
+ /**
+ * Maximum number of elements that can be stored in
+ * a <code>BigArray</code>. Successor of the greatest
+ * integer value that can be used as index.
+ *
+ * @memberOf __jsx.array.BigArray
+ */
+ MAX_LENGTH: Math.pow(2, 53),
+
+ /**
+ * Determines if a value can be used as <code>BigArray</code>
+ * index.
+ *
+ * @param {any} i
+ */
+ isIndex: function (i) {
+ return parseInt(i, 10).toString() == i
+ && i > -1 && i < _BigArray.MAX_LENGTH;
+ },
+
+ /**
+ * Determines if an object is a <code>BigArray</code>.
+ *
+ * @param {Object} o
+ * @return {boolean}
+ */
+ isInstance: function (o) {
+ return o.constructor == _BigArray;
+ }
+ }
+ ).extend(Array, {
+ /**
+ * Returns the string representations of this array's
+ * elements, separated by another string (representation).
+ *
+ * @memberOf jsx.array.BigArray.prototype
+ * @param {String} glue
+ * The separator between the string representations
+ * @return {string}
+ */
+ join: function (glue) {
+ var len = this.getLength();
+
+ if (len <= _MAX_ARRAY_LENGTH)
+ {
+ return [].join.apply(this, arguments);
+ }
+
+ if (arguments.length < 1)
+ {
+ glue = ",";
+ }
+
+ var s = "";
+
+ for (var i = 0; i < len; ++i)
+ {
+ s += this.get(i);
+
+ if (glue !== "" && i < len - 1)
+ {
+ s += glue;
+ }
+ }
+
+ return s;
+ },
+
+ /**
+ * Sets all elements based on another object.
+ *
+ * @param {Object} src
+ * If an <code>Array</code> or </code>BigArray</code>,
+ * copies all array elements (enumerable properties whose
+ * name is an array index) to this array.
+ * Otherwise, copies all properties with numeric name, from
+ * 0 to the name specified by the value of the object's
+ * <code>length</code> property, to this array.
+ */
+ setAll: function (src) {
+ if (_isArray(src) || src instanceof _BigArray)
+ {
+ for (var i in src)
+ {
+ if (_BigArray.isIndex(i))
+ {
+ this.set(i, src[i]);
+ }
+ }
+ }
+ else
+ {
+ for (i = src.length; i--;)
+ {
+ if (_BigArray.isIndex(i))
+ {
+ this.set(i, src[i]);
+ }
+ }
+ }
+ },
+
+ /**
+ * Returns this <code>BigArray</code> as an {@link Array}
+ * with extra indexes.
+ *
+ * @return {Array}
+ */
+ toArray: function () {
+ var a = [];
+ a.length = this.length;
+
+ for (var i in this)
+ {
+ if (_BigArray.isIndex(i) && i < _MAX_ARRAY_LENGTH)
+ {
+ a[i] = this.get(i);
+ }
+ }
+
+ return a;
+ },
+
+ /**
+ * Returns the string representation of this array
+ * as a comma-separated list.
+ */
+ toString: function () {
+ return this.join(",");
+ }
+ });
+
return {
+ /**
+ * @memberOf jsx.array
+ */
version: "0.1.$Rev$",
copyright: "Copyright \xA9 2004-2013",
author: "Thomas Lahn",
@@ -131,7 +461,6 @@
path: "http://pointedears.de/scripts/",
/**
- * @memberOf jsx.array
* @param {string} sMsg (optional)
* @return {boolean} false
*/
@@ -150,6 +479,9 @@
return false;
},
+ BigArray: _BigArray,
+ RangeError: _RangeError,
+
/**
* Splits the array <code>a</code> into several arrays with
* <code>iSize</code> values in them.
@@ -291,7 +623,7 @@
}
else
{
- jsx.throwThis('TypeError');
+ _jsx.throwThis('TypeError');
}
}
else
@@ -305,7 +637,7 @@
if (typeof fCallback != "function")
{
- jsx.throwThis('TypeError');
+ _jsx.throwThis('TypeError');
}
var res = [];
@@ -388,11 +720,6 @@
a = this;
}
- if (_isNativeMethod(a, "pop"))
- {
- return a.pop();
- }
-
var result = null;
if (a.length > 0)
@@ -728,9 +1055,9 @@
* @function
*/
splice: (function() {
- if (typeof jsx.global.array_splice != "undefined")
+ if (typeof _jsx.global.array_splice != "undefined")
{
- return jsx.global.array_splice;
+ return _jsx.global.array_splice;
}
else if (typeof Array != "undefined"
&& _jsx_object.isNativeMethod(Array, "prototype", "splice"))