kareem 2.6.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -24,127 +24,69 @@ Kareem.overwriteResult = function overwriteResult() {
24
24
  this.args = [...arguments];
25
25
  };
26
26
 
27
+ Kareem.overwriteArguments = function overwriteArguments() {
28
+ if (!(this instanceof Kareem.overwriteArguments)) {
29
+ return new Kareem.overwriteArguments(...arguments);
30
+ }
31
+
32
+ this.args = [...arguments];
33
+ };
34
+
27
35
  /**
28
36
  * Execute all "pre" hooks for "name"
29
37
  * @param {String} name The hook name to execute
30
38
  * @param {*} context Overwrite the "this" for the hook
31
- * @param {Array|Function} args Optional arguments or directly the callback
32
- * @param {Function} [callback] The callback to call when executing all hooks are finished
33
- * @returns {void}
39
+ * @param {Array} args arguments passed to the pre hooks
40
+ * @returns {Array} The potentially modified arguments
34
41
  */
35
- Kareem.prototype.execPre = function(name, context, args, callback) {
36
- if (arguments.length === 3) {
37
- callback = args;
38
- args = [];
39
- }
42
+ Kareem.prototype.execPre = async function execPre(name, context, args) {
40
43
  const pres = this._pres.get(name) || [];
41
44
  const numPres = pres.length;
42
- const numAsyncPres = pres.numAsync || 0;
43
- let currentPre = 0;
44
- let asyncPresLeft = numAsyncPres;
45
- let done = false;
46
- const $args = args;
47
- let shouldSkipWrappedFunction = null;
45
+ let $args = args;
46
+ let skipWrappedFunction = null;
48
47
 
49
48
  if (!numPres) {
50
- return nextTick(function() {
51
- callback(null);
52
- });
49
+ return $args;
53
50
  }
54
51
 
55
- function next() {
56
- if (currentPre >= numPres) {
57
- return;
58
- }
59
- const pre = pres[currentPre];
60
-
61
- if (pre.isAsync) {
62
- const args = [
63
- decorateNextFn(_next),
64
- decorateNextFn(function(error) {
65
- if (error) {
66
- if (done) {
67
- return;
68
- }
69
- if (error instanceof Kareem.skipWrappedFunction) {
70
- shouldSkipWrappedFunction = error;
71
- } else {
72
- done = true;
73
- return callback(error);
74
- }
75
- }
76
- if (--asyncPresLeft === 0 && currentPre >= numPres) {
77
- return callback(shouldSkipWrappedFunction);
78
- }
79
- })
80
- ];
81
-
82
- callMiddlewareFunction(pre.fn, context, args, args[0]);
83
- } else if (pre.fn.length > 0) {
84
- const args = [decorateNextFn(_next)];
85
- const _args = arguments.length >= 2 ? arguments : [null].concat($args);
86
- for (let i = 1; i < _args.length; ++i) {
87
- if (i === _args.length - 1 && typeof _args[i] === 'function') {
88
- continue; // skip callbacks to avoid accidentally calling the callback from a hook
89
- }
90
- args.push(_args[i]);
91
- }
92
-
93
- callMiddlewareFunction(pre.fn, context, args, args[0]);
94
- } else {
95
- let maybePromiseLike = null;
96
- try {
97
- maybePromiseLike = pre.fn.call(context);
98
- } catch (err) {
99
- if (err != null) {
100
- return callback(err);
101
- }
52
+ for (const pre of pres) {
53
+ const args = [];
54
+ const _args = [null].concat($args);
55
+ for (let i = 1; i < _args.length; ++i) {
56
+ if (i === _args.length - 1 && typeof _args[i] === 'function') {
57
+ continue; // skip callbacks to avoid accidentally calling the callback from a hook
102
58
  }
59
+ args.push(_args[i]);
60
+ }
103
61
 
62
+ try {
63
+ const maybePromiseLike = pre.fn.apply(context, args);
104
64
  if (isPromiseLike(maybePromiseLike)) {
105
- maybePromiseLike.then(() => _next(), err => _next(err));
106
- } else {
107
- if (++currentPre >= numPres) {
108
- if (asyncPresLeft > 0) {
109
- // Leave parallel hooks to run
110
- return;
111
- } else {
112
- return nextTick(function() {
113
- callback(shouldSkipWrappedFunction);
114
- });
115
- }
65
+ const result = await maybePromiseLike;
66
+ if (result instanceof Kareem.overwriteArguments) {
67
+ $args = result.args;
116
68
  }
117
- next();
118
- }
119
- }
120
- }
121
-
122
- next.apply(null, [null].concat(args));
123
-
124
- function _next(error) {
125
- if (error) {
126
- if (done) {
127
- return;
69
+ } else if (maybePromiseLike instanceof Kareem.overwriteArguments) {
70
+ $args = maybePromiseLike.args;
128
71
  }
72
+ } catch (error) {
129
73
  if (error instanceof Kareem.skipWrappedFunction) {
130
- shouldSkipWrappedFunction = error;
131
- } else {
132
- done = true;
133
- return callback(error);
74
+ skipWrappedFunction = error;
75
+ continue;
134
76
  }
135
- }
136
-
137
- if (++currentPre >= numPres) {
138
- if (asyncPresLeft > 0) {
139
- // Leave parallel hooks to run
140
- return;
141
- } else {
142
- return callback(shouldSkipWrappedFunction);
77
+ if (error instanceof Kareem.overwriteArguments) {
78
+ $args = error.args;
79
+ continue;
143
80
  }
81
+ throw error;
144
82
  }
83
+ }
145
84
 
146
- next.apply(context, arguments);
85
+ if (skipWrappedFunction) {
86
+ throw skipWrappedFunction;
147
87
  }
88
+
89
+ return $args;
148
90
  };
149
91
 
150
92
  /**
@@ -152,34 +94,34 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
152
94
  * @param {String} name The hook name to execute
153
95
  * @param {*} context Overwrite the "this" for the hook
154
96
  * @param {Array} [args] Apply custom arguments to the hook
155
- * @returns {void}
97
+ * @returns {Array} The potentially modified arguments
156
98
  */
157
99
  Kareem.prototype.execPreSync = function(name, context, args) {
158
100
  const pres = this._pres.get(name) || [];
159
101
  const numPres = pres.length;
102
+ let $args = args || [];
160
103
 
161
104
  for (let i = 0; i < numPres; ++i) {
162
- pres[i].fn.apply(context, args || []);
105
+ const result = pres[i].fn.apply(context, $args);
106
+ if (result instanceof Kareem.overwriteArguments) {
107
+ $args = result.args;
108
+ }
163
109
  }
110
+
111
+ return $args;
164
112
  };
165
113
 
166
114
  /**
167
115
  * Execute all "post" hooks for "name"
168
116
  * @param {String} name The hook name to execute
169
117
  * @param {*} context Overwrite the "this" for the hook
170
- * @param {Array|Function} args Apply custom arguments to the hook
118
+ * @param {Array} args Apply custom arguments to the hook
171
119
  * @param {*} options Optional options or directly the callback
172
- * @param {Function} [callback] The callback to call when executing all hooks are finished
173
120
  * @returns {void}
174
121
  */
175
- Kareem.prototype.execPost = function(name, context, args, options, callback) {
176
- if (arguments.length < 5) {
177
- callback = options;
178
- options = null;
179
- }
122
+ Kareem.prototype.execPost = async function execPost(name, context, args, options) {
180
123
  const posts = this._posts.get(name) || [];
181
124
  const numPosts = posts.length;
182
- let currentPost = 0;
183
125
 
184
126
  let firstError = null;
185
127
  if (options && options.error) {
@@ -187,120 +129,108 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
187
129
  }
188
130
 
189
131
  if (!numPosts) {
190
- return nextTick(function() {
191
- callback.apply(null, [firstError].concat(args));
192
- });
132
+ if (firstError != null) {
133
+ throw firstError;
134
+ }
135
+ return args;
193
136
  }
194
137
 
195
- function next() {
196
- const post = posts[currentPost].fn;
138
+ for (const currentPost of posts) {
139
+ const post = currentPost.fn;
197
140
  let numArgs = 0;
198
- const argLength = args.length;
199
141
  const newArgs = [];
142
+ const argLength = args.length;
200
143
  for (let i = 0; i < argLength; ++i) {
201
- numArgs += args[i] && args[i]._kareemIgnore ? 0 : 1;
202
144
  if (!args[i] || !args[i]._kareemIgnore) {
145
+ numArgs += 1;
203
146
  newArgs.push(args[i]);
204
147
  }
205
148
  }
149
+ // If numCallbackParams set, fill in the rest with null to enforce consistent number of args
150
+ if (options?.numCallbackParams != null) {
151
+ numArgs = options.numCallbackParams;
152
+ for (let i = newArgs.length; i < numArgs; ++i) {
153
+ newArgs.push(null);
154
+ }
155
+ }
206
156
 
207
- if (firstError) {
208
- if (isErrorHandlingMiddleware(posts[currentPost], numArgs)) {
209
- const _cb = decorateNextFn(function(error) {
210
- if (error) {
211
- if (error instanceof Kareem.overwriteResult) {
212
- args = error.args;
213
- if (++currentPost >= numPosts) {
214
- return callback.call(null, firstError);
215
- }
216
- return next();
217
- }
218
- firstError = error;
219
- }
220
- if (++currentPost >= numPosts) {
221
- return callback.call(null, firstError);
222
- }
223
- next();
224
- });
225
-
226
- callMiddlewareFunction(post, context,
227
- [firstError].concat(newArgs).concat([_cb]), _cb);
157
+ let resolve;
158
+ let reject;
159
+ const cbPromise = new Promise((_resolve, _reject) => {
160
+ resolve = _resolve;
161
+ reject = _reject;
162
+ });
163
+ newArgs.push(function nextCallback(err) {
164
+ if (err) {
165
+ reject(err);
228
166
  } else {
229
- if (++currentPost >= numPosts) {
230
- return callback.call(null, firstError);
231
- }
232
- next();
167
+ resolve();
233
168
  }
234
- } else {
235
- const _cb = decorateNextFn(function(error) {
236
- if (error) {
169
+ });
170
+
171
+ if (firstError) {
172
+ if (isErrorHandlingMiddleware(currentPost, numArgs)) {
173
+ try {
174
+ const res = post.apply(context, [firstError].concat(newArgs));
175
+ if (isPromiseLike(res)) {
176
+ await res;
177
+ } else if (post.length === numArgs + 2) {
178
+ // `numArgs + 2` because we added the error and the callback
179
+ await cbPromise;
180
+ }
181
+ } catch (error) {
237
182
  if (error instanceof Kareem.overwriteResult) {
238
183
  args = error.args;
239
- if (++currentPost >= numPosts) {
240
- return callback.apply(null, [null].concat(args));
241
- }
242
- return next();
184
+ continue;
243
185
  }
244
186
  firstError = error;
245
- return next();
246
187
  }
247
-
248
- if (++currentPost >= numPosts) {
249
- return callback.apply(null, [null].concat(args));
250
- }
251
-
252
- next();
253
- });
254
-
255
- if (isErrorHandlingMiddleware(posts[currentPost], numArgs)) {
256
- // Skip error handlers if no error
257
- if (++currentPost >= numPosts) {
258
- return callback.apply(null, [null].concat(args));
259
- }
260
- return next();
188
+ } else {
189
+ continue;
261
190
  }
262
- if (post.length === numArgs + 1) {
263
- callMiddlewareFunction(post, context, newArgs.concat([_cb]), _cb);
191
+ } else {
192
+ if (isErrorHandlingMiddleware(currentPost, numArgs)) {
193
+ // Skip error handlers if no error
194
+ continue;
264
195
  } else {
265
- let error;
266
- let maybePromiseLike;
196
+ let res = null;
267
197
  try {
268
- maybePromiseLike = post.apply(context, newArgs);
269
- } catch (err) {
270
- error = err;
271
- firstError = err;
272
- }
273
-
274
- if (isPromiseLike(maybePromiseLike)) {
275
- return maybePromiseLike.then(
276
- (res) => {
277
- _cb(res instanceof Kareem.overwriteResult ? res : null);
278
- },
279
- err => _cb(err)
280
- );
281
- }
282
-
283
- if (maybePromiseLike instanceof Kareem.overwriteResult) {
284
- args = maybePromiseLike.args;
198
+ res = post.apply(context, newArgs);
199
+ if (isPromiseLike(res)) {
200
+ res = await res;
201
+ } else if (post.length === numArgs + 1) {
202
+ // If post function takes a callback, wait for the post function to call the callback
203
+ res = await cbPromise;
204
+ }
205
+ } catch (error) {
206
+ if (error instanceof Kareem.overwriteResult) {
207
+ args = error.args;
208
+ continue;
209
+ }
210
+ firstError = error;
211
+ continue;
285
212
  }
286
213
 
287
- if (++currentPost >= numPosts) {
288
- return callback.apply(null, [error].concat(args));
214
+ if (res instanceof Kareem.overwriteResult) {
215
+ args = res.args;
216
+ continue;
289
217
  }
290
-
291
- next();
292
218
  }
293
219
  }
294
220
  }
295
221
 
296
- next();
222
+ if (firstError != null) {
223
+ throw firstError;
224
+ }
225
+
226
+ return args;
297
227
  };
298
228
 
299
229
  /**
300
230
  * Execute all "post" hooks for "name" synchronously
301
231
  * @param {String} name The hook name to execute
302
232
  * @param {*} context Overwrite the "this" for the hook
303
- * @param {Array|Function} args Apply custom arguments to the hook
233
+ * @param {Array} args Apply custom arguments to the hook
304
234
  * @returns {Array} The used arguments
305
235
  */
306
236
  Kareem.prototype.execPostSync = function(name, context, args) {
@@ -326,9 +256,9 @@ Kareem.prototype.execPostSync = function(name, context, args) {
326
256
  Kareem.prototype.createWrapperSync = function(name, fn) {
327
257
  const _this = this;
328
258
  return function syncWrapper() {
329
- _this.execPreSync(name, this, arguments);
259
+ const modifiedArgs = _this.execPreSync(name, this, Array.from(arguments));
330
260
 
331
- const toReturn = fn.apply(this, arguments);
261
+ const toReturn = fn.apply(this, modifiedArgs);
332
262
 
333
263
  const result = _this.execPostSync(name, this, [toReturn]);
334
264
 
@@ -336,98 +266,37 @@ Kareem.prototype.createWrapperSync = function(name, fn) {
336
266
  };
337
267
  };
338
268
 
339
- function _handleWrapError(instance, error, name, context, args, options, callback) {
340
- if (options.useErrorHandlers) {
341
- return instance.execPost(name, context, args, { error: error }, function(error) {
342
- return typeof callback === 'function' && callback(error);
343
- });
344
- } else {
345
- return typeof callback === 'function' && callback(error);
346
- }
347
- }
348
-
349
269
  /**
350
270
  * Executes pre hooks, followed by the wrapped function, followed by post hooks.
351
271
  * @param {String} name The name of the hook
352
272
  * @param {Function} fn The function for the hook
353
273
  * @param {*} context Overwrite the "this" for the hook
354
274
  * @param {Array} args Apply custom arguments to the hook
355
- * @param {Object} [options]
356
- * @param {Boolean} [options.checkForPromise]
275
+ * @param {Object} options Additional options for the hook
357
276
  * @returns {void}
358
277
  */
359
- Kareem.prototype.wrap = function(name, fn, context, args, options) {
360
- const lastArg = (args.length > 0 ? args[args.length - 1] : null);
361
- const argsWithoutCb = Array.from(args);
362
- typeof lastArg === 'function' && argsWithoutCb.pop();
363
- const _this = this;
364
-
365
- options = options || {};
366
- const checkForPromise = options.checkForPromise;
367
-
368
- this.execPre(name, context, args, function(error) {
369
- if (error && !(error instanceof Kareem.skipWrappedFunction)) {
370
- const numCallbackParams = options.numCallbackParams || 0;
371
- const errorArgs = options.contextParameter ? [context] : [];
372
- for (let i = errorArgs.length; i < numCallbackParams; ++i) {
373
- errorArgs.push(null);
374
- }
375
- return _handleWrapError(_this, error, name, context, errorArgs,
376
- options, lastArg);
377
- }
378
-
379
- const numParameters = fn.length;
380
- let ret;
381
-
278
+ Kareem.prototype.wrap = async function wrap(name, fn, context, args, options) {
279
+ let ret;
280
+ let skipWrappedFunction = false;
281
+ let modifiedArgs = args;
282
+ try {
283
+ modifiedArgs = await this.execPre(name, context, args);
284
+ } catch (error) {
382
285
  if (error instanceof Kareem.skipWrappedFunction) {
383
- ret = error.args[0];
384
- return _cb(null, ...error.args);
286
+ ret = error.args;
287
+ skipWrappedFunction = true;
385
288
  } else {
386
- try {
387
- ret = fn.apply(context, argsWithoutCb.concat(_cb));
388
- } catch (err) {
389
- return _cb(err);
390
- }
289
+ await this.execPost(name, context, args, { ...options, error });
391
290
  }
291
+ }
392
292
 
393
- if (checkForPromise) {
394
- if (isPromiseLike(ret)) {
395
- // Thenable, use it
396
- return ret.then(
397
- res => _cb(null, res),
398
- err => _cb(err)
399
- );
400
- }
293
+ if (!skipWrappedFunction) {
294
+ ret = await fn.apply(context, modifiedArgs);
295
+ }
401
296
 
402
- // If `fn()` doesn't have a callback argument and doesn't return a
403
- // promise, assume it is sync
404
- if (numParameters < argsWithoutCb.length + 1) {
405
- return _cb(null, ret);
406
- }
407
- }
297
+ ret = await this.execPost(name, context, [ret], options);
408
298
 
409
- function _cb() {
410
- const argsWithoutError = Array.from(arguments);
411
- argsWithoutError.shift();
412
- if (options.nullResultByDefault && argsWithoutError.length === 0) {
413
- argsWithoutError.push(null);
414
- }
415
- if (arguments[0]) {
416
- // Assume error
417
- return _handleWrapError(_this, arguments[0], name, context,
418
- argsWithoutError, options, lastArg);
419
- } else {
420
- _this.execPost(name, context, argsWithoutError, function() {
421
- if (lastArg === null) {
422
- return;
423
- }
424
- arguments[0]
425
- ? lastArg(arguments[0])
426
- : lastArg.apply(context, arguments);
427
- });
428
- }
429
- }
430
- });
299
+ return ret[0];
431
300
  };
432
301
 
433
302
  /**
@@ -449,8 +318,6 @@ Kareem.prototype.filter = function(fn) {
449
318
  continue;
450
319
  }
451
320
 
452
- hooks.numAsync = hooks.filter(h => h.isAsync).length;
453
-
454
321
  clone._pres.set(name, hooks);
455
322
  }
456
323
 
@@ -491,53 +358,43 @@ Kareem.prototype.hasHooks = function(name) {
491
358
  Kareem.prototype.createWrapper = function(name, fn, context, options) {
492
359
  const _this = this;
493
360
  if (!this.hasHooks(name)) {
494
- // Fast path: if there's no hooks for this function, just return the
495
- // function wrapped in a nextTick()
496
- return function() {
497
- nextTick(() => fn.apply(this, arguments));
498
- };
361
+ // Fast path: if there's no hooks for this function, just return the function
362
+ return fn;
499
363
  }
500
- return function() {
364
+ return function kareemWrappedFunction() {
501
365
  const _context = context || this;
502
- _this.wrap(name, fn, _context, Array.from(arguments), options);
366
+ return _this.wrap(name, fn, _context, Array.from(arguments), options);
503
367
  };
504
368
  };
505
369
 
506
370
  /**
507
371
  * Register a new hook for "pre"
508
372
  * @param {String} name The name of the hook
509
- * @param {Boolean} [isAsync]
373
+ * @param {Object} [options]
510
374
  * @param {Function} fn The function to register for "name"
511
375
  * @param {never} error Unused
512
376
  * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
513
377
  * @returns {Kareem}
514
378
  */
515
- Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
516
- let options = {};
517
- if (typeof isAsync === 'object' && isAsync !== null) {
518
- options = isAsync;
519
- isAsync = options.isAsync;
520
- } else if (typeof arguments[1] !== 'boolean') {
521
- fn = isAsync;
522
- isAsync = false;
379
+ Kareem.prototype.pre = function(name, options, fn, error, unshift) {
380
+ if (typeof options === 'function') {
381
+ fn = options;
382
+ options = {};
383
+ } else if (options == null) {
384
+ options = {};
523
385
  }
524
386
 
525
387
  const pres = this._pres.get(name) || [];
526
388
  this._pres.set(name, pres);
527
389
 
528
- if (isAsync) {
529
- pres.numAsync = pres.numAsync || 0;
530
- ++pres.numAsync;
531
- }
532
-
533
390
  if (typeof fn !== 'function') {
534
391
  throw new Error('pre() requires a function, got "' + typeof fn + '"');
535
392
  }
536
393
 
537
394
  if (unshift) {
538
- pres.unshift(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
395
+ pres.unshift(Object.assign({}, options, { fn: fn }));
539
396
  } else {
540
- pres.push(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
397
+ pres.push(Object.assign({}, options, { fn: fn }));
541
398
  }
542
399
 
543
400
  return this;
@@ -547,6 +404,7 @@ Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
547
404
  * Register a new hook for "post"
548
405
  * @param {String} name The name of the hook
549
406
  * @param {Object} [options]
407
+ * @param {Boolean} [options.errorHandler] Whether this is an error handler
550
408
  * @param {Function} fn The function to register for "name"
551
409
  * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
552
410
  * @returns {Kareem}
@@ -573,6 +431,24 @@ Kareem.prototype.post = function(name, options, fn, unshift) {
573
431
  return this;
574
432
  };
575
433
 
434
+ /**
435
+ * Register a new error handler for "name"
436
+ * @param {String} name The name of the hook
437
+ * @param {Object} [options]
438
+ * @param {Function} fn The function to register for "name"
439
+ * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
440
+ * @returns {Kareem}
441
+ */
442
+
443
+ Kareem.prototype.postError = function postError(name, options, fn, unshift) {
444
+ if (typeof options === 'function') {
445
+ unshift = !!fn;
446
+ fn = options;
447
+ options = {};
448
+ }
449
+ return this.post(name, { ...options, errorHandler: true }, fn, unshift);
450
+ };
451
+
576
452
  /**
577
453
  * Clone the current instance
578
454
  * @returns {Kareem} The cloned instance
@@ -582,7 +458,6 @@ Kareem.prototype.clone = function() {
582
458
 
583
459
  for (const key of this._pres.keys()) {
584
460
  const clone = this._pres.get(key).slice();
585
- clone.numAsync = this._pres.get(key).numAsync;
586
461
  n._pres.set(key, clone);
587
462
  }
588
463
  for (const key of this._posts.keys()) {
@@ -608,8 +483,6 @@ Kareem.prototype.merge = function(other, clone) {
608
483
  // Deduplicate based on `fn`
609
484
  filter(p => sourcePres.map(_p => _p.fn).indexOf(p.fn) === -1);
610
485
  const combined = sourcePres.concat(deduplicated);
611
- combined.numAsync = sourcePres.numAsync || 0;
612
- combined.numAsync += deduplicated.filter(p => p.isAsync).length;
613
486
  ret._pres.set(key, combined);
614
487
  }
615
488
  for (const key of other._posts.keys()) {
@@ -622,42 +495,10 @@ Kareem.prototype.merge = function(other, clone) {
622
495
  return ret;
623
496
  };
624
497
 
625
- function callMiddlewareFunction(fn, context, args, next) {
626
- let maybePromiseLike;
627
- try {
628
- maybePromiseLike = fn.apply(context, args);
629
- } catch (error) {
630
- return next(error);
631
- }
632
-
633
- if (isPromiseLike(maybePromiseLike)) {
634
- maybePromiseLike.then(() => next(), err => next(err));
635
- }
636
- }
637
-
638
498
  function isPromiseLike(v) {
639
499
  return (typeof v === 'object' && v !== null && typeof v.then === 'function');
640
500
  }
641
501
 
642
- function decorateNextFn(fn) {
643
- let called = false;
644
- const _this = this;
645
- return function() {
646
- // Ensure this function can only be called once
647
- if (called) {
648
- return;
649
- }
650
- called = true;
651
- // Make sure to clear the stack so try/catch doesn't catch errors
652
- // in subsequent middleware
653
- return nextTick(() => fn.apply(_this, arguments));
654
- };
655
- }
656
-
657
- const nextTick = typeof process === 'object' && process !== null && process.nextTick || function nextTick(cb) {
658
- setTimeout(cb, 0);
659
- };
660
-
661
502
  function isErrorHandlingMiddleware(post, numArgs) {
662
503
  if (post.errorHandler) {
663
504
  return true;