assert.js (5454B)
1 // Copyright (c) 2012, Mark Cavage. All rights reserved. 2 // Copyright 2015 Joyent, Inc. 3 4 var assert = require('assert'); 5 var Stream = require('stream').Stream; 6 var util = require('util'); 7 8 9 ///--- Globals 10 11 /* JSSTYLED */ 12 var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/; 13 14 15 ///--- Internal 16 17 function _capitalize(str) { 18 return (str.charAt(0).toUpperCase() + str.slice(1)); 19 } 20 21 function _toss(name, expected, oper, arg, actual) { 22 throw new assert.AssertionError({ 23 message: util.format('%s (%s) is required', name, expected), 24 actual: (actual === undefined) ? typeof (arg) : actual(arg), 25 expected: expected, 26 operator: oper || '===', 27 stackStartFunction: _toss.caller 28 }); 29 } 30 31 function _getClass(arg) { 32 return (Object.prototype.toString.call(arg).slice(8, -1)); 33 } 34 35 function noop() { 36 // Why even bother with asserts? 37 } 38 39 40 ///--- Exports 41 42 var types = { 43 bool: { 44 check: function (arg) { return typeof (arg) === 'boolean'; } 45 }, 46 func: { 47 check: function (arg) { return typeof (arg) === 'function'; } 48 }, 49 string: { 50 check: function (arg) { return typeof (arg) === 'string'; } 51 }, 52 object: { 53 check: function (arg) { 54 return typeof (arg) === 'object' && arg !== null; 55 } 56 }, 57 number: { 58 check: function (arg) { 59 return typeof (arg) === 'number' && !isNaN(arg); 60 } 61 }, 62 finite: { 63 check: function (arg) { 64 return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg); 65 } 66 }, 67 buffer: { 68 check: function (arg) { return Buffer.isBuffer(arg); }, 69 operator: 'Buffer.isBuffer' 70 }, 71 array: { 72 check: function (arg) { return Array.isArray(arg); }, 73 operator: 'Array.isArray' 74 }, 75 stream: { 76 check: function (arg) { return arg instanceof Stream; }, 77 operator: 'instanceof', 78 actual: _getClass 79 }, 80 date: { 81 check: function (arg) { return arg instanceof Date; }, 82 operator: 'instanceof', 83 actual: _getClass 84 }, 85 regexp: { 86 check: function (arg) { return arg instanceof RegExp; }, 87 operator: 'instanceof', 88 actual: _getClass 89 }, 90 uuid: { 91 check: function (arg) { 92 return typeof (arg) === 'string' && UUID_REGEXP.test(arg); 93 }, 94 operator: 'isUUID' 95 } 96 }; 97 98 function _setExports(ndebug) { 99 var keys = Object.keys(types); 100 var out; 101 102 /* re-export standard assert */ 103 if (process.env.NODE_NDEBUG) { 104 out = noop; 105 } else { 106 out = function (arg, msg) { 107 if (!arg) { 108 _toss(msg, 'true', arg); 109 } 110 }; 111 } 112 113 /* standard checks */ 114 keys.forEach(function (k) { 115 if (ndebug) { 116 out[k] = noop; 117 return; 118 } 119 var type = types[k]; 120 out[k] = function (arg, msg) { 121 if (!type.check(arg)) { 122 _toss(msg, k, type.operator, arg, type.actual); 123 } 124 }; 125 }); 126 127 /* optional checks */ 128 keys.forEach(function (k) { 129 var name = 'optional' + _capitalize(k); 130 if (ndebug) { 131 out[name] = noop; 132 return; 133 } 134 var type = types[k]; 135 out[name] = function (arg, msg) { 136 if (arg === undefined || arg === null) { 137 return; 138 } 139 if (!type.check(arg)) { 140 _toss(msg, k, type.operator, arg, type.actual); 141 } 142 }; 143 }); 144 145 /* arrayOf checks */ 146 keys.forEach(function (k) { 147 var name = 'arrayOf' + _capitalize(k); 148 if (ndebug) { 149 out[name] = noop; 150 return; 151 } 152 var type = types[k]; 153 var expected = '[' + k + ']'; 154 out[name] = function (arg, msg) { 155 if (!Array.isArray(arg)) { 156 _toss(msg, expected, type.operator, arg, type.actual); 157 } 158 var i; 159 for (i = 0; i < arg.length; i++) { 160 if (!type.check(arg[i])) { 161 _toss(msg, expected, type.operator, arg, type.actual); 162 } 163 } 164 }; 165 }); 166 167 /* optionalArrayOf checks */ 168 keys.forEach(function (k) { 169 var name = 'optionalArrayOf' + _capitalize(k); 170 if (ndebug) { 171 out[name] = noop; 172 return; 173 } 174 var type = types[k]; 175 var expected = '[' + k + ']'; 176 out[name] = function (arg, msg) { 177 if (arg === undefined || arg === null) { 178 return; 179 } 180 if (!Array.isArray(arg)) { 181 _toss(msg, expected, type.operator, arg, type.actual); 182 } 183 var i; 184 for (i = 0; i < arg.length; i++) { 185 if (!type.check(arg[i])) { 186 _toss(msg, expected, type.operator, arg, type.actual); 187 } 188 } 189 }; 190 }); 191 192 /* re-export built-in assertions */ 193 Object.keys(assert).forEach(function (k) { 194 if (k === 'AssertionError') { 195 out[k] = assert[k]; 196 return; 197 } 198 if (ndebug) { 199 out[k] = noop; 200 return; 201 } 202 out[k] = assert[k]; 203 }); 204 205 /* export ourselves (for unit tests _only_) */ 206 out._setExports = _setExports; 207 208 return out; 209 } 210 211 module.exports = _setExports(process.env.NODE_NDEBUG);