Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Bugs/array.prototype.find in v1 master #188

Merged
merged 7 commits into from
Dec 7, 2017
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ NodeJS or open `test/run.html` in a browser.
To run the tests in your browser, simply use `npm run test:jasmine`.

To run the tests using Karma use `npm run test:karma` and for continious tests run with file changes detection `npm run test:karma-dev`. Finally to open a remote debug console on karma use `npm run test:karma-debug`.
=======
## Design principles

- extends core types (e.g extends `Array.prototype` with additional non-enumerable properties like `.set`)

30 changes: 26 additions & 4 deletions deque.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,25 @@ Deque.prototype.lastIndexOf = function (value, index) {
return -1;
}

// TODO rename findValue
Deque.prototype.find = function (value, equals, index) {
var deprecatedWarnNonce = {};
function deprecatedWarn(msg, notOnce) {
if (
typeof console !== 'undefined' &&
typeof console.warn === 'function' &&
(notOnce !== true && deprecatedWarnNonce.hasOwnProperty(msg) === false)
) {
console.warn(msg);
deprecatedWarnNonce[msg]++;
}
}

// TODO remove in v6 (not present in v2)
Deque.prototype.find = function () {
deprecatedWarn('Deque#find function is deprecated please use Deque#findValue instead.');
return this.findValue.apply(this, arguments);
};

Deque.prototype.findValue = function (value, equals, index) {
equals = equals || Object.equals;
// Default start index at beginning
if (index == null) {
Expand All @@ -368,8 +385,13 @@ Deque.prototype.find = function (value, equals, index) {
return -1;
};

// TODO rename findLastValue
Deque.prototype.findLast = function (value, equals, index) {
// TODO remove in v6 (not present in v2)
Deque.prototype.findLast = function () {
deprecatedWarn('Deque#findLast function is deprecated please use Deque#findLastValue instead.');
return this.findLastValue.apply(this, arguments);
};

Deque.prototype.findLastValue = function (value, equals, index) {
equals = equals || Object.equals;
// Default start position at the end
if (index == null) {
Expand Down
93 changes: 87 additions & 6 deletions shim-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ define("constructClone", function (values) {
});

define("has", function (value, equals) {
return this.find(value, equals) !== -1;
return this.findValue(value, equals) !== -1;
});

define("get", function (index, defaultValue) {
if (+index !== index)
if (+index !== index) {
throw new Error("Indicies must be numbers");
if (!index in this) {
} else if (!index in this) {
return defaultValue;
} else {
return this[index];
Expand All @@ -110,7 +110,7 @@ define("add", function (value) {
});

define("delete", function (value, equals) {
var index = this.find(value, equals);
var index = this.findValue(value, equals);
if (index !== -1) {
this.spliceOne(index);
return true;
Expand All @@ -132,7 +132,81 @@ define("deleteAll", function (value, equals) {
return count;
});

define("find", function (value, equals) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
// https://tc39.github.io/ecma262/#sec-array.prototype.find
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}

var o = Object(this);

// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;

// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}

// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];

// 5. Let k be 0.
var k = 0;

// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
// e. Increase k by 1.
k++;
}
}
});
}

// TODO remove in v6 (not present in v2)
var deprecatedWarnNonce = {};
function deprecatedWarn(msg, notOnce) {
if (
typeof console !== 'undefined' &&
typeof console.warn === 'function' &&
(notOnce !== true && deprecatedWarnNonce.hasOwnProperty(msg) === false)
) {
console.warn(msg);
deprecatedWarnNonce[msg]++;
}
}

// Save Array.prototype.find in order to support legacy and display warning.
// TODO remove in v6 (not present in v2)
var ArrayFindPrototype = Object.getOwnPropertyDescriptor(Array.prototype, 'find').value;
define("find", function (value, equals, index) {
if (
typeof arguments[0] === 'function' &&
this instanceof Array
) {
return ArrayFindPrototype.apply(this, arguments);
} else {
deprecatedWarn('Array#find usage is deprecated please use Array#findValue');
return this.findValue.apply(this, arguments);
}
});

define("findValue", function (value, equals, index) {
if (index) {
throw new Error("Array#findValue does not support third argument: index");
}
equals = equals || this.contentEquals || Object.equals;
for (var index = 0; index < this.length; index++) {
if (index in this && equals(value, this[index])) {
Expand All @@ -142,7 +216,13 @@ define("find", function (value, equals) {
return -1;
});

// TODO remove in v6 (not present in v2)
define("findLast", function (value, equals) {
deprecatedWarn('Array#findLast function is deprecated please use Array#findLastValue instead.');
return this.findLastValue.apply(this, arguments);
});

define("findLastValue", function (value, equals) {
equals = equals || this.contentEquals || Object.equals;
var index = this.length;
do {
Expand Down Expand Up @@ -358,7 +438,8 @@ function ArrayIterator(array, start, end) {
this.array = array;
this.start = start == null ? 0 : start;
this.end = end;
};
}

ArrayIterator.prototype.__iterationObject = null;
Object.defineProperty(ArrayIterator.prototype,"_iterationObject", {
get: function() {
Expand Down
32 changes: 28 additions & 4 deletions sorted-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,24 +198,48 @@ SortedArray.prototype.lastIndexOf = function (value) {
return searchLast(this.array, value, this.contentCompare, this.contentEquals);
};

var deprecatedWarnNonce = {};
function deprecatedWarn(msg, notOnce) {
if (
typeof console !== 'undefined' &&
typeof console.warn === 'function' &&
(notOnce !== true && deprecatedWarnNonce.hasOwnProperty(msg) === false)
) {
console.warn(msg);
deprecatedWarnNonce[msg]++;
}
}

// TODO remove in v6 (not present in v2)
SortedArray.prototype.find = function (value, equals, index) {
deprecatedWarn('This SortedArray#find usage is deprecated please use SortedArray#findValue');
return this.findValue.apply(this, arguments);
};

SortedArray.prototype.findValue = function (value, equals, index) {
// TODO throw error if provided a start index
if (equals) {
throw new Error("SortedArray#find does not support second argument: equals");
throw new Error("SortedArray#findValue does not support second argument: equals");
}
if (index) {
throw new Error("SortedArray#find does not support third argument: index");
throw new Error("SortedArray#findValue does not support third argument: index");
}
// TODO support initial partition index
return searchFirst(this.array, value, this.contentCompare, this.contentEquals);
};

// TODO remove in v6 (not present in v2)
SortedArray.prototype.findLast = function (value, equals, index) {
deprecatedWarn('This SortedArray#findLast usage is deprecated please use SortedArray#findLastValue');
return this.findLastValue.apply(this, arguments);
};

SortedArray.prototype.findLastValue = function (value, equals, index) {
if (equals) {
throw new Error("SortedArray#findLast does not support second argument: equals");
throw new Error("SortedArray#findLastValue does not support second argument: equals");
}
if (index) {
throw new Error("SortedArray#findLast does not support third argument: index");
throw new Error("SortedArray#findLastValue does not support third argument: index");
}
// TODO support initial partition index
return searchLast(this.array, value, this.contentCompare, this.contentEquals);
Expand Down
53 changes: 49 additions & 4 deletions test/spec/array-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,45 @@ describe("Array-spec", function () {

describe("find", function () {

it("should find an object in an array by one of its properties", function () {
var inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];

function isCherries(fruit) {
return fruit.name === 'cherries';
}

expect(inventory.find(isCherries)).toEqual(inventory[2]);
});

describe("find (deprecated support)", function () {

it("should find equivalent objects", function () {
expect([{a:10}].find({a:10})).toEqual(0);
});

it("should allow equality comparison override", function () {
expect([{a:10}].find({a:10}, Object.is)).toEqual(-1);
});
});

});

describe("findValue", function () {

it("should find equivalent objects", function () {
expect([{a:10}].find({a:10})).toEqual(0);
expect([{a:10}].findValue({a:10})).toEqual(0);
});

it("should allow equality comparison override", function () {
expect([{a:10}].find({a:10}, Object.is)).toEqual(-1);
expect([{a:10}].findValue({a:10}, Object.is)).toEqual(-1);
});

});

describe("findLast", function () {
describe("findLast (deprecated support)", function () {

it("should find equivalent objects", function () {
expect([{a:10}].findLast({a:10})).toEqual(0);
Expand All @@ -102,6 +130,23 @@ describe("Array-spec", function () {

});

describe("findLastValue", function () {

it("should find equivalent objects", function () {
expect([{a:10}].findLastValue({a:10})).toEqual(0);
});

it("should allow equality comparison override", function () {
expect([{a:10}].findLastValue({a:10}, Object.is)).toEqual(-1);
});

it("should find the last of equivalent objects", function () {
var object = {a: 10};
expect([object, {a: 10}].findLastValue(object)).toEqual(1);
});

});

describe("has", function () {

it("should find equivalent objects", function () {
Expand Down
23 changes: 21 additions & 2 deletions test/spec/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function describeOrder(Collection) {

});

describe("find", function () {
describe("find (deprecated support)", function () {

it("finds equivalent values", function () {
expect(Collection([10, 10, 10]).find(10)).toEqual(0);
Expand All @@ -159,11 +159,30 @@ function describeOrder(Collection) {

});

describe("findLast", function () {
describe("findValue", function () {

it("finds equivalent values", function () {
expect(Collection([10, 10, 10]).findValue(10)).toEqual(0);
});

it("finds equivalent values", function () {
expect(Collection([10, 10, 10]).findValue(10)).toEqual(0);
});

});

describe("findLast (deprecated support)", function () {

it("finds equivalent values", function () {
expect(Collection([10, 10, 10]).findLast(10)).toEqual(2);
});
});

describe("findLastValue", function () {

it("finds equivalent values", function () {
expect(Collection([10, 10, 10]).findLastValue(10)).toEqual(2);
});

});

Expand Down