shimUsing.js
3.38 KB
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
102
103
104
105
106
107
108
109
110
111
112
113
114
'use strict';
/*
* cls-bluebird
* Function to shim `Promise.using`
*
* `Promise.using()` calls `.then()` and `.lastly` internally which leads to
* unnecessary CLS context binding with a naive patch.
*
* This custom patch intercepts calls to `Promise.all()` (v3) or `Promise.settle()` (v2)
* within `Promise.using()` and patches the resulting promise's `.then`/`.lastly` methods
* so they do not bind callbacks to CLS context.
*
* NB This patch could break if bluebird internals change, but this is covered by the tests.
*/
// Modules
var shimmer = require('shimmer');
// Exports
/**
* Patch `Promise.using` method to run callbacks in current CLS context.
*
* @param {Function} Promise - Bluebird Promise constructor to patch
* @param {Object} ns - CLS namespace to bind callbacks to
* @param {boolean} v3 - `true` if bluebird being patched is v3.x
* @returns {undefined}
*/
module.exports = function(Promise, ns, v3) {
(v3 ? patchV3 : patchV2)(Promise, ns);
};
// Patch for `Promise.using()` in bluebird v3
function patchV3(Promise, ns) {
var thenOriginal = Promise.prototype.then.__original,
lastlyOriginal = Promise.prototype.lastly.__original;
// Patch method
shimmer.wrap(Promise, 'using', function(usingOriginal) {
return function() {
// Bind `using` callback (last arg)
var argIndex = arguments.length - 1,
callback = arguments[argIndex];
if (typeof callback === 'function') arguments[argIndex] = ns.bind(callback);
// Temporarily patch `Promise.all()`
shimmer.wrap(Promise, 'all', function(allOriginal) {
return function(promises) {
// Remove temporary patch on `Promise.all()`
Promise.all = allOriginal;
// Call original `Promise.all()`
var p = allOriginal.call(this, promises);
// Patch `.then()` method on this promise to not bind callbacks
p.then = function() {
var p = thenOriginal.apply(this, arguments);
// Patch `.lastly()` method on this promise to not bind callbacks
p.lastly = lastlyOriginal;
return p;
};
return p;
};
});
// Call original `Promise.using()` method
return usingOriginal.apply(this, arguments);
};
});
}
// Patch for `Promise.using()` in bluebird v2
function patchV2(Promise, ns) {
var thenOriginal = Promise.prototype.then.__original;
// Patch method
shimmer.wrap(Promise, 'using', function(usingOriginal) {
return function() {
// Bind `using` callback (last arg)
var argIndex = arguments.length - 1,
callback = arguments[argIndex];
if (typeof callback === 'function') arguments[argIndex] = ns.bind(callback);
// Temporarily patch `Promise.settle()`
shimmer.wrap(Promise, 'settle', function(settleOriginal) {
return function(resources) {
// Remove temporary patch on `Promise.settle()`
Promise.settle = settleOriginal;
// Call original `Promise.settle()`
var p = settleOriginal.call(this, resources);
// Patch `.then()` method on this promise to not bind callbacks
p.then = function() {
var p = thenOriginal.apply(this, arguments);
// Patch `.then()` method on this promise to not bind callbacks
p.then = thenOriginal;
return p;
};
return p;
};
});
// Call original `Promise.using()` method
return usingOriginal.apply(this, arguments);
};
});
}