From d1dd8a8e4ded2806c868a63aeee5cff81cf1579d Mon Sep 17 00:00:00 2001 From: David Glasser Date: Thu, 11 Apr 2013 17:11:45 -0700 Subject: [PATCH] Refactor Avi's improved Meteor.Error to make it possible to use for other Error subclasses. --- packages/livedata/livedata_common.js | 73 ++++++++++------------------ packages/meteor/errors.js | 39 +++++++++++++++ packages/meteor/package.js | 1 + 3 files changed, 65 insertions(+), 48 deletions(-) create mode 100644 packages/meteor/errors.js diff --git a/packages/livedata/livedata_common.js b/packages/livedata/livedata_common.js index 15344c9629..e2543581fc 100644 --- a/packages/livedata/livedata_common.js +++ b/packages/livedata/livedata_common.js @@ -119,55 +119,32 @@ Meteor._CurrentInvocation = new Meteor.EnvironmentVariable; // The DDP client manually puts these into Meteor.Error objects. (We don't use // EJSON.addType here because the type is determined by location in the // protocol, not text on the wire.) -Meteor.Error = function (error, reason, details) { - var self = this; +Meteor.Error = Meteor.makeErrorType( + "Meteor.Error", + function (error, reason, details) { + var self = this; - // Ensure we get a proper stack trace in most Javascript environments - if (Error.captureStackTrace) { - // V8 environments (Chrome and Node.js) - Error.captureStackTrace(self, Meteor.Error); - } else { - // Firefox - var e = new Error; - e.__proto__ = Meteor.Error.prototype; - if (e instanceof Meteor.Error) - self = e; - } - // Safari magically works. + // Currently, a numeric code, likely similar to a HTTP code (eg, + // 404, 500). That is likely to change though. + self.error = error; - // Currently, a numeric code, likely similar to a HTTP code (eg, - // 404, 500). That is likely to change though. - self.error = error; + // Optional: A short human-readable summary of the error. Not + // intended to be shown to end users, just developers. ("Not Found", + // "Internal Server Error") + self.reason = reason; - // Optional: A short human-readable summary of the error. Not - // intended to be shown to end users, just developers. ("Not Found", - // "Internal Server Error") - self.reason = reason; + // Optional: Additional information about the error, say for + // debugging. It might be a (textual) stack trace if the server is + // willing to provide one. The corresponding thing in HTTP would be + // the body of a 404 or 500 response. (The difference is that we + // never expect this to be shown to end users, only developers, so + // it doesn't need to be pretty.) + self.details = details; - // Optional: Additional information about the error, say for - // debugging. It might be a (textual) stack trace if the server is - // willing to provide one. The corresponding thing in HTTP would be - // the body of a 404 or 500 response. (The difference is that we - // never expect this to be shown to end users, only developers, so - // it doesn't need to be pretty.) - self.details = details; - - // This is what gets displayed at the top of a stack trace. Current - // format is "[404]" (if no reason is set) or "File not found [404]" - if (self.reason) - self.message = self.reason + ' [' + self.error + ']'; - else - self.message = '[' + self.error + ']'; - - return self; -}; - -// http://davidshariff.com/blog/javascript-inheritance-patterns/ -var inherits = function (child, parent) { - var tmp = function () {}; - tmp.prototype = parent.prototype; - child.prototype = new tmp; - child.prototype.constructor = child; -}; - -inherits(Meteor.Error, Error); \ No newline at end of file + // This is what gets displayed at the top of a stack trace. Current + // format is "[404]" (if no reason is set) or "File not found [404]" + if (self.reason) + self.message = self.reason + ' [' + self.error + ']'; + else + self.message = '[' + self.error + ']'; + }); diff --git a/packages/meteor/errors.js b/packages/meteor/errors.js new file mode 100644 index 0000000000..7a63778556 --- /dev/null +++ b/packages/meteor/errors.js @@ -0,0 +1,39 @@ +// http://davidshariff.com/blog/javascript-inheritance-patterns/ +var inherits = function (child, parent) { + var tmp = function () {}; + tmp.prototype = parent.prototype; + child.prototype = new tmp; + child.prototype.constructor = child; +}; + +// Makes an error subclass which properly contains a stack trace in most +// environments. constructor can set fields on `this` (and should probably set +// `message`, which is what gets displayed at the top of a stack trace). +Meteor.makeErrorType = function (name, constructor) { + var errorClass = function (/*arguments*/) { + var self = this; + + // Ensure we get a proper stack trace in most Javascript environments + if (Error.captureStackTrace) { + // V8 environments (Chrome and Node.js) + Error.captureStackTrace(self, errorClass); + } else { + // Firefox + var e = new Error; + e.__proto__ = errorClass.prototype; + if (e instanceof errorClass) + self = e; + } + // Safari magically works. + + constructor.apply(self, arguments); + + self.errorType = name; + + return self; + }; + + inherits(errorClass, Error); + + return errorClass; +}; diff --git a/packages/meteor/package.js b/packages/meteor/package.js index 7b0ab1a2e8..25251f9937 100644 --- a/packages/meteor/package.js +++ b/packages/meteor/package.js @@ -34,6 +34,7 @@ Package.on_use(function (api, where) { api.add_files('server_environment.js', 'server'); api.add_files('helpers.js', ['client', 'server']); api.add_files('timers.js', ['client', 'server']); + api.add_files('errors.js', ['client', 'server']); api.add_files('fiber_helpers.js', 'server'); // dynamic variables, bindEnvironment