File: find.js

package info (click to toggle)
node-tad 3.1.1%2B~cs11.22.49-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,400 kB
  • sloc: javascript: 25,549; makefile: 6
file content (98 lines) | stat: -rw-r--r-- 2,363 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Promise aware Array's find
// Additionally differs from some that it returns *first in order* item that matches constraint

"use strict";

var assign          = require("es5-ext/object/assign")
  , isValue         = require("es5-ext/object/is-value")
  , ensureValue     = require("es5-ext/object/valid-value")
  , callable        = require("es5-ext/object/valid-callable")
  , toNaturalNumber = require("es5-ext/number/to-pos-integer")
  , deferred        = require("../../deferred")
  , isPromise       = require("../../is-promise")
  , assimilate      = require("../../assimilate");

var call = Function.prototype.call, resolve = deferred.resolve, Find;

Find = function (list, cb, context) {
	this.list = list;
	this.cb = cb;
	this.context = context;
	this.length = toNaturalNumber(list.length);

	while (this.current < this.length) {
		if (this.current in list) {
			assign(this, deferred());
			this.processCb = this.processCb.bind(this);
			this.process();
			return this.promise;
		}
		++this.current;
	}
	return resolve(undefined);
};

Find.prototype = {
	current: 0,
	process: function () {
		var value = assimilate(this.list[this.current]);
		if (isPromise(value)) {
			if (!value.resolved) {
				value.done(this.processCb, this.reject);
				return;
			}
			if (value.failed) {
				this.reject(value.value);
				return;
			}
			value = value.value;
		}
		this.processCb(value);
	},
	processCb: function (listValue) {
		var value;
		if (this.cb) {
			try {
				value = call.call(this.cb, this.context, listValue, this.current, this.list);
			} catch (e) {
				this.reject(e);
				return;
			}
			value = assimilate(value);
			if (isPromise(value)) {
				if (!value.resolved) {
					value.done(this.processValue.bind(this, listValue), this.reject);
					return;
				}
				if (value.failed) {
					this.reject(value.value);
					return;
				}
				value = value.value;
			}
		} else {
			value = listValue;
		}
		this.processValue(listValue, value);
	},
	processValue: function (listValue, value) {
		if (value) {
			this.resolve(listValue);
			return;
		}
		while (++this.current < this.length) {
			if (this.current in this.list) {
				this.process();
				return;
			}
		}
		this.resolve(undefined);
	}
};

module.exports = function (cb/*, thisArg*/) {
	ensureValue(this);
	if (isValue(cb)) callable(cb);

	return new Find(this, cb, arguments[1]);
};