forked from dexie/Dexie.js
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchaining-functions.js
101 lines (93 loc) · 3.86 KB
/
chaining-functions.js
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
99
100
101
import {extend} from './utils';
export function nop() { }
export function mirror(val) { return val; }
export function pureFunctionChain(f1, f2) {
// Enables chained events that takes ONE argument and returns it to the next function in chain.
// This pattern is used in the hook("reading") event.
if (f1 == null || f1 === mirror) return f2;
return function (val) {
return f2(f1(val));
};
}
export function callBoth(on1, on2) {
return function () {
on1.apply(this, arguments);
on2.apply(this, arguments);
};
}
export function hookCreatingChain(f1, f2) {
// Enables chained events that takes several arguments and may modify first argument by making a modification and then returning the same instance.
// This pattern is used in the hook("creating") event.
if (f1 === nop) return f2;
return function () {
var res = f1.apply(this, arguments);
if (res !== undefined) arguments[0] = res;
var onsuccess = this.onsuccess, // In case event listener has set this.onsuccess
onerror = this.onerror; // In case event listener has set this.onerror
this.onsuccess = null;
this.onerror = null;
var res2 = f2.apply(this, arguments);
if (onsuccess) this.onsuccess = this.onsuccess ? callBoth(onsuccess, this.onsuccess) : onsuccess;
if (onerror) this.onerror = this.onerror ? callBoth(onerror, this.onerror) : onerror;
return res2 !== undefined ? res2 : res;
};
}
export function hookDeletingChain(f1, f2) {
if (f1 === nop) return f2;
return function () {
f1.apply(this, arguments);
var onsuccess = this.onsuccess, // In case event listener has set this.onsuccess
onerror = this.onerror; // In case event listener has set this.onerror
this.onsuccess = this.onerror = null;
f2.apply(this, arguments);
if (onsuccess) this.onsuccess = this.onsuccess ? callBoth(onsuccess, this.onsuccess) : onsuccess;
if (onerror) this.onerror = this.onerror ? callBoth(onerror, this.onerror) : onerror;
};
}
export function hookUpdatingChain(f1, f2) {
if (f1 === nop) return f2;
return function (modifications) {
var res = f1.apply(this, arguments);
extend(modifications, res); // If f1 returns new modifications, extend caller's modifications with the result before calling next in chain.
var onsuccess = this.onsuccess, // In case event listener has set this.onsuccess
onerror = this.onerror; // In case event listener has set this.onerror
this.onsuccess = null;
this.onerror = null;
var res2 = f2.apply(this, arguments);
if (onsuccess) this.onsuccess = this.onsuccess ? callBoth(onsuccess, this.onsuccess) : onsuccess;
if (onerror) this.onerror = this.onerror ? callBoth(onerror, this.onerror) : onerror;
return res === undefined ?
(res2 === undefined ? undefined : res2) :
(extend(res, res2));
};
}
export function reverseStoppableEventChain(f1, f2) {
if (f1 === nop) return f2;
return function () {
if (f2.apply(this, arguments) === false) return false;
return f1.apply(this, arguments);
};
}
export function nonStoppableEventChain(f1, f2) {
if (f1 === nop) return f2;
return function () {
f1.apply(this, arguments);
f2.apply(this, arguments);
};
}
export function promisableChain(f1, f2) {
if (f1 === nop) return f2;
return function () {
var res = f1.apply(this, arguments);
if (res && typeof res.then === 'function') {
var thiz = this,
i = arguments.length,
args = new Array(i);
while (i--) args[i] = arguments[i];
return res.then(function () {
return f2.apply(thiz, args);
});
}
return f2.apply(this, arguments);
};
}