pax_global_header00006660000000000000000000000064130754542510014520gustar00rootroot0000000000000052 comment=ecddeda07827742bd2c598033a02f4c42a6fdc26 node-verror-1.10.0/000077500000000000000000000000001307545425100140415ustar00rootroot00000000000000node-verror-1.10.0/.gitignore000066400000000000000000000000151307545425100160250ustar00rootroot00000000000000node_modules node-verror-1.10.0/.gitmodules000066400000000000000000000001321307545425100162120ustar00rootroot00000000000000[submodule "deps/catest"] path = deps/catest url = https://github.com/joyent/catest.git node-verror-1.10.0/.npmignore000066400000000000000000000001331307545425100160350ustar00rootroot00000000000000.gitignore .gitmodules deps examples experiments jsl.node.conf Makefile Makefile.targ test node-verror-1.10.0/CHANGES.md000066400000000000000000000007711307545425100154400ustar00rootroot00000000000000# Changelog ## Not yet released None yet. ## v1.10.0 * #49 want convenience functions for MultiErrors ## v1.9.0 * #47 could use VError.hasCauseWithName() ## v1.8.1 * #39 captureStackTrace lost when inheriting from WError ## v1.8.0 * #23 Preserve original stack trace(s) ## v1.7.0 * #10 better support for extra properties on Errors * #11 make it easy to find causes of a particular kind * #29 No documentation on how to Install this package * #36 elide development-only files from npm package node-verror-1.10.0/CONTRIBUTING.md000066400000000000000000000014021307545425100162670ustar00rootroot00000000000000# Contributing This repository uses [cr.joyent.us](https://cr.joyent.us) (Gerrit) for new changes. Anyone can submit changes. To get started, see the [cr.joyent.us user guide](https://github.com/joyent/joyent-gerrit/blob/master/docs/user/README.md). This repo does not use GitHub pull requests. See the [Joyent Engineering Guidelines](https://github.com/joyent/eng/blob/master/docs/index.md) for general best practices expected in this repository. Contributions should be "make prepush" clean. The "prepush" target runs the "check" target, which requires these separate tools: * https://github.com/davepacheco/jsstyle * https://github.com/davepacheco/javascriptlint If you're changing something non-trivial or user-facing, you may want to submit an issue first. node-verror-1.10.0/LICENSE000066400000000000000000000020651307545425100150510ustar00rootroot00000000000000Copyright (c) 2016, Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE node-verror-1.10.0/Makefile000066400000000000000000000011701307545425100155000ustar00rootroot00000000000000# # Copyright (c) 2016, Joyent, Inc. All rights reserved. # # Makefile: top-level Makefile # # This Makefile contains only repo-specific logic and uses included makefiles # to supply common targets (javascriptlint, jsstyle, restdown, etc.), which are # used by other repos as well. # # # Tools # CATEST = deps/catest/catest NPM = npm # # Files # JS_FILES := $(shell find lib examples test -name '*.js') JSL_FILES_NODE = $(JS_FILES) JSSTYLE_FILES = $(JS_FILES) JSL_CONF_NODE = jsl.node.conf .PHONY: all all: $(NPM) install .PHONY: test test: $(CATEST) $(CATEST) -a $(CATEST): deps/catest/.git include ./Makefile.targ node-verror-1.10.0/Makefile.targ000066400000000000000000000225121307545425100164370ustar00rootroot00000000000000# -*- mode: makefile -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # # Copyright (c) 2014, Joyent, Inc. # # # Makefile.targ: common targets. # # NOTE: This makefile comes from the "eng" repo. It's designed to be dropped # into other repos as-is without requiring any modifications. If you find # yourself changing this file, you should instead update the original copy in # eng.git and then update your repo to use the new version. # # This Makefile defines several useful targets and rules. You can use it by # including it from a Makefile that specifies some of the variables below. # # Targets defined in this Makefile: # # check Checks JavaScript files for lint and style # Checks bash scripts for syntax # Checks SMF manifests for validity against the SMF DTD # # clean Removes built files # # docs Builds restdown documentation in docs/ # # prepush Depends on "check" and "test" # # test Does nothing (you should override this) # # xref Generates cscope (source cross-reference index) # # For details on what these targets are supposed to do, see the Joyent # Engineering Guide. # # To make use of these targets, you'll need to set some of these variables. Any # variables left unset will simply not be used. # # BASH_FILES Bash scripts to check for syntax # (paths relative to top-level Makefile) # # CLEAN_FILES Files to remove as part of the "clean" target. Note # that files generated by targets in this Makefile are # automatically included in CLEAN_FILES. These include # restdown-generated HTML and JSON files. # # DOC_FILES Restdown (documentation source) files. These are # assumed to be contained in "docs/", and must NOT # contain the "docs/" prefix. # # JSL_CONF_NODE Specify JavaScriptLint configuration files # JSL_CONF_WEB (paths relative to top-level Makefile) # # Node.js and Web configuration files are separate # because you'll usually want different global variable # configurations. If no file is specified, none is given # to jsl, which causes it to use a default configuration, # which probably isn't what you want. # # JSL_FILES_NODE JavaScript files to check with Node config file. # JSL_FILES_WEB JavaScript files to check with Web config file. # # JSON_FILES JSON files to be validated # # JSSTYLE_FILES JavaScript files to be style-checked # # You can also override these variables: # # BASH Path to bash (default: "bash") # # CSCOPE_DIRS Directories to search for source files for the cscope # index. (default: ".") # # JSL Path to JavaScriptLint (default: "jsl") # # JSL_FLAGS_NODE Additional flags to pass through to JSL # JSL_FLAGS_WEB # JSL_FLAGS # # JSON Path to json tool (default: "json") # # JSSTYLE Path to jsstyle (default: "jsstyle") # # JSSTYLE_FLAGS Additional flags to pass through to jsstyle # # RESTDOWN_EXT By default '.restdown' is required for DOC_FILES # (see above). If you want to use, say, '.md' instead, then # set 'RESTDOWN_EXT=.md' in your Makefile. # # # Defaults for the various tools we use. # BASH ?= bash BASHSTYLE ?= tools/bashstyle CP ?= cp CSCOPE ?= cscope CSCOPE_DIRS ?= . JSL ?= jsl JSON ?= json JSSTYLE ?= jsstyle MKDIR ?= mkdir -p MV ?= mv RESTDOWN_FLAGS ?= RESTDOWN_EXT ?= .restdown RMTREE ?= rm -rf JSL_FLAGS ?= --nologo --nosummary ifeq ($(shell uname -s),SunOS) TAR ?= gtar else TAR ?= tar endif # # Defaults for other fixed values. # BUILD = build DISTCLEAN_FILES += $(BUILD) DOC_BUILD = $(BUILD)/docs/public # # Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}. # ifneq ($(origin JSL_CONF_NODE), undefined) JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE) endif ifneq ($(origin JSL_CONF_WEB), undefined) JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB) endif # # Targets. For descriptions on what these are supposed to do, see the # Joyent Engineering Guide. # # # Instruct make to keep around temporary files. We have rules below that # automatically update git submodules as needed, but they employ a deps/*/.git # temporary file. Without this directive, make tries to remove these .git # directories after the build has completed. # .SECONDARY: $($(wildcard deps/*):%=%/.git) # # This rule enables other rules that use files from a git submodule to have # those files depend on deps/module/.git and have "make" automatically check # out the submodule as needed. # deps/%/.git: git submodule update --init deps/$* # # These recipes make heavy use of dynamically-created phony targets. The parent # Makefile defines a list of input files like BASH_FILES. We then say that each # of these files depends on a fake target called filename.bashchk, and then we # define a pattern rule for those targets that runs bash in check-syntax-only # mode. This mechanism has the nice properties that if you specify zero files, # the rule becomes a noop (unlike a single rule to check all bash files, which # would invoke bash with zero files), and you can check individual files from # the command line with "make filename.bashchk". # .PHONY: check-bash check-bash: $(BASH_FILES:%=%.bashchk) $(BASH_FILES:%=%.bashstyle) %.bashchk: % $(BASH) -n $^ %.bashstyle: % $(BASHSTYLE) $^ .PHONY: check-json check-json: $(JSON_FILES:%=%.jsonchk) %.jsonchk: % $(JSON) --validate -f $^ # # The above approach can be slow when there are many files to check because it # requires that "make" invoke the check tool once for each file, rather than # passing in several files at once. For the JavaScript check targets, we define # a variable for the target itself *only if* the list of input files is # non-empty. This avoids invoking the tool if there are no files to check. # JSL_NODE_TARGET = $(if $(JSL_FILES_NODE), check-jsl-node) .PHONY: check-jsl-node check-jsl-node: $(JSL_EXEC) $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $(JSL_FILES_NODE) JSL_WEB_TARGET = $(if $(JSL_FILES_WEB), check-jsl-web) .PHONY: check-jsl-web check-jsl-web: $(JSL_EXEC) $(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $(JSL_FILES_WEB) .PHONY: check-jsl check-jsl: $(JSL_NODE_TARGET) $(JSL_WEB_TARGET) JSSTYLE_TARGET = $(if $(JSSTYLE_FILES), check-jsstyle) .PHONY: check-jsstyle check-jsstyle: $(JSSTYLE_EXEC) $(JSSTYLE) $(JSSTYLE_FLAGS) $(JSSTYLE_FILES) .PHONY: check check: check-jsl check-json $(JSSTYLE_TARGET) check-bash @echo check ok .PHONY: clean clean:: -$(RMTREE) $(CLEAN_FILES) .PHONY: distclean distclean:: clean -$(RMTREE) $(DISTCLEAN_FILES) CSCOPE_FILES = cscope.in.out cscope.out cscope.po.out CLEAN_FILES += $(CSCOPE_FILES) .PHONY: xref xref: cscope.files $(CSCOPE) -bqR .PHONY: cscope.files cscope.files: find $(CSCOPE_DIRS) -name '*.c' -o -name '*.h' -o -name '*.cc' \ -o -name '*.js' -o -name '*.s' -o -name '*.cpp' > $@ # # The "docs" target is complicated because we do several things here: # # (1) Use restdown to build HTML and JSON files from each of DOC_FILES. # # (2) Copy these files into $(DOC_BUILD) (build/docs/public), which # functions as a complete copy of the documentation that could be # mirrored or served over HTTP. # # (3) Then copy any directories and media from docs/media into # $(DOC_BUILD)/media. This allows projects to include their own media, # including files that will override same-named files provided by # restdown. # # Step (3) is the surprisingly complex part: in order to do this, we need to # identify the subdirectories in docs/media, recreate them in # $(DOC_BUILD)/media, then do the same with the files. # DOC_MEDIA_DIRS := $(shell find docs/media -type d 2>/dev/null | grep -v "^docs/media$$") DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/media/%=%) DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%) DOC_MEDIA_FILES := $(shell find docs/media -type f 2>/dev/null) DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%) DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%) # # Like the other targets, "docs" just depends on the final files we want to # create in $(DOC_BUILD), leveraging other targets and recipes to define how # to get there. # .PHONY: docs docs: \ $(DOC_FILES:%$(RESTDOWN_EXT)=$(DOC_BUILD)/%.html) \ $(DOC_FILES:%$(RESTDOWN_EXT)=$(DOC_BUILD)/%.json) \ $(DOC_MEDIA_FILES_BUILD) # # We keep the intermediate files so that the next build can see whether the # files in DOC_BUILD are up to date. # .PRECIOUS: \ $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.html) \ $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%json) # # We do clean those intermediate files, as well as all of DOC_BUILD. # CLEAN_FILES += \ $(DOC_BUILD) \ $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.html) \ $(DOC_FILES:%$(RESTDOWN_EXT)=docs/%.json) # # Before installing the files, we must make sure the directories exist. The | # syntax tells make that the dependency need only exist, not be up to date. # Otherwise, it might try to rebuild spuriously because the directory itself # appears out of date. # $(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD) $(DOC_BUILD)/%: docs/% | $(DOC_BUILD) $(CP) $< $@ docs/%.json docs/%.html: docs/%$(RESTDOWN_EXT) | $(DOC_BUILD) $(RESTDOWN_EXEC) $(RESTDOWN) $(RESTDOWN_FLAGS) -m $(DOC_BUILD) $< $(DOC_BUILD): $(MKDIR) $@ $(DOC_MEDIA_DIRS_BUILD): $(MKDIR) $@ # # The default "test" target does nothing. This should usually be overridden by # the parent Makefile. It's included here so we can define "prepush" without # requiring the repo to define "test". # .PHONY: test test: .PHONY: prepush prepush: check test node-verror-1.10.0/README.md000066400000000000000000000512031307545425100153210ustar00rootroot00000000000000# verror: rich JavaScript errors This module provides several classes in support of Joyent's [Best Practices for Error Handling in Node.js](http://www.joyent.com/developers/node/design/errors). If you find any of the behavior here confusing or surprising, check out that document first. The error classes here support: * printf-style arguments for the message * chains of causes * properties to provide extra information about the error * creating your own subclasses that support all of these The classes here are: * **VError**, for chaining errors while preserving each one's error message. This is useful in servers and command-line utilities when you want to propagate an error up a call stack, but allow various levels to add their own context. See examples below. * **WError**, for wrapping errors while hiding the lower-level messages from the top-level error. This is useful for API endpoints where you don't want to expose internal error messages, but you still want to preserve the error chain for logging and debugging. * **SError**, which is just like VError but interprets printf-style arguments more strictly. * **MultiError**, which is just an Error that encapsulates one or more other errors. (This is used for parallel operations that return several errors.) # Quick start First, install the package: npm install verror If nothing else, you can use VError as a drop-in replacement for the built-in JavaScript Error class, with the addition of printf-style messages: ```javascript var err = new VError('missing file: "%s"', '/etc/passwd'); console.log(err.message); ``` This prints: missing file: "/etc/passwd" You can also pass a `cause` argument, which is any other Error object: ```javascript var fs = require('fs'); var filename = '/nonexistent'; fs.stat(filename, function (err1) { var err2 = new VError(err1, 'stat "%s"', filename); console.error(err2.message); }); ``` This prints out: stat "/nonexistent": ENOENT, stat '/nonexistent' which resembles how Unix programs typically report errors: $ sort /nonexistent sort: open failed: /nonexistent: No such file or directory To match the Unixy feel, when you print out the error, just prepend the program's name to the VError's `message`. Or just call [node-cmdutil.fail(your_verror)](https://github.com/joyent/node-cmdutil), which does this for you. You can get the next-level Error using `err.cause()`: ```javascript console.error(err2.cause().message); ``` prints: ENOENT, stat '/nonexistent' Of course, you can chain these as many times as you want, and it works with any kind of Error: ```javascript var err1 = new Error('No such file or directory'); var err2 = new VError(err1, 'failed to stat "%s"', '/junk'); var err3 = new VError(err2, 'request failed'); console.error(err3.message); ``` This prints: request failed: failed to stat "/junk": No such file or directory The idea is that each layer in the stack annotates the error with a description of what it was doing. The end result is a message that explains what happened at each level. You can also decorate Error objects with additional information so that callers can not only handle each kind of error differently, but also construct their own error messages (e.g., to localize them, format them, group them by type, and so on). See the example below. # Deeper dive The two main goals for VError are: * **Make it easy to construct clear, complete error messages intended for people.** Clear error messages greatly improve both user experience and debuggability, so we wanted to make it easy to build them. That's why the constructor takes printf-style arguments. * **Make it easy to construct objects with programmatically-accessible metadata** (which we call _informational properties_). Instead of just saying "connection refused while connecting to 192.168.1.2:80", you can add properties like `"ip": "192.168.1.2"` and `"tcpPort": 80`. This can be used for feeding into monitoring systems, analyzing large numbers of Errors (as from a log file), or localizing error messages. To really make this useful, it also needs to be easy to compose Errors: higher-level code should be able to augment the Errors reported by lower-level code to provide a more complete description of what happened. Instead of saying "connection refused", you can say "operation X failed: connection refused". That's why VError supports `causes`. In order for all this to work, programmers need to know that it's generally safe to wrap lower-level Errors with higher-level ones. If you have existing code that handles Errors produced by a library, you should be able to wrap those Errors with a VError to add information without breaking the error handling code. There are two obvious ways that this could break such consumers: * The error's name might change. People typically use `name` to determine what kind of Error they've got. To ensure compatibility, you can create VErrors with custom names, but this approach isn't great because it prevents you from representing complex failures. For this reason, VError provides `findCauseByName`, which essentially asks: does this Error _or any of its causes_ have this specific type? If error handling code uses `findCauseByName`, then subsystems can construct very specific causal chains for debuggability and still let people handle simple cases easily. There's an example below. * The error's properties might change. People often hang additional properties off of Error objects. If we wrap an existing Error in a new Error, those properties would be lost unless we copied them. But there are a variety of both standard and non-standard Error properties that should _not_ be copied in this way: most obviously `name`, `message`, and `stack`, but also `fileName`, `lineNumber`, and a few others. Plus, it's useful for some Error subclasses to have their own private properties -- and there'd be no way to know whether these should be copied. For these reasons, VError first-classes these information properties. You have to provide them in the constructor, you can only fetch them with the `info()` function, and VError takes care of making sure properties from causes wind up in the `info()` output. Let's put this all together with an example from the node-fast RPC library. node-fast implements a simple RPC protocol for Node programs. There's a server and client interface, and clients make RPC requests to servers. Let's say the server fails with an UnauthorizedError with message "user 'bob' is not authorized". The client wraps all server errors with a FastServerError. The client also wraps all request errors with a FastRequestError that includes the name of the RPC call being made. The result of this failed RPC might look like this: name: FastRequestError message: "request failed: server error: user 'bob' is not authorized" rpcMsgid: rpcMethod: GetObject cause: name: FastServerError message: "server error: user 'bob' is not authorized" cause: name: UnauthorizedError message: "user 'bob' is not authorized" rpcUser: "bob" When the caller uses `VError.info()`, the information properties are collapsed so that it looks like this: message: "request failed: server error: user 'bob' is not authorized" rpcMsgid: rpcMethod: GetObject rpcUser: "bob" Taking this apart: * The error's message is a complete description of the problem. The caller can report this directly to its caller, which can potentially make its way back to an end user (if appropriate). It can also be logged. * The caller can tell that the request failed on the server, rather than as a result of a client problem (e.g., failure to serialize the request), a transport problem (e.g., failure to connect to the server), or something else (e.g., a timeout). They do this using `findCauseByName('FastServerError')` rather than checking the `name` field directly. * If the caller logs this error, the logs can be analyzed to aggregate errors by cause, by RPC method name, by user, or whatever. Or the error can be correlated with other events for the same rpcMsgid. * It wasn't very hard for any part of the code to contribute to this Error. Each part of the stack has just a few lines to provide exactly what it knows, with very little boilerplate. It's not expected that you'd use these complex forms all the time. Despite supporting the complex case above, you can still just do: new VError("my service isn't working"); for the simple cases. # Reference: VError, WError, SError VError, WError, and SError are convenient drop-in replacements for `Error` that support printf-style arguments, first-class causes, informational properties, and other useful features. ## Constructors The VError constructor has several forms: ```javascript /* * This is the most general form. You can specify any supported options * (including "cause" and "info") this way. */ new VError(options, sprintf_args...) /* * This is a useful shorthand when the only option you need is "cause". */ new VError(cause, sprintf_args...) /* * This is a useful shorthand when you don't need any options at all. */ new VError(sprintf_args...) ``` All of these forms construct a new VError that behaves just like the built-in JavaScript `Error` class, with some additional methods described below. In the first form, `options` is a plain object with any of the following optional properties: Option name | Type | Meaning ---------------- | ---------------- | ------- `name` | string | Describes what kind of error this is. This is intended for programmatic use to distinguish between different kinds of errors. Note that in modern versions of Node.js, this name is ignored in the `stack` property value, but callers can still use the `name` property to get at it. `cause` | any Error object | Indicates that the new error was caused by `cause`. See `cause()` below. If unspecified, the cause will be `null`. `strict` | boolean | If true, then `null` and `undefined` values in `sprintf_args` are passed through to `sprintf()`. Otherwise, these are replaced with the strings `'null'`, and '`undefined`', respectively. `constructorOpt` | function | If specified, then the stack trace for this error ends at function `constructorOpt`. Functions called by `constructorOpt` will not show up in the stack. This is useful when this class is subclassed. `info` | object | Specifies arbitrary informational properties that are available through the `VError.info(err)` static class method. See that method for details. The second form is equivalent to using the first form with the specified `cause` as the error's cause. This form is distinguished from the first form because the first argument is an Error. The third form is equivalent to using the first form with all default option values. This form is distinguished from the other forms because the first argument is not an object or an Error. The `WError` constructor is used exactly the same way as the `VError` constructor. The `SError` constructor is also used the same way as the `VError` constructor except that in all cases, the `strict` property is overriden to `true. ## Public properties `VError`, `WError`, and `SError` all provide the same public properties as JavaScript's built-in Error objects. Property name | Type | Meaning ------------- | ------ | ------- `name` | string | Programmatically-usable name of the error. `message` | string | Human-readable summary of the failure. Programmatically-accessible details are provided through `VError.info(err)` class method. `stack` | string | Human-readable stack trace where the Error was constructed. For all of these classes, the printf-style arguments passed to the constructor are processed with `sprintf()` to form a message. For `WError`, this becomes the complete `message` property. For `SError` and `VError`, this message is prepended to the message of the cause, if any (with a suitable separator), and the result becomes the `message` property. The `stack` property is managed entirely by the underlying JavaScript implementation. It's generally implemented using a getter function because constructing the human-readable stack trace is somewhat expensive. ## Class methods The following methods are defined on the `VError` class and as exported functions on the `verror` module. They're defined this way rather than using methods on VError instances so that they can be used on Errors not created with `VError`. ### `VError.cause(err)` The `cause()` function returns the next Error in the cause chain for `err`, or `null` if there is no next error. See the `cause` argument to the constructor. Errors can have arbitrarily long cause chains. You can walk the `cause` chain by invoking `VError.cause(err)` on each subsequent return value. If `err` is not a `VError`, the cause is `null`. ### `VError.info(err)` Returns an object with all of the extra error information that's been associated with this Error and all of its causes. These are the properties passed in using the `info` option to the constructor. Properties not specified in the constructor for this Error are implicitly inherited from this error's cause. These properties are intended to provide programmatically-accessible metadata about the error. For an error that indicates a failure to resolve a DNS name, informational properties might include the DNS name to be resolved, or even the list of resolvers used to resolve it. The values of these properties should generally be plain objects (i.e., consisting only of null, undefined, numbers, booleans, strings, and objects and arrays containing only other plain objects). ### `VError.fullStack(err)` Returns a string containing the full stack trace, with all nested errors recursively reported as `'caused by:' + err.stack`. ### `VError.findCauseByName(err, name)` The `findCauseByName()` function traverses the cause chain for `err`, looking for an error whose `name` property matches the passed in `name` value. If no match is found, `null` is returned. If all you want is to know _whether_ there's a cause (and you don't care what it is), you can use `VError.hasCauseWithName(err, name)`. If a vanilla error or a non-VError error is passed in, then there is no cause chain to traverse. In this scenario, the function will check the `name` property of only `err`. ### `VError.hasCauseWithName(err, name)` Returns true if and only if `VError.findCauseByName(err, name)` would return a non-null value. This essentially determines whether `err` has any cause in its cause chain that has name `name`. ### `VError.errorFromList(errors)` Given an array of Error objects (possibly empty), return a single error representing the whole collection of errors. If the list has: * 0 elements, returns `null` * 1 element, returns the sole error * more than 1 element, returns a MultiError referencing the whole list This is useful for cases where an operation may produce any number of errors, and you ultimately want to implement the usual `callback(err)` pattern. You can accumulate the errors in an array and then invoke `callback(VError.errorFromList(errors))` when the operation is complete. ### `VError.errorForEach(err, func)` Convenience function for iterating an error that may itself be a MultiError. In all cases, `err` must be an Error. If `err` is a MultiError, then `func` is invoked as `func(errorN)` for each of the underlying errors of the MultiError. If `err` is any other kind of error, `func` is invoked once as `func(err)`. In all cases, `func` is invoked synchronously. This is useful for cases where an operation may produce any number of warnings that may be encapsulated with a MultiError -- but may not be. This function does not iterate an error's cause chain. ## Examples The "Demo" section above covers several basic cases. Here's a more advanced case: ```javascript var err1 = new VError('something bad happened'); /* ... */ var err2 = new VError({ 'name': 'ConnectionError', 'cause': err1, 'info': { 'errno': 'ECONNREFUSED', 'remote_ip': '127.0.0.1', 'port': 215 } }, 'failed to connect to "%s:%d"', '127.0.0.1', 215); console.log(err2.message); console.log(err2.name); console.log(VError.info(err2)); console.log(err2.stack); ``` This outputs: failed to connect to "127.0.0.1:215": something bad happened ConnectionError { errno: 'ECONNREFUSED', remote_ip: '127.0.0.1', port: 215 } ConnectionError: failed to connect to "127.0.0.1:215": something bad happened at Object. (/home/dap/node-verror/examples/info.js:5:12) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Function.Module.runMain (module.js:497:10) at startup (node.js:119:16) at node.js:935:3 Information properties are inherited up the cause chain, with values at the top of the chain overriding same-named values lower in the chain. To continue that example: ```javascript var err3 = new VError({ 'name': 'RequestError', 'cause': err2, 'info': { 'errno': 'EBADREQUEST' } }, 'request failed'); console.log(err3.message); console.log(err3.name); console.log(VError.info(err3)); console.log(err3.stack); ``` This outputs: request failed: failed to connect to "127.0.0.1:215": something bad happened RequestError { errno: 'EBADREQUEST', remote_ip: '127.0.0.1', port: 215 } RequestError: request failed: failed to connect to "127.0.0.1:215": something bad happened at Object. (/home/dap/node-verror/examples/info.js:20:12) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Function.Module.runMain (module.js:497:10) at startup (node.js:119:16) at node.js:935:3 You can also print the complete stack trace of combined `Error`s by using `VError.fullStack(err).` ```javascript var err1 = new VError('something bad happened'); /* ... */ var err2 = new VError(err1, 'something really bad happened here'); console.log(VError.fullStack(err2)); ``` This outputs: VError: something really bad happened here: something bad happened at Object. (/home/dap/node-verror/examples/fullStack.js:5:12) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:968:3 caused by: VError: something bad happened at Object. (/home/dap/node-verror/examples/fullStack.js:3:12) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:968:3 `VError.fullStack` is also safe to use on regular `Error`s, so feel free to use it whenever you need to extract the stack trace from an `Error`, regardless if it's a `VError` or not. # Reference: MultiError MultiError is an Error class that represents a group of Errors. This is used when you logically need to provide a single Error, but you want to preserve information about multiple underying Errors. A common case is when you execute several operations in parallel and some of them fail. MultiErrors are constructed as: ```javascript new MultiError(error_list) ``` `error_list` is an array of at least one `Error` object. The cause of the MultiError is the first error provided. None of the other `VError` options are supported. The `message` for a MultiError consists the `message` from the first error, prepended with a message indicating that there were other errors. For example: ```javascript err = new MultiError([ new Error('failed to resolve DNS name "abc.example.com"'), new Error('failed to resolve DNS name "def.example.com"'), ]); console.error(err.message); ``` outputs: first of 2 errors: failed to resolve DNS name "abc.example.com" See the convenience function `VError.errorFromList`, which is sometimes simpler to use than this constructor. ## Public methods ### `errors()` Returns an array of the errors used to construct this MultiError. # Contributing See separate [contribution guidelines](CONTRIBUTING.md). node-verror-1.10.0/deps/000077500000000000000000000000001307545425100147745ustar00rootroot00000000000000node-verror-1.10.0/deps/catest/000077500000000000000000000000001307545425100162575ustar00rootroot00000000000000node-verror-1.10.0/examples/000077500000000000000000000000001307545425100156575ustar00rootroot00000000000000node-verror-1.10.0/examples/fullStack.js000066400000000000000000000003141307545425100201430ustar00rootroot00000000000000var VError = require('../lib/verror'); var err1 = new VError('something bad happened'); /* ... */ var err2 = new VError(err1, 'something really bad happened here'); console.log(VError.fullStack(err2)); node-verror-1.10.0/examples/info.js000066400000000000000000000012351307545425100171510ustar00rootroot00000000000000var VError = require('../lib/verror'); var err1 = new VError('something bad happened'); /* ... */ var err2 = new VError({ 'name': 'ConnectionError', 'cause': err1, 'info': { 'errno': 'ECONNREFUSED', 'remote_ip': '127.0.0.1', 'port': 215 } }, 'failed to connect to "%s:%d"', '127.0.0.1', 215); console.log(err2.message); console.log(err2.name); console.log(VError.info(err2)); console.log(err2.stack); var err3 = new VError({ 'name': 'RequestError', 'cause': err2, 'info': { 'errno': 'EBADREQUEST' } }, 'request failed'); console.log(err3.message); console.log(err3.name); console.log(VError.info(err3)); console.log(err3.stack); node-verror-1.10.0/examples/levels-verror.js000066400000000000000000000014121307545425100210220ustar00rootroot00000000000000var extsprintf = require('extsprintf'); var fs = require('fs'); var VError = require('../lib/verror'); function checkFile(filename, callback) { fs.stat(filename, function (err) { if (err) /* Annotate the "stat" error with what we were doing. */ return (callback(new VError(err, 'failed to check "%s"', filename))); /* ... */ return (callback()); }); } function handleRequest(filename, callback) { checkFile('/nonexistent', function (err) { if (err) /* Annotate the "checkFile" error. */ return (callback(new VError( err, 'request failed'))); /* ... */ return (callback()); }); } handleRequest('/nonexistent', function (err) { if (err) { console.log(err.message); console.log(extsprintf.sprintf('%r', err)); } /* ... */ }); node-verror-1.10.0/examples/levels-werror.js000066400000000000000000000013621307545425100210270ustar00rootroot00000000000000var extsprintf = require('extsprintf'); var fs = require('fs'); var VError = require('../lib/verror'); function checkFile(filename, callback) { fs.stat(filename, function (err) { if (err) /* Annotate the "stat" error with what we were doing. */ return (callback(new VError(err, 'failed to check "%s"', filename))); /* ... */ return (callback()); }); } function handleRequest(filename, callback) { checkFile('/nonexistent', function (err) { if (err) /* Wrap the "checkFile" error. */ return (callback(new VError.WError( err, 'request failed'))); /* ... */ return (callback()); }); } handleRequest('/nonexistent', function (err) { if (err) { console.log(err.message); console.log(err.toString()); } }); node-verror-1.10.0/examples/multierror.js000066400000000000000000000003571307545425100204260ustar00rootroot00000000000000var MultiError = require('../lib/verror').MultiError; var err = new MultiError([ new Error('failed to resolve DNS name "abc.example.com"'), new Error('failed to resolve DNS name "def.example.com"') ]); console.error(err.message); node-verror-1.10.0/examples/nested.js000066400000000000000000000003431307545425100174770ustar00rootroot00000000000000var VError = require('../lib/verror'); var err1 = new Error('No such file or directory'); var err2 = new VError(err1, 'failed to stat "%s"', '/junk'); var err3 = new VError(err2, 'request failed'); console.error(err3.message); node-verror-1.10.0/examples/varargs.js000066400000000000000000000002461307545425100176640ustar00rootroot00000000000000var VError = require('../lib/verror'); var opname = 'read'; var err = new VError('"%s" operation failed', opname); console.log(err.message); console.log(err.stack); node-verror-1.10.0/examples/verror.js000066400000000000000000000004071307545425100175350ustar00rootroot00000000000000var fs = require('fs'); var VError = require('../lib/verror'); var filename = '/nonexistent'; fs.stat(filename, function (err1) { var err2 = new VError(err1, 'stat "%s" failed', filename); console.error(err2.message); console.error(err2.cause().message); }); node-verror-1.10.0/examples/werror.js000066400000000000000000000006651307545425100175440ustar00rootroot00000000000000var mod_fs = require('fs'); var mod_verror = require('../lib/verror'); var filename = '/nonexistent'; mod_fs.stat(filename, function (err1) { var err2 = new mod_verror.WError(err1, 'failed to stat "%s"', filename); /* The following would normally be higher up the stack. */ var err3 = new mod_verror.WError(err2, 'failed to handle request'); console.log(err3.message); console.log(err3.toString()); console.log(err3.stack); }); node-verror-1.10.0/experiments/000077500000000000000000000000001307545425100164045ustar00rootroot00000000000000node-verror-1.10.0/experiments/test-error-properties.js000066400000000000000000000056331307545425100232510ustar00rootroot00000000000000/* * This program attempts to determine what's possible with Node.js Error * objects, particularly around the properties we'd like to have: * * - "name" property can be set and read * - "name" property appears correct in toString() * - "message" property can be set and read * - "message" property appears correct in toString() * - instanceof Error is true * - ... even for second- and third-level subclasses * - instanceof is true for each parent class * - "stack" exists * - "stack" is a lazy property * - "stack" is correct (shows the right stack trace) * - other properties can be added * * In both v0.10.28 and v0.11.14-pre, the "err.name" and "err.message" * properties can be set both before and after fetching "err.stack", and their * values are always correct in err.toString(). * * In v0.10.28, the values of "err.name" and "err.message" as of the *first* * time "err.stack" is accessed are immortalized in the "err.stack" value. As a * result, if you set "err.name" and "err.message" in subclass constructors, we * should be fine. * * In v0.11.14-pre, the initial values of "err.name" and "err.message" are * immortalized in the "err.stack" value, so if these are changed after * construction, "err.stack" will always refer to the constructor name and * initial message. This is unfortunate, but probably also not a big deal. */ var VError = require('../lib/verror'); var errorname = 'OtherName'; var message = 'my sample error'; var omessage = 'other error message'; function main() { console.log('node %s', process.version); runBattery(Error); console.log('==============================='); runBattery(VError); } function runBattery(klass) { var name, error; name = klass.name; error = new klass(message); printErrorInfo(name, 'simple', error); error.name = errorname; printErrorInfo(name, 'changed "name" after fetching stack', error); error = new klass(message); error.name = errorname; printErrorInfo(name, 'changed "name" before fetching stack', error); error = new klass(message); error.message = omessage; printErrorInfo(name, 'changed "message" before fetching stack', error); error.message = message; printErrorInfo(name, 'changed "message" back after fetching stack', error); error = new klass(message); error.otherprop = 'otherpropvalue'; printErrorInfo(name, 'with "otherprop" property', error); } function printErrorInfo(classname, label, err) { console.log('------------------'); console.log('test: %s, %s', classname, label); console.log('instanceof Error: %s', err instanceof Error); console.log('constructor: %s', err.constructor.name); console.log('error name: %s', err.name); console.log('error message: %s', err.message); console.log('error toString: %s', err.toString()); console.log('has "otherprop": %s', err.hasOwnProperty('otherprop')); console.log('error stack: %s', err.stack); console.log('inspect: ', err); } main(); node-verror-1.10.0/jsl.node.conf000066400000000000000000000155721307545425100164360ustar00rootroot00000000000000# # Configuration File for JavaScript Lint # # This configuration file can be used to lint a collection of scripts, or to enable # or disable warnings for scripts that are linted via the command line. # ### Warnings # Enable or disable warnings based on requirements. # Use "+WarningName" to display or "-WarningName" to suppress. # +ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent +ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity +ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement +anon_no_return_value # anonymous function does not always return value +assign_to_function_call # assignment to a function call -block_without_braces # block statement without curly braces +comma_separated_stmts # multiple statements separated by commas (use semicolons?) +comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) +default_not_at_end # the default case is not at the end of the switch statement +dup_option_explicit # duplicate "option explicit" control comment +duplicate_case_in_switch # duplicate case in switch statement +duplicate_formal # duplicate formal argument {name} +empty_statement # empty statement or extra semicolon +identifier_hides_another # identifer {name} hides an identifier in a parent scope -inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement +incorrect_version # Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version. +invalid_fallthru # unexpected "fallthru" control comment +invalid_pass # unexpected "pass" control comment +jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax +leading_decimal_point # leading decimal point may indicate a number or an object member +legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax +meaningless_block # meaningless block; curly braces have no impact +mismatch_ctrl_comments # mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence +misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma +missing_break # missing break statement +missing_break_for_last_case # missing break statement for last case in switch +missing_default_case # missing default case in switch statement +missing_option_explicit # the "option explicit" control comment is missing +missing_semicolon # missing semicolon +missing_semicolon_for_lambda # missing semicolon for lambda assignment +multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs +nested_comment # nested comment +no_return_value # function {name} does not always return a value +octal_number # leading zeros make an octal number +parseint_missing_radix # parseInt missing radix parameter +partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag +redeclared_var # redeclaration of {name} +trailing_comma_in_array # extra comma is not recommended in array initializers +trailing_decimal_point # trailing decimal point may indicate a number or an object member +undeclared_identifier # undeclared identifier: {name} +unreachable_code # unreachable code -unreferenced_argument # argument declared but never referenced: {name} -unreferenced_function # function is declared but never referenced: {name} +unreferenced_variable # variable is declared but never referenced: {name} +unsupported_version # JavaScript {version} is not supported +use_of_label # use of label +useless_assign # useless assignment +useless_comparison # useless comparison; comparing identical expressions -useless_quotes # the quotation marks are unnecessary +useless_void # use of the void type may be unnecessary (void is always undefined) +var_hides_arg # variable {name} hides argument +want_assign_or_call # expected an assignment or function call +with_statement # with statement hides undeclared variables; use temporary variable instead ### Output format # Customize the format of the error message. # __FILE__ indicates current file path # __FILENAME__ indicates current file name # __LINE__ indicates current line # __COL__ indicates current column # __ERROR__ indicates error message (__ERROR_PREFIX__: __ERROR_MSG__) # __ERROR_NAME__ indicates error name (used in configuration file) # __ERROR_PREFIX__ indicates error prefix # __ERROR_MSG__ indicates error message # # For machine-friendly output, the output format can be prefixed with # "encode:". If specified, all items will be encoded with C-slashes. # # Visual Studio syntax (default): +output-format __FILE__(__LINE__): __ERROR__ # Alternative syntax: #+output-format __FILE__:__LINE__: __ERROR__ ### Context # Show the in-line position of the error. # Use "+context" to display or "-context" to suppress. # +context ### Control Comments # Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for # the /*@keyword@*/ control comments and JScript conditional comments. (The latter is # enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason, # although legacy control comments are enabled by default for backward compatibility. # -legacy_control_comments ### Defining identifiers # By default, "option explicit" is enabled on a per-file basis. # To enable this for all files, use "+always_use_option_explicit" -always_use_option_explicit # Define certain identifiers of which the lint is not aware. # (Use this in conjunction with the "undeclared identifier" warning.) # # Common uses for webpages might be: +define __dirname +define clearInterval +define clearTimeout +define console +define exports +define global +define module +define process +define require +define setInterval +define setTimeout +define Buffer +define JSON +define Math +define __dirname +define __filename ### JavaScript Version # To change the default JavaScript version: #+default-type text/javascript;version=1.5 #+default-type text/javascript;e4x=1 ### Files # Specify which files to lint # Use "+recurse" to enable recursion (disabled by default). # To add a set of files, use "+process FileName", "+process Folder\Path\*.js", # or "+process Folder\Path\*.htm". # node-verror-1.10.0/lib/000077500000000000000000000000001307545425100146075ustar00rootroot00000000000000node-verror-1.10.0/lib/verror.js000066400000000000000000000271311307545425100164700ustar00rootroot00000000000000/* * verror.js: richer JavaScript errors */ var mod_assertplus = require('assert-plus'); var mod_util = require('util'); var mod_extsprintf = require('extsprintf'); var mod_isError = require('core-util-is').isError; var sprintf = mod_extsprintf.sprintf; /* * Public interface */ /* So you can 'var VError = require('verror')' */ module.exports = VError; /* For compatibility */ VError.VError = VError; /* Other exported classes */ VError.SError = SError; VError.WError = WError; VError.MultiError = MultiError; /* * Common function used to parse constructor arguments for VError, WError, and * SError. Named arguments to this function: * * strict force strict interpretation of sprintf arguments, even * if the options in "argv" don't say so * * argv error's constructor arguments, which are to be * interpreted as described in README.md. For quick * reference, "argv" has one of the following forms: * * [ sprintf_args... ] (argv[0] is a string) * [ cause, sprintf_args... ] (argv[0] is an Error) * [ options, sprintf_args... ] (argv[0] is an object) * * This function normalizes these forms, producing an object with the following * properties: * * options equivalent to "options" in third form. This will never * be a direct reference to what the caller passed in * (i.e., it may be a shallow copy), so it can be freely * modified. * * shortmessage result of sprintf(sprintf_args), taking options.strict * into account as described in README.md. */ function parseConstructorArguments(args) { var argv, options, sprintf_args, shortmessage, k; mod_assertplus.object(args, 'args'); mod_assertplus.bool(args.strict, 'args.strict'); mod_assertplus.array(args.argv, 'args.argv'); argv = args.argv; /* * First, figure out which form of invocation we've been given. */ if (argv.length === 0) { options = {}; sprintf_args = []; } else if (mod_isError(argv[0])) { options = { 'cause': argv[0] }; sprintf_args = argv.slice(1); } else if (typeof (argv[0]) === 'object') { options = {}; for (k in argv[0]) { options[k] = argv[0][k]; } sprintf_args = argv.slice(1); } else { mod_assertplus.string(argv[0], 'first argument to VError, SError, or WError ' + 'constructor must be a string, object, or Error'); options = {}; sprintf_args = argv; } /* * Now construct the error's message. * * extsprintf (which we invoke here with our caller's arguments in order * to construct this Error's message) is strict in its interpretation of * values to be processed by the "%s" specifier. The value passed to * extsprintf must actually be a string or something convertible to a * String using .toString(). Passing other values (notably "null" and * "undefined") is considered a programmer error. The assumption is * that if you actually want to print the string "null" or "undefined", * then that's easy to do that when you're calling extsprintf; on the * other hand, if you did NOT want that (i.e., there's actually a bug * where the program assumes some variable is non-null and tries to * print it, which might happen when constructing a packet or file in * some specific format), then it's better to stop immediately than * produce bogus output. * * However, sometimes the bug is only in the code calling VError, and a * programmer might prefer to have the error message contain "null" or * "undefined" rather than have the bug in the error path crash the * program (making the first bug harder to identify). For that reason, * by default VError converts "null" or "undefined" arguments to their * string representations and passes those to extsprintf. Programmers * desiring the strict behavior can use the SError class or pass the * "strict" option to the VError constructor. */ mod_assertplus.object(options); if (!options.strict && !args.strict) { sprintf_args = sprintf_args.map(function (a) { return (a === null ? 'null' : a === undefined ? 'undefined' : a); }); } if (sprintf_args.length === 0) { shortmessage = ''; } else { shortmessage = sprintf.apply(null, sprintf_args); } return ({ 'options': options, 'shortmessage': shortmessage }); } /* * See README.md for reference documentation. */ function VError() { var args, obj, parsed, cause, ctor, message, k; args = Array.prototype.slice.call(arguments, 0); /* * This is a regrettable pattern, but JavaScript's built-in Error class * is defined to work this way, so we allow the constructor to be called * without "new". */ if (!(this instanceof VError)) { obj = Object.create(VError.prototype); VError.apply(obj, arguments); return (obj); } /* * For convenience and backwards compatibility, we support several * different calling forms. Normalize them here. */ parsed = parseConstructorArguments({ 'argv': args, 'strict': false }); /* * If we've been given a name, apply it now. */ if (parsed.options.name) { mod_assertplus.string(parsed.options.name, 'error\'s "name" must be a string'); this.name = parsed.options.name; } /* * For debugging, we keep track of the original short message (attached * this Error particularly) separately from the complete message (which * includes the messages of our cause chain). */ this.jse_shortmsg = parsed.shortmessage; message = parsed.shortmessage; /* * If we've been given a cause, record a reference to it and update our * message appropriately. */ cause = parsed.options.cause; if (cause) { mod_assertplus.ok(mod_isError(cause), 'cause is not an Error'); this.jse_cause = cause; if (!parsed.options.skipCauseMessage) { message += ': ' + cause.message; } } /* * If we've been given an object with properties, shallow-copy that * here. We don't want to use a deep copy in case there are non-plain * objects here, but we don't want to use the original object in case * the caller modifies it later. */ this.jse_info = {}; if (parsed.options.info) { for (k in parsed.options.info) { this.jse_info[k] = parsed.options.info[k]; } } this.message = message; Error.call(this, message); if (Error.captureStackTrace) { ctor = parsed.options.constructorOpt || this.constructor; Error.captureStackTrace(this, ctor); } return (this); } mod_util.inherits(VError, Error); VError.prototype.name = 'VError'; VError.prototype.toString = function ve_toString() { var str = (this.hasOwnProperty('name') && this.name || this.constructor.name || this.constructor.prototype.name); if (this.message) str += ': ' + this.message; return (str); }; /* * This method is provided for compatibility. New callers should use * VError.cause() instead. That method also uses the saner `null` return value * when there is no cause. */ VError.prototype.cause = function ve_cause() { var cause = VError.cause(this); return (cause === null ? undefined : cause); }; /* * Static methods * * These class-level methods are provided so that callers can use them on * instances of Errors that are not VErrors. New interfaces should be provided * only using static methods to eliminate the class of programming mistake where * people fail to check whether the Error object has the corresponding methods. */ VError.cause = function (err) { mod_assertplus.ok(mod_isError(err), 'err must be an Error'); return (mod_isError(err.jse_cause) ? err.jse_cause : null); }; VError.info = function (err) { var rv, cause, k; mod_assertplus.ok(mod_isError(err), 'err must be an Error'); cause = VError.cause(err); if (cause !== null) { rv = VError.info(cause); } else { rv = {}; } if (typeof (err.jse_info) == 'object' && err.jse_info !== null) { for (k in err.jse_info) { rv[k] = err.jse_info[k]; } } return (rv); }; VError.findCauseByName = function (err, name) { var cause; mod_assertplus.ok(mod_isError(err), 'err must be an Error'); mod_assertplus.string(name, 'name'); mod_assertplus.ok(name.length > 0, 'name cannot be empty'); for (cause = err; cause !== null; cause = VError.cause(cause)) { mod_assertplus.ok(mod_isError(cause)); if (cause.name == name) { return (cause); } } return (null); }; VError.hasCauseWithName = function (err, name) { return (VError.findCauseByName(err, name) !== null); }; VError.fullStack = function (err) { mod_assertplus.ok(mod_isError(err), 'err must be an Error'); var cause = VError.cause(err); if (cause) { return (err.stack + '\ncaused by: ' + VError.fullStack(cause)); } return (err.stack); }; VError.errorFromList = function (errors) { mod_assertplus.arrayOfObject(errors, 'errors'); if (errors.length === 0) { return (null); } errors.forEach(function (e) { mod_assertplus.ok(mod_isError(e)); }); if (errors.length == 1) { return (errors[0]); } return (new MultiError(errors)); }; VError.errorForEach = function (err, func) { mod_assertplus.ok(mod_isError(err), 'err must be an Error'); mod_assertplus.func(func, 'func'); if (err instanceof MultiError) { err.errors().forEach(function iterError(e) { func(e); }); } else { func(err); } }; /* * SError is like VError, but stricter about types. You cannot pass "null" or * "undefined" as string arguments to the formatter. */ function SError() { var args, obj, parsed, options; args = Array.prototype.slice.call(arguments, 0); if (!(this instanceof SError)) { obj = Object.create(SError.prototype); SError.apply(obj, arguments); return (obj); } parsed = parseConstructorArguments({ 'argv': args, 'strict': true }); options = parsed.options; VError.call(this, options, '%s', parsed.shortmessage); return (this); } /* * We don't bother setting SError.prototype.name because once constructed, * SErrors are just like VErrors. */ mod_util.inherits(SError, VError); /* * Represents a collection of errors for the purpose of consumers that generally * only deal with one error. Callers can extract the individual errors * contained in this object, but may also just treat it as a normal single * error, in which case a summary message will be printed. */ function MultiError(errors) { mod_assertplus.array(errors, 'list of errors'); mod_assertplus.ok(errors.length > 0, 'must be at least one error'); this.ase_errors = errors; VError.call(this, { 'cause': errors[0] }, 'first of %d error%s', errors.length, errors.length == 1 ? '' : 's'); } mod_util.inherits(MultiError, VError); MultiError.prototype.name = 'MultiError'; MultiError.prototype.errors = function me_errors() { return (this.ase_errors.slice(0)); }; /* * See README.md for reference details. */ function WError() { var args, obj, parsed, options; args = Array.prototype.slice.call(arguments, 0); if (!(this instanceof WError)) { obj = Object.create(WError.prototype); WError.apply(obj, args); return (obj); } parsed = parseConstructorArguments({ 'argv': args, 'strict': false }); options = parsed.options; options['skipCauseMessage'] = true; VError.call(this, options, '%s', parsed.shortmessage); return (this); } mod_util.inherits(WError, VError); WError.prototype.name = 'WError'; WError.prototype.toString = function we_toString() { var str = (this.hasOwnProperty('name') && this.name || this.constructor.name || this.constructor.prototype.name); if (this.message) str += ': ' + this.message; if (this.jse_cause && this.jse_cause.message) str += '; caused by ' + this.jse_cause.toString(); return (str); }; /* * For purely historical reasons, WError's cause() function allows you to set * the cause. */ WError.prototype.cause = function we_cause(c) { if (mod_isError(c)) this.jse_cause = c; return (this.jse_cause); }; node-verror-1.10.0/package.json000066400000000000000000000006261307545425100163330ustar00rootroot00000000000000{ "name": "verror", "version": "1.10.0", "description": "richer JavaScript errors", "main": "./lib/verror.js", "repository": { "type": "git", "url": "git://github.com/davepacheco/node-verror.git" }, "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" }, "engines": [ "node >=0.6.0" ], "scripts": { "test": "make test" }, "license": "MIT" } node-verror-1.10.0/test/000077500000000000000000000000001307545425100150205ustar00rootroot00000000000000node-verror-1.10.0/test/common.js000066400000000000000000000012411307545425100166440ustar00rootroot00000000000000/* * test/common.js: common utility functions used in multiple tests */ exports.cleanStack = cleanStack; exports.oldNode = oldNode; /* * Remove full paths and relative line numbers from stack traces so that we can * compare against "known-good" output. */ function cleanStack(stacktxt) { var re = new RegExp('\\(/.*/tst.*js:\\d+:\\d+\\)', 'gm'); stacktxt = stacktxt.replace(re, '(dummy filename)'); return (stacktxt); } /* * Node's behavior with respect to Error's names and messages changed * significantly with v0.12, so a number of tests regrettably need to check for * that. */ function oldNode() { return (/^0\.10\./.test(process.versions['node'])); } node-verror-1.10.0/test/tst.common.js000066400000000000000000000135201307545425100174600ustar00rootroot00000000000000/* * tst.common.js: tests functionality that's common to the VError, SError, and * WError classes. */ var mod_assert = require('assert'); var mod_verror = require('../lib/verror'); var mod_testcommon = require('./common'); var SError = mod_verror.SError; var VError = mod_verror.VError; var WError = mod_verror.WError; /* * Save the generic parts of all stack traces so we can avoid hardcoding * Node-specific implementation details in our testing of stack traces. * The stack trace limit has to be large enough to capture all of Node's frames, * which are more than the default (10 frames) in Node v6.x. */ Error.stackTraceLimit = 20; var nodestack = new Error().stack.split('\n').slice(2).join('\n'); /* * Runs all tests using the class "cons". We'll apply this to each of the main * classes. */ function runTests(cons, label) { var err, stack, stackname; console.error('running common tests for: %s', cons.name); /* * On Node v0.10 and earlier, the name that's used in the "stack" output * is the constructor that was used for this object. On Node v0.12 and * later, it's the value of the "name" property on the Error when it was * constructed. */ if (mod_testcommon.oldNode()) { stackname = cons.name; } else { stackname = label; } /* no arguments */ err = new cons(); mod_assert.equal(err.name, label); mod_assert.ok(err instanceof Error); mod_assert.ok(err instanceof cons); mod_assert.equal(err.message, ''); mod_assert.ok(err.cause() === undefined); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackname, ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* used without "new" */ err = cons('test %s', 'foo'); mod_assert.equal(err.name, label); mod_assert.ok(err instanceof Error); mod_assert.ok(err instanceof cons); mod_assert.equal(err.message, 'test foo'); /* options-argument form */ err = new cons({}); mod_assert.equal(err.name, label); mod_assert.equal(err.message, ''); mod_assert.ok(err.cause() === undefined); /* simple message */ err = new cons('my error'); mod_assert.equal(err.name, label); mod_assert.equal(err.message, 'my error'); mod_assert.ok(err.cause() === undefined); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackname + ': my error', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = new cons({}, 'my error'); mod_assert.equal(err.name, label); mod_assert.equal(err.message, 'my error'); mod_assert.ok(err.cause() === undefined); /* fullStack */ err = new cons('Some error'); stack = mod_testcommon.cleanStack(VError.fullStack(err)); mod_assert.equal(stack, [ stackname + ': Some error', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = new Error('Some error'); stack = mod_testcommon.cleanStack(VError.fullStack(err)); mod_assert.equal(stack, [ 'Error: Some error', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* printf-style message */ err = new cons('%s error: %3d problems', 'very bad', 15); mod_assert.equal(err.message, 'very bad error: 15 problems'); mod_assert.ok(err.cause() === undefined); err = new cons({}, '%s error: %3d problems', 'very bad', 15); mod_assert.equal(err.message, 'very bad error: 15 problems'); mod_assert.ok(err.cause() === undefined); /* null cause (for backwards compatibility with older versions) */ err = new cons(null, 'my error'); mod_assert.equal(err.message, 'my error'); mod_assert.ok(err.cause() === undefined); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackname + ': my error', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = new cons({ 'cause': null }, 'my error'); mod_assert.equal(err.message, 'my error'); mod_assert.ok(err.cause() === undefined); err = new cons(null); mod_assert.equal(err.message, ''); mod_assert.ok(err.cause() === undefined); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackname, ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* constructorOpt */ function makeErr(options) { return (new cons(options, 'test error')); } err = makeErr({}); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackname + ': test error', ' at makeErr (dummy filename)', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = makeErr({ 'constructorOpt': makeErr }); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackname + ': test error', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* invoked without "new" */ err = cons('my %s string', 'testing!'); mod_assert.equal(err.name, label); mod_assert.ok(err instanceof cons); mod_assert.ok(err instanceof Error); mod_assert.equal(err.message, 'my testing! string'); /* custom "name" */ err = new cons({ 'name': 'SomeOtherError' }, 'another kind of error'); mod_assert.equal(err.name, 'SomeOtherError'); mod_assert.ok(err instanceof cons); mod_assert.ok(err instanceof Error); mod_assert.equal(err.message, 'another kind of error'); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ 'SomeOtherError: another kind of error', ' at runTests (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); } runTests(VError, 'VError'); runTests(WError, 'WError'); runTests(SError, 'VError'); node-verror-1.10.0/test/tst.context.js000066400000000000000000000012171307545425100176540ustar00rootroot00000000000000/* * tst.context.js: tests that cause works with errors from different contexts. */ var mod_assert = require('assert'); var mod_verror = require('../lib/verror'); var mod_isError = require('core-util-is').isError; var mod_vm = require('vm'); var VError = mod_verror.VError; var WError = mod_verror.WError; var err = new Error(); var verr = new VError(err); mod_assert.ok(mod_isError(verr.cause())); var context = mod_vm.createContext({ 'callback': function callback(err2) { mod_assert.ok(mod_isError(err2)); var verr2 = new VError(err); mod_assert.ok(mod_isError(verr2.cause())); } }); mod_vm.runInContext('callback(new Error())', context); node-verror-1.10.0/test/tst.findcause.js000066400000000000000000000100121307545425100201220ustar00rootroot00000000000000/* * tst.findcause.js: tests findCauseByName()/hasCauseWithName(). */ var mod_assert = require('assert'); var mod_util = require('util'); var mod_verror = require('../lib/verror'); var SError = mod_verror.SError; var VError = mod_verror.VError; var WError = mod_verror.WError; var findCauseByName = VError.findCauseByName; var hasCauseWithName = VError.hasCauseWithName; /* * This class deliberately doesn't inherit from our error classes. */ function MyError() { Error.call(this, 'here is my error'); } mod_util.inherits(MyError, Error); MyError.prototype.name = 'MyError'; function main() { /* * We'll build up a cause chain using each of our classes and make sure * that findCauseByName() traverses all the way to the bottom. This * ends up testing that findCauseByName() works with each of these * classes. */ var err1, err2, err3, err4; err1 = new MyError(); err2 = new VError({ 'name': 'ErrorTwo', 'cause': err1 }, 'basic verror (number two)'); err3 = new SError({ 'name': 'ErrorThree', 'cause': err2 }, 'strict error (number three)'); err4 = new WError({ 'name': 'ErrorFour', 'cause': err3 }, 'werror (number four)'); /* * Our top-level error should have all of the causes in its chain. */ mod_assert.strictEqual(err4, findCauseByName(err4, 'ErrorFour')); mod_assert.strictEqual(true, hasCauseWithName(err4, 'ErrorFour')); mod_assert.strictEqual(err3, findCauseByName(err4, 'ErrorThree')); mod_assert.strictEqual(true, hasCauseWithName(err4, 'ErrorThree')); mod_assert.strictEqual(err2, findCauseByName(err4, 'ErrorTwo')); mod_assert.strictEqual(true, hasCauseWithName(err4, 'ErrorTwo')); mod_assert.strictEqual(err1, findCauseByName(err4, 'MyError')); mod_assert.strictEqual(true, hasCauseWithName(err4, 'MyError')); /* * By contrast, the next-level errors should have only their own causes. */ mod_assert.strictEqual(null, findCauseByName(err3, 'ErrorFour')); mod_assert.strictEqual(false, hasCauseWithName(err3, 'ErrorFour')); mod_assert.strictEqual(err3, findCauseByName(err3, 'ErrorThree')); mod_assert.strictEqual(true, hasCauseWithName(err3, 'ErrorThree')); mod_assert.strictEqual(err2, findCauseByName(err3, 'ErrorTwo')); mod_assert.strictEqual(true, hasCauseWithName(err3, 'ErrorTwo')); mod_assert.strictEqual(err1, findCauseByName(err3, 'MyError')); mod_assert.strictEqual(true, hasCauseWithName(err3, 'MyError')); mod_assert.strictEqual(null, findCauseByName(err2, 'ErrorFour')); mod_assert.strictEqual(false, hasCauseWithName(err2, 'ErrorFour')); mod_assert.strictEqual(null, findCauseByName(err2, 'ErrorThree')); mod_assert.strictEqual(false, hasCauseWithName(err2, 'ErrorThree')); mod_assert.strictEqual(err2, findCauseByName(err2, 'ErrorTwo')); mod_assert.strictEqual(true, hasCauseWithName(err2, 'ErrorTwo')); mod_assert.strictEqual(err1, findCauseByName(err2, 'MyError')); mod_assert.strictEqual(true, hasCauseWithName(err2, 'MyError')); /* * These functions must work on non-VError errors. */ mod_assert.strictEqual(err1, findCauseByName(err1, 'MyError')); mod_assert.strictEqual(true, hasCauseWithName(err1, 'MyError')); mod_assert.strictEqual(null, findCauseByName(err1, 'ErrorTwo')); mod_assert.strictEqual(false, hasCauseWithName(err1, 'ErrorTwo')); err1 = new Error('a very basic error'); mod_assert.strictEqual(err1, findCauseByName(err1, 'Error')); mod_assert.strictEqual(true, hasCauseWithName(err1, 'Error')); mod_assert.strictEqual(null, findCauseByName(err1, 'MyError')); mod_assert.strictEqual(false, hasCauseWithName(err1, 'MyError')); /* * These functions should throw an Error when given bad argument types. */ mod_assert.throws(function () { findCauseByName(null, 'AnError'); }, /err must be an Error/); mod_assert.throws(function () { hasCauseWithName(null, 'AnError'); }, /err must be an Error/); mod_assert.throws(function () { findCauseByName(err1, null); }, /string.*is required/); mod_assert.throws(function () { hasCauseWithName(err1, null); }, /string.*is required/); console.error('test passed'); } main(); node-verror-1.10.0/test/tst.info.js000066400000000000000000000036161307545425100171300ustar00rootroot00000000000000/* * tst.info.js: tests the way informational properties are inherited with nested * errors. */ var mod_assert = require('assert'); var mod_fs = require('fs'); var mod_verror = require('../lib/verror'); var VError = mod_verror.VError; var err1, err2, err3; /* base case using "options" to specify cause */ err1 = new Error('bad'); err2 = new VError({ 'cause': err1 }, 'worse'); mod_assert.equal(err2.cause(), err1); mod_assert.equal(err2.message, 'worse: bad'); mod_assert.deepEqual(VError.info(err2), {}); /* simple info usage */ err1 = new VError({ 'name': 'MyError', 'info': { 'errno': 'EDEADLK', 'anobject': { 'hello': 'world' } } }, 'bad'); mod_assert.equal(err1.name, 'MyError'); mod_assert.deepEqual(VError.info(err1), { 'errno': 'EDEADLK', 'anobject': { 'hello': 'world' } }); /* simple property propagation using old syntax */ err2 = new VError(err1, 'worse'); mod_assert.equal(err2.cause(), err1); mod_assert.equal(err2.message, 'worse: bad'); mod_assert.deepEqual(VError.info(err2), { 'errno': 'EDEADLK', 'anobject': { 'hello': 'world' } }); /* one property override */ err2 = new VError({ 'cause': err1, 'info': { 'anobject': { 'hello': 'moon' } } }, 'worse'); mod_assert.equal(err2.cause(), err1); mod_assert.equal(err2.message, 'worse: bad'); mod_assert.deepEqual(VError.info(err2), { 'errno': 'EDEADLK', 'anobject': { 'hello': 'moon' } }); /* add a third-level to the chain */ err3 = new VError({ 'cause': err2, 'name': 'BigError', 'info': { 'remote_ip': '127.0.0.1' } }, 'what next'); mod_assert.equal(err3.name, 'BigError'); mod_assert.equal(VError.info(err3).remote_ip, '127.0.0.1'); mod_assert.equal(err3.cause(), err2); mod_assert.equal(err3.message, 'what next: worse: bad'); mod_assert.equal(VError.info(err3).errno, 'EDEADLK'); mod_assert.deepEqual(VError.info(err3).anobject, { 'hello': 'moon' }); console.log('test passed'); node-verror-1.10.0/test/tst.inherit.js000066400000000000000000000103461307545425100176350ustar00rootroot00000000000000/* * tst.inherit.js: test that inheriting from VError and WError work as expected. */ var mod_assert = require('assert'); var mod_util = require('util'); var mod_testcommon = require('./common'); var VError = require('../lib/verror'); var WError = VError.WError; var err, suberr, stack, nodestack; function VErrorChild() { VError.apply(this, Array.prototype.slice.call(arguments)); } mod_util.inherits(VErrorChild, VError); VErrorChild.prototype.name = 'VErrorChild'; function WErrorChild() { WError.apply(this, Array.prototype.slice.call(arguments)); } mod_util.inherits(WErrorChild, WError); WErrorChild.prototype.name = 'WErrorChild'; /* * Save the generic parts of all stack traces so we can avoid hardcoding * Node-specific implementation details in our testing of stack traces. * The stack trace limit has to be large enough to capture all of Node's frames, * which are more than the default (10 frames) in Node v6.x. */ Error.stackTraceLimit = 20; nodestack = new Error().stack.split('\n').slice(2).join('\n'); suberr = new Error('root cause'); err = new VErrorChild(suberr, 'top'); mod_assert.ok(err instanceof Error); mod_assert.ok(err instanceof VError); mod_assert.ok(err instanceof VErrorChild); mod_assert.equal(err.cause(), suberr); mod_assert.equal(err.message, 'top: root cause'); mod_assert.equal(err.toString(), 'VErrorChild: top: root cause'); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ 'VErrorChild: top: root cause', ' at Object. (dummy filename)', nodestack ].join('\n')); suberr = new Error('root cause'); err = new WErrorChild(suberr, 'top'); mod_assert.ok(err instanceof Error); mod_assert.ok(err instanceof WError); mod_assert.ok(err instanceof WErrorChild); mod_assert.equal(err.cause(), suberr); mod_assert.equal(err.message, 'top'); mod_assert.equal(err.toString(), 'WErrorChild: top; caused by Error: root cause'); stack = mod_testcommon.cleanStack(err.stack); /* * On Node 0.10 and earlier, the 'stack' property appears to use the error's * toString() method. On newer versions, it appears to use the message * property the first time err.stack is accessed (_not_ when it was * constructed). Since the point of WError is to omit the cause messages from * the WError's message, there's no way to have the err.stack property show the * detailed message in Node 0.12 and later. */ if (mod_testcommon.oldNode()) { mod_assert.equal(stack, [ 'WErrorChild: top; caused by Error: root cause', ' at Object. (dummy filename)', nodestack ].join('\n')); } else { mod_assert.equal(stack, [ 'WErrorChild: top', ' at Object. (dummy filename)', nodestack ].join('\n')); } /* * Test that ".toString()" uses the constructor name, so that setting * ".prototype.name" isn't necessary. */ function VErrorChildNoName() { VError.apply(this, Array.prototype.slice.call(arguments)); } mod_util.inherits(VErrorChildNoName, VError); err = new VErrorChildNoName('top'); mod_assert.equal(err.toString(), 'VErrorChildNoName: top'); function WErrorChildNoName() { WError.apply(this, Array.prototype.slice.call(arguments)); } mod_util.inherits(WErrorChildNoName, WError); err = new WErrorChildNoName('top'); mod_assert.equal(err.toString(), 'WErrorChildNoName: top'); /* * Test that `.prototype.name` can be used for the `.toString()` * when the ctor is anonymous. */ var VErrorChildAnon = function () { VError.apply(this, Array.prototype.slice.call(arguments)); }; mod_util.inherits(VErrorChildAnon, VError); VErrorChildAnon.prototype.name = 'VErrorChildAnon'; err = new VErrorChildAnon('top'); mod_assert.equal(err.toString(), 'VErrorChildAnon: top'); var WErrorChildAnon = function () { WError.apply(this, Array.prototype.slice.call(arguments)); }; mod_util.inherits(WErrorChildAnon, WError); WErrorChildAnon.prototype.name = 'WErrorChildAnon'; err = new WErrorChildAnon('top'); mod_assert.equal(err.toString(), 'WErrorChildAnon: top'); /* * Test that we get an appropriate exception name in toString() output. */ err = new VError('top'); err.name = 'CustomNameError'; mod_assert.equal(err.toString(), 'CustomNameError: top'); err = new WError('top'); err.name = 'CustomNameError'; mod_assert.equal(err.toString(), 'CustomNameError: top'); node-verror-1.10.0/test/tst.multierror.js000066400000000000000000000077661307545425100204130ustar00rootroot00000000000000/* * tst.multierror.js: tests MultiError class */ var mod_assert = require('assert'); var mod_verror = require('../lib/verror'); var mod_testcommon = require('./common'); var MultiError = mod_verror.MultiError; var errorFromList = mod_verror.errorFromList; var errorForEach = mod_verror.errorForEach; /* * Save the generic parts of all stack traces so we can avoid hardcoding * Node-specific implementation details in our testing of stack traces. * The stack trace limit has to be large enough to capture all of Node's frames, * which are more than the default (10 frames) in Node v6.x. */ Error.stackTraceLimit = 20; var nodestack = new Error().stack.split('\n').slice(2).join('\n'); function main() { var err1, err2, err3, merr, stack; var accum, doAccum; mod_assert.throws(function () { console.error(new MultiError()); }, /list of errors \(array\) is required/); mod_assert.throws(function () { console.error(new MultiError([])); }, /must be at least one error/); err1 = new Error('error one'); err2 = new Error('error two'); err3 = new Error('error three'); merr = new MultiError([ err1, err2, err3 ]); mod_assert.equal(err1, merr.cause()); mod_assert.equal(merr.message, 'first of 3 errors: error one'); mod_assert.equal(merr.name, 'MultiError'); stack = mod_testcommon.cleanStack(merr.stack); mod_assert.equal(stack, [ 'MultiError: first of 3 errors: error one', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); merr = new MultiError([ err1 ]); mod_assert.equal(merr.message, 'first of 1 error: error one'); mod_assert.equal(merr.name, 'MultiError'); stack = mod_testcommon.cleanStack(merr.stack); mod_assert.equal(stack, [ 'MultiError: first of 1 error: error one', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* errorFromList */ mod_assert.throws(function () { console.error(errorFromList()); }, /^AssertionError: errors \(\[object\]\) is required$/); mod_assert.throws(function () { console.error(errorFromList(null)); }, /^AssertionError: errors \(\[object\]\) is required$/); mod_assert.throws(function () { console.error(errorFromList({})); }, /^AssertionError: errors \(\[object\]\) is required$/); mod_assert.throws(function () { console.error(errorFromList('asdf')); }, /^AssertionError: errors \(\[object\]\) is required$/); mod_assert.throws(function () { console.error(errorFromList([ new Error(), 17 ])); }, /^AssertionError: errors \(\[object\]\) is required$/); mod_assert.throws(function () { console.error(errorFromList([ new Error(), {} ])); }, /^AssertionError/); mod_assert.strictEqual(null, errorFromList([])); mod_assert.ok(err1 == errorFromList([ err1 ])); mod_assert.ok(err2 == errorFromList([ err2 ])); merr = errorFromList([ err1, err2, err3 ]); mod_assert.ok(merr instanceof MultiError); mod_assert.ok(merr.errors()[0] == err1); mod_assert.ok(merr.errors()[1] == err2); mod_assert.ok(merr.errors()[2] == err3); /* errorForEach */ mod_assert.throws(function () { console.error(errorForEach()); }, /^AssertionError: err must be an Error$/); mod_assert.throws(function () { console.error(errorForEach(null)); }, /^AssertionError: err must be an Error$/); mod_assert.throws(function () { console.error(errorForEach(err1)); }, /^AssertionError: func \(func\) is required$/); mod_assert.throws(function () { console.error(errorForEach(err1, {})); }, /^AssertionError: func \(func\) is required$/); mod_assert.throws(function () { console.error(errorForEach({}, function () {})); }, /^AssertionError: err must be an Error$/); accum = []; doAccum = function (e) { accum.push(e); }; accum = []; errorForEach(err1, doAccum); mod_assert.equal(accum.length, 1); mod_assert.ok(accum[0] == err1); accum = []; errorForEach(merr, doAccum); mod_assert.equal(accum.length, 3); mod_assert.ok(accum[0] == err1); mod_assert.ok(accum[1] == err2); mod_assert.ok(accum[2] == err3); } main(); node-verror-1.10.0/test/tst.verror.js000066400000000000000000000102751307545425100175130ustar00rootroot00000000000000/* * tst.verror.js: tests functionality that's specific to the VError and SError * classes. */ var mod_assert = require('assert'); var mod_verror = require('../lib/verror'); var mod_testcommon = require('./common'); var SError = mod_verror.SError; var VError = mod_verror.VError; var WError = mod_verror.WError; /* * Save the generic parts of all stack traces so we can avoid hardcoding * Node-specific implementation details in our testing of stack traces. * The stack trace limit has to be large enough to capture all of Node's frames, * which are more than the default (10 frames) in Node v6.x. */ Error.stackTraceLimit = 20; var nodestack = new Error().stack.split('\n').slice(2).join('\n'); function main() { var err, suberr, stack, stackname; console.error('running VError/SError tests'); /* "null" or "undefined" as string for extsprintf */ err = new VError('my %s string', null); mod_assert.equal('my null string', err.message); err = new VError('my %s string', undefined); mod_assert.equal('my undefined string', err.message); mod_assert.throws(function () { console.error( new VError({ 'strict': true }, 'my %s string', null)); }, /attempted to print undefined or null as a string/); mod_assert.throws(function () { console.error(new SError('my %s string', undefined)); }, /attempted to print undefined or null as a string/); mod_assert.throws(function () { console.error(new SError('my %s string', null)); }, /attempted to print undefined or null as a string/); mod_assert.throws(function () { console.error(new SError('my %s string', undefined)); }, /attempted to print undefined or null as a string/); /* caused by another error, with no additional message */ suberr = new Error('root cause'); err = new VError(suberr); mod_assert.equal(err.message, ': root cause'); mod_assert.ok(err.cause() === suberr); err = new VError({ 'cause': suberr }); mod_assert.equal(err.message, ': root cause'); mod_assert.ok(err.cause() === suberr); /* caused by another error, with annotation */ err = new VError(suberr, 'proximate cause: %d issues', 3); mod_assert.equal(err.message, 'proximate cause: 3 issues: root cause'); mod_assert.ok(err.cause() === suberr); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ 'VError: proximate cause: 3 issues: root cause', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = new SError({ 'cause': suberr }, 'proximate cause: %d issues', 3); mod_assert.equal(err.message, 'proximate cause: 3 issues: root cause'); mod_assert.ok(err.cause() === suberr); stack = mod_testcommon.cleanStack(err.stack); /* See the comment in tst.common.js. */ stackname = mod_testcommon.oldNode() ? 'SError': 'VError'; mod_assert.equal(stack, [ stackname + ': proximate cause: 3 issues: root cause', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* caused by another VError, with annotation. */ suberr = err; err = new VError(suberr, 'top'); mod_assert.equal(err.message, 'top: proximate cause: 3 issues: root cause'); mod_assert.ok(err.cause() === suberr); err = new VError({ 'cause': suberr }, 'top'); mod_assert.equal(err.message, 'top: proximate cause: 3 issues: root cause'); mod_assert.ok(err.cause() === suberr); /* caused by a WError */ suberr = new WError(new Error('root cause'), 'mid'); err = new VError(suberr, 'top'); mod_assert.equal(err.message, 'top: mid'); mod_assert.ok(err.cause() === suberr); /* fullStack */ suberr = new VError(new Error('root cause'), 'mid'); err = new VError(suberr, 'top'); stack = mod_testcommon.cleanStack(VError.fullStack(err)); mod_assert.equal(stack, [ 'VError: top: mid: root cause', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack + '\n' + [ 'caused by: VError: mid: root cause', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack + '\n' + [ 'caused by: Error: root cause', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); } main(); node-verror-1.10.0/test/tst.werror.js000066400000000000000000000125321307545425100175120ustar00rootroot00000000000000/* * tst.werror.js: tests basic functionality specific to the WError class. */ var mod_assert = require('assert'); var mod_verror = require('../lib/verror'); var mod_testcommon = require('./common'); var VError = mod_verror.VError; var WError = mod_verror.WError; /* * Save the generic parts of all stack traces so we can avoid hardcoding * Node-specific implementation details in our testing of stack traces. * The stack trace limit has to be large enough to capture all of Node's frames, * which are more than the default (10 frames) in Node v6.x. */ Error.stackTraceLimit = 20; var nodestack = new Error().stack.split('\n').slice(2).join('\n'); function main() { var err, suberr, stack, stackmessageTop, stackmessageMid; /* * Most of the test cases here have analogs in tst.common.js. In this * test, we check for WError-specific behavior (e.g., toString()). */ console.error('running WError-specific tests'); /* no arguments */ err = new WError(); mod_assert.equal(err.toString(), 'WError'); mod_assert.ok(err.cause() === undefined); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ 'WError', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* options-argument form */ err = new WError({}); mod_assert.equal(err.toString(), 'WError'); mod_assert.ok(err.cause() === undefined); /* simple message */ err = new WError('my error'); mod_assert.equal(err.message, 'my error'); mod_assert.equal(err.toString(), 'WError: my error'); mod_assert.ok(err.cause() === undefined); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ 'WError: my error', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = new WError({}, 'my error'); mod_assert.equal(err.toString(), 'WError: my error'); mod_assert.ok(err.cause() === undefined); /* caused by another error, with no additional message */ suberr = new Error('root cause'); err = new WError(suberr); mod_assert.equal(err.message, ''); mod_assert.equal(err.toString(), 'WError; caused by Error: root cause'); mod_assert.ok(err.cause() === suberr); err = new WError({ 'cause': suberr }); mod_assert.equal(err.message, ''); mod_assert.equal(err.toString(), 'WError; caused by Error: root cause'); mod_assert.ok(err.cause() === suberr); /* caused by another error, with annotation */ err = new WError(suberr, 'proximate cause: %d issues', 3); mod_assert.equal(err.message, 'proximate cause: 3 issues'); mod_assert.equal(err.toString(), 'WError: proximate cause: 3 issues; ' + 'caused by Error: root cause'); mod_assert.ok(err.cause() === suberr); stack = mod_testcommon.cleanStack(err.stack); /* See the comment in tst.inherit.js. */ stackmessageTop = mod_testcommon.oldNode() ? 'WError: proximate cause: 3 issues; caused by Error: root cause' : 'WError: proximate cause: 3 issues'; mod_assert.equal(stack, [ stackmessageTop, ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); err = new WError({ 'cause': suberr }, 'proximate cause: %d issues', 3); mod_assert.equal(err.message, 'proximate cause: 3 issues'); mod_assert.equal(err.toString(), 'WError: proximate cause: 3 issues; ' + 'caused by Error: root cause'); mod_assert.ok(err.cause() === suberr); stack = mod_testcommon.cleanStack(err.stack); mod_assert.equal(stack, [ stackmessageTop, ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); /* caused by another WError, with annotation. */ suberr = err; err = new WError(suberr, 'top'); mod_assert.equal(err.message, 'top'); mod_assert.equal(err.toString(), 'WError: top; caused by WError: ' + 'proximate cause: 3 issues; caused by Error: root cause'); mod_assert.ok(err.cause() === suberr); err = new WError({ 'cause': suberr }, 'top'); mod_assert.equal(err.message, 'top'); mod_assert.equal(err.toString(), 'WError: top; caused by WError: ' + 'proximate cause: 3 issues; caused by Error: root cause'); mod_assert.ok(err.cause() === suberr); /* caused by a VError */ suberr = new VError(new Error('root cause'), 'mid'); err = new WError(suberr, 'top'); mod_assert.equal(err.message, 'top'); mod_assert.equal(err.toString(), 'WError: top; caused by VError: mid: root cause'); mod_assert.ok(err.cause() === suberr); /* fullStack */ suberr = new WError(new Error('root cause'), 'mid'); err = new WError(suberr, 'top'); stack = mod_testcommon.cleanStack(VError.fullStack(err)); /* See the comment in tst.inherit.js. */ stackmessageMid = mod_testcommon.oldNode() ? 'WError: mid; caused by Error: root cause' : 'WError: mid'; stackmessageTop = mod_testcommon.oldNode() ? 'WError: top; caused by ' + stackmessageMid : 'WError: top'; mod_assert.equal(stack, [ stackmessageTop, ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack + '\n' + [ 'caused by: ' + stackmessageMid, ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack + '\n' + [ 'caused by: Error: root cause', ' at main (dummy filename)', ' at Object. (dummy filename)' ].join('\n') + '\n' + nodestack); } main();