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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | 40 40 40 40 40 40 7138 3893 40 40 40 40 82 40 40 40 40 40 89 89 40 40 40 1034 1034 1034 1030 1030 1034 1034 1032 1032 2 1 2 2 2 2 1032 40 1946 1946 1946 1946 40 917 917 903 903 903 903 40 28 5 23 4 23 23 23 40 4 4 4 40 49 49 49 49 1 1 1 2 1 48 34 34 40 4 4 2 2 2 2 2 2 2 2 2 3 2 2 2 40 4 40 4 4 40 1134 1134 1134 1134 132 1002 131 131 40 32 40 1134 32 32 40 4 4 4 4 4 | (function () { 'use strict'; // WARNING: THIS MODULE IS PENDING DEPRECATION. // // No new pull requests targeting this module will be accepted // unless they address existing, critical bugs. const util = require('util'); const EventEmitter = require('events'); const inherits = util.inherits; // communicate with events module, but don't require that // module to have to load this one, since this module has // a few side effects. EventEmitter.usingDomains = true; // overwrite process.domain with a getter/setter that will allow for more // effective optimizations var _domain = [null]; Object.defineProperty(process, 'domain', { enumerable: true, get: function() { return _domain[0]; }, set: function(arg) { return _domain[0] = arg; } }); // objects with external array data are excellent ways to communicate state // between js and c++ w/o much overhead var _domain_flag = {}; // let the process know we're using domains process._setupDomainUse(_domain, _domain_flag); exports.Domain = Domain; exports.create = exports.createDomain = function() { return new Domain(); }; // it's possible to enter one domain while already inside // another one. the stack is each entered domain. var stack = []; exports._stack = stack; // the active domain is always the one that we're currently in. exports.active = null; inherits(Domain, EventEmitter); function Domain() { EventEmitter.call(this); this.members = []; } Domain.prototype.members = undefined; Domain.prototype._disposed = undefined; // Called by process._fatalException in case an error was thrown. Domain.prototype._errorHandler = function errorHandler(er) { var caught = false; // ignore errors on disposed domains. // // XXX This is a bit stupid. We should probably get rid of // domain.dispose() altogether. It's almost always a terrible // idea. --isaacs Iif (this._disposed) return true; if (!util.isPrimitive(er)) { er.domain = this; er.domainThrown = true; } // wrap this in a try/catch so we don't get infinite throwing try { // One of three things will happen here. // // 1. There is a handler, caught = true // 2. There is no handler, caught = false // 3. It throws, caught = false // // If caught is false after this, then there's no need to exit() // the domain, because we're going to crash the process anyway. caught = this.emit('error', er); // Exit all domains on the stack. Uncaught exceptions end the // current tick and no domains should be left on the stack // between ticks. stack.length = 0; exports.active = process.domain = null; } catch (er2) { // The domain error handler threw! oh no! // See if another domain can catch THIS error, // or else crash on the original one. // If the user already exited it, then don't double-exit. if (this === exports.active) { stack.pop(); } Eif (stack.length) { exports.active = process.domain = stack[stack.length - 1]; caught = process._fatalException(er2); } else { caught = false; } return caught; } return caught; }; Domain.prototype.enter = function() { Iif (this._disposed) return; // note that this might be a no-op, but we still need // to push it onto the stack so that we can pop it later. exports.active = process.domain = this; stack.push(this); _domain_flag[0] = stack.length; }; Domain.prototype.exit = function() { // skip disposed domains, as usual, but also don't do anything if this // domain is not on the stack. var index = stack.lastIndexOf(this); if (this._disposed || index === -1) return; // exit all domains until this one. stack.splice(index); _domain_flag[0] = stack.length; exports.active = stack[stack.length - 1]; process.domain = exports.active; }; // note: this works for timers as well. Domain.prototype.add = function(ee) { // If the domain is disposed or already added, then nothing left to do. if (this._disposed || ee.domain === this) return; // has a domain already - remove it first. if (ee.domain) ee.domain.remove(ee); // check for circular Domain->Domain links. // This causes bad insanity! // // For example: // var d = domain.create(); // var e = domain.create(); // d.add(e); // e.add(d); // e.emit('error', er); // RangeError, stack overflow! Iif (this.domain && (ee instanceof Domain)) { for (var d = this.domain; d; d = d.domain) { if (ee === d) return; } } ee.domain = this; this.members.push(ee); }; Domain.prototype.remove = function(ee) { ee.domain = null; var index = this.members.indexOf(ee); Iif (index !== -1) this.members.splice(index, 1); }; Domain.prototype.run = function(fn) { Iif (this._disposed) return; var ret; this.enter(); if (arguments.length >= 2) { var len = arguments.length; var args = new Array(len - 1); for (var i = 1; i < len; i++) args[i - 1] = arguments[i]; ret = fn.apply(this, args); } else { ret = fn.call(this); } this.exit(); return ret; }; function intercepted(_this, self, cb, fnargs) { Iif (self._disposed) return; if (fnargs[0] && fnargs[0] instanceof Error) { var er = fnargs[0]; util._extend(er, { domainBound: cb, domainThrown: false, domain: self }); self.emit('error', er); return; } var args = []; var i, ret; self.enter(); Eif (fnargs.length > 1) { for (i = 1; i < fnargs.length; i++) args.push(fnargs[i]); ret = cb.apply(_this, args); } else { ret = cb.call(_this); } self.exit(); return ret; } Domain.prototype.intercept = function(cb) { var self = this; function runIntercepted() { return intercepted(this, self, cb, arguments); } return runIntercepted; }; function bound(_this, self, cb, fnargs) { Iif (self._disposed) return; var ret; self.enter(); if (fnargs.length > 0) ret = cb.apply(_this, fnargs); else ret = cb.call(_this); self.exit(); return ret; } Domain.prototype.bind = function(cb) { var self = this; function runBound() { return bound(this, self, cb, arguments); } runBound.domain = this; return runBound; }; Domain.prototype.dispose = util.deprecate(function() { Iif (this._disposed) return; // if we're the active domain, then get out now. this.exit(); // remove from parent domain, if there is one. Iif (this.domain) this.domain.remove(this); // kill the references so that they can be properly gc'ed. this.members.length = 0; // mark this domain as 'no longer relevant' // so that it can't be entered or activated. this._disposed = true; }); }()); |