├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── protect.js └── tests ├── index.html ├── mocha.css ├── mocha.js └── tests.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | coverage 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "7" 5 | - "6" 6 | - "5" 7 | - "4" 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Tremayne Christ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProtectJS / Protect JS 2 | 3 | [![Build Status](https://travis-ci.org/TremayneChrist/ProtectJS.svg?branch=master)](https://travis-ci.org/TremayneChrist/ProtectJS) 4 | [![Coverage Status](https://coveralls.io/repos/github/TremayneChrist/ProtectJS/badge.svg?branch=master)](https://coveralls.io/github/TremayneChrist/ProtectJS?branch=master) 5 | 6 | #### Methods/Functions 7 | Adding private methods to an object in JavaScript has always been an awkward thing to do, as JavaScript doesn't exactly support it. Instead, we either place enclosed functions in the constructor, which consumes more memory per object, or, we enclose both the object definition and our private methods inside of a closure. 8 | 9 | The latter is a good way to accomplish private methods in JavaScript as it creates truly private methods and doesn't add to the memory consumption. The problem with it is, is that your private methods are separate from the object and your coding style is different compared to public definitions on the prototype. 10 | 11 | **ProtectJS** is a library that extends objects you define, to allow you to add all your private methods to the prototype chain. It does this by adding protection checks to all of your methods, any marked with a prepending underscore (_) is treated as a private method. 12 | 13 | #### Other properties 14 | 15 | As well as methods, JavaScript doesn't exactly support any type of private property. This becomes a problem when dangerous modifications to these properties occur. 16 | 17 | Think of complex algorithms - If these could be modified by external sources, their output would be completely invalidated, potentially causing huge implications. 18 | 19 | 20 | ### Examples 21 | 22 | In many languages, it is custom to prepend private variables with an underscore (_), so we use this in JavaScript to show that an object should be considered as a private. Obviously this has absolutely no affect to whether it is actually private or not, it's more of a visual reference for a developer. 23 | 24 | Let's create a basic object using this approach... 25 | 26 | ```javascript 27 | 28 | // Create the object 29 | function MyObject() {} 30 | 31 | // This is our public method 32 | MyObject.prototype.public = function () { 33 | console.log('PUBLIC method has been called'); 34 | }; 35 | 36 | // This is our private method, using (_) 37 | MyObject.prototype._private = function () { 38 | console.log('PRIVATE method has been called'); 39 | }; 40 | 41 | // Create an instance of the object 42 | var mo = new MyObject(); 43 | 44 | // Call its methods 45 | mo.public(); // Pass 46 | mo._private(); // Pass 47 | 48 | ``` 49 | As I stated previously, there is no protection here, so I could easily call the **_private()** method and get a message saying "PRIVATE method has been called". 50 | 51 | **Now let's protect the object with ProtectJS!..** 52 | 53 | Add ProtectJS into your source, making sure it loads before the code you want to protect. 54 | 55 | ```html 56 | 57 | PrivateJS 58 | 59 | 60 | 61 | ``` 62 | 63 | Now that ProtectJS is available, we need to use it on the object 64 | 65 | ```javascript 66 | 67 | // Create the object 68 | function MyObject() {} 69 | 70 | // This is our public method 71 | MyObject.prototype.public = function () { 72 | console.log('PUBLIC method has been called'); 73 | }; 74 | 75 | // This is our private method, using (_) 76 | MyObject.prototype._private = function () { 77 | console.log('PRIVATE method has been called'); 78 | }; 79 | 80 | protect(MyObject); // Protect the object prototype 81 | 82 | // Create an instance of the object 83 | var mo = new MyObject(); 84 | 85 | // Call its methods 86 | mo.public(); // Pass 87 | mo._private(); // Fail 88 | 89 | ``` 90 | 91 | ProtectJS assumes that all methods starting with underscores in the prototype are private, and will add protection checks to prevent them from being called outside of the object. 92 | 93 | Once protected, the only way to call a private method is by calling it through another method inside the same object. 94 | 95 | 96 | --- 97 | 98 | ### Pros 99 | 100 | 1. Enables private methods to be added onto the prototype, keeping object memory to a minimum. 101 | 102 | 2. Protects your other properties from being modified by external sources. 103 | 104 | 3. Keeps code creation clean and easy to read. 105 | 106 | 4. Allows you to define objects in a natural way. 107 | 108 | 5. Doesn't change your coding style. 109 | 110 | 6. Protects properties you don't want to be used. 111 | 112 | 113 | ### Cons 114 | 115 | 1. You have to include the ProtectJS library in your project. 116 | 2. Marginal overheads to be considered (Performance tests to come) 117 | 118 | --- 119 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protect.js", 3 | "version": "3.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abbrev": { 8 | "version": "1.0.9", 9 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", 10 | "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", 11 | "dev": true 12 | }, 13 | "ajv": { 14 | "version": "5.2.3", 15 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz", 16 | "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=", 17 | "dev": true, 18 | "requires": { 19 | "co": "4.6.0", 20 | "fast-deep-equal": "1.0.0", 21 | "json-schema-traverse": "0.3.1", 22 | "json-stable-stringify": "1.0.1" 23 | } 24 | }, 25 | "align-text": { 26 | "version": "0.1.4", 27 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 28 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 29 | "dev": true, 30 | "requires": { 31 | "kind-of": "3.2.2", 32 | "longest": "1.0.1", 33 | "repeat-string": "1.6.1" 34 | } 35 | }, 36 | "amdefine": { 37 | "version": "1.0.1", 38 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 39 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 40 | "dev": true 41 | }, 42 | "argparse": { 43 | "version": "1.0.9", 44 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", 45 | "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", 46 | "dev": true, 47 | "requires": { 48 | "sprintf-js": "1.0.3" 49 | } 50 | }, 51 | "asn1": { 52 | "version": "0.2.3", 53 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 54 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", 55 | "dev": true 56 | }, 57 | "assert-plus": { 58 | "version": "1.0.0", 59 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 60 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 61 | "dev": true 62 | }, 63 | "assertion-error": { 64 | "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", 65 | "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", 66 | "dev": true 67 | }, 68 | "async": { 69 | "version": "1.5.2", 70 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 71 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", 72 | "dev": true 73 | }, 74 | "asynckit": { 75 | "version": "0.4.0", 76 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 77 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 78 | "dev": true 79 | }, 80 | "aws-sign2": { 81 | "version": "0.7.0", 82 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 83 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 84 | "dev": true 85 | }, 86 | "aws4": { 87 | "version": "1.6.0", 88 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", 89 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", 90 | "dev": true 91 | }, 92 | "balanced-match": { 93 | "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", 94 | "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", 95 | "dev": true 96 | }, 97 | "bcrypt-pbkdf": { 98 | "version": "1.0.1", 99 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 100 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 101 | "dev": true, 102 | "optional": true, 103 | "requires": { 104 | "tweetnacl": "0.14.5" 105 | } 106 | }, 107 | "boom": { 108 | "version": "4.3.1", 109 | "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", 110 | "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", 111 | "dev": true, 112 | "requires": { 113 | "hoek": "4.2.0" 114 | } 115 | }, 116 | "brace-expansion": { 117 | "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", 118 | "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", 119 | "dev": true, 120 | "requires": { 121 | "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", 122 | "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" 123 | } 124 | }, 125 | "browser-stdout": { 126 | "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 127 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 128 | "dev": true 129 | }, 130 | "camelcase": { 131 | "version": "1.2.1", 132 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 133 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", 134 | "dev": true, 135 | "optional": true 136 | }, 137 | "caseless": { 138 | "version": "0.12.0", 139 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 140 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 141 | "dev": true 142 | }, 143 | "center-align": { 144 | "version": "0.1.3", 145 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 146 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 147 | "dev": true, 148 | "optional": true, 149 | "requires": { 150 | "align-text": "0.1.4", 151 | "lazy-cache": "1.0.4" 152 | } 153 | }, 154 | "chai": { 155 | "version": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", 156 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", 157 | "dev": true, 158 | "requires": { 159 | "assertion-error": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", 160 | "deep-eql": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", 161 | "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz" 162 | } 163 | }, 164 | "cliui": { 165 | "version": "2.1.0", 166 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 167 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 168 | "dev": true, 169 | "optional": true, 170 | "requires": { 171 | "center-align": "0.1.3", 172 | "right-align": "0.1.3", 173 | "wordwrap": "0.0.2" 174 | }, 175 | "dependencies": { 176 | "wordwrap": { 177 | "version": "0.0.2", 178 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 179 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", 180 | "dev": true, 181 | "optional": true 182 | } 183 | } 184 | }, 185 | "co": { 186 | "version": "4.6.0", 187 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 188 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 189 | "dev": true 190 | }, 191 | "combined-stream": { 192 | "version": "1.0.5", 193 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", 194 | "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", 195 | "dev": true, 196 | "requires": { 197 | "delayed-stream": "1.0.0" 198 | } 199 | }, 200 | "commander": { 201 | "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 202 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 203 | "dev": true, 204 | "requires": { 205 | "graceful-readlink": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" 206 | } 207 | }, 208 | "concat-map": { 209 | "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 210 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 211 | "dev": true 212 | }, 213 | "core-util-is": { 214 | "version": "1.0.2", 215 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 216 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 217 | "dev": true 218 | }, 219 | "coveralls": { 220 | "version": "3.0.0", 221 | "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.0.tgz", 222 | "integrity": "sha512-ZppXR9y5PraUOrf/DzHJY6gzNUhXYE3b9D43xEXs4QYZ7/Oe0Gy0CS+IPKWFfvQFXB3RG9QduaQUFehzSpGAFw==", 223 | "dev": true, 224 | "requires": { 225 | "js-yaml": "3.10.0", 226 | "lcov-parse": "0.0.10", 227 | "log-driver": "1.2.5", 228 | "minimist": "1.2.0", 229 | "request": "2.83.0" 230 | }, 231 | "dependencies": { 232 | "minimist": { 233 | "version": "1.2.0", 234 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 235 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 236 | "dev": true 237 | } 238 | } 239 | }, 240 | "cryptiles": { 241 | "version": "3.1.2", 242 | "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", 243 | "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", 244 | "dev": true, 245 | "requires": { 246 | "boom": "5.2.0" 247 | }, 248 | "dependencies": { 249 | "boom": { 250 | "version": "5.2.0", 251 | "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", 252 | "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", 253 | "dev": true, 254 | "requires": { 255 | "hoek": "4.2.0" 256 | } 257 | } 258 | } 259 | }, 260 | "dashdash": { 261 | "version": "1.14.1", 262 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 263 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 264 | "dev": true, 265 | "requires": { 266 | "assert-plus": "1.0.0" 267 | } 268 | }, 269 | "debug": { 270 | "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 271 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 272 | "dev": true, 273 | "requires": { 274 | "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" 275 | } 276 | }, 277 | "decamelize": { 278 | "version": "1.2.0", 279 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 280 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 281 | "dev": true, 282 | "optional": true 283 | }, 284 | "deep-eql": { 285 | "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", 286 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", 287 | "dev": true, 288 | "requires": { 289 | "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" 290 | }, 291 | "dependencies": { 292 | "type-detect": { 293 | "version": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", 294 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", 295 | "dev": true 296 | } 297 | } 298 | }, 299 | "deep-is": { 300 | "version": "0.1.3", 301 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 302 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 303 | "dev": true 304 | }, 305 | "delayed-stream": { 306 | "version": "1.0.0", 307 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 308 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 309 | "dev": true 310 | }, 311 | "diff": { 312 | "version": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", 313 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", 314 | "dev": true 315 | }, 316 | "ecc-jsbn": { 317 | "version": "0.1.1", 318 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 319 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 320 | "dev": true, 321 | "optional": true, 322 | "requires": { 323 | "jsbn": "0.1.1" 324 | } 325 | }, 326 | "escape-string-regexp": { 327 | "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 328 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 329 | "dev": true 330 | }, 331 | "escodegen": { 332 | "version": "1.8.1", 333 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", 334 | "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", 335 | "dev": true, 336 | "requires": { 337 | "esprima": "2.7.3", 338 | "estraverse": "1.9.3", 339 | "esutils": "2.0.2", 340 | "optionator": "0.8.2", 341 | "source-map": "0.2.0" 342 | }, 343 | "dependencies": { 344 | "esprima": { 345 | "version": "2.7.3", 346 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", 347 | "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", 348 | "dev": true 349 | } 350 | } 351 | }, 352 | "esprima": { 353 | "version": "4.0.0", 354 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", 355 | "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", 356 | "dev": true 357 | }, 358 | "estraverse": { 359 | "version": "1.9.3", 360 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", 361 | "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", 362 | "dev": true 363 | }, 364 | "esutils": { 365 | "version": "2.0.2", 366 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 367 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 368 | "dev": true 369 | }, 370 | "extend": { 371 | "version": "3.0.1", 372 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 373 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", 374 | "dev": true 375 | }, 376 | "extsprintf": { 377 | "version": "1.3.0", 378 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 379 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 380 | "dev": true 381 | }, 382 | "fast-deep-equal": { 383 | "version": "1.0.0", 384 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", 385 | "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", 386 | "dev": true 387 | }, 388 | "fast-levenshtein": { 389 | "version": "2.0.6", 390 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 391 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 392 | "dev": true 393 | }, 394 | "forever-agent": { 395 | "version": "0.6.1", 396 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 397 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 398 | "dev": true 399 | }, 400 | "form-data": { 401 | "version": "2.3.1", 402 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", 403 | "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", 404 | "dev": true, 405 | "requires": { 406 | "asynckit": "0.4.0", 407 | "combined-stream": "1.0.5", 408 | "mime-types": "2.1.17" 409 | } 410 | }, 411 | "fs.realpath": { 412 | "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 413 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 414 | "dev": true 415 | }, 416 | "getpass": { 417 | "version": "0.1.7", 418 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 419 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 420 | "dev": true, 421 | "requires": { 422 | "assert-plus": "1.0.0" 423 | } 424 | }, 425 | "glob": { 426 | "version": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", 427 | "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", 428 | "dev": true, 429 | "requires": { 430 | "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 431 | "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 432 | "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 433 | "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", 434 | "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 435 | "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 436 | } 437 | }, 438 | "graceful-readlink": { 439 | "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 440 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 441 | "dev": true 442 | }, 443 | "growl": { 444 | "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 445 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 446 | "dev": true 447 | }, 448 | "handlebars": { 449 | "version": "4.0.10", 450 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", 451 | "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", 452 | "dev": true, 453 | "requires": { 454 | "async": "1.5.2", 455 | "optimist": "0.6.1", 456 | "source-map": "0.4.4", 457 | "uglify-js": "2.8.29" 458 | }, 459 | "dependencies": { 460 | "source-map": { 461 | "version": "0.4.4", 462 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 463 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 464 | "dev": true, 465 | "requires": { 466 | "amdefine": "1.0.1" 467 | } 468 | } 469 | } 470 | }, 471 | "har-schema": { 472 | "version": "2.0.0", 473 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 474 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 475 | "dev": true 476 | }, 477 | "har-validator": { 478 | "version": "5.0.3", 479 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", 480 | "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", 481 | "dev": true, 482 | "requires": { 483 | "ajv": "5.2.3", 484 | "har-schema": "2.0.0" 485 | } 486 | }, 487 | "has-flag": { 488 | "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 489 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 490 | "dev": true 491 | }, 492 | "hawk": { 493 | "version": "6.0.2", 494 | "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", 495 | "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", 496 | "dev": true, 497 | "requires": { 498 | "boom": "4.3.1", 499 | "cryptiles": "3.1.2", 500 | "hoek": "4.2.0", 501 | "sntp": "2.0.2" 502 | } 503 | }, 504 | "hoek": { 505 | "version": "4.2.0", 506 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", 507 | "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", 508 | "dev": true 509 | }, 510 | "http-signature": { 511 | "version": "1.2.0", 512 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 513 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 514 | "dev": true, 515 | "requires": { 516 | "assert-plus": "1.0.0", 517 | "jsprim": "1.4.1", 518 | "sshpk": "1.13.1" 519 | } 520 | }, 521 | "inflight": { 522 | "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 523 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 524 | "dev": true, 525 | "requires": { 526 | "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 527 | "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 528 | } 529 | }, 530 | "inherits": { 531 | "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 532 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 533 | "dev": true 534 | }, 535 | "is-buffer": { 536 | "version": "1.1.5", 537 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", 538 | "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", 539 | "dev": true 540 | }, 541 | "is-typedarray": { 542 | "version": "1.0.0", 543 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 544 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 545 | "dev": true 546 | }, 547 | "isexe": { 548 | "version": "2.0.0", 549 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 550 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 551 | "dev": true 552 | }, 553 | "isstream": { 554 | "version": "0.1.2", 555 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 556 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 557 | "dev": true 558 | }, 559 | "istanbul": { 560 | "version": "0.4.5", 561 | "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", 562 | "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", 563 | "dev": true, 564 | "requires": { 565 | "abbrev": "1.0.9", 566 | "async": "1.5.2", 567 | "escodegen": "1.8.1", 568 | "esprima": "2.7.3", 569 | "glob": "5.0.15", 570 | "handlebars": "4.0.10", 571 | "js-yaml": "3.10.0", 572 | "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 573 | "nopt": "3.0.6", 574 | "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 575 | "resolve": "1.1.7", 576 | "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 577 | "which": "1.3.0", 578 | "wordwrap": "1.0.0" 579 | }, 580 | "dependencies": { 581 | "esprima": { 582 | "version": "2.7.3", 583 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", 584 | "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", 585 | "dev": true 586 | }, 587 | "glob": { 588 | "version": "5.0.15", 589 | "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", 590 | "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", 591 | "dev": true, 592 | "requires": { 593 | "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 594 | "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 595 | "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", 596 | "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 597 | "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 598 | } 599 | } 600 | } 601 | }, 602 | "js-yaml": { 603 | "version": "3.10.0", 604 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", 605 | "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", 606 | "dev": true, 607 | "requires": { 608 | "argparse": "1.0.9", 609 | "esprima": "4.0.0" 610 | } 611 | }, 612 | "jsbn": { 613 | "version": "0.1.1", 614 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 615 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 616 | "dev": true, 617 | "optional": true 618 | }, 619 | "json-schema": { 620 | "version": "0.2.3", 621 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 622 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 623 | "dev": true 624 | }, 625 | "json-schema-traverse": { 626 | "version": "0.3.1", 627 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 628 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 629 | "dev": true 630 | }, 631 | "json-stable-stringify": { 632 | "version": "1.0.1", 633 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 634 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 635 | "dev": true, 636 | "requires": { 637 | "jsonify": "0.0.0" 638 | } 639 | }, 640 | "json-stringify-safe": { 641 | "version": "5.0.1", 642 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 643 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 644 | "dev": true 645 | }, 646 | "json3": { 647 | "version": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 648 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 649 | "dev": true 650 | }, 651 | "jsonify": { 652 | "version": "0.0.0", 653 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 654 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 655 | "dev": true 656 | }, 657 | "jsprim": { 658 | "version": "1.4.1", 659 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 660 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 661 | "dev": true, 662 | "requires": { 663 | "assert-plus": "1.0.0", 664 | "extsprintf": "1.3.0", 665 | "json-schema": "0.2.3", 666 | "verror": "1.10.0" 667 | } 668 | }, 669 | "kind-of": { 670 | "version": "3.2.2", 671 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 672 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 673 | "dev": true, 674 | "requires": { 675 | "is-buffer": "1.1.5" 676 | } 677 | }, 678 | "lazy-cache": { 679 | "version": "1.0.4", 680 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 681 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", 682 | "dev": true, 683 | "optional": true 684 | }, 685 | "lcov-parse": { 686 | "version": "0.0.10", 687 | "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", 688 | "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", 689 | "dev": true 690 | }, 691 | "levn": { 692 | "version": "0.3.0", 693 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 694 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 695 | "dev": true, 696 | "requires": { 697 | "prelude-ls": "1.1.2", 698 | "type-check": "0.3.2" 699 | } 700 | }, 701 | "lodash._baseassign": { 702 | "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 703 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 704 | "dev": true, 705 | "requires": { 706 | "lodash._basecopy": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 707 | "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" 708 | } 709 | }, 710 | "lodash._basecopy": { 711 | "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 712 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 713 | "dev": true 714 | }, 715 | "lodash._basecreate": { 716 | "version": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 717 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 718 | "dev": true 719 | }, 720 | "lodash._getnative": { 721 | "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 722 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 723 | "dev": true 724 | }, 725 | "lodash._isiterateecall": { 726 | "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 727 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 728 | "dev": true 729 | }, 730 | "lodash.create": { 731 | "version": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 732 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 733 | "dev": true, 734 | "requires": { 735 | "lodash._baseassign": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 736 | "lodash._basecreate": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 737 | "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" 738 | } 739 | }, 740 | "lodash.isarguments": { 741 | "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 742 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 743 | "dev": true 744 | }, 745 | "lodash.isarray": { 746 | "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 747 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 748 | "dev": true 749 | }, 750 | "lodash.keys": { 751 | "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 752 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 753 | "dev": true, 754 | "requires": { 755 | "lodash._getnative": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 756 | "lodash.isarguments": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 757 | "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" 758 | } 759 | }, 760 | "log-driver": { 761 | "version": "1.2.5", 762 | "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", 763 | "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", 764 | "dev": true 765 | }, 766 | "longest": { 767 | "version": "1.0.1", 768 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 769 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", 770 | "dev": true 771 | }, 772 | "mime-db": { 773 | "version": "1.30.0", 774 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 775 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", 776 | "dev": true 777 | }, 778 | "mime-types": { 779 | "version": "2.1.17", 780 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 781 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 782 | "dev": true, 783 | "requires": { 784 | "mime-db": "1.30.0" 785 | } 786 | }, 787 | "minimatch": { 788 | "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", 789 | "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", 790 | "dev": true, 791 | "requires": { 792 | "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" 793 | } 794 | }, 795 | "minimist": { 796 | "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 797 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 798 | "dev": true 799 | }, 800 | "mkdirp": { 801 | "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 802 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 803 | "dev": true, 804 | "requires": { 805 | "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" 806 | } 807 | }, 808 | "mocha": { 809 | "version": "https://registry.npmjs.org/mocha/-/mocha-3.2.0.tgz", 810 | "integrity": "sha1-fcT0XlCIB1FxpoiWgU5q6et6heM=", 811 | "dev": true, 812 | "requires": { 813 | "browser-stdout": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 814 | "commander": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 815 | "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 816 | "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", 817 | "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 818 | "glob": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", 819 | "growl": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 820 | "json3": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 821 | "lodash.create": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 822 | "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 823 | "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz" 824 | } 825 | }, 826 | "ms": { 827 | "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 828 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", 829 | "dev": true 830 | }, 831 | "nopt": { 832 | "version": "3.0.6", 833 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", 834 | "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", 835 | "dev": true, 836 | "requires": { 837 | "abbrev": "1.0.9" 838 | } 839 | }, 840 | "oauth-sign": { 841 | "version": "0.8.2", 842 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 843 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", 844 | "dev": true 845 | }, 846 | "once": { 847 | "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 848 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 849 | "dev": true, 850 | "requires": { 851 | "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 852 | } 853 | }, 854 | "optimist": { 855 | "version": "0.6.1", 856 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 857 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 858 | "dev": true, 859 | "requires": { 860 | "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 861 | "wordwrap": "0.0.3" 862 | }, 863 | "dependencies": { 864 | "wordwrap": { 865 | "version": "0.0.3", 866 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 867 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 868 | "dev": true 869 | } 870 | } 871 | }, 872 | "optionator": { 873 | "version": "0.8.2", 874 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 875 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 876 | "dev": true, 877 | "requires": { 878 | "deep-is": "0.1.3", 879 | "fast-levenshtein": "2.0.6", 880 | "levn": "0.3.0", 881 | "prelude-ls": "1.1.2", 882 | "type-check": "0.3.2", 883 | "wordwrap": "1.0.0" 884 | } 885 | }, 886 | "path-is-absolute": { 887 | "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 888 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 889 | "dev": true 890 | }, 891 | "performance-now": { 892 | "version": "2.1.0", 893 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 894 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 895 | "dev": true 896 | }, 897 | "prelude-ls": { 898 | "version": "1.1.2", 899 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 900 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 901 | "dev": true 902 | }, 903 | "punycode": { 904 | "version": "1.4.1", 905 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 906 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 907 | "dev": true 908 | }, 909 | "qs": { 910 | "version": "6.5.1", 911 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 912 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", 913 | "dev": true 914 | }, 915 | "repeat-string": { 916 | "version": "1.6.1", 917 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 918 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", 919 | "dev": true 920 | }, 921 | "request": { 922 | "version": "2.83.0", 923 | "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", 924 | "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", 925 | "dev": true, 926 | "requires": { 927 | "aws-sign2": "0.7.0", 928 | "aws4": "1.6.0", 929 | "caseless": "0.12.0", 930 | "combined-stream": "1.0.5", 931 | "extend": "3.0.1", 932 | "forever-agent": "0.6.1", 933 | "form-data": "2.3.1", 934 | "har-validator": "5.0.3", 935 | "hawk": "6.0.2", 936 | "http-signature": "1.2.0", 937 | "is-typedarray": "1.0.0", 938 | "isstream": "0.1.2", 939 | "json-stringify-safe": "5.0.1", 940 | "mime-types": "2.1.17", 941 | "oauth-sign": "0.8.2", 942 | "performance-now": "2.1.0", 943 | "qs": "6.5.1", 944 | "safe-buffer": "5.1.1", 945 | "stringstream": "0.0.5", 946 | "tough-cookie": "2.3.3", 947 | "tunnel-agent": "0.6.0", 948 | "uuid": "3.1.0" 949 | } 950 | }, 951 | "resolve": { 952 | "version": "1.1.7", 953 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 954 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", 955 | "dev": true 956 | }, 957 | "right-align": { 958 | "version": "0.1.3", 959 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 960 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 961 | "dev": true, 962 | "optional": true, 963 | "requires": { 964 | "align-text": "0.1.4" 965 | } 966 | }, 967 | "safe-buffer": { 968 | "version": "5.1.1", 969 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 970 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 971 | "dev": true 972 | }, 973 | "sntp": { 974 | "version": "2.0.2", 975 | "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz", 976 | "integrity": "sha1-UGQRDwr4X3z9t9a2ekACjOUrSys=", 977 | "dev": true, 978 | "requires": { 979 | "hoek": "4.2.0" 980 | } 981 | }, 982 | "source-map": { 983 | "version": "0.2.0", 984 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", 985 | "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", 986 | "dev": true, 987 | "optional": true, 988 | "requires": { 989 | "amdefine": "1.0.1" 990 | } 991 | }, 992 | "sprintf-js": { 993 | "version": "1.0.3", 994 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 995 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 996 | "dev": true 997 | }, 998 | "sshpk": { 999 | "version": "1.13.1", 1000 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", 1001 | "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", 1002 | "dev": true, 1003 | "requires": { 1004 | "asn1": "0.2.3", 1005 | "assert-plus": "1.0.0", 1006 | "bcrypt-pbkdf": "1.0.1", 1007 | "dashdash": "1.14.1", 1008 | "ecc-jsbn": "0.1.1", 1009 | "getpass": "0.1.7", 1010 | "jsbn": "0.1.1", 1011 | "tweetnacl": "0.14.5" 1012 | } 1013 | }, 1014 | "stringstream": { 1015 | "version": "0.0.5", 1016 | "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", 1017 | "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", 1018 | "dev": true 1019 | }, 1020 | "supports-color": { 1021 | "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 1022 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 1023 | "dev": true, 1024 | "requires": { 1025 | "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" 1026 | } 1027 | }, 1028 | "tough-cookie": { 1029 | "version": "2.3.3", 1030 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", 1031 | "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", 1032 | "dev": true, 1033 | "requires": { 1034 | "punycode": "1.4.1" 1035 | } 1036 | }, 1037 | "tunnel-agent": { 1038 | "version": "0.6.0", 1039 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1040 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1041 | "dev": true, 1042 | "requires": { 1043 | "safe-buffer": "5.1.1" 1044 | } 1045 | }, 1046 | "tweetnacl": { 1047 | "version": "0.14.5", 1048 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1049 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1050 | "dev": true, 1051 | "optional": true 1052 | }, 1053 | "type-check": { 1054 | "version": "0.3.2", 1055 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1056 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1057 | "dev": true, 1058 | "requires": { 1059 | "prelude-ls": "1.1.2" 1060 | } 1061 | }, 1062 | "type-detect": { 1063 | "version": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", 1064 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", 1065 | "dev": true 1066 | }, 1067 | "uglify-js": { 1068 | "version": "2.8.29", 1069 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 1070 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 1071 | "dev": true, 1072 | "optional": true, 1073 | "requires": { 1074 | "source-map": "0.5.7", 1075 | "uglify-to-browserify": "1.0.2", 1076 | "yargs": "3.10.0" 1077 | }, 1078 | "dependencies": { 1079 | "source-map": { 1080 | "version": "0.5.7", 1081 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1082 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1083 | "dev": true, 1084 | "optional": true 1085 | } 1086 | } 1087 | }, 1088 | "uglify-to-browserify": { 1089 | "version": "1.0.2", 1090 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 1091 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 1092 | "dev": true, 1093 | "optional": true 1094 | }, 1095 | "uuid": { 1096 | "version": "3.1.0", 1097 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 1098 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", 1099 | "dev": true 1100 | }, 1101 | "verror": { 1102 | "version": "1.10.0", 1103 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1104 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1105 | "dev": true, 1106 | "requires": { 1107 | "assert-plus": "1.0.0", 1108 | "core-util-is": "1.0.2", 1109 | "extsprintf": "1.3.0" 1110 | } 1111 | }, 1112 | "which": { 1113 | "version": "1.3.0", 1114 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", 1115 | "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", 1116 | "dev": true, 1117 | "requires": { 1118 | "isexe": "2.0.0" 1119 | } 1120 | }, 1121 | "window-size": { 1122 | "version": "0.1.0", 1123 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 1124 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", 1125 | "dev": true, 1126 | "optional": true 1127 | }, 1128 | "wordwrap": { 1129 | "version": "1.0.0", 1130 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1131 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1132 | "dev": true 1133 | }, 1134 | "wrappy": { 1135 | "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1136 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1137 | "dev": true 1138 | }, 1139 | "yargs": { 1140 | "version": "3.10.0", 1141 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 1142 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 1143 | "dev": true, 1144 | "optional": true, 1145 | "requires": { 1146 | "camelcase": "1.2.1", 1147 | "cliui": "2.1.0", 1148 | "decamelize": "1.2.0", 1149 | "window-size": "0.1.0" 1150 | } 1151 | } 1152 | } 1153 | } 1154 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protect.js", 3 | "version": "3.1.0", 4 | "description": "Tool for protecting private properties", 5 | "main": "protect.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "devDependencies": { 10 | "chai": "^3.5.0", 11 | "coveralls": "^3.0.0", 12 | "istanbul": "^0.4.5", 13 | "mocha": "^3.0.1" 14 | }, 15 | "scripts": { 16 | "ut": "mocha tests --reporter min", 17 | "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha tests -- -R spec", 18 | "test": "istanbul cover ./node_modules/mocha/bin/_mocha tests --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/TremayneChrist/ProtectJS.git" 23 | }, 24 | "keywords": [ 25 | "private", 26 | "methods", 27 | "functions", 28 | "properties" 29 | ], 30 | "author": "Tremayne Christ", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/TremayneChrist/ProtectJS/issues" 34 | }, 35 | "homepage": "https://github.com/TremayneChrist/ProtectJS#readme" 36 | } 37 | -------------------------------------------------------------------------------- /protect.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | // The protect object 6 | this.protect = function (_O) { 7 | 8 | var callDepth = 0; // Stores the call depth of the current execution 9 | 10 | var locked = function () { 11 | return !callDepth; 12 | }; 13 | 14 | var O = _O.prototype || _O; // Protect the prototype, if there is one 15 | 16 | Object.keys(O).forEach(function (key) { 17 | 18 | var value = O[key]; // The original property value 19 | var isFunction = typeof value === 'function'; 20 | 21 | if (key.indexOf('_') === 0) { // Should the object be protected 22 | Object.defineProperty(O, key, { 23 | get: function () { 24 | if (locked()) { 25 | return undefined; 26 | } 27 | else { 28 | if (!isFunction) { 29 | return value; 30 | } 31 | return function () { 32 | return value.apply(this, arguments); 33 | }; 34 | } 35 | }, 36 | set: function () { 37 | if (!locked()) { 38 | value = arguments[0]; 39 | isFunction = typeof value === 'function'; 40 | } 41 | }, 42 | enumerable: false // Remove from Object.keys 43 | }); 44 | } 45 | else { // Allow functions to retrieve private properties 46 | Object.defineProperty(O, key, { 47 | get: function () { 48 | if (!isFunction) { 49 | return value; 50 | } 51 | return function () { 52 | var result; 53 | try { 54 | callDepth++; 55 | result = value.apply(this, arguments); 56 | } 57 | catch (e) { 58 | throw e; 59 | } 60 | finally { 61 | callDepth--; 62 | } 63 | return result; 64 | }; 65 | }, 66 | set: function () { 67 | value = arguments[0]; 68 | isFunction = false; // New functions cannot unlock private properties 69 | } 70 | }); 71 | } 72 | }); 73 | }; 74 | 75 | // Make it available for both Node and Browser 76 | if(typeof module !== 'undefined' && module.exports) { 77 | module.exports = this.protect; 78 | } 79 | 80 | }).call(this); 81 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/mocha.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body { 4 | margin:0; 5 | } 6 | 7 | #mocha { 8 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; 9 | margin: 60px 50px; 10 | } 11 | 12 | #mocha ul, 13 | #mocha li { 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | #mocha ul { 19 | list-style: none; 20 | } 21 | 22 | #mocha h1, 23 | #mocha h2 { 24 | margin: 0; 25 | } 26 | 27 | #mocha h1 { 28 | margin-top: 15px; 29 | font-size: 1em; 30 | font-weight: 200; 31 | } 32 | 33 | #mocha h1 a { 34 | text-decoration: none; 35 | color: inherit; 36 | } 37 | 38 | #mocha h1 a:hover { 39 | text-decoration: underline; 40 | } 41 | 42 | #mocha .suite .suite h1 { 43 | margin-top: 0; 44 | font-size: .8em; 45 | } 46 | 47 | #mocha .hidden { 48 | display: none; 49 | } 50 | 51 | #mocha h2 { 52 | font-size: 12px; 53 | font-weight: normal; 54 | cursor: pointer; 55 | } 56 | 57 | #mocha .suite { 58 | margin-left: 15px; 59 | } 60 | 61 | #mocha .test { 62 | margin-left: 15px; 63 | overflow: hidden; 64 | } 65 | 66 | #mocha .test.pending:hover h2::after { 67 | content: '(pending)'; 68 | font-family: arial, sans-serif; 69 | } 70 | 71 | #mocha .test.pass.medium .duration { 72 | background: #c09853; 73 | } 74 | 75 | #mocha .test.pass.slow .duration { 76 | background: #b94a48; 77 | } 78 | 79 | #mocha .test.pass::before { 80 | content: '✓'; 81 | font-size: 12px; 82 | display: block; 83 | float: left; 84 | margin-right: 5px; 85 | color: #00d6b2; 86 | } 87 | 88 | #mocha .test.pass .duration { 89 | font-size: 9px; 90 | margin-left: 5px; 91 | padding: 2px 5px; 92 | color: #fff; 93 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 94 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 95 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 96 | -webkit-border-radius: 5px; 97 | -moz-border-radius: 5px; 98 | -ms-border-radius: 5px; 99 | -o-border-radius: 5px; 100 | border-radius: 5px; 101 | } 102 | 103 | #mocha .test.pass.fast .duration { 104 | display: none; 105 | } 106 | 107 | #mocha .test.pending { 108 | color: #0b97c4; 109 | } 110 | 111 | #mocha .test.pending::before { 112 | content: '◦'; 113 | color: #0b97c4; 114 | } 115 | 116 | #mocha .test.fail { 117 | color: #c00; 118 | } 119 | 120 | #mocha .test.fail pre { 121 | color: black; 122 | } 123 | 124 | #mocha .test.fail::before { 125 | content: '✖'; 126 | font-size: 12px; 127 | display: block; 128 | float: left; 129 | margin-right: 5px; 130 | color: #c00; 131 | } 132 | 133 | #mocha .test pre.error { 134 | color: #c00; 135 | max-height: 300px; 136 | overflow: auto; 137 | } 138 | 139 | #mocha .test .html-error { 140 | overflow: auto; 141 | color: black; 142 | line-height: 1.5; 143 | display: block; 144 | float: left; 145 | clear: left; 146 | font: 12px/1.5 monaco, monospace; 147 | margin: 5px; 148 | padding: 15px; 149 | border: 1px solid #eee; 150 | max-width: 85%; /*(1)*/ 151 | max-width: -webkit-calc(100% - 42px); 152 | max-width: -moz-calc(100% - 42px); 153 | max-width: calc(100% - 42px); /*(2)*/ 154 | max-height: 300px; 155 | word-wrap: break-word; 156 | border-bottom-color: #ddd; 157 | -webkit-box-shadow: 0 1px 3px #eee; 158 | -moz-box-shadow: 0 1px 3px #eee; 159 | box-shadow: 0 1px 3px #eee; 160 | -webkit-border-radius: 3px; 161 | -moz-border-radius: 3px; 162 | border-radius: 3px; 163 | } 164 | 165 | #mocha .test .html-error pre.error { 166 | border: none; 167 | -webkit-border-radius: 0; 168 | -moz-border-radius: 0; 169 | border-radius: 0; 170 | -webkit-box-shadow: 0; 171 | -moz-box-shadow: 0; 172 | box-shadow: 0; 173 | padding: 0; 174 | margin: 0; 175 | margin-top: 18px; 176 | max-height: none; 177 | } 178 | 179 | /** 180 | * (1): approximate for browsers not supporting calc 181 | * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border) 182 | * ^^ seriously 183 | */ 184 | #mocha .test pre { 185 | display: block; 186 | float: left; 187 | clear: left; 188 | font: 12px/1.5 monaco, monospace; 189 | margin: 5px; 190 | padding: 15px; 191 | border: 1px solid #eee; 192 | max-width: 85%; /*(1)*/ 193 | max-width: -webkit-calc(100% - 42px); 194 | max-width: -moz-calc(100% - 42px); 195 | max-width: calc(100% - 42px); /*(2)*/ 196 | word-wrap: break-word; 197 | border-bottom-color: #ddd; 198 | -webkit-box-shadow: 0 1px 3px #eee; 199 | -moz-box-shadow: 0 1px 3px #eee; 200 | box-shadow: 0 1px 3px #eee; 201 | -webkit-border-radius: 3px; 202 | -moz-border-radius: 3px; 203 | border-radius: 3px; 204 | } 205 | 206 | #mocha .test h2 { 207 | position: relative; 208 | } 209 | 210 | #mocha .test a.replay { 211 | position: absolute; 212 | top: 3px; 213 | right: 0; 214 | text-decoration: none; 215 | vertical-align: middle; 216 | display: block; 217 | width: 15px; 218 | height: 15px; 219 | line-height: 15px; 220 | text-align: center; 221 | background: #eee; 222 | font-size: 15px; 223 | -webkit-border-radius: 15px; 224 | -moz-border-radius: 15px; 225 | border-radius: 15px; 226 | -webkit-transition:opacity 200ms; 227 | -moz-transition:opacity 200ms; 228 | -o-transition:opacity 200ms; 229 | transition: opacity 200ms; 230 | opacity: 0.3; 231 | color: #888; 232 | } 233 | 234 | #mocha .test:hover a.replay { 235 | opacity: 1; 236 | } 237 | 238 | #mocha-report.pass .test.fail { 239 | display: none; 240 | } 241 | 242 | #mocha-report.fail .test.pass { 243 | display: none; 244 | } 245 | 246 | #mocha-report.pending .test.pass, 247 | #mocha-report.pending .test.fail { 248 | display: none; 249 | } 250 | #mocha-report.pending .test.pass.pending { 251 | display: block; 252 | } 253 | 254 | #mocha-error { 255 | color: #c00; 256 | font-size: 1.5em; 257 | font-weight: 100; 258 | letter-spacing: 1px; 259 | } 260 | 261 | #mocha-stats { 262 | position: fixed; 263 | top: 15px; 264 | right: 10px; 265 | font-size: 12px; 266 | margin: 0; 267 | color: #888; 268 | z-index: 1; 269 | } 270 | 271 | #mocha-stats .progress { 272 | float: right; 273 | padding-top: 0; 274 | 275 | /** 276 | * Set safe initial values, so mochas .progress does not inherit these 277 | * properties from Bootstrap .progress (which causes .progress height to 278 | * equal line height set in Bootstrap). 279 | */ 280 | height: auto; 281 | -webkit-box-shadow: none; 282 | -moz-box-shadow: none; 283 | box-shadow: none; 284 | background-color: initial; 285 | } 286 | 287 | #mocha-stats em { 288 | color: black; 289 | } 290 | 291 | #mocha-stats a { 292 | text-decoration: none; 293 | color: inherit; 294 | } 295 | 296 | #mocha-stats a:hover { 297 | border-bottom: 1px solid #eee; 298 | } 299 | 300 | #mocha-stats li { 301 | display: inline-block; 302 | margin: 0 5px; 303 | list-style: none; 304 | padding-top: 11px; 305 | } 306 | 307 | #mocha-stats canvas { 308 | width: 40px; 309 | height: 40px; 310 | } 311 | 312 | #mocha code .comment { color: #ddd; } 313 | #mocha code .init { color: #2f6fad; } 314 | #mocha code .string { color: #5890ad; } 315 | #mocha code .keyword { color: #8a6343; } 316 | #mocha code .number { color: #2f6fad; } 317 | 318 | @media screen and (max-device-width: 480px) { 319 | #mocha { 320 | margin: 60px 0px; 321 | } 322 | 323 | #mocha #stats { 324 | position: absolute; 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | 2 | var fn; 3 | var testObject; 4 | var autoProtect; 5 | var protect = this.protect || require('../protect.js'); 6 | var chai = this.chai || require('chai'); 7 | var expect = chai.expect; 8 | 9 | describe('ProtectJS', function () { 10 | 11 | var test = function () { 12 | 13 | it('Should successfully protect the object', function () { 14 | fn = function () { 15 | protect(testObj); 16 | autoProtect = true; 17 | } 18 | // Should show all properties as enumerable 19 | expect(Object.keys(testObj.prototype || testObj)).lengthOf(16); 20 | // Should protect the object without any errors 21 | expect(fn).to.not.throw(); 22 | // Once protected, the enumerable values should only be public ones 23 | expect(Object.keys(testObj.prototype || testObj)).lengthOf(8); 24 | }); 25 | 26 | it('Should NOT return PRIVATE properties', function () { 27 | fn = function () { 28 | return testObj._function(); 29 | } 30 | expect(testObj._string).to.be.undefined; 31 | expect(testObj._number).to.be.undefined; 32 | expect(testObj._object).to.be.undefined; 33 | expect(testObj._null).to.be.undefined; 34 | expect(testObj._undefined).to.be.undefined; 35 | expect(testObj._function).to.be.undefined; 36 | expect(fn).to.throw(); 37 | }); 38 | 39 | it('Should return PUBLIC properties', function () { 40 | expect(testObj.string).to.equal('Hello Universe'); 41 | expect(testObj.number).to.equal(2016); 42 | expect(testObj.object).to.not.be.undefined; 43 | expect(testObj.null).to.be.null; 44 | expect(testObj.undefined).to.be.undefined; 45 | expect(testObj.function).to.not.throw(); 46 | expect(testObj.function()).to.equal('Hello Universe 2016'); 47 | }); 48 | 49 | it('Should allow PRIVATE methods to be called from PUBLIC ones', function () { 50 | fn = function () { 51 | return testObj.public(); 52 | } 53 | expect(fn).to.not.throw(); 54 | expect(function () { 55 | return testObj._private(); 56 | }).to.throw(); 57 | expect(fn()).to.equal(2016); 58 | }); 59 | 60 | it('Should allow PUBLIC strings to be set', function () { 61 | expect(testObj.string).to.equal('Hello Universe'); 62 | testObj.string = 'ProtectJS is cool!'; 63 | expect(testObj.string).to.equal('ProtectJS is cool!'); 64 | }); 65 | 66 | it('Should allow PUBLIC numbers to be set', function () { 67 | expect(testObj.number).to.equal(2016); 68 | testObj.number *= 2; 69 | expect(testObj.number).to.equal(4032); 70 | }); 71 | 72 | it('Should allow PUBLIC functions to be set', function () { 73 | var newFn = function () {}; 74 | expect(testObj.function).to.not.be.undefined; 75 | testObj.function = newFn; 76 | expect(testObj.function).to.equal(newFn); 77 | }); 78 | 79 | it('Should allow PUBLIC functions to set PUBLIC & PRIVATE properties', function () { 80 | var obj = testObj.object; 81 | var newObj = {}; 82 | expect(obj).to.not.equal(newObj); 83 | expect(testObj.setFunction(newObj)).to.equal(true); 84 | }); 85 | 86 | it('Should allow PUBLIC properties\' types to be changed', function () { 87 | fn = function () { return 'fn'; }; 88 | expect(testObj.number).to.equal(2016); 89 | testObj.number = 'hello'; 90 | expect(testObj.number).to.equal('hello'); 91 | testObj.number = fn; 92 | testObj.function = 123; 93 | expect(testObj.number).to.equal(fn); 94 | expect(testObj.number()).to.equal('fn'); 95 | expect(testObj.function).to.equal(123); 96 | }); 97 | 98 | it('Should allow new PUBLIC functions to access PUBLIC properties', function () { 99 | testObj.newFn = function () { return this.number; }; 100 | expect(testObj.newFn()).to.equal(2016); 101 | }); 102 | 103 | it('Should NOT allow new PUBLIC functions to access PRIVATE properties', function () { 104 | testObj.newFn = function () { return this._number; }; 105 | expect(testObj.newFn()).to.be.undefined; 106 | }); 107 | 108 | it('Should NOT allow modified PUBLIC functions to access private properties', function () { 109 | var newFn = function () { 110 | return 10 + this._private(); 111 | }; 112 | expect(testObj.public()).to.equal(2016); 113 | testObj.public = newFn; 114 | expect(testObj.public).to.throw(); 115 | }); 116 | 117 | it('Should NOT allow PRIVATE strings to be set', function () { 118 | expect(testObj._string).to.be.undefined; 119 | testObj._string = 'ProtectJS is cool!'; 120 | expect(testObj._string).to.be.undefined; 121 | }); 122 | 123 | it('Should NOT allow PRIVATE numbers to be set', function () { 124 | expect(testObj._number).to.be.undefined; 125 | testObj._number = 'ProtectJS is cool!'; 126 | expect(testObj._number).to.be.undefined; 127 | }); 128 | 129 | it('Should NOT allow PRIVATE functions to be set', function () { 130 | expect(testObj._function).to.be.undefined; 131 | testObj._function = function () {}; 132 | expect(testObj._function).to.be.undefined; 133 | }); 134 | 135 | it('Should NOT allow PRIVATE property access from other objects', function () { 136 | var obj2 = { 137 | fn: function () { 138 | return testObj._function(); 139 | }, 140 | prop: function () { 141 | return testObj._number + testObj._string; 142 | } 143 | }; 144 | 145 | // Unprotected 146 | expect(obj2.fn).to.throw(); 147 | expect(obj2.prop()).to.be.NaN; 148 | 149 | // Protected 150 | protect(obj2); 151 | expect(obj2.fn).to.throw(); 152 | expect(obj2.prop()).to.be.NaN; 153 | }); 154 | }; 155 | 156 | describe('Literal Objects', function () { 157 | 158 | before(function () { 159 | autoProtect = false; 160 | }); 161 | 162 | beforeEach(function () { 163 | 164 | testObj = { 165 | 166 | // Private 167 | '_string': 'Hello Universe', 168 | '_number': 2016, 169 | '_object': {}, 170 | '_null': null, 171 | '_undefined': undefined, 172 | '_function': function () { 173 | return [this._string, this.number].join(' '); 174 | }, 175 | 176 | // Public 177 | 'string': 'Hello Universe', 178 | 'number': 2016, 179 | 'object': {}, 180 | 'null': null, 181 | 'undefined': undefined, 182 | 'function': function () { 183 | return [this.string, this.number].join(' '); 184 | }, 185 | 186 | // Test functions 187 | setFunction: function (newObj) { 188 | this._object = newObj; 189 | return newObj === this._setFunction(); 190 | }, 191 | _setFunction: function () { 192 | this.object = this._object; 193 | return this.object; 194 | }, 195 | public: function () { 196 | return 10 + this._private(); 197 | }, 198 | _private: function() { 199 | return 2006; 200 | } 201 | 202 | }; 203 | 204 | if (autoProtect) { 205 | protect(testObj); 206 | } 207 | 208 | }); 209 | 210 | test(); // Run the generic tests 211 | 212 | }); 213 | 214 | describe('Instance Objects', function () { 215 | 216 | before(function () { 217 | autoProtect = false; 218 | }); 219 | 220 | beforeEach(function () { 221 | 222 | var MyObject = function () { 223 | 224 | // Private 225 | this._string = 'Hello Universe'; 226 | this._number = 2016; 227 | this._object = {}; 228 | this._null = null; 229 | this._undefined = undefined; 230 | this._function = function () { 231 | return [this.string, this.number].join(' '); 232 | }; 233 | 234 | // Public 235 | this.string = 'Hello Universe'; 236 | this.number = 2016; 237 | this.object = {}; 238 | this.null = null; 239 | this.undefined = undefined; 240 | this.function = function () { 241 | return [this.string, this.number].join(' '); 242 | }; 243 | 244 | // Test functions 245 | this.setFunction = function (newObj) { 246 | this._object = newObj; 247 | return newObj === this._setFunction(); 248 | } 249 | this._setFunction = function () { 250 | this.object = this._object; 251 | return this.object; 252 | } 253 | this.public = function () { 254 | return 10 + this._private(); 255 | } 256 | this._private = function () { 257 | return 2006; 258 | } 259 | 260 | if (autoProtect) { 261 | protect(this); 262 | } 263 | 264 | }; 265 | 266 | testObj = new MyObject(); 267 | 268 | }); 269 | 270 | test(); // Run the generic tests 271 | 272 | }); 273 | 274 | describe('Prototyped Objects', function () { 275 | 276 | before(function () { 277 | autoProtect = false; 278 | }); 279 | 280 | beforeEach(function () { 281 | 282 | var MyObject = function () {}; 283 | 284 | // Private 285 | MyObject.prototype._string = 'Hello Universe'; 286 | MyObject.prototype._number = 2016; 287 | MyObject.prototype._object = {}; 288 | MyObject.prototype._null = null; 289 | MyObject.prototype._undefined = undefined; 290 | MyObject.prototype._function = function () { 291 | return [this.string, this.number].join(' '); 292 | }; 293 | 294 | // Public 295 | MyObject.prototype.string = 'Hello Universe'; 296 | MyObject.prototype.number = 2016; 297 | MyObject.prototype.object = {}; 298 | MyObject.prototype.null = null; 299 | MyObject.prototype.undefined = undefined; 300 | MyObject.prototype.function = function () { 301 | return [this.string, this.number].join(' '); 302 | }; 303 | 304 | // Test functions 305 | MyObject.prototype.setFunction = function (newObj) { 306 | this._object = newObj; 307 | return newObj === this._setFunction(); 308 | } 309 | MyObject.prototype._setFunction = function () { 310 | this.object = this._object; 311 | return this.object; 312 | } 313 | MyObject.prototype.public = function () { 314 | return 10 + this._private(); 315 | } 316 | MyObject.prototype._private = function () { 317 | return 2006; 318 | } 319 | 320 | if (autoProtect) { 321 | protect(MyObject); 322 | testObj = new MyObject(); 323 | } 324 | else { 325 | testObj = MyObject; 326 | } 327 | 328 | }); 329 | 330 | test(); // Run the generic tests 331 | 332 | }); 333 | 334 | }); 335 | --------------------------------------------------------------------------------