collections
Advanced tools
Comparing version 2.0.2 to 3.0.0
@@ -0,9 +1,38 @@ | ||
## v3.0.0 | ||
## v2.0.0 :warning: BACKWARD INCOMPATIBLE | ||
- Aligns iterations with latest standard with PR #137 | ||
- Iterators have been reimplemented with an ES6 alike interface. | ||
- Change observers have been reimplemented with an FRB alike interface. | ||
- Removes support for `any` and `all`. Use `some(Boolean)` or | ||
`every(Boolean)`. | ||
## v1.2.4 | ||
- Optimise performance of PropertyChanges with PR#126 and avoid unnecessary calls to require in Map Changes with PR #129 | ||
## v1.2.3 | ||
- Dict Optimization to remove the need to mangle/unmangle keys. This minimize the amount of string creation and therefore garbage collection | ||
## v1.2.2 | ||
- Vlad Alexandru Ionescu fixed a bug in dictionaries with single character keys. | ||
- Optimizations for push to avoid creating unnecessary arrays through splice | ||
- Fixes for a few regressions in listen and impacting Montage | ||
## v1.2.0 | ||
- Trevor Dixon fixed bugs in SortedSet find methods. | ||
- Adds toJSON method to all collections. | ||
- Adds deleteAll to some collections. | ||
- Eliminate some extra work in change listener registration and dispatch by | ||
using namespaced properties instead of a weak map, precomputing event | ||
handler method names, and reusing an array to capture a snapshot of active | ||
change listeners during dispatch. | ||
- Fix SortedArrayMap isSorted flag. | ||
- Fix Array find such that the sought value may be a wild card. | ||
- MultiMap provides the key to the bucket maker | ||
- Improve support for strings, maps, and arguments across implementations of | ||
addEach | ||
- Fix a bug in the generic join method | ||
- Dict uses $ in mangled names instead of ~, so names are more frequently | ||
valid identifiers. May have a performance win. | ||
- Ignore property changes in non-configurable objects. | ||
## v1.1.0 | ||
@@ -160,2 +189,1 @@ | ||
`isObservable` is true. | ||
86
deque.js
"use strict"; | ||
require("./shim-object"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericOrder = require("./generic-order"); | ||
var GenericOrder = require("./generic-order"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var Iterator = require("./iterator"); | ||
var copyProperties = require("./copy"); | ||
var equalsOperator = require("pop-equals"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
@@ -31,6 +27,5 @@ // by Petka Antonov | ||
copyProperties(Deque.prototype, GenericCollection.prototype); | ||
copyProperties(Deque.prototype, GenericOrder.prototype); | ||
copyProperties(Deque.prototype, ObservableRange.prototype); | ||
copyProperties(Deque.prototype, ObservableObject.prototype); | ||
Object.addEach(Deque.prototype, GenericCollection.prototype); | ||
Object.addEach(Deque.prototype, GenericOrder.prototype); | ||
Object.addEach(Deque.prototype, RangeChanges.prototype); | ||
@@ -46,3 +41,2 @@ Deque.prototype.maxCapacity = (1 << 30) | 0; | ||
this.push(value); | ||
return true; | ||
}; | ||
@@ -60,3 +54,3 @@ | ||
var minus = []; | ||
this.dispatchRangeWillChange(plus, minus, length); | ||
this.dispatchBeforeRangeChange(plus, minus, length); | ||
} | ||
@@ -107,3 +101,3 @@ | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [result], length - 1); | ||
this.dispatchBeforeRangeChange([], [result], length - 1); | ||
} | ||
@@ -127,3 +121,3 @@ | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [result], 0); | ||
this.dispatchBeforeRangeChange([], [result], 0); | ||
} | ||
@@ -153,3 +147,3 @@ | ||
var minus = []; | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -252,3 +246,3 @@ | ||
for (var index = 0; index < this.capacity; ++index) { | ||
this[index] = void 0; | ||
this[index] = "nil"; // TODO void 0 | ||
} | ||
@@ -360,4 +354,5 @@ }; | ||
Deque.prototype.findValue = function (value, equals, index) { | ||
equals = equals || equalsOperator; | ||
// TODO rename findValue | ||
Deque.prototype.find = function (value, equals, index) { | ||
equals = equals || Object.equals; | ||
// Default start index at beginning | ||
@@ -382,4 +377,5 @@ if (index == null) { | ||
Deque.prototype.findLastValue = function (value, equals, index) { | ||
equals = equals || equalsOperator; | ||
// TODO rename findLastValue | ||
Deque.prototype.findLast = function (value, equals, index) { | ||
equals = equals || Object.equals; | ||
// Default start position at the end | ||
@@ -405,3 +401,3 @@ if (index == null) { | ||
Deque.prototype.has = function (value, equals) { | ||
equals = equals || equalsOperator; | ||
equals = equals || Object.equals; | ||
// Left to right walk | ||
@@ -411,3 +407,3 @@ var mask = this.capacity - 1; | ||
var offset = (this.front + index) & mask; | ||
if (equals(value, this[offset])) { | ||
if (this[offset] === value) { | ||
return true; | ||
@@ -441,48 +437,2 @@ } | ||
Deque.prototype.iterate = function (start, stop, step) { | ||
if (step == null) { | ||
step = 1; | ||
} | ||
if (stop == null) { | ||
stop = start; | ||
start = 0; | ||
} | ||
if (start == null) { | ||
start = 0; | ||
} | ||
if (step == null) { | ||
step = 1; | ||
} | ||
if (stop == null) { | ||
stop = this.length; | ||
} | ||
return new DequeIterator(this, start, stop, step); | ||
}; | ||
function DequeIterator(deque, start, stop, step) { | ||
this.deque = deque; | ||
this.start = start; | ||
this.stop = stop; | ||
this.step = step; | ||
} | ||
DequeIterator.prototype = Object.create(Iterator.prototype); | ||
DequeIterator.prototype.constructor = DequeIterator; | ||
DequeIterator.prototype.next = function () { | ||
if (this.start < this.stop) { | ||
var deque = this.deque; | ||
var mask = deque.capacity - 1; | ||
var offset = (deque.front + this.start) & mask; | ||
var iteration = new Iterator.Iteration( | ||
deque[offset], | ||
this.start | ||
); | ||
this.start += this.step; | ||
return iteration; | ||
} else { | ||
return Iterator.done; | ||
} | ||
}; | ||
function copy(source, sourceIndex, target, targetIndex, length) { | ||
@@ -489,0 +439,0 @@ for (var index = 0; index < length; ++index) { |
205
dict.js
"use strict"; | ||
var Shim = require("./shim"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var Iterator = require("./iterator"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -16,5 +15,5 @@ // Burgled from https://github.com/domenic/dict | ||
} | ||
getDefault = getDefault || this.getDefault; | ||
getDefault = getDefault || Function.noop; | ||
this.getDefault = getDefault; | ||
this.store = {}; | ||
this.store = Object.create(null); | ||
this.length = 0; | ||
@@ -26,42 +25,68 @@ this.addEach(values); | ||
function mangle(key) { | ||
return "$" + key; | ||
} | ||
Object.addEach(Dict.prototype, GenericCollection.prototype); | ||
Object.addEach(Dict.prototype, GenericMap.prototype); | ||
Object.addEach(Dict.prototype, PropertyChanges.prototype); | ||
function unmangle(mangled) { | ||
return mangled.slice(1); | ||
Dict.prototype.constructClone = function (values) { | ||
return new this.constructor(values, this.getDefault); | ||
}; | ||
Dict.prototype.assertString = function (key) { | ||
if (typeof key !== "string") { | ||
throw new TypeError("key must be a string but Got " + key); | ||
} | ||
} | ||
copy(Dict.prototype, GenericCollection.prototype); | ||
copy(Dict.prototype, GenericMap.prototype); | ||
copy(Dict.prototype, ObservableObject.prototype); | ||
Object.defineProperty(Dict.prototype,"$__proto__",{writable:true}); | ||
Object.defineProperty(Dict.prototype,"_hasProto",{ | ||
get:function() { | ||
return this.hasOwnProperty("$__proto__") && typeof this._protoValue !== "undefined"; | ||
} | ||
}); | ||
Object.defineProperty(Dict.prototype,"_protoValue",{ | ||
get:function() { | ||
return this["$__proto__"]; | ||
}, | ||
set: function(value) { | ||
this["$__proto__"] = value; | ||
} | ||
}); | ||
Dict.prototype.isDict = true; | ||
Dict.prototype.constructClone = function (values) { | ||
return new this.constructor(values, this.mangle, this.getDefault); | ||
}; | ||
Dict.prototype.get = function (key, defaultValue) { | ||
var mangled = mangle(key); | ||
if (mangled in this.store) { | ||
return this.store[mangled]; | ||
} else if (arguments.length > 1) { | ||
return defaultValue; | ||
} else { | ||
return this.getDefault(key); | ||
this.assertString(key); | ||
if (key === "__proto__") { | ||
if (this._hasProto) { | ||
return this._protoValue; | ||
} else if (arguments.length > 1) { | ||
return defaultValue; | ||
} else { | ||
return this.getDefault(key); | ||
} | ||
} | ||
else { | ||
if (key in this.store) { | ||
return this.store[key]; | ||
} else if (arguments.length > 1) { | ||
return defaultValue; | ||
} else { | ||
return this.getDefault(key); | ||
} | ||
} | ||
}; | ||
Dict.prototype.set = function (key, value) { | ||
var mangled = mangle(key); | ||
var from; | ||
if (mangled in this.store) { // update | ||
this.assertString(key); | ||
var isProtoKey = (key === "__proto__"); | ||
if (isProtoKey ? this._hasProto : key in this.store) { // update | ||
if (this.dispatchesMapChanges) { | ||
from = this.store[mangled]; | ||
this.dispatchMapWillChange("update", key, value, from); | ||
this.dispatchBeforeMapChange(key, isProtoKey ? this._protoValue : this.store[key]); | ||
} | ||
this.store[mangled] = value; | ||
isProtoKey | ||
? this._protoValue = value | ||
: this.store[key] = value; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("update", key, value, from); | ||
this.dispatchMapChange(key, value); | ||
} | ||
@@ -71,8 +96,12 @@ return false; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapWillChange("create", key, value); | ||
this.dispatchBeforeMapChange(key, undefined); | ||
} | ||
this.length++; | ||
this.store[mangled] = value; | ||
isProtoKey | ||
? this._protoValue = value | ||
: this.store[key] = value; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("create", key, value); | ||
this.dispatchMapChange(key, value); | ||
} | ||
@@ -84,37 +113,58 @@ return true; | ||
Dict.prototype.has = function (key) { | ||
var mangled = mangle(key); | ||
return mangled in this.store; | ||
this.assertString(key); | ||
return key === "__proto__" ? this._hasProto : key in this.store; | ||
}; | ||
Dict.prototype["delete"] = function (key) { | ||
var mangled = mangle(key); | ||
var from; | ||
if (mangled in this.store) { | ||
if (this.dispatchesMapChanges) { | ||
from = this.store[mangled]; | ||
this.dispatchMapWillChange("delete", key, void 0, from); | ||
this.assertString(key); | ||
if (key === "__proto__") { | ||
if (this._hasProto) { | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchBeforeMapChange(key, this._protoValue); | ||
} | ||
this._protoValue = undefined; | ||
this.length--; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange(key, undefined); | ||
} | ||
return true; | ||
} | ||
delete this.store[mangle(key)]; | ||
this.length--; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("delete", key, void 0, from); | ||
return false; | ||
} | ||
else { | ||
if (key in this.store) { | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchBeforeMapChange(key, this.store[key]); | ||
} | ||
delete this.store[key]; | ||
this.length--; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange(key, undefined); | ||
} | ||
return true; | ||
} | ||
return true; | ||
return false; | ||
} | ||
return false; | ||
}; | ||
Dict.prototype.clear = function () { | ||
var key, mangled, from; | ||
for (mangled in this.store) { | ||
key = unmangle(mangled); | ||
var key; | ||
if (this._hasProto) { | ||
if (this.dispatchesMapChanges) { | ||
from = this.store[mangled]; | ||
this.dispatchMapWillChange("delete", key, void 0, from); | ||
this.dispatchBeforeMapChange("__proto__", this._protoValue); | ||
} | ||
delete this.store[mangled]; | ||
this._protoValue = undefined; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("delete", key, void 0, from); | ||
this.dispatchMapChange("__proto__", undefined); | ||
} | ||
} | ||
for (key in this.store) { | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchBeforeMapChange(key, this.store[key]); | ||
} | ||
delete this.store[key]; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange(key, undefined); | ||
} | ||
} | ||
this.length = 0; | ||
@@ -124,5 +174,9 @@ }; | ||
Dict.prototype.reduce = function (callback, basis, thisp) { | ||
for (var mangled in this.store) { | ||
basis = callback.call(thisp, basis, this.store[mangled], unmangle(mangled), this); | ||
if(this._hasProto) { | ||
basis = callback.call(thisp, basis, "$__proto__", "__proto__", this); | ||
} | ||
var store = this.store; | ||
for (var key in this.store) { | ||
basis = callback.call(thisp, basis, store[key], key, this); | ||
} | ||
return basis; | ||
@@ -134,5 +188,10 @@ }; | ||
var store = this.store; | ||
return Object.keys(this.store).reduceRight(function (basis, mangled) { | ||
return callback.call(thisp, basis, store[mangled], unmangle(mangled), self); | ||
basis = Object.keys(this.store).reduceRight(function (basis, key) { | ||
return callback.call(thisp, basis, store[key], key, self); | ||
}, basis); | ||
if(this._hasProto) { | ||
return callback.call(thisp, basis, this._protoValue, "__proto__", self); | ||
} | ||
return basis; | ||
}; | ||
@@ -145,25 +204,7 @@ | ||
} | ||
return this._protoValue; | ||
}; | ||
Dict.prototype.iterate = function () { | ||
return new this.Iterator(new Iterator(this.store)); | ||
Dict.prototype.toJSON = function () { | ||
return this.toObject(); | ||
}; | ||
Dict.prototype.Iterator = DictIterator; | ||
function DictIterator(storeIterator) { | ||
this.storeIterator = storeIterator; | ||
} | ||
DictIterator.prototype.next = function () { | ||
var iteration = this.storeIterator.next(); | ||
if (iteration.done) { | ||
return iteration; | ||
} else { | ||
return new Iterator.Iteration( | ||
iteration.value, | ||
unmangle(iteration.index) | ||
); | ||
} | ||
}; | ||
"use strict"; | ||
var Shim = require("./shim"); | ||
var Set = require("./fast-set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -17,5 +15,5 @@ module.exports = FastMap; | ||
} | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || this.getDefault; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -39,5 +37,5 @@ this.contentHash = hash; | ||
copy(FastMap.prototype, GenericCollection.prototype); | ||
copy(FastMap.prototype, GenericMap.prototype); | ||
copy(FastMap.prototype, ObservableObject.prototype); | ||
Object.addEach(FastMap.prototype, GenericCollection.prototype); | ||
Object.addEach(FastMap.prototype, GenericMap.prototype); | ||
Object.addEach(FastMap.prototype, PropertyChanges.prototype); | ||
@@ -44,0 +42,0 @@ FastMap.prototype.constructClone = function (values) { |
"use strict"; | ||
var Shim = require("./shim"); | ||
var Dict = require("./dict"); | ||
@@ -8,8 +9,3 @@ var List = require("./list"); | ||
var TreeLog = require("./tree-log"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var hashOperator = require("pop-hash"); | ||
var equalsOperator = require("pop-equals"); | ||
var iterate = require("pop-iterate"); | ||
var arrayify = require("pop-arrayify"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -24,9 +20,12 @@ var object_has = Object.prototype.hasOwnProperty; | ||
} | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || noop; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
this.contentHash = hash; | ||
this.getDefault = getDefault; | ||
this.buckets = new this.Buckets(null, this.Bucket); | ||
var self = this; | ||
this.buckets = new this.Buckets(null, function getDefaultBucket() { | ||
return new self.Bucket(); | ||
}); | ||
this.length = 0; | ||
@@ -38,5 +37,5 @@ this.addEach(values); | ||
copy(FastSet.prototype, GenericCollection.prototype); | ||
copy(FastSet.prototype, GenericSet.prototype); | ||
copy(FastSet.prototype, ObservableObject.prototype); | ||
Object.addEach(FastSet.prototype, GenericCollection.prototype); | ||
Object.addEach(FastSet.prototype, GenericSet.prototype); | ||
Object.addEach(FastSet.prototype, PropertyChanges.prototype); | ||
@@ -60,3 +59,6 @@ FastSet.prototype.Buckets = Dict; | ||
FastSet.prototype.get = function (value) { | ||
FastSet.prototype.get = function (value, equals) { | ||
if (equals) { | ||
throw new Error("FastSet#get does not support second argument: equals"); | ||
} | ||
var hash = this.contentHash(value); | ||
@@ -71,3 +73,6 @@ var buckets = this.buckets; | ||
FastSet.prototype['delete'] = function (value) { | ||
FastSet.prototype["delete"] = function (value, equals) { | ||
if (equals) { | ||
throw new Error("FastSet#delete does not support second argument: equals"); | ||
} | ||
var hash = this.contentHash(value); | ||
@@ -124,8 +129,4 @@ var buckets = this.buckets; | ||
FastSet.prototype.toArray = function () { | ||
return flatten(this.buckets.map(arrayify)); | ||
}; | ||
FastSet.prototype.iterate = function () { | ||
return iterate(this.toArray()); | ||
return this.buckets.values().flatten().iterate(); | ||
}; | ||
@@ -140,10 +141,4 @@ | ||
} | ||
callback = callback.bind(thisp); | ||
// Bind is unavailable in PhantomJS, the only environment of consequence | ||
// that does not implement it yet. | ||
var originalCallback = callback; | ||
callback = function () { | ||
return originalCallback.apply(thisp, arguments); | ||
}; | ||
var buckets = this.buckets; | ||
@@ -205,6 +200,1 @@ var hashes = buckets.keys(); | ||
function flatten(arrays) { | ||
return Array.prototype.concat.apply([], arrays); | ||
} | ||
function noop() {} |
"use strict"; | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var cloneOperator = require("pop-clone"); | ||
var unzipOperator = require("pop-zip/pop-unzip"); | ||
module.exports = GenericCollection; | ||
@@ -13,2 +8,4 @@ function GenericCollection() { | ||
GenericCollection.EmptyArray = Object.freeze([]); | ||
GenericCollection.prototype.addEach = function (values) { | ||
@@ -29,2 +26,7 @@ if (values && Object(values) === values) { | ||
} | ||
} else if (values && typeof values.length === "number") { | ||
// Strings | ||
for (var i = 0; i < values.length; i++) { | ||
this.add(values[i], i); | ||
} | ||
} | ||
@@ -74,3 +76,3 @@ return this; | ||
GenericCollection.prototype.group = function (callback, thisp, equals) { | ||
equals = equals || equalsOperator; | ||
equals = equals || Object.equals; | ||
var groups = []; | ||
@@ -95,3 +97,3 @@ var keys = []; | ||
GenericCollection.prototype.toArray = function () { | ||
return this.map(identity); | ||
return this.map(Function.identity); | ||
}; | ||
@@ -124,11 +126,5 @@ | ||
var thisp = arguments[1]; | ||
var iterator = this.iterate(); | ||
while (true) { | ||
var iteration = iterator.next(); | ||
if (iteration.done) { | ||
return true; | ||
} else if (!callback.call(thisp, iteration.value, iteration.index, this)) { | ||
return false; | ||
} | ||
} | ||
return this.reduce(function (result, value, key, object, depth) { | ||
return result && callback.call(thisp, value, key, object, depth); | ||
}, true); | ||
}; | ||
@@ -138,15 +134,17 @@ | ||
var thisp = arguments[1]; | ||
var iterator = this.iterate(); | ||
while (true) { | ||
var iteration = iterator.next(); | ||
if (iteration.done) { | ||
return false; | ||
} else if (callback.call(thisp, iteration.value, iteration.index, this)) { | ||
return true; | ||
} | ||
} | ||
return this.reduce(function (result, value, key, object, depth) { | ||
return result || callback.call(thisp, value, key, object, depth); | ||
}, false); | ||
}; | ||
GenericCollection.prototype.all = function () { | ||
return this.every(Boolean); | ||
}; | ||
GenericCollection.prototype.any = function () { | ||
return this.some(Boolean); | ||
}; | ||
GenericCollection.prototype.min = function (compare) { | ||
compare = compare || this.contentCompare || compareOperator; | ||
compare = compare || this.contentCompare || Object.compare; | ||
var first = true; | ||
@@ -164,3 +162,3 @@ return this.reduce(function (result, value) { | ||
GenericCollection.prototype.max = function (compare) { | ||
compare = compare || this.contentCompare || compareOperator; | ||
compare = compare || this.contentCompare || Object.compare; | ||
var first = true; | ||
@@ -215,3 +213,3 @@ return this.reduce(function (result, value) { | ||
table.unshift(this); | ||
return unzipOperator(table); | ||
return Array.unzip(table); | ||
} | ||
@@ -221,14 +219,19 @@ | ||
return this.reduce(function (result, string) { | ||
return result + delimiter + string; | ||
}); | ||
// work-around for reduce that does not support no-basis form | ||
if (result === void 0) { | ||
return string; | ||
} else { | ||
return result + delimiter + string; | ||
} | ||
}, void 0); | ||
}; | ||
GenericCollection.prototype.sorted = function (compare, by, order) { | ||
compare = compare || this.contentCompare || compareOperator; | ||
compare = compare || this.contentCompare || Object.compare; | ||
// account for comparators generated by Function.by | ||
if (compare.by) { | ||
by = compare.by; | ||
compare = compare.compare || this.contentCompare || compareOperator; | ||
compare = compare.compare || this.contentCompare || Object.compare; | ||
} else { | ||
by = by || identity; | ||
by = by || Function.identity; | ||
} | ||
@@ -255,3 +258,3 @@ if (order === undefined) | ||
GenericCollection.prototype.clone = function (depth, memo, clone) { | ||
GenericCollection.prototype.clone = function (depth, memo) { | ||
if (depth === undefined) { | ||
@@ -262,8 +265,7 @@ depth = Infinity; | ||
} | ||
clone = clone || cloneOperator; | ||
var collection = this.constructClone(); | ||
var clone = this.constructClone(); | ||
this.forEach(function (value, key) { | ||
collection.add(clone(value, depth - 1, memo), key); | ||
clone.add(Object.clone(value, depth - 1, memo), key); | ||
}, this); | ||
return collection; | ||
return clone; | ||
}; | ||
@@ -277,2 +279,16 @@ | ||
function identity(value) { return value; } | ||
GenericCollection.prototype.iterator = function () { | ||
return this.iterate.apply(this, arguments); | ||
}; | ||
GenericCollection._sizePropertyDescriptor = { | ||
get: function() { | ||
return this.length; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}; | ||
Object.defineProperty(GenericCollection.prototype,"size",GenericCollection._sizePropertyDescriptor); | ||
require("./shim-array"); |
"use strict"; | ||
var ObservableMap = require("pop-observe/observable-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var Iterator = require("./iterator"); | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var copy = require("./copy"); | ||
var Object = require("./shim-object"); | ||
var MapChanges = require("./listen/map-changes"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -15,4 +12,4 @@ module.exports = GenericMap; | ||
copy(GenericMap.prototype, ObservableMap.prototype); | ||
copy(GenericMap.prototype, ObservableObject.prototype); | ||
Object.addEach(GenericMap.prototype, MapChanges.prototype); | ||
Object.addEach(GenericMap.prototype, PropertyChanges.prototype); | ||
@@ -37,2 +34,8 @@ // all of these methods depend on the constructor providing a `store` set | ||
} | ||
} else if (typeof values.length === "number") { | ||
// Array-like objects that do not implement forEach, ergo, | ||
// Arguments | ||
for (var i = 0; i < values.length; i++) { | ||
this.add(values[i], i); | ||
} | ||
} else { | ||
@@ -44,2 +47,7 @@ // copy other objects as map-alikes | ||
} | ||
} else if (values && typeof values.length === "number") { | ||
// String | ||
for (var i = 0; i < values.length; i++) { | ||
this.add(values[i], i); | ||
} | ||
} | ||
@@ -60,5 +68,2 @@ return this; | ||
GenericMap.prototype.getDefault = function () { | ||
}; | ||
GenericMap.prototype.set = function (key, value) { | ||
@@ -69,14 +74,12 @@ var item = new this.Item(key, value); | ||
if (found) { // update | ||
var from; | ||
if (this.dispatchesMapChanges) { | ||
from = found.value; | ||
this.dispatchMapWillChange("update", key, value, from); | ||
this.dispatchBeforeMapChange(key, found.value); | ||
} | ||
found.value = value; | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("update", key, value, from); | ||
this.dispatchMapChange(key, value); | ||
} | ||
} else { // create | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapWillChange("create", key, value); | ||
this.dispatchBeforeMapChange(key, undefined); | ||
} | ||
@@ -88,3 +91,3 @@ if (this.store.add(item)) { | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("create", key, value); | ||
this.dispatchMapChange(key, value); | ||
} | ||
@@ -106,6 +109,5 @@ } | ||
if (this.store.has(item)) { | ||
var from; | ||
var from = this.store.get(item).value; | ||
if (this.dispatchesMapChanges) { | ||
from = this.store.get(item).value; | ||
this.dispatchMapWillChange("delete", key, void 0, from); | ||
this.dispatchBeforeMapChange(key, from); | ||
} | ||
@@ -115,3 +117,3 @@ this.store["delete"](item); | ||
if (this.dispatchesMapChanges) { | ||
this.dispatchMapChange("delete", key, void 0, from); | ||
this.dispatchMapChange(key, undefined); | ||
} | ||
@@ -124,8 +126,8 @@ return true; | ||
GenericMap.prototype.clear = function () { | ||
var from; | ||
var keys; | ||
if (this.dispatchesMapChanges) { | ||
this.forEach(function (value, key) { | ||
this.dispatchMapWillChange("delete", key, void 0, value); | ||
this.dispatchBeforeMapChange(key, value); | ||
}, this); | ||
from = this.constructClone(this); | ||
keys = this.keys(); | ||
} | ||
@@ -135,4 +137,4 @@ this.store.clear(); | ||
if (this.dispatchesMapChanges) { | ||
from.forEach(function (value, key) { | ||
this.dispatchMapChange("delete", key, void 0, value); | ||
keys.forEach(function (key) { | ||
this.dispatchMapChange(key); | ||
}, this); | ||
@@ -142,6 +144,2 @@ } | ||
GenericMap.prototype.iterate = function () { | ||
return new this.Iterator(this); | ||
}; | ||
GenericMap.prototype.reduce = function (callback, basis, thisp) { | ||
@@ -166,3 +164,3 @@ return this.store.reduce(function (basis, item) { | ||
GenericMap.prototype.values = function () { | ||
return this.map(identity); | ||
return this.map(Function.identity); | ||
}; | ||
@@ -176,4 +174,9 @@ | ||
// XXX deprecated | ||
GenericMap.prototype.items = function () { | ||
return this.entries(); | ||
}; | ||
GenericMap.prototype.equals = function (that, equals) { | ||
equals = equals || equalsOperator; | ||
equals = equals || Object.equals; | ||
if (this === that) { | ||
@@ -193,4 +196,7 @@ return true; | ||
GenericMap.prototype.toJSON = function () { | ||
return this.entries(); | ||
}; | ||
GenericMap.prototype.Item = Item; | ||
GenericMap.prototype.Iterator = GenericMapIterator; | ||
@@ -203,28 +209,8 @@ function Item(key, value) { | ||
Item.prototype.equals = function (that) { | ||
return equalsOperator(this.key, that.key) && equalsOperator(this.value, that.value); | ||
return Object.equals(this.key, that.key) && Object.equals(this.value, that.value); | ||
}; | ||
Item.prototype.compare = function (that) { | ||
return compareOperator(this.key, that.key); | ||
return Object.compare(this.key, that.key); | ||
}; | ||
function GenericMapIterator(map) { | ||
this.storeIterator = new Iterator(map.store); | ||
} | ||
GenericMapIterator.prototype = Object.create(Iterator.prototype); | ||
GenericMapIterator.prototype.constructor = GenericMapIterator; | ||
GenericMapIterator.prototype.next = function () { | ||
var iteration = this.storeIterator.next(); | ||
if (iteration.done) { | ||
return iteration; | ||
} else { | ||
return new Iterator.Iteration( | ||
iteration.value.value, | ||
iteration.value.key | ||
); | ||
} | ||
}; | ||
function identity(value) { return value; } |
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var Object = require("./shim-object"); | ||
@@ -11,3 +10,3 @@ module.exports = GenericOrder; | ||
GenericOrder.prototype.equals = function (that, equals) { | ||
equals = equals || this.contentEquals || equalsOperator; | ||
equals = equals || this.contentEquals || Object.equals; | ||
@@ -31,3 +30,3 @@ if (this === that) { | ||
GenericOrder.prototype.compare = function (that, compare) { | ||
compare = compare || this.contentCompare || compareOperator; | ||
compare = compare || this.contentCompare || Object.compare; | ||
@@ -59,1 +58,4 @@ if (this === that) { | ||
GenericOrder.prototype.toJSON = function () { | ||
return this.toArray(); | ||
}; |
var has = require("pop-has"); | ||
module.exports = GenericSet; | ||
@@ -19,3 +17,3 @@ function GenericSet() { | ||
return this.constructClone(this.filter(function (value) { | ||
return has(that, value); | ||
return that.has(value); | ||
})); | ||
@@ -36,2 +34,9 @@ }; | ||
GenericSet.prototype.deleteAll = function (value) { | ||
// deleteAll is equivalent to delete for sets since they guarantee that | ||
// only one value exists for an equivalence class, but deleteAll returns | ||
// the count of deleted values instead of whether a value was deleted. | ||
return +this["delete"](value); | ||
}; | ||
GenericSet.prototype.equals = function (that, equals) { | ||
@@ -48,2 +53,6 @@ var self = this; | ||
GenericSet.prototype.toJSON = function () { | ||
return this.toArray(); | ||
}; | ||
// W3C DOMTokenList API overlap (does not handle variadic arguments) | ||
@@ -50,0 +59,0 @@ |
93
heap.js
@@ -5,10 +5,8 @@ | ||
var ArrayChanges = require("./listen/array-changes"); | ||
var Shim = require("./shim"); | ||
var GenericCollection = require("./generic-collection"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var ObservableMap = require("pop-observe/observable-map"); | ||
var O = require("pop-observe"); | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var copy = require("./copy"); | ||
var MapChanges = require("./listen/map-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -23,4 +21,4 @@ // Max Heap by default. Comparison can be reversed to produce a Min Heap. | ||
} | ||
this.contentEquals = equals || equalsOperator; | ||
this.contentCompare = compare || compareOperator; | ||
this.contentEquals = equals || Object.equals; | ||
this.contentCompare = compare || Object.compare; | ||
this.content = []; | ||
@@ -33,6 +31,6 @@ this.length = 0; | ||
copy(Heap.prototype, GenericCollection.prototype); | ||
copy(Heap.prototype, ObservableObject.prototype); | ||
copy(Heap.prototype, ObservableRange.prototype); | ||
copy(Heap.prototype, ObservableMap.prototype); | ||
Object.addEach(Heap.prototype, GenericCollection.prototype); | ||
Object.addEach(Heap.prototype, PropertyChanges.prototype); | ||
Object.addEach(Heap.prototype, RangeChanges.prototype); | ||
Object.addEach(Heap.prototype, MapChanges.prototype); | ||
@@ -47,2 +45,3 @@ Heap.prototype.constructClone = function (values) { | ||
// TODO variadic | ||
Heap.prototype.push = function (value) { | ||
@@ -66,7 +65,3 @@ this.content.push(value); | ||
if (this.content.length > 0) { | ||
if (this.content.set) { | ||
this.content.set(0, top); | ||
} else { | ||
this.content[0] = top; | ||
} | ||
this.content.set(0, top); | ||
this.sink(0); | ||
@@ -95,3 +90,6 @@ } | ||
Heap.prototype.delete = function (value) { | ||
Heap.prototype["delete"] = function (value, equals) { | ||
if (equals) { | ||
throw new Error("Heap#delete does not support second argument: equals"); | ||
} | ||
var index = this.indexOf(value); | ||
@@ -104,7 +102,3 @@ if (index === -1) | ||
return true; | ||
if (this.content.set) { | ||
this.content.set(index, top); | ||
} else { | ||
this.content[index] = top; | ||
} | ||
this.content.set(index, top); | ||
var comparison = this.contentCompare(top, value); | ||
@@ -144,9 +138,4 @@ if (comparison > 0) { | ||
if (this.contentCompare(parent, value) < 0) { | ||
if (this.content.set) { | ||
this.content.set(parentIndex, value); | ||
this.content.set(index, parent); | ||
} else { | ||
this.content[parentIndex] = value; | ||
this.content[index] = parent; | ||
} | ||
this.content.set(parentIndex, value); | ||
this.content.set(index, parent); | ||
} else { | ||
@@ -204,9 +193,4 @@ // Stop propagating if the parent is greater than the value. | ||
if (needsSwap) { | ||
if (this.content.set) { | ||
this.content.set(index, this.content[swapIndex]); | ||
this.content.set(swapIndex, value); | ||
} else { | ||
this.content[index] = this.content[swapIndex]; | ||
this.content[swapIndex] = value; | ||
} | ||
this.content.set(index, this.content[swapIndex]); | ||
this.content.set(swapIndex, value); | ||
index = swapIndex; | ||
@@ -242,21 +226,14 @@ // and continue sinking | ||
Heap.prototype.makeMapChangesObservable = function () { | ||
this.makeChangesObservable(); | ||
this.dispatchesMapChanges = true; | ||
Heap.prototype.toJSON = function () { | ||
return this.toArray(); | ||
}; | ||
Heap.prototype.makeRangeChangesObservable = function () { | ||
this.makeChangesObservable(); | ||
this.dispatchesRangeChanges = true; | ||
Heap.prototype.makeObservable = function () { | ||
// TODO refactor dispatchers to allow direct forwarding | ||
this.content.addRangeChangeListener(this, "content"); | ||
this.content.addBeforeRangeChangeListener(this, "content"); | ||
this.content.addMapChangeListener(this, "content"); | ||
this.content.addBeforeMapChangeListener(this, "content"); | ||
}; | ||
Heap.prototype.makeChangesObservable = function () { | ||
if (this.dispatchesChanges) { | ||
return; | ||
} | ||
O.observeMapChange(this.content, this, "content"); | ||
O.observeMapWillChange(this.content, this, "content"); | ||
this.dispatchesChanges = true; | ||
}; | ||
Heap.prototype.handleContentRangeChange = function (plus, minus, index) { | ||
@@ -267,12 +244,12 @@ this.dispatchRangeChange(plus, minus, index); | ||
Heap.prototype.handleContentRangeWillChange = function (plus, minus, index) { | ||
this.dispatchRangeWillChange(plus, minus, index); | ||
this.dispatchBeforeRangeChange(plus, minus, index); | ||
}; | ||
Heap.prototype.handleContentMapChange = function (plus, minus, key, type) { | ||
this.dispatchMapChange(type, key, plus, minus); | ||
Heap.prototype.handleContentMapChange = function (value, key) { | ||
this.dispatchMapChange(key, value); | ||
}; | ||
Heap.prototype.handleContentMapWillChange = function (plus, minus, key, type) { | ||
this.dispatchMapWillChange(type, key, plus, minus); | ||
Heap.prototype.handleContentMapWillChange = function (value, key) { | ||
this.dispatchBeforeMapChange(key, value); | ||
}; | ||
654
iterator.js
@@ -5,36 +5,36 @@ "use strict"; | ||
var WeakMap = require("weak-map"); | ||
var Object = require("./shim-object"); | ||
var GenericCollection = require("./generic-collection"); | ||
// upgrades an iterable to a Iterator | ||
function Iterator(iterable, start, stop, step) { | ||
if (!iterable) { | ||
return Iterator.empty; | ||
} else if (iterable instanceof Iterator) { | ||
return iterable; | ||
} else if (!(this instanceof Iterator)) { | ||
return new Iterator(iterable, start, stop, step); | ||
} else if (Array.isArray(iterable) || typeof iterable === "string") { | ||
iterators.set(this, new IndexIterator(iterable, start, stop, step)); | ||
return; | ||
function Iterator(iterable) { | ||
if (!(this instanceof Iterator)) { | ||
return new Iterator(iterable); | ||
} | ||
if (Array.isArray(iterable) || typeof iterable === "string") | ||
return Iterator.iterate(iterable); | ||
iterable = Object(iterable); | ||
if (iterable.next) { | ||
iterators.set(this, iterable); | ||
if (iterable instanceof Iterator) { | ||
return iterable; | ||
} else if (iterable.next) { | ||
this.next = function () { | ||
return iterable.next(); | ||
}; | ||
} else if (iterable.iterate) { | ||
iterators.set(this, iterable.iterate(start, stop, step)); | ||
var iterator = iterable.iterate(); | ||
this.next = function () { | ||
return iterator.next(); | ||
}; | ||
} else if (Object.prototype.toString.call(iterable) === "[object Function]") { | ||
this.next = iterable; | ||
} else if (Object.getPrototypeOf(iterable) === Object.prototype) { | ||
iterators.set(this, new ObjectIterator(iterable)); | ||
} else { | ||
throw new TypeError("Can't iterate " + iterable); | ||
} | ||
} | ||
// Using iterators as a hidden table associating a full-fledged Iterator with | ||
// an underlying, usually merely "nextable", iterator. | ||
var iterators = new WeakMap(); | ||
// Selectively apply generic methods of GenericCollection | ||
Iterator.prototype.forEach = GenericCollection.prototype.forEach; | ||
@@ -45,2 +45,4 @@ Iterator.prototype.map = GenericCollection.prototype.map; | ||
Iterator.prototype.some = GenericCollection.prototype.some; | ||
Iterator.prototype.any = GenericCollection.prototype.any; | ||
Iterator.prototype.all = GenericCollection.prototype.all; | ||
Iterator.prototype.min = GenericCollection.prototype.min; | ||
@@ -58,4 +60,14 @@ Iterator.prototype.max = GenericCollection.prototype.max; | ||
Iterator.prototype.toObject = GenericCollection.prototype.toObject; | ||
Iterator.prototype.iterator = GenericCollection.prototype.iterator; | ||
// This is a bit of a cheat so flatten and such work with the generic reducible | ||
Iterator.prototype.__iterationObject = null; | ||
Object.defineProperty(Iterator.prototype,"_iterationObject", { | ||
get: function() { | ||
return this.__iterationObject || (this.__iterationObject = { done: false, value:void 0}); | ||
} | ||
}); | ||
// this is a bit of a cheat so flatten and such work with the generic | ||
// reducible | ||
Iterator.prototype.constructClone = function (values) { | ||
@@ -67,75 +79,41 @@ var clone = []; | ||
// A level of indirection so a full-interface iterator can proxy for a simple | ||
// nextable iterator. | ||
Iterator.prototype.next = function () { | ||
var nextable = iterators.get(this); | ||
if (nextable) { | ||
return nextable.next(); | ||
} else { | ||
return Iterator.done; | ||
} | ||
}; | ||
Iterator.prototype.iterateMap = function (callback /*, thisp*/) { | ||
Iterator.prototype.mapIterator = function (callback /*, thisp*/) { | ||
var self = Iterator(this), | ||
thisp = arguments[1]; | ||
return new MapIterator(self, callback, thisp); | ||
}; | ||
thisp = arguments[1], | ||
i = 0; | ||
function MapIterator(iterator, callback, thisp) { | ||
this.iterator = iterator; | ||
this.callback = callback; | ||
this.thisp = thisp; | ||
} | ||
if (Object.prototype.toString.call(callback) != "[object Function]") | ||
throw new TypeError(); | ||
MapIterator.prototype = Object.create(Iterator.prototype); | ||
MapIterator.prototype.constructor = MapIterator; | ||
MapIterator.prototype.next = function () { | ||
var iteration = this.iterator.next(); | ||
if (iteration.done) { | ||
return iteration; | ||
} else { | ||
return new Iteration( | ||
this.callback.call( | ||
this.thisp, | ||
iteration.value, | ||
iteration.index, | ||
this.iteration | ||
), | ||
iteration.index | ||
); | ||
} | ||
return new self.constructor(function () { | ||
if(self._iterationObject.done !== true) { | ||
var callbackValue = callback.call(thisp, self.next().value, i++, self); | ||
self._iterationObject.value = callbackValue; | ||
} | ||
return self._iterationObject; | ||
}); | ||
}; | ||
Iterator.prototype.iterateFilter = function (callback /*, thisp*/) { | ||
Iterator.prototype.filterIterator = function (callback /*, thisp*/) { | ||
var self = Iterator(this), | ||
thisp = arguments[1], | ||
index = 0; | ||
i = 0; | ||
return new FilterIterator(self, callback, thisp); | ||
}; | ||
if (Object.prototype.toString.call(callback) != "[object Function]") | ||
throw new TypeError(); | ||
function FilterIterator(iterator, callback, thisp) { | ||
this.iterator = iterator; | ||
this.callback = callback; | ||
this.thisp = thisp; | ||
} | ||
FilterIterator.prototype = Object.create(Iterator.prototype); | ||
FilterIterator.prototype.constructor = FilterIterator; | ||
FilterIterator.prototype.next = function () { | ||
var iteration; | ||
while (true) { | ||
iteration = this.iterator.next(); | ||
if (iteration.done || this.callback.call( | ||
this.thisp, | ||
iteration.value, | ||
iteration.index, | ||
this.iteration | ||
)) { | ||
return iteration; | ||
return new self.constructor(function () { | ||
var nextEntry; | ||
while (true) { | ||
nextEntry = self.next(); | ||
if(nextEntry.done !== true) { | ||
if (callback.call(thisp, nextEntry.value, i++, self)) | ||
return nextEntry; | ||
} | ||
else { | ||
//done true and value undefined at this point | ||
return nextEntry; | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
@@ -147,72 +125,69 @@ | ||
thisp = arguments[2], | ||
iteration; | ||
i = 0, | ||
nextEntry; | ||
// First iteration unrolled | ||
iteration = self.next(); | ||
if (iteration.done) { | ||
if (Object.prototype.toString.call(callback) != "[object Function]") | ||
throw new TypeError(); | ||
// first iteration unrolled | ||
nextEntry = self.next(); | ||
if(nextEntry.done === true) { | ||
if (arguments.length > 1) { | ||
return arguments[1]; | ||
return arguments[1]; // initial | ||
} else { | ||
throw TypeError("Reduce of empty iterator with no initial value"); | ||
throw TypeError("cannot reduce a value from an empty iterator with no initial value"); | ||
} | ||
} else if (arguments.length > 1) { | ||
result = callback.call( | ||
thisp, | ||
result, | ||
iteration.value, | ||
iteration.index, | ||
self | ||
); | ||
} | ||
if (arguments.length > 1) { | ||
result = callback.call(thisp, result, nextEntry.value, i, self); | ||
} else { | ||
result = iteration.value; | ||
result = nextEntry.value; | ||
} | ||
// Remaining entries | ||
i++; | ||
// remaining entries | ||
while (true) { | ||
iteration = self.next(); | ||
if (iteration.done) { | ||
nextEntry = self.next(); | ||
if(nextEntry.done === true) { | ||
return result; | ||
} else { | ||
result = callback.call( | ||
thisp, | ||
result, | ||
iteration.value, | ||
iteration.index, | ||
self | ||
); | ||
} | ||
result = callback.call(thisp, result, nextEntry.value, i, self); | ||
i++; | ||
} | ||
}; | ||
Iterator.prototype.concat = function () { | ||
return Iterator.concat( | ||
Array.prototype.concat.apply(this, arguments) | ||
); | ||
}; | ||
Iterator.prototype.dropWhile = function (callback /*, thisp */) { | ||
var self = Iterator(this), | ||
thisp = arguments[1], | ||
iteration; | ||
stopped = false, | ||
stopValue, | ||
nextEntry, | ||
i = 0; | ||
if (Object.prototype.toString.call(callback) != "[object Function]") | ||
throw new TypeError(); | ||
while (true) { | ||
iteration = self.next(); | ||
if (iteration.done) { | ||
return Iterator.empty; | ||
} else if (!callback.call(thisp, iteration.value, iteration.index, self)) { | ||
return new DropWhileIterator(iteration, self); | ||
nextEntry = self.next(); | ||
if(nextEntry.done === true) { | ||
break; | ||
} | ||
if (!callback.call(thisp, nextEntry.value, i, self)) { | ||
stopped = true; | ||
stopValue = nextEntry.value; | ||
break; | ||
} | ||
i++; | ||
} | ||
}; | ||
function DropWhileIterator(iteration, iterator) { | ||
this.iteration = iteration; | ||
this.iterator = iterator; | ||
this.parent = null; | ||
} | ||
DropWhileIterator.prototype = Object.create(Iterator.prototype); | ||
DropWhileIterator.prototype.constructor = DropWhileIterator; | ||
DropWhileIterator.prototype.next = function () { | ||
var result = this.iteration; | ||
if (result) { | ||
this.iteration = null; | ||
return result; | ||
if (stopped) { | ||
return self.constructor([stopValue]).concat(self); | ||
} else { | ||
return this.iterator.next(); | ||
return self.constructor([]); | ||
} | ||
@@ -223,197 +198,109 @@ }; | ||
var self = Iterator(this), | ||
thisp = arguments[1]; | ||
return new TakeWhileIterator(self, callback, thisp); | ||
}; | ||
thisp = arguments[1], | ||
nextEntry, | ||
i = 0; | ||
function TakeWhileIterator(iterator, callback, thisp) { | ||
this.iterator = iterator; | ||
this.callback = callback; | ||
this.thisp = thisp; | ||
} | ||
if (Object.prototype.toString.call(callback) != "[object Function]") | ||
throw new TypeError(); | ||
TakeWhileIterator.prototype = Object.create(Iterator.prototype); | ||
TakeWhileIterator.prototype.constructor = TakeWhileIterator; | ||
return new self.constructor(function () { | ||
if(self._iterationObject.done !== true) { | ||
var value = self.next().value; | ||
if(callback.call(thisp, value, i++, self)) { | ||
self._iterationObject.value = value; | ||
} | ||
else { | ||
self._iterationObject.done = true; | ||
self._iterationObject.value = void 0; | ||
} | ||
} | ||
return self._iterationObject; | ||
}); | ||
TakeWhileIterator.prototype.next = function () { | ||
var iteration = this.iterator.next(); | ||
if (iteration.done) { | ||
return iteration; | ||
} else if (this.callback.call( | ||
this.thisp, | ||
iteration.value, | ||
iteration.index, | ||
this.iterator | ||
)) { | ||
return iteration; | ||
} else { | ||
return Iterator.done; | ||
} | ||
}; | ||
Iterator.prototype.iterateZip = function () { | ||
return Iterator.unzip(Array.prototype.concat.apply(this, arguments)); | ||
Iterator.prototype.zipIterator = function () { | ||
return Iterator.unzip( | ||
Array.prototype.concat.apply(this, arguments) | ||
); | ||
}; | ||
Iterator.prototype.iterateUnzip = function () { | ||
return Iterator.unzip(this); | ||
Iterator.prototype.enumerateIterator = function (start) { | ||
return Iterator.count(start).zipIterator(this); | ||
}; | ||
Iterator.prototype.iterateEnumerate = function (start) { | ||
return Iterator.count(start).iterateZip(this); | ||
}; | ||
Iterator.prototype.iterateConcat = function () { | ||
return Iterator.flatten(Array.prototype.concat.apply(this, arguments)); | ||
}; | ||
Iterator.prototype.iterateFlatten = function () { | ||
return Iterator.flatten(this); | ||
}; | ||
Iterator.prototype.recount = function (start) { | ||
return new RecountIterator(this, start); | ||
}; | ||
function RecountIterator(iterator, start) { | ||
this.iterator = iterator; | ||
this.index = start || 0; | ||
} | ||
RecountIterator.prototype = Object.create(Iterator.prototype); | ||
RecountIterator.prototype.constructor = RecountIterator; | ||
RecountIterator.prototype.next = function () { | ||
var iteration = this.iterator.next(); | ||
if (iteration.done) { | ||
return iteration; | ||
} else { | ||
return new Iteration( | ||
iteration.value, | ||
this.index++ | ||
); | ||
} | ||
}; | ||
// creates an iterator for Array and String | ||
function IndexIterator(iterable, start, stop, step) { | ||
if (step == null) { | ||
step = 1; | ||
} | ||
if (stop == null) { | ||
stop = start; | ||
start = 0; | ||
} | ||
if (start == null) { | ||
start = 0; | ||
} | ||
if (step == null) { | ||
step = 1; | ||
} | ||
if (stop == null) { | ||
stop = iterable.length; | ||
} | ||
this.iterable = iterable; | ||
this.start = start; | ||
this.stop = stop; | ||
this.step = step; | ||
} | ||
IndexIterator.prototype.next = function () { | ||
// Advance to next owned entry | ||
if (typeof this.iterable === "object") { // as opposed to string | ||
while (!(this.start in this.iterable)) { | ||
if (this.start >= this.stop) { | ||
return Iterator.done; | ||
} else { | ||
this.start += this.step; | ||
Iterator.iterate = function (iterable) { | ||
var start; | ||
start = 0; | ||
return new Iterator(function () { | ||
// advance to next owned entry | ||
if (typeof iterable === "object") { | ||
while (!(start in iterable)) { | ||
// deliberately late bound | ||
if (start >= iterable.length) { | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
break; | ||
} | ||
else start += 1; | ||
} | ||
} else if (start >= iterable.length) { | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
} | ||
} | ||
if (this.start >= this.stop) { // end of string | ||
return Iterator.done; | ||
} | ||
var iteration = new Iteration( | ||
this.iterable[this.start], | ||
this.start | ||
); | ||
this.start += this.step; | ||
return iteration; | ||
}; | ||
function ObjectIterator(object) { | ||
this.object = object; | ||
this.iterator = new Iterator(Object.keys(object)); | ||
} | ||
ObjectIterator.prototype.next = function () { | ||
var iteration = this.iterator.next(); | ||
if (iteration.done) { | ||
return iteration; | ||
} else { | ||
var key = iteration.value; | ||
return new Iteration(this.object[key], key); | ||
} | ||
if(!this._iterationObject.done) { | ||
this._iterationObject.value = iterable[start]; | ||
start += 1; | ||
} | ||
return this._iterationObject; | ||
}); | ||
}; | ||
Iterator.cycle = function (cycle, times) { | ||
if (arguments.length < 2) { | ||
var next; | ||
if (arguments.length < 2) | ||
times = Infinity; | ||
} | ||
return new CycleIterator(cycle, times); | ||
}; | ||
//cycle = Iterator(cycle).toArray(); | ||
return new Iterator(function () { | ||
var iteration, nextEntry; | ||
function CycleIterator(cycle, times) { | ||
this.cycle = cycle; | ||
this.times = times; | ||
this.iterator = Iterator.empty; | ||
} | ||
if(next) { | ||
nextEntry = next(); | ||
} | ||
CycleIterator.prototype = Object.create(Iterator.prototype); | ||
CycleIterator.prototype.constructor = CycleIterator; | ||
CycleIterator.prototype.next = function () { | ||
var iteration = this.iterator.next(); | ||
if (iteration.done) { | ||
if (this.times > 0) { | ||
this.times--; | ||
this.iterator = new Iterator(this.cycle); | ||
return this.iterator.next(); | ||
} else { | ||
return iteration; | ||
if(!next || nextEntry.done === true) { | ||
if (times > 0) { | ||
times--; | ||
iteration = Iterator.iterate(cycle); | ||
nextEntry = (next = iteration.next.bind(iteration))(); | ||
} | ||
else { | ||
this._iterationObject.done = true; | ||
nextEntry = this._iterationObject; } | ||
} | ||
} else { | ||
return iteration; | ||
} | ||
return nextEntry; | ||
}); | ||
}; | ||
Iterator.concat = function (/* ...iterators */) { | ||
return Iterator.flatten(Array.prototype.slice.call(arguments)); | ||
}; | ||
Iterator.flatten = function (iterators) { | ||
Iterator.concat = function (iterators) { | ||
iterators = Iterator(iterators); | ||
return new ChainIterator(iterators); | ||
}; | ||
function ChainIterator(iterators) { | ||
this.iterators = iterators; | ||
this.iterator = Iterator.empty; | ||
} | ||
ChainIterator.prototype = Object.create(Iterator.prototype); | ||
ChainIterator.prototype.constructor = ChainIterator; | ||
ChainIterator.prototype.next = function () { | ||
var iteration = this.iterator.next(); | ||
if (iteration.done) { | ||
var iteratorIteration = this.iterators.next(); | ||
if (iteratorIteration.done) { | ||
return Iterator.done; | ||
} else { | ||
this.iterator = new Iterator(iteratorIteration.value); | ||
return this.iterator.next(); | ||
var next; | ||
return new Iterator(function (){ | ||
var iteration, nextEntry; | ||
if(next) nextEntry = next(); | ||
if(!nextEntry || nextEntry.done === true) { | ||
nextEntry = iterators.next(); | ||
if(nextEntry.done === false) { | ||
iteration = Iterator(nextEntry.value); | ||
next = iteration.next.bind(iteration); | ||
return next(); | ||
} | ||
else { | ||
return nextEntry; | ||
} | ||
} | ||
} else { | ||
return iteration; | ||
} | ||
else return nextEntry; | ||
}); | ||
}; | ||
@@ -424,35 +311,35 @@ | ||
if (iterators.length === 0) | ||
return new Iterator.empty; | ||
return new UnzipIterator(iterators); | ||
}; | ||
function UnzipIterator(iterators) { | ||
this.iterators = iterators; | ||
this.index = 0; | ||
} | ||
UnzipIterator.prototype = Object.create(Iterator.prototype); | ||
UnzipIterator.prototype.constructor = UnzipIterator; | ||
UnzipIterator.prototype.next = function () { | ||
var done = false | ||
var result = this.iterators.map(function (iterator) { | ||
var iteration = iterator.next(); | ||
if (iteration.done) { | ||
done = true; | ||
} else { | ||
return iteration.value; | ||
return new Iterator([]); | ||
return new Iterator(function () { | ||
var stopped, nextEntry; | ||
var result = iterators.map(function (iterator) { | ||
nextEntry = iterator.next(); | ||
if (nextEntry.done === true ) { | ||
stopped = true; | ||
} | ||
return nextEntry.value; | ||
}); | ||
if (stopped) { | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
} | ||
else { | ||
this._iterationObject.value = result; | ||
} | ||
return this._iterationObject; | ||
}); | ||
if (done) { | ||
return Iterator.done; | ||
} else { | ||
return new Iteration(result, this.index++); | ||
} | ||
}; | ||
Iterator.zip = function () { | ||
return Iterator.unzip(Array.prototype.slice.call(arguments)); | ||
return Iterator.unzip( | ||
Array.prototype.slice.call(arguments) | ||
); | ||
}; | ||
Iterator.chain = function () { | ||
return Iterator.concat( | ||
Array.prototype.slice.call(arguments) | ||
); | ||
}; | ||
Iterator.range = function (start, stop, step) { | ||
@@ -468,3 +355,13 @@ if (arguments.length < 3) { | ||
step = step || 1; | ||
return new RangeIterator(start, stop, step); | ||
return new Iterator(function () { | ||
if (start >= stop) { | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
} | ||
var result = start; | ||
start += step; | ||
this._iterationObject.value = result; | ||
return this._iterationObject; | ||
}); | ||
}; | ||
@@ -476,93 +373,6 @@ | ||
function RangeIterator(start, stop, step) { | ||
this.start = start; | ||
this.stop = stop; | ||
this.step = step; | ||
this.index = 0; | ||
} | ||
RangeIterator.prototype = Object.create(Iterator.prototype); | ||
RangeIterator.prototype.constructor = RangeIterator; | ||
RangeIterator.prototype.next = function () { | ||
if (this.start >= this.stop) { | ||
return Iterator.done; | ||
} else { | ||
var result = this.start; | ||
this.start += this.step; | ||
return new Iteration(result, this.index++); | ||
} | ||
}; | ||
Iterator.repeat = function (value, times) { | ||
if (times == null) { | ||
times = Infinity; | ||
} | ||
return new RepeatIterator(value, times); | ||
return new Iterator.range(times).mapIterator(function () { | ||
return value; | ||
}); | ||
}; | ||
function RepeatIterator(value, times) { | ||
this.value = value; | ||
this.times = times; | ||
this.index = 0; | ||
} | ||
RepeatIterator.prototype = Object.create(Iterator.prototype); | ||
RepeatIterator.prototype.constructor = RepeatIterator; | ||
RepeatIterator.prototype.next = function () { | ||
if (this.index < this.times) { | ||
return new Iteration(this.value, this.index++); | ||
} else { | ||
return Iterator.done; | ||
} | ||
}; | ||
Iterator.enumerate = function (values, start) { | ||
return Iterator.count(start).iterateZip(new Iterator(values)); | ||
}; | ||
function EmptyIterator() {} | ||
EmptyIterator.prototype = Object.create(Iterator.prototype); | ||
EmptyIterator.prototype.constructor = EmptyIterator; | ||
EmptyIterator.prototype.next = function () { | ||
return Iterator.done; | ||
}; | ||
Iterator.empty = new EmptyIterator(); | ||
// Iteration and DoneIteration exist here only to encourage hidden classes. | ||
// Otherwise, iterations are merely duck-types. | ||
function Iteration(value, index) { | ||
this.value = value; | ||
this.index = index; | ||
} | ||
Iteration.prototype.done = false; | ||
Iteration.prototype.equals = function (that, equals, memo) { | ||
if (!that) return false; | ||
return ( | ||
equals(this.value, that.value, equals, memo) && | ||
this.index === that.index && | ||
this.done === that.done | ||
); | ||
}; | ||
function DoneIteration(value) { | ||
Iteration.call(this, value); | ||
this.done = true; // reflected on the instance to make it more obvious | ||
} | ||
DoneIteration.prototype = Object.create(Iteration.prototype); | ||
DoneIteration.prototype.constructor = DoneIteration; | ||
DoneIteration.prototype.done = true; | ||
Iterator.Iteration = Iteration; | ||
Iterator.DoneIteration = DoneIteration; | ||
Iterator.done = new DoneIteration(); | ||
"use strict"; | ||
var Shim = require("./shim"); | ||
var LfuSet = require("./lfu-set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -17,5 +15,5 @@ module.exports = LfuMap; | ||
} | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || this.getDefault; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -40,5 +38,5 @@ this.contentHash = hash; | ||
copy(LfuMap.prototype, GenericCollection.prototype); | ||
copy(LfuMap.prototype, GenericMap.prototype); | ||
copy(LfuMap.prototype, ObservableObject.prototype); | ||
Object.addEach(LfuMap.prototype, GenericCollection.prototype); | ||
Object.addEach(LfuMap.prototype, GenericMap.prototype); | ||
Object.addEach(LfuMap.prototype, PropertyChanges.prototype); | ||
@@ -64,29 +62,21 @@ LfuMap.prototype.constructClone = function (values) { | ||
LfuMap.prototype.observeMapChange = function () { | ||
return GenericMap.prototype.observeMapChange.apply(this, arguments); | ||
}; | ||
LfuMap.prototype.makeMapChangesObservable = function () { | ||
if (this.dispatchesMapChanges) { | ||
return; | ||
LfuMap.prototype.addMapChangeListener = function () { | ||
if (!this.dispatchesMapChanges) { | ||
// Detect LFU deletions in the LfuSet and emit as MapChanges. | ||
// Array and Heap have no store. | ||
// Dict and FastMap define no listeners on their store. | ||
var self = this; | ||
this.store.addBeforeRangeChangeListener(function(plus, minus) { | ||
if (plus.length && minus.length) { // LFU item pruned | ||
self.dispatchBeforeMapChange(minus[0].key, undefined); | ||
} | ||
}); | ||
this.store.addRangeChangeListener(function(plus, minus) { | ||
if (plus.length && minus.length) { | ||
self.dispatchMapChange(minus[0].key, undefined); | ||
} | ||
}); | ||
} | ||
// Detect LRU deletions in the LfuSet and emit as MapChanges. | ||
// Array and Heap have no store. | ||
// Dict and FastMap define no listeners on their store. | ||
this.store.observeRangeWillChange(this, "store"); | ||
this.store.observeRangeChange(this, "store"); | ||
this.dispatchMapChanges = true; | ||
GenericMap.prototype.addMapChangeListener.apply(this, arguments); | ||
}; | ||
LfuMap.prototype.handleStoreRangeWillChange = function (plus, minus, index) { | ||
if (plus.length && minus.length) { // LRU item pruned | ||
this.dispatchMapWillChange("delete", minus[0].key, undefined, minus[0].value); | ||
} | ||
}; | ||
LfuMap.prototype.handleStoreRangeChange = function (plus, minus, index) { | ||
if (plus.length && minus.length) { | ||
this.dispatchMapChange("delete", minus[0].key, undefined, minus[0].value); | ||
} | ||
}; | ||
@@ -5,11 +5,8 @@ "use strict"; | ||
var Shim = require("./shim"); | ||
var Set = require("./set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericSet = require("./generic-set"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var iterateOperator = require("pop-iterate"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
@@ -23,5 +20,5 @@ module.exports = LfuSet; | ||
capacity = capacity || Infinity; | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || noop; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
@@ -50,6 +47,6 @@ // TODO | ||
copy(LfuSet.prototype, GenericCollection.prototype); | ||
copy(LfuSet.prototype, GenericSet.prototype); | ||
copy(LfuSet.prototype, ObservableRange.prototype); | ||
copy(LfuSet.prototype, ObservableObject.prototype); | ||
Object.addEach(LfuSet.prototype, GenericCollection.prototype); | ||
Object.addEach(LfuSet.prototype, GenericSet.prototype); | ||
Object.addEach(LfuSet.prototype, PropertyChanges.prototype); | ||
Object.addEach(LfuSet.prototype, RangeChanges.prototype); | ||
@@ -114,3 +111,3 @@ LfuSet.prototype.constructClone = function (values) { | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -160,3 +157,3 @@ | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [value], 0); | ||
this.dispatchBeforeRangeChange([], [value], 0); | ||
} | ||
@@ -228,5 +225,5 @@ var frequencyNode = node.frequencyNode; | ||
LfuSet.prototype.iterate = function () { | ||
return iterateOperator(this.store.map(function (node) { | ||
return this.store.map(function (node) { | ||
return node.value; | ||
})); | ||
}).iterate(); | ||
}; | ||
@@ -256,3 +253,1 @@ | ||
function noop() {} | ||
@@ -0,21 +1,31 @@ | ||
3-clause BSD license | ||
==================== | ||
Copyright 2012 Kristopher Michael Kowal. All rights reserved. | ||
Copyright 2012-2014 Motorola Mobility LLC, Montage Studio Inc, and contributors. | ||
All rights reserved. | ||
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: | ||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
* Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
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. | ||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
* Neither the name of Montage nor the names of its | ||
contributors may be used to endorse or promote products derived from this | ||
software without specific prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
POSSIBILITY OF SUCH DAMAGE. |
134
list.js
@@ -5,13 +5,8 @@ "use strict"; | ||
var Shim = require("./shim"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericOrder = require("./generic-order"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var Iterator = require("./iterator"); | ||
var equalsOperator = require("pop-equals"); | ||
var arrayify = require("pop-arrayify"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
var emptyArray = []; | ||
function List(values, equals, getDefault) { | ||
@@ -24,4 +19,4 @@ if (!(this instanceof List)) { | ||
head.prev = head; | ||
this.contentEquals = equals || equalsOperator; | ||
this.getDefault = getDefault || noop; | ||
this.contentEquals = equals || Object.equals; | ||
this.getDefault = getDefault || Function.noop; | ||
this.length = 0; | ||
@@ -33,6 +28,6 @@ this.addEach(values); | ||
copy(List.prototype, GenericCollection.prototype); | ||
copy(List.prototype, GenericOrder.prototype); | ||
copy(List.prototype, ObservableObject.prototype); | ||
copy(List.prototype, ObservableRange.prototype); | ||
Object.addEach(List.prototype, GenericCollection.prototype); | ||
Object.addEach(List.prototype, GenericOrder.prototype); | ||
Object.addEach(List.prototype, PropertyChanges.prototype); | ||
Object.addEach(List.prototype, RangeChanges.prototype); | ||
@@ -43,10 +38,8 @@ List.prototype.constructClone = function (values) { | ||
List.prototype.findValue = function (value, equals) { | ||
List.prototype.find = function (value, equals, index) { | ||
equals = equals || this.contentEquals; | ||
var head = this.head; | ||
var at = head.next; | ||
var at = this.scan(index, head.next); | ||
while (at !== head) { | ||
// Note that the given value occurs first so that it can be a matcher | ||
// like an Any(Number) object. | ||
if (equals(value, at.value)) { | ||
if (equals(at.value, value)) { | ||
return at; | ||
@@ -58,8 +51,8 @@ } | ||
List.prototype.findLastValue = function (value, equals) { | ||
List.prototype.findLast = function (value, equals, index) { | ||
equals = equals || this.contentEquals; | ||
var head = this.head; | ||
var at = head.prev; | ||
var at = this.scan(index, head.prev); | ||
while (at !== head) { | ||
if (equals(value, at.value)) { | ||
if (equals(at.value, value)) { | ||
return at; | ||
@@ -72,7 +65,7 @@ } | ||
List.prototype.has = function (value, equals) { | ||
return !!this.findValue(value, equals); | ||
return !!this.find(value, equals); | ||
}; | ||
List.prototype.get = function (value, equals) { | ||
var found = this.findValue(value, equals); | ||
var found = this.find(value, equals); | ||
if (found) { | ||
@@ -85,4 +78,4 @@ return found.value; | ||
// LIFO (delete removes the most recently added equivalent value) | ||
List.prototype['delete'] = function (value, equals) { | ||
var found = this.findLastValue(value, equals); | ||
List.prototype["delete"] = function (value, equals) { | ||
var found = this.findLast(value, equals); | ||
if (found) { | ||
@@ -92,9 +85,9 @@ if (this.dispatchesRangeChanges) { | ||
var minus = [value]; | ||
this.dispatchRangeWillChange(plus, minus, found.index); | ||
this.dispatchBeforeRangeChange(plus, minus, found.index); | ||
} | ||
found['delete'](); | ||
found["delete"](); | ||
this.length--; | ||
if (this.dispatchesRangeChanges) { | ||
this.updateIndexes(found.next, found.index); | ||
this.dispatchRangeChange(plus, minus, found.index); | ||
this.updateIndexes(found.next, found.index); | ||
} | ||
@@ -106,2 +99,18 @@ return true; | ||
List.prototype.deleteAll = function (value, equals) { | ||
equals = equals || this.contentEquals; | ||
var head = this.head; | ||
var at = head.next; | ||
var count = 0; | ||
while (at !== head) { | ||
if (equals(value, at.value)) { | ||
at["delete"](); | ||
count++; | ||
} | ||
at = at.next; | ||
} | ||
this.length -= count; | ||
return count; | ||
}; | ||
List.prototype.clear = function () { | ||
@@ -112,3 +121,3 @@ var plus, minus; | ||
plus = []; | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -126,3 +135,3 @@ this.head.next = this.head.prev = this.head; | ||
node.index = this.length; | ||
this.dispatchRangeWillChange([value], [], node.index); | ||
this.dispatchBeforeRangeChange([value], [], node.index); | ||
} | ||
@@ -143,3 +152,3 @@ this.head.addBefore(node); | ||
var index = this.length; | ||
this.dispatchRangeWillChange(plus, minus, index); | ||
this.dispatchBeforeRangeChange(plus, minus, index); | ||
var start = this.head.prev; | ||
@@ -154,3 +163,3 @@ } | ||
if (this.dispatchesRangeChanges) { | ||
this.updateIndexes(start, start.index); | ||
this.updateIndexes(start.next, start.index === undefined ? 0 : start.index + 1); | ||
this.dispatchRangeChange(plus, minus, index); | ||
@@ -164,3 +173,3 @@ } | ||
var minus = []; | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -176,3 +185,3 @@ var at = this.head; | ||
if (this.dispatchesRangeChanges) { | ||
this.updateIndexes(this.head, -1); | ||
this.updateIndexes(this.head.next, 0); | ||
this.dispatchRangeChange(plus, minus, 0); | ||
@@ -191,3 +200,3 @@ } | ||
var index = this.length - 1; | ||
this.dispatchRangeWillChange(plus, minus, index); | ||
this.dispatchBeforeRangeChange(plus, minus, index); | ||
} | ||
@@ -211,3 +220,3 @@ head.prev['delete'](); | ||
var minus = [value]; | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -217,3 +226,3 @@ head.next['delete'](); | ||
if (this.dispatchesRangeChanges) { | ||
this.updateIndexes(this.head, -1); | ||
this.updateIndexes(this.head.next, 0); | ||
this.dispatchRangeChange(plus, minus, 0); | ||
@@ -309,3 +318,3 @@ } | ||
} | ||
plus = arrayify(plus); | ||
plus = Array.from(plus); | ||
@@ -331,3 +340,3 @@ // collect the minus array | ||
startNode = start.prev; | ||
this.dispatchRangeWillChange(plus, minus, index); | ||
this.dispatchBeforeRangeChange(plus, minus, index); | ||
} | ||
@@ -354,5 +363,5 @@ | ||
if (start === this.head) { | ||
this.updateIndexes(this.head, -1); | ||
this.updateIndexes(this.head.next, 0); | ||
} else { | ||
this.updateIndexes(startNode, startNode.index); | ||
this.updateIndexes(startNode.next, startNode.index + 1); | ||
} | ||
@@ -369,3 +378,3 @@ this.dispatchRangeChange(plus, minus, index); | ||
var plus = minus.reversed(); | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -413,17 +422,14 @@ var at = this.head; | ||
List.prototype.updateIndexes = function (node, index) { | ||
do { | ||
while (node !== this.head) { | ||
node.index = index++; | ||
node = node.next; | ||
} while (node !== this.head); | ||
} | ||
}; | ||
List.prototype.makeRangeChangesObservable = function () { | ||
this.updateIndexes(this.head, -1); | ||
List.prototype.makeObservable = function () { | ||
this.head.index = -1; | ||
this.updateIndexes(this.head.next, 0); | ||
this.dispatchesRangeChanges = true; | ||
}; | ||
List.prototype.toArray = function () { | ||
return this.slice(); | ||
}; | ||
List.prototype.iterate = function () { | ||
@@ -436,19 +442,22 @@ return new ListIterator(this.head); | ||
this.at = head.next; | ||
this.index = 0; | ||
}; | ||
ListIterator.prototype = Object.create(Iterator.prototype); | ||
ListIterator.prototype.constructor = ListIterator; | ||
ListIterator.prototype.__iterationObject = null; | ||
Object.defineProperty(ListIterator.prototype,"_iterationObject", { | ||
get: function() { | ||
return this.__iterationObject || (this.__iterationObject = { done: false, value:null}); | ||
} | ||
}); | ||
ListIterator.prototype.next = function () { | ||
if (this.at === this.head) { | ||
return Iterator.done; | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
} else { | ||
var at = this.at; | ||
var value = this.at.value; | ||
this.at = this.at.next; | ||
return new Iterator.Iteration( | ||
at.value, | ||
this.index++ | ||
); | ||
this._iterationObject.value = value; | ||
} | ||
return this._iterationObject; | ||
}; | ||
@@ -464,3 +473,3 @@ | ||
Node.prototype['delete'] = function () { | ||
Node.prototype["delete"] = function () { | ||
this.prev.next = this.next; | ||
@@ -485,4 +494,1 @@ this.next.prev = this.prev; | ||
}; | ||
function noop() {} | ||
"use strict"; | ||
var Shim = require("./shim"); | ||
var LruSet = require("./lru-set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
module.exports = LruMap; | ||
function LruMap(values, capacity, equals, hash, getDefault) { | ||
function LruMap(values, maxLength, equals, hash, getDefault) { | ||
if (!(this instanceof LruMap)) { | ||
return new LruMap(values, capacity, equals, hash, getDefault); | ||
return new LruMap(values, maxLength, equals, hash, getDefault); | ||
} | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || this.getDefault; | ||
this.capacity = capacity || Infinity; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -26,3 +23,3 @@ this.contentHash = hash; | ||
undefined, | ||
capacity, | ||
maxLength, | ||
function keysEqual(a, b) { | ||
@@ -41,5 +38,5 @@ return equals(a.key, b.key); | ||
copy(LruMap.prototype, GenericCollection.prototype); | ||
copy(LruMap.prototype, GenericMap.prototype); | ||
copy(LruMap.prototype, ObservableObject.prototype); | ||
Object.addEach(LruMap.prototype, GenericCollection.prototype); | ||
Object.addEach(LruMap.prototype, GenericMap.prototype); | ||
Object.addEach(LruMap.prototype, PropertyChanges.prototype); | ||
@@ -49,3 +46,3 @@ LruMap.prototype.constructClone = function (values) { | ||
values, | ||
this.capacity, | ||
this.maxLength, | ||
this.contentEquals, | ||
@@ -66,3 +63,3 @@ this.contentHash, | ||
LruMap.prototype.observeMapChange = function () { | ||
LruMap.prototype.addMapChangeListener = function () { | ||
if (!this.dispatchesMapChanges) { | ||
@@ -72,19 +69,16 @@ // Detect LRU deletions in the LruSet and emit as MapChanges. | ||
// Dict and FastMap define no listeners on their store. | ||
this.store.observeRangeWillChange(this, "store"); | ||
this.store.observeRangeChange(this, "store"); | ||
var self = this; | ||
this.store.addBeforeRangeChangeListener(function(plus, minus) { | ||
if (plus.length && minus.length) { // LRU item pruned | ||
self.dispatchBeforeMapChange(minus[0].key, undefined); | ||
} | ||
}); | ||
this.store.addRangeChangeListener(function(plus, minus) { | ||
if (plus.length && minus.length) { | ||
self.dispatchMapChange(minus[0].key, undefined); | ||
} | ||
}); | ||
} | ||
return GenericMap.prototype.observeMapChange.apply(this, arguments); | ||
GenericMap.prototype.addMapChangeListener.apply(this, arguments); | ||
}; | ||
LruMap.prototype.handleStoreRangeWillChange = function (plus, minus, index) { | ||
if (plus.length && minus.length) { // LRU item pruned | ||
this.dispatchMapWillChange("delete", minus[0].key, undefined, minus[0].value); | ||
} | ||
}; | ||
LruMap.prototype.handleStoreRangeChange = function (plus, minus, index) { | ||
if (plus.length && minus.length) { | ||
this.dispatchMapChange("delete", minus[0].key, undefined, minus[0].value); | ||
} | ||
}; | ||
"use strict"; | ||
var Shim = require("./shim"); | ||
var Set = require("./set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericSet = require("./generic-set"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
module.exports = LruSet; | ||
function LruSet(values, maxLength, equals, hash, getDefault) { | ||
function LruSet(values, capacity, equals, hash, getDefault) { | ||
if (!(this instanceof LruSet)) { | ||
return new LruSet(values, maxLength, equals, hash, getDefault); | ||
return new LruSet(values, capacity, equals, hash, getDefault); | ||
} | ||
maxLength = maxLength || Infinity; | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || noop; | ||
capacity = capacity || Infinity; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.store = new Set(undefined, equals, hash); | ||
@@ -26,3 +24,3 @@ this.contentEquals = equals; | ||
this.getDefault = getDefault; | ||
this.maxLength = maxLength; | ||
this.capacity = capacity; | ||
this.length = 0; | ||
@@ -34,6 +32,6 @@ this.addEach(values); | ||
copy(LruSet.prototype, GenericCollection.prototype); | ||
copy(LruSet.prototype, GenericSet.prototype); | ||
copy(LruSet.prototype, ObservableObject.prototype); | ||
copy(LruSet.prototype, ObservableRange.prototype); | ||
Object.addEach(LruSet.prototype, GenericCollection.prototype); | ||
Object.addEach(LruSet.prototype, GenericSet.prototype); | ||
Object.addEach(LruSet.prototype, PropertyChanges.prototype); | ||
Object.addEach(LruSet.prototype, RangeChanges.prototype); | ||
@@ -43,3 +41,3 @@ LruSet.prototype.constructClone = function (values) { | ||
values, | ||
this.maxLength, | ||
this.capacity, | ||
this.contentEquals, | ||
@@ -55,3 +53,6 @@ this.contentHash, | ||
LruSet.prototype.get = function (value) { | ||
LruSet.prototype.get = function (value, equals) { | ||
if (equals) { | ||
throw new Error("LruSet#get does not support second argument: equals"); | ||
} | ||
value = this.store.get(value); | ||
@@ -75,7 +76,7 @@ if (value !== undefined) { | ||
this.store.add(value); | ||
} else if (this.maxLength > 0) { // add | ||
} else if (this.capacity > 0) { // add | ||
// because minus is constructed before adding value, we must ensure the | ||
// set has positive length. hence the maxLength check. | ||
// set has positive length. hence the capacity check. | ||
plus.push(value); | ||
if (this.length >= this.maxLength) { | ||
if (this.length >= this.capacity) { | ||
eldest = this.store.order.head.next; | ||
@@ -85,3 +86,3 @@ minus.push(eldest.value); | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange(plus, minus, 0); | ||
this.dispatchBeforeRangeChange(plus, minus, 0); | ||
} | ||
@@ -103,7 +104,10 @@ this.store.add(value); | ||
LruSet.prototype["delete"] = function (value) { | ||
LruSet.prototype["delete"] = function (value, equals) { | ||
if (equals) { | ||
throw new Error("LruSet#delete does not support second argument: equals"); | ||
} | ||
var found = this.store.has(value); | ||
if (found) { | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [value], 0); | ||
this.dispatchBeforeRangeChange([], [value], 0); | ||
} | ||
@@ -152,2 +156,1 @@ this.store["delete"](value); | ||
function noop() {} |
20
map.js
"use strict"; | ||
var Shim = require("./shim"); | ||
var Set = require("./set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -17,5 +15,5 @@ module.exports = Map; | ||
} | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || this.getDefault; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -39,5 +37,6 @@ this.contentHash = hash; | ||
copy(Map.prototype, GenericCollection.prototype); | ||
copy(Map.prototype, GenericMap.prototype); // overrides GenericCollection | ||
copy(Map.prototype, ObservableObject.prototype); | ||
Object.addEach(Map.prototype, GenericCollection.prototype); | ||
Object.addEach(Map.prototype, GenericMap.prototype); // overrides GenericCollection | ||
Object.addEach(Map.prototype, PropertyChanges.prototype); | ||
Object.defineProperty(Map.prototype,"size",GenericCollection._sizePropertyDescriptor); | ||
@@ -64,2 +63,1 @@ Map.prototype.constructClone = function (values) { | ||
}; | ||
@@ -12,3 +12,3 @@ "use strict"; | ||
Map.call(this, values, equals, hash, function getDefault(key) { | ||
var bucket = this.bucket(); | ||
var bucket = this.bucket(key); | ||
Map.prototype.set.call(this, key, bucket); | ||
@@ -15,0 +15,0 @@ return bucket; |
{ | ||
"name": "collections", | ||
"version": "2.0.2", | ||
"publishConfig": { | ||
"tag": "future" | ||
}, | ||
"version": "3.0.0", | ||
"description": "data structures with idiomatic JavaScript collection interfaces", | ||
"homepage": "http://github.com/montagejs/collections", | ||
"homepage": "http://www.collectionsjs.com", | ||
"author": "Kris Kowal <kris@cixar.com> (http://github.com/kriskowal)", | ||
@@ -34,27 +31,13 @@ "keywords": [ | ||
"dependencies": { | ||
"mini-map": "^1.0.0", | ||
"pop-arrayify": "^1.0.0", | ||
"pop-clear": "^1.0.0", | ||
"pop-clone": "^1.0.1", | ||
"pop-compare": "^1.0.0", | ||
"pop-equals": "^1.0.0", | ||
"pop-has": "^1.0.0", | ||
"pop-hash": "^1.0.0", | ||
"pop-iterate": "^1.0.1", | ||
"pop-observe": "^2.0.2", | ||
"pop-swap": "^1.0.0", | ||
"pop-zip": "^1.0.0", | ||
"regexp-escape": "0.0.1", | ||
"weak-map": "^1.0.4" | ||
"weak-map": "~1.0.x" | ||
}, | ||
"devDependencies": { | ||
"istanbul": "^0.2.4", | ||
"jasminum": "^2.0.6", | ||
"opener": "^1.3.0", | ||
"sinon": "^1.9.0" | ||
"jasmine-node": "~1.14.x", | ||
"istanbul": "*", | ||
"opener": "*" | ||
}, | ||
"scripts": { | ||
"test": "jasminum spec", | ||
"cover": "istanbul cover spec/index.js spec && istanbul report html && opener coverage/index.html" | ||
"test": "jasmine-node spec", | ||
"cover": "istanbul cover node_modules/jasmine-node/bin/jasmine-node spec && istanbul report html && opener coverage/index.html" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
[![Build Status](https://travis-ci.org/kriskowal/collections.png?branch=v2)](http://travis-ci.org/montagejs/collections) | ||
[![Build Status](https://travis-ci.org/montagejs/collections.png?branch=master)](http://travis-ci.org/montagejs/collections) | ||
@@ -3,0 +3,0 @@ # Collections |
58
set.js
"use strict"; | ||
var Shim = require("./shim"); | ||
var List = require("./list"); | ||
@@ -7,7 +8,5 @@ var FastSet = require("./fast-set"); | ||
var GenericSet = require("./generic-set"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var equalsOperator = require("pop-equals"); | ||
var hashOperator = require("pop-hash"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
var Iterator = require("./iterator"); | ||
@@ -20,5 +19,5 @@ module.exports = Set; | ||
} | ||
equals = equals || equalsOperator; | ||
hash = hash || hashOperator; | ||
getDefault = getDefault || noop; | ||
equals = equals || Object.equals; | ||
hash = hash || Object.hash; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -47,7 +46,9 @@ this.contentHash = hash; | ||
copy(Set.prototype, GenericCollection.prototype); | ||
copy(Set.prototype, GenericSet.prototype); | ||
copy(Set.prototype, ObservableObject.prototype); | ||
copy(Set.prototype, ObservableRange.prototype); | ||
Object.addEach(Set.prototype, GenericCollection.prototype); | ||
Object.addEach(Set.prototype, GenericSet.prototype); | ||
Object.addEach(Set.prototype, PropertyChanges.prototype); | ||
Object.addEach(Set.prototype, RangeChanges.prototype); | ||
Object.defineProperty(Set.prototype,"size",GenericCollection._sizePropertyDescriptor); | ||
Set.prototype.Order = List; | ||
@@ -65,3 +66,6 @@ Set.prototype.Store = FastSet; | ||
Set.prototype.get = function (value) { | ||
Set.prototype.get = function (value, equals) { | ||
if (equals) { | ||
throw new Error("Set#get does not support second argument: equals"); | ||
} | ||
var node = new this.order.Node(value); | ||
@@ -81,3 +85,3 @@ node = this.store.get(node); | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([value], [], index); | ||
this.dispatchBeforeRangeChange([value], [], index); | ||
} | ||
@@ -96,8 +100,11 @@ this.order.add(value); | ||
Set.prototype["delete"] = function (value) { | ||
Set.prototype["delete"] = function (value, equals) { | ||
if (equals) { | ||
throw new Error("Set#delete does not support second argument: equals"); | ||
} | ||
var node = new this.order.Node(value); | ||
if (this.store.has(node)) { | ||
var node = this.store.get(node); | ||
node = this.store.get(node); | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [value], node.index); | ||
this.dispatchBeforeRangeChange([], [value], node.index); | ||
} | ||
@@ -141,3 +148,3 @@ this.store["delete"](node); // removes from the set | ||
clearing = this.toArray(); | ||
this.dispatchRangeWillChange([], clearing, 0); | ||
this.dispatchBeforeRangeChange([], clearing, 0); | ||
} | ||
@@ -170,6 +177,2 @@ this.store.clear(); | ||
Set.prototype.toArray = function () { | ||
return this.order.toArray(); | ||
}; | ||
Set.prototype.iterate = function () { | ||
@@ -179,2 +182,6 @@ return this.order.iterate(); | ||
Set.prototype.values = function () { | ||
return new Iterator(this); | ||
}; | ||
Set.prototype.log = function () { | ||
@@ -185,7 +192,4 @@ var set = this.store; | ||
Set.prototype.makeRangeChangesObservable = function () { | ||
this.order.makeRangeChangesObservable(); | ||
Set.prototype.makeObservable = function () { | ||
this.order.makeObservable(); | ||
}; | ||
function noop() {} | ||
"use strict"; | ||
var Shim = require("./shim"); | ||
var SortedArraySet = require("./sorted-array-set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -17,5 +15,5 @@ module.exports = SortedArrayMap; | ||
} | ||
equals = equals || equalsOperator; | ||
compare = compare || compareOperator; | ||
getDefault = getDefault || this.getDefault; | ||
equals = equals || Object.equals; | ||
compare = compare || Object.compare; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -40,6 +38,8 @@ this.contentCompare = compare; | ||
copy(SortedArrayMap.prototype, GenericCollection.prototype); | ||
copy(SortedArrayMap.prototype, GenericMap.prototype); | ||
copy(SortedArrayMap.prototype, ObservableObject.prototype); | ||
Object.addEach(SortedArrayMap.prototype, GenericCollection.prototype); | ||
Object.addEach(SortedArrayMap.prototype, GenericMap.prototype); | ||
Object.addEach(SortedArrayMap.prototype, PropertyChanges.prototype); | ||
SortedArrayMap.prototype.isSorted = true; | ||
SortedArrayMap.prototype.constructClone = function (values) { | ||
@@ -46,0 +46,0 @@ return new this.constructor( |
"use strict"; | ||
module.exports = SortedArraySet; | ||
var Shim = require("./shim"); | ||
var SortedArray = require("./sorted-array"); | ||
var GenericSet = require("./generic-set"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
module.exports = SortedArraySet; | ||
function SortedArraySet(values, equals, compare, getDefault) { | ||
@@ -24,4 +24,4 @@ if (!(this instanceof SortedArraySet)) { | ||
copy(SortedArraySet.prototype, GenericSet.prototype); | ||
copy(SortedArraySet.prototype, ObservableObject.prototype); | ||
Object.addEach(SortedArraySet.prototype, GenericSet.prototype); | ||
Object.addEach(SortedArraySet.prototype, PropertyChanges.prototype); | ||
@@ -28,0 +28,0 @@ SortedArraySet.prototype.isSorted = true; |
@@ -5,12 +5,6 @@ "use strict"; | ||
var Shim = require("./shim"); | ||
var GenericCollection = require("./generic-collection"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var hasOperator = require("pop-has"); | ||
var iterateOperator = require("pop-iterate"); | ||
var clear = require("pop-clear"); | ||
var swap = require("pop-swap/swap"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
@@ -27,5 +21,5 @@ function SortedArray(values, equals, compare, getDefault) { | ||
} | ||
this.contentEquals = equals || equalsOperator; | ||
this.contentCompare = compare || compareOperator; | ||
this.getDefault = getDefault || noop; | ||
this.contentEquals = equals || Object.equals; | ||
this.contentCompare = compare || Object.compare; | ||
this.getDefault = getDefault || Function.noop; | ||
@@ -39,5 +33,5 @@ this.length = 0; | ||
copy(SortedArray.prototype, GenericCollection.prototype); | ||
copy(SortedArray.prototype, ObservableObject.prototype); | ||
copy(SortedArray.prototype, ObservableRange.prototype); | ||
Object.addEach(SortedArray.prototype, GenericCollection.prototype); | ||
Object.addEach(SortedArray.prototype, PropertyChanges.prototype); | ||
Object.addEach(SortedArray.prototype, RangeChanges.prototype); | ||
@@ -119,10 +113,12 @@ SortedArray.prototype.isSorted = true; | ||
if (equals) { | ||
return hasOperator(this.array, value, equals); | ||
} else { | ||
var index = search(this.array, value, this.contentCompare); | ||
return index >= 0 && this.contentEquals(this.array[index], value); | ||
throw new Error("SortedSet#has does not support second argument: equals"); | ||
} | ||
var index = search(this.array, value, this.contentCompare); | ||
return index >= 0 && this.contentEquals(this.array[index], value); | ||
}; | ||
SortedArray.prototype.get = function (value) { | ||
SortedArray.prototype.get = function (value, equals) { | ||
if (equals) { | ||
throw new Error("SortedArray#get does not support second argument: equals"); | ||
} | ||
var index = searchFirst(this.array, value, this.contentCompare, this.contentEquals); | ||
@@ -139,3 +135,3 @@ if (index !== -1) { | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([value], [], index); | ||
this.dispatchBeforeRangeChange([value], [], index); | ||
} | ||
@@ -150,7 +146,10 @@ this.array.splice(index, 0, value); | ||
SortedArray.prototype["delete"] = function (value) { | ||
SortedArray.prototype["delete"] = function (value, equals) { | ||
if (equals) { | ||
throw new Error("SortedArray#delete does not support second argument: equals"); | ||
} | ||
var index = searchFirst(this.array, value, this.contentCompare, this.contentEquals); | ||
if (index !== -1) { | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [value], index); | ||
this.dispatchBeforeRangeChange([], [value], index); | ||
} | ||
@@ -168,3 +167,32 @@ this.array.splice(index, 1); | ||
SortedArray.prototype.deleteAll = function (value, equals) { | ||
if (equals) { | ||
var count = this.array.deleteAll(value, equals); | ||
this.length -= count; | ||
return count; | ||
} else { | ||
var start = searchFirst(this.array, value, this.contentCompare, this.contentEquals); | ||
if (start !== -1) { | ||
var end = start; | ||
while (this.contentEquals(value, this.array[end])) { | ||
end++; | ||
} | ||
var minus = this.slice(start, end); | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchBeforeRangeChange([], minus, start); | ||
} | ||
this.array.splice(start, minus.length); | ||
this.length -= minus.length; | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeChange([], minus, start); | ||
} | ||
return minus.length; | ||
} else { | ||
return 0; | ||
} | ||
} | ||
}; | ||
SortedArray.prototype.indexOf = function (value) { | ||
// TODO throw error if provided a start index | ||
return searchFirst(this.array, value, this.contentCompare, this.contentEquals); | ||
@@ -174,10 +202,26 @@ }; | ||
SortedArray.prototype.lastIndexOf = function (value) { | ||
// TODO throw error if provided a start index | ||
return searchLast(this.array, value, this.contentCompare, this.contentEquals); | ||
}; | ||
SortedArray.prototype.findValue = function (value) { | ||
SortedArray.prototype.find = 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"); | ||
} | ||
if (index) { | ||
throw new Error("SortedArray#find does not support third argument: index"); | ||
} | ||
// TODO support initial partition index | ||
return searchFirst(this.array, value, this.contentCompare, this.contentEquals); | ||
}; | ||
SortedArray.prototype.findLastValue = function (value) { | ||
SortedArray.prototype.findLast = function (value, equals, index) { | ||
if (equals) { | ||
throw new Error("SortedArray#findLast does not support second argument: equals"); | ||
} | ||
if (index) { | ||
throw new Error("SortedArray#findLast does not support third argument: index"); | ||
} | ||
// TODO support initial partition index | ||
return searchLast(this.array, value, this.contentCompare, this.contentEquals); | ||
@@ -195,11 +239,11 @@ }; | ||
SortedArray.prototype.pop = function () { | ||
var value = this.array.pop(); | ||
var val = this.array.pop(); | ||
this.length = this.array.length; | ||
return value; | ||
return val; | ||
}; | ||
SortedArray.prototype.shift = function () { | ||
var value = this.array.shift(); | ||
var val = this.array.shift(); | ||
this.length = this.array.length; | ||
return value; | ||
return val; | ||
}; | ||
@@ -227,11 +271,11 @@ | ||
var minus = this.slice(index, index + length); | ||
plus = plus || []; | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange(plus, minus, index); | ||
this.dispatchBeforeRangeChange(plus, minus, index); | ||
} | ||
swap(this.array, index, length, plus); | ||
this.length += plus.length - length; | ||
this.array.splice(index, length); | ||
this.length -= minus.length; | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeChange(plus, minus, index); | ||
this.dispatchRangeChange([], minus, index); | ||
} | ||
this.addEach(plus); | ||
return minus; | ||
@@ -267,3 +311,3 @@ }; | ||
SortedArray.prototype.one = function () { | ||
return this.array[0]; | ||
return this.array.one(); | ||
}; | ||
@@ -275,6 +319,6 @@ | ||
minus = this.array.slice(); | ||
this.dispatchRangeWillChange([], minus, 0); | ||
this.dispatchBeforeRangeChange([], minus, 0); | ||
} | ||
this.length = 0; | ||
clear(this.array); | ||
this.array.clear(); | ||
if (this.dispatchesRangeChanges) { | ||
@@ -286,14 +330,17 @@ this.dispatchRangeChange([], minus, 0); | ||
SortedArray.prototype.equals = function (that, equals) { | ||
return equalsOperator(this.array, that, equals); | ||
return this.array.equals(that, equals); | ||
}; | ||
SortedArray.prototype.compare = function (that, compare) { | ||
return compareOperator(this.array, that, compare); | ||
return this.array.compare(that, compare); | ||
}; | ||
SortedArray.prototype.iterate = function (start, stop, step) { | ||
return iterateOperator(this.array, start, stop, step); | ||
SortedArray.prototype.iterate = function (start, end) { | ||
return new this.Iterator(this.array, start, end); | ||
}; | ||
function noop() {} | ||
SortedArray.prototype.toJSON = function () { | ||
return this.toArray(); | ||
}; | ||
SortedArray.prototype.Iterator = Array.prototype.Iterator; |
"use strict"; | ||
var Shim = require("./shim"); | ||
var SortedSet = require("./sorted-set"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericMap = require("./generic-map"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var copy = require("./copy"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
@@ -17,5 +15,5 @@ module.exports = SortedMap; | ||
} | ||
equals = equals || equalsOperator; | ||
compare = compare || compareOperator; | ||
getDefault = getDefault || this.getDefault; | ||
equals = equals || Object.equals; | ||
compare = compare || Object.compare; | ||
getDefault = getDefault || Function.noop; | ||
this.contentEquals = equals; | ||
@@ -40,5 +38,5 @@ this.contentCompare = compare; | ||
copy(SortedMap.prototype, GenericCollection.prototype); | ||
copy(SortedMap.prototype, GenericMap.prototype); | ||
copy(SortedMap.prototype, ObservableObject.prototype); | ||
Object.addEach(SortedMap.prototype, GenericCollection.prototype); | ||
Object.addEach(SortedMap.prototype, GenericMap.prototype); | ||
Object.addEach(SortedMap.prototype, PropertyChanges.prototype); | ||
@@ -45,0 +43,0 @@ SortedMap.prototype.constructClone = function (values) { |
@@ -5,11 +5,8 @@ "use strict"; | ||
var Shim = require("./shim"); | ||
var GenericCollection = require("./generic-collection"); | ||
var GenericSet = require("./generic-set"); | ||
var ObservableObject = require("pop-observe/observable-object"); | ||
var ObservableRange = require("pop-observe/observable-range"); | ||
var Iterator = require("./iterator"); | ||
var PropertyChanges = require("./listen/property-changes"); | ||
var RangeChanges = require("./listen/range-changes"); | ||
var TreeLog = require("./tree-log"); | ||
var equalsOperator = require("pop-equals"); | ||
var compareOperator = require("pop-compare"); | ||
var copy = require("./copy"); | ||
@@ -20,5 +17,5 @@ function SortedSet(values, equals, compare, getDefault) { | ||
} | ||
this.contentEquals = equals || equalsOperator; | ||
this.contentCompare = compare || compareOperator; | ||
this.getDefault = getDefault || noop; | ||
this.contentEquals = equals || Object.equals; | ||
this.contentCompare = compare || Object.compare; | ||
this.getDefault = getDefault || Function.noop; | ||
this.root = null; | ||
@@ -32,6 +29,6 @@ this.length = 0; | ||
copy(SortedSet.prototype, GenericCollection.prototype); | ||
copy(SortedSet.prototype, GenericSet.prototype); | ||
copy(SortedSet.prototype, ObservableObject.prototype); | ||
copy(SortedSet.prototype, ObservableRange.prototype); | ||
Object.addEach(SortedSet.prototype, GenericCollection.prototype); | ||
Object.addEach(SortedSet.prototype, GenericSet.prototype); | ||
Object.addEach(SortedSet.prototype, PropertyChanges.prototype); | ||
Object.addEach(SortedSet.prototype, RangeChanges.prototype); | ||
@@ -49,3 +46,6 @@ SortedSet.prototype.isSorted = true; | ||
SortedSet.prototype.has = function (value) { | ||
SortedSet.prototype.has = function (value, equals) { | ||
if (equals) { | ||
throw new Error("SortedSet#has does not support second argument: equals"); | ||
} | ||
if (this.root) { | ||
@@ -59,3 +59,6 @@ this.splay(value); | ||
SortedSet.prototype.get = function (value) { | ||
SortedSet.prototype.get = function (value, equals) { | ||
if (equals) { | ||
throw new Error("SortedSet#get does not support second argument: equals"); | ||
} | ||
if (this.root) { | ||
@@ -80,3 +83,3 @@ this.splay(value); | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([value], [], this.root.index); | ||
this.dispatchBeforeRangeChange([value], [], this.root.index); | ||
} | ||
@@ -118,3 +121,3 @@ if (comparison < 0) { | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([value], [], 0); | ||
this.dispatchBeforeRangeChange([value], [], 0); | ||
} | ||
@@ -131,3 +134,6 @@ this.root = node; | ||
SortedSet.prototype['delete'] = function (value) { | ||
SortedSet.prototype['delete'] = function (value, equals) { | ||
if (equals) { | ||
throw new Error("SortedSet#delete does not support second argument: equals"); | ||
} | ||
if (this.root) { | ||
@@ -138,3 +144,3 @@ this.splay(value); | ||
if (this.dispatchesRangeChanges) { | ||
this.dispatchRangeWillChange([], [value], index); | ||
this.dispatchBeforeRangeChange([], [value], index); | ||
} | ||
@@ -167,3 +173,6 @@ if (!this.root.left) { | ||
SortedSet.prototype.indexOf = function (value) { | ||
SortedSet.prototype.indexOf = function (value, index) { | ||
if (index) { | ||
throw new Error("SortedSet#indexOf does not support second argument: startIndex"); | ||
} | ||
if (this.root) { | ||
@@ -178,3 +187,11 @@ this.splay(value); | ||
SortedSet.prototype.findValue = function (value) { | ||
SortedSet.prototype.find = function (value, equals, index) { | ||
if (equals) { | ||
throw new Error("SortedSet#find does not support second argument: equals"); | ||
} | ||
if (index) { | ||
// TODO contemplate using splayIndex to isolate a subtree in | ||
// which to search. | ||
throw new Error("SortedSet#find does not support third argument: index"); | ||
} | ||
if (this.root) { | ||
@@ -523,3 +540,3 @@ this.splay(value); | ||
minus = this.toArray(); | ||
this.dispatchRangeWillChange([], minus, 0); | ||
this.dispatchBeforeRangeChange([], minus, 0); | ||
} | ||
@@ -537,3 +554,3 @@ this.root = null; | ||
SortedSet.prototype.Iterator = SortedSetIterator; | ||
SortedSet.prototype.Iterator = Iterator; | ||
@@ -555,10 +572,3 @@ SortedSet.prototype.summary = function () { | ||
} | ||
// Bind is unavailable in PhantomJS, the only environment of consequence | ||
// that does not implement it yet. | ||
var originalCallback = callback; | ||
callback = function () { | ||
return originalCallback.apply(thisp, arguments); | ||
}; | ||
callback = callback.bind(thisp); | ||
if (this.root) { | ||
@@ -737,3 +747,3 @@ this.root.log(charmap, logNode, callback, callback); | ||
function SortedSetIterator(set, start, end) { | ||
function Iterator(set, start, end) { | ||
this.set = set; | ||
@@ -749,9 +759,11 @@ this.prev = null; | ||
} | ||
this.index = 0; | ||
} | ||
Iterator.prototype.__iterationObject = null; | ||
Object.defineProperty(Iterator.prototype,"_iterationObject", { | ||
get: function() { | ||
return this.__iterationObject || (this.__iterationObject = { done: false, value:null}); | ||
} | ||
}); | ||
SortedSetIterator.prototype = Object.create(SortedSetIterator.prototype); | ||
SortedSetIterator.prototype.constructor = SortedSetIterator; | ||
SortedSetIterator.prototype.next = function () { | ||
Iterator.prototype.next = function () { | ||
var next; | ||
@@ -764,17 +776,20 @@ if (this.prev) { | ||
if (!next) { | ||
return Iterator.done; | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
} | ||
if ( | ||
this.end !== undefined && | ||
this.set.contentCompare(next.value, this.end) >= 0 | ||
) { | ||
return Iterator.done; | ||
else { | ||
if ( | ||
this.end !== undefined && | ||
this.set.contentCompare(next.value, this.end) >= 0 | ||
) { | ||
this._iterationObject.done = true; | ||
this._iterationObject.value = void 0; | ||
} | ||
else { | ||
this.prev = next; | ||
this._iterationObject.value = next.value; | ||
} | ||
} | ||
this.prev = next; | ||
return new Iterator.Iteration( | ||
next.value, | ||
this.index++ | ||
); | ||
return this._iterationObject; | ||
}; | ||
function noop() {} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
217531
1
3
41
5953
1
- Removedmini-map@^1.0.0
- Removedpop-arrayify@^1.0.0
- Removedpop-clear@^1.0.0
- Removedpop-clone@^1.0.1
- Removedpop-compare@^1.0.0
- Removedpop-equals@^1.0.0
- Removedpop-has@^1.0.0
- Removedpop-hash@^1.0.0
- Removedpop-iterate@^1.0.1
- Removedpop-observe@^2.0.2
- Removedpop-swap@^1.0.0
- Removedpop-zip@^1.0.0
- Removedregexp-escape@0.0.1
- Removedmini-map@1.0.0(transitive)
- Removedpop-arrayify@1.0.0(transitive)
- Removedpop-clear@1.0.0(transitive)
- Removedpop-clone@1.0.1(transitive)
- Removedpop-compare@1.0.0(transitive)
- Removedpop-equals@1.0.0(transitive)
- Removedpop-has@1.0.0(transitive)
- Removedpop-hash@1.0.1(transitive)
- Removedpop-iterate@1.0.1(transitive)
- Removedpop-observe@2.0.2(transitive)
- Removedpop-swap@1.0.0(transitive)
- Removedpop-zip@1.0.0(transitive)
- Removedregexp-escape@0.0.1(transitive)
Updatedweak-map@~1.0.x