├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── Readme.md ├── docs ├── Resources.md └── UnitTests.md ├── index.js ├── package-lock.json ├── package.json └── test ├── browser ├── sample.test.js └── testRunner.html ├── node ├── detectBrowserUnsupportedFeatures.test.js └── polyfillLoader.test.js └── utils ├── IE11.Config.js └── base.Config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 2 | .grunt 3 | 4 | # Dependency directories 5 | node_modules 6 | 7 | # Optional npm cache directory 8 | .npm 9 | npm-debug.log* -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 José Quinto 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Polyfill.io Features Detection in the browser 2 | Feature detection in the browser before loading polyfill using services like polyfill.io 3 | 4 | [![npm version](https://badge.fury.io/js/polyfill-io-feature-detection.svg)](https://badge.fury.io/js/polyfill-io-feature-detection) 5 | [![NSP Status](https://nodesecurity.io/orgs/jquinto/projects/97ba8357-aca4-44b2-b17a-62e69e9d0bd2/badge)](https://nodesecurity.io/orgs/jquinto/projects/97ba8357-aca4-44b2-b17a-62e69e9d0bd2) 6 | [![Code Climate](https://codeclimate.com/github/jquintozamora/polyfill-io-feature-detection/badges/gpa.svg)](https://codeclimate.com/github/jquintozamora/polyfill-io-feature-detection) 7 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/jquintozamora/polyfill-io-feature-detection/master/LICENSE) 8 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](Readme.md#want-to-contribute) 9 | 10 | [![NPM](https://nodei.co/npm/polyfill-io-feature-detection.png?downloads=true)](https://nodei.co/npm/polyfill-io-feature-detection/) 11 | 12 |
13 | 14 | ## When should I use polyfill-io-feature-detection? 15 | + You want to isolate your app code from the browser supported features (applying polyfills) 16 | + You have to add polyfills to yout web application because requires support to different browsers and devices 17 | + You want to use polyfill service like [polyfill.io](https://polyfill.io/v2/docs) instead of including the polyfills in your bundle 18 | + You want (should) to [load polyfills only when needed](https://philipwalton.com/articles/loading-polyfills-only-when-needed) 19 | + You want to optimize the experience for users on modern browser 20 | + You want to save the polyfill service call when possible (using this polyfillLoader) 21 | 22 | If you meet all these requirements, you probably will love this package. Because it allows you to load polyfills dynamically only when your browser really need it. 23 | 24 | 25 | ## Usage 26 | ```js 27 | function App () { 28 | // your app code here 29 | } 30 | 31 | import { polyfillLoader } from 'polyfill-io-feature-detection'; 32 | polyfillLoader({ 33 | "features": "Promise", 34 | "onCompleted": App 35 | }); 36 | ``` 37 | 38 | ## Usage with React 39 | ```js 40 | // index.jsx 41 | import React from 'react'; 42 | import {render} from 'react-dom'; 43 | import App from './containers/App.jsx'; 44 | 45 | import { polyfillLoader } from 'polyfill-io-feature-detection'; 46 | // This function load polyfills only if needed. By default it uses polyfill.io 47 | polyfillLoader({ 48 | "features": "Promise,fetch", 49 | "onCompleted": main 50 | }); 51 | 52 | // That function will be called after loading polyfills 53 | function main() { 54 | render( 55 | 56 | , document.getElementById('starter') 57 | ); 58 | } 59 | ``` 60 | More information: [Getting React to Load polyfills only when needed](https://blog.josequinto.com/2017/01/20/getting-react-to-load-polyfills-only-when-needed) 61 | 62 | ## Want to contribute? 63 | Anyone can help make this project better 64 | 65 | ## License 66 | (The MIT License) 67 | Copyright (c) 2017 Jose Quinto (https://blog.josequinto.com) 68 | 69 | 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: 70 | 71 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 72 | 73 | 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. 74 | -------------------------------------------------------------------------------- /docs/Resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | - [Load polyfills only when needed](https://philipwalton.com/articles/loading-polyfills-only-when-needed) 3 | - Feature Detection: 4 | - [Writing Polyfills](https://addyosmani.com/blog/writing-polyfills) 5 | - [An easier way of using polyfills](https://hacks.mozilla.org/2014/11/an-easier-way-of-using-polyfills) 6 | - [Polyfill.io feature detectin](https://polyfill.io/v2/docs/examples#feature-detection) 7 | - [Utility to convert between polyfill list and a query string representation](https://github.com/Financial-Times/polyfill-service/blob/master/service/PolyfillSet.js) 8 | - [Testing with Mocha and Proclaim](https://github.com/Financial-Times/polyfill-service/blob/master/test/node/lib/test_aliases.js) 9 | - [Using console.log asserts with Mocha and Chai without Stubbs](https://github.com/mochajs/mocha/wiki/Mess-with-globals) 10 | -------------------------------------------------------------------------------- /docs/UnitTests.md: -------------------------------------------------------------------------------- 1 | ## Unit Tests 2 | Testing Platform: Mocha 3 | Assert Library: Chai 4 | Testing folder structure: 5 | ``` 6 | test 7 | browser --> just a sample test folder, not used in the project 8 | node 9 | JS Unit test files 10 | utils 11 | IE11.Config.js --> specific IE11 window configuration for Testing 12 | ``` -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (!Array.prototype.filter) { 4 | Array.prototype.filter = function (func, thisArg) { 5 | 'use strict'; 6 | if (!((typeof func === 'Function' || typeof func === 'function') && this)) 7 | throw new TypeError(); 8 | 9 | var len = this.length >>> 0, 10 | res = new Array(len), // preallocate array 11 | t = this, c = 0, i = -1; 12 | if (thisArg === undefined) { 13 | while (++i !== len) { 14 | // checks to see if the key was set 15 | if (i in this) { 16 | if (func(t[i], i, t)) { 17 | res[c++] = t[i]; 18 | } 19 | } 20 | } 21 | } 22 | else { 23 | while (++i !== len) { 24 | // checks to see if the key was set 25 | if (i in this) { 26 | if (func.call(thisArg, t[i], i, t)) { 27 | res[c++] = t[i]; 28 | } 29 | } 30 | } 31 | } 32 | 33 | res.length = c; // shrink down array to proper size 34 | return res; 35 | }; 36 | } 37 | 38 | // Production steps of ECMA-262, Edition 5, 15.4.4.19 39 | // Reference: http://es5.github.io/#x15.4.4.19 40 | if (!Array.prototype.map) { 41 | Array.prototype.map = function (callback/*, thisArg*/) { 42 | 43 | var T, A, k; 44 | 45 | if (this == null) { 46 | throw new TypeError('this is null or not defined'); 47 | } 48 | 49 | // 1. Let O be the result of calling ToObject passing the |this| 50 | // value as the argument. 51 | var O = Object(this); 52 | 53 | // 2. Let lenValue be the result of calling the Get internal 54 | // method of O with the argument "length". 55 | // 3. Let len be ToUint32(lenValue). 56 | var len = O.length >>> 0; 57 | 58 | // 4. If IsCallable(callback) is false, throw a TypeError exception. 59 | // See: http://es5.github.com/#x9.11 60 | if (typeof callback !== 'function') { 61 | throw new TypeError(callback + ' is not a function'); 62 | } 63 | 64 | // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. 65 | if (arguments.length > 1) { 66 | T = arguments[1]; 67 | } 68 | 69 | // 6. Let A be a new array created as if by the expression new Array(len) 70 | // where Array is the standard built-in constructor with that name and 71 | // len is the value of len. 72 | A = new Array(len); 73 | 74 | // 7. Let k be 0 75 | k = 0; 76 | 77 | // 8. Repeat, while k < len 78 | while (k < len) { 79 | 80 | var kValue, mappedValue; 81 | 82 | // a. Let Pk be ToString(k). 83 | // This is implicit for LHS operands of the in operator 84 | // b. Let kPresent be the result of calling the HasProperty internal 85 | // method of O with argument Pk. 86 | // This step can be combined with c 87 | // c. If kPresent is true, then 88 | if (k in O) { 89 | 90 | // i. Let kValue be the result of calling the Get internal 91 | // method of O with argument Pk. 92 | kValue = O[k]; 93 | 94 | // ii. Let mappedValue be the result of calling the Call internal 95 | // method of callback with T as the this value and argument 96 | // list containing kValue, k, and O. 97 | mappedValue = callback.call(T, kValue, k, O); 98 | 99 | // For best browser support, use the following: 100 | A[k] = mappedValue; 101 | } 102 | // d. Increase k by 1. 103 | k++; 104 | } 105 | 106 | // 9. return A 107 | return A; 108 | }; 109 | } 110 | 111 | // Check each feature in the featureString parameter (comma separated) 112 | // and returns an array with all unsupported features for the current browser 113 | var detectBrowserUnsupportedFeatures = function (featureStringCommaSeparated) { 114 | var arrayFeatures = featureStringCommaSeparated 115 | .split(',') 116 | .filter(function (x) { return x.length }) 117 | .map(function (x) { return x.replace(/[\*\/]/g, '') }); // Eliminate XSS vuln 118 | var arrayUnsupportedFeatures = []; 119 | for (var i = 0; i < arrayFeatures.length; i++) { 120 | var supportedFeature = true; 121 | var fullFeature = arrayFeatures[i]; 122 | if (contains(fullFeature, "~")) { 123 | if (contains(fullFeature, "Intl.~locale")) { 124 | supportedFeature = checkIntlLocale(window, fullFeature); 125 | } else { 126 | console.warn('Feature ' + fullFeature + ' can not be detected because it has not JavaScript API.'); 127 | } 128 | } else { 129 | // Get the feature and the container Object 130 | var featureString = fullFeature.substring(fullFeature.lastIndexOf('.') + 1); 131 | if (contains(featureString, "@@")) { 132 | console.warn('Feature ' + featureString + ' can not be detected because it depends on Symbol.'); 133 | } else { 134 | var objectString = fullFeature.substring(0, fullFeature.lastIndexOf('.')); 135 | var object = getDescendantProp(window, objectString); 136 | if (object !== undefined) { 137 | //if ((object.hasOwnProperty(featureString)) === false) { 138 | if ((featureString in object) === false) { 139 | supportedFeature = false; 140 | } 141 | } else { 142 | supportedFeature = false; 143 | } 144 | } 145 | } 146 | // If the feature is not supported by the browser, then add it to polyfill it 147 | if (supportedFeature === false) { 148 | arrayUnsupportedFeatures.push(fullFeature); 149 | } 150 | } 151 | return arrayUnsupportedFeatures; 152 | } 153 | 154 | function checkIntlLocale(obj, feature) { 155 | var localeArray = feature.split("Intl.~locale"); 156 | var locale = ""; 157 | if (localeArray.length === 2) { 158 | var tempLocale = localeArray[1]; 159 | if (tempLocale && tempLocale !== "") { 160 | locale = tempLocale.replace(".", ""); 161 | 162 | if (!("Intl" in obj && 163 | "Collator" in obj.Intl && 164 | "supportedLocalesOf" in obj.Intl.Collator && 165 | obj.Intl.Collator.supportedLocalesOf(locale).length === 1 && 166 | "DateTimeFormat" in obj.Intl && 167 | "supportedLocalesOf" in obj.Intl.DateTimeFormat && 168 | obj.Intl.DateTimeFormat.supportedLocalesOf(locale).length === 1 && 169 | "NumberFormat" in obj.Intl && 170 | "supportedLocalesOf" in obj.Intl.NumberFormat && 171 | obj.Intl.NumberFormat.supportedLocalesOf(locale).length === 1)) { 172 | return false; 173 | } else { 174 | return true; 175 | } 176 | } else { 177 | console.warn('Feature ' + feature + ' has wrong Intl.~locale.XX format. For example Intl.~locale.en-US'); 178 | } 179 | } else { 180 | console.warn('Feature ' + feature + ' has wrong Intl.~locale format. For example Intl.~locale.en-US'); 181 | } 182 | // if any error, returns false 183 | return false; 184 | } 185 | 186 | // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/includes 187 | function contains(origin, search, start) { 188 | 'use strict'; 189 | if (typeof start !== 'number') { 190 | start = 0; 191 | } 192 | if (start + search.length > origin.length) { 193 | return false; 194 | } else { 195 | return origin.indexOf(search, start) !== -1; 196 | } 197 | } 198 | 199 | function getDescendantProp(obj, desc) { 200 | var arr = desc.split("."); 201 | if (arr.length > 0 && arr[0] !== "") { 202 | while (arr.length) { 203 | var name = arr.shift(); 204 | if (name in obj) { 205 | obj = obj[name]; 206 | } else { 207 | console.warn('[getDescendantProp] - ' + name + ' property does not exists.'); 208 | return undefined; 209 | } 210 | } 211 | } 212 | return obj; 213 | } 214 | 215 | function loadScript(src, done) { 216 | var finished = false 217 | 218 | function handleLoad() { 219 | if (!finished) { 220 | finished = true 221 | done(src) 222 | } 223 | } 224 | 225 | function handleReadyStateChange() { 226 | if (!finished) { 227 | if (script.readyState === 'complete') { 228 | handleLoad() 229 | } 230 | } 231 | } 232 | 233 | function handleError() { 234 | if (!finished) { 235 | finished = true 236 | done(new Error('Failed to load script ' + src)) 237 | } 238 | } 239 | var script = document.createElement('script') 240 | script.onload = handleLoad 241 | script.type = 'text/javascript' 242 | script.onreadystatechange = handleReadyStateChange 243 | script.onerror = handleError 244 | script.src = src 245 | document.head.appendChild(script) 246 | } 247 | 248 | var polyfillLoader = function (options) { 249 | var onCompleted = options.onCompleted; 250 | if (onCompleted === undefined) { 251 | return new Error("options.onCompleted function is required."); 252 | } 253 | var featureString = options.features || ''; 254 | var features = detectBrowserUnsupportedFeatures(featureString); 255 | if (features.length === 0) { 256 | onCompleted(); 257 | } else { 258 | var polyfillService = options.polyfillService || 'https://cdn.polyfill.io/v2/polyfill.min.js'; 259 | // https://polyfill.io/v2/docs/examples#feature-detection 260 | var polyfillServiceUrl = polyfillService + '?features=' + features.join(',') + '&flags=gated,always'; 261 | loadScript(polyfillServiceUrl, onCompleted); 262 | } 263 | } 264 | 265 | module.exports = { 266 | polyfillLoader: polyfillLoader, 267 | detectBrowserUnsupportedFeatures: detectBrowserUnsupportedFeatures 268 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polyfill-io-feature-detection", 3 | "version": "1.1.14", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ajv": { 8 | "version": "5.5.2", 9 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 10 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 11 | "dev": true, 12 | "requires": { 13 | "co": "^4.6.0", 14 | "fast-deep-equal": "^1.0.0", 15 | "fast-json-stable-stringify": "^2.0.0", 16 | "json-schema-traverse": "^0.3.0" 17 | } 18 | }, 19 | "asn1": { 20 | "version": "0.2.3", 21 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 22 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", 23 | "dev": true 24 | }, 25 | "assert-plus": { 26 | "version": "1.0.0", 27 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 28 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 29 | "dev": true 30 | }, 31 | "assertion-error": { 32 | "version": "1.1.0", 33 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 34 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 35 | "dev": true 36 | }, 37 | "asynckit": { 38 | "version": "0.4.0", 39 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 40 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 41 | "dev": true 42 | }, 43 | "aws-sign2": { 44 | "version": "0.7.0", 45 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 46 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 47 | "dev": true 48 | }, 49 | "aws4": { 50 | "version": "1.7.0", 51 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", 52 | "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", 53 | "dev": true 54 | }, 55 | "balanced-match": { 56 | "version": "1.0.0", 57 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 58 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 59 | "dev": true 60 | }, 61 | "bcrypt-pbkdf": { 62 | "version": "1.0.2", 63 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 64 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 65 | "dev": true, 66 | "optional": true, 67 | "requires": { 68 | "tweetnacl": "^0.14.3" 69 | } 70 | }, 71 | "brace-expansion": { 72 | "version": "1.1.11", 73 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 74 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 75 | "dev": true, 76 | "requires": { 77 | "balanced-match": "^1.0.0", 78 | "concat-map": "0.0.1" 79 | } 80 | }, 81 | "browser-stdout": { 82 | "version": "1.3.1", 83 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 84 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 85 | "dev": true 86 | }, 87 | "caseless": { 88 | "version": "0.12.0", 89 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 90 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 91 | "dev": true 92 | }, 93 | "chai": { 94 | "version": "4.1.2", 95 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", 96 | "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", 97 | "dev": true, 98 | "requires": { 99 | "assertion-error": "^1.0.1", 100 | "check-error": "^1.0.1", 101 | "deep-eql": "^3.0.0", 102 | "get-func-name": "^2.0.0", 103 | "pathval": "^1.0.0", 104 | "type-detect": "^4.0.0" 105 | } 106 | }, 107 | "chai-as-promised": { 108 | "version": "5.3.0", 109 | "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-5.3.0.tgz", 110 | "integrity": "sha1-CdekApCKpw39vq1T5YU/x50+8hw=", 111 | "dev": true 112 | }, 113 | "chai-subset": { 114 | "version": "1.6.0", 115 | "resolved": "https://registry.npmjs.org/chai-subset/-/chai-subset-1.6.0.tgz", 116 | "integrity": "sha1-pdDKFOMpp5WW7XAFi2ZGvWmIz+k=", 117 | "dev": true 118 | }, 119 | "chakram": { 120 | "version": "1.5.0", 121 | "resolved": "https://registry.npmjs.org/chakram/-/chakram-1.5.0.tgz", 122 | "integrity": "sha1-PYsKiPdo3WraWSpSRmPMDcFKwc8=", 123 | "dev": true, 124 | "requires": { 125 | "chai": "3.x.x", 126 | "chai-as-promised": "5.x.x", 127 | "chai-subset": "1.x.x", 128 | "extend-object": "1.x.x", 129 | "q": "1.x.x", 130 | "request": "2.x.x", 131 | "request-debug": "0.x.x", 132 | "tv4": "1.x.x" 133 | }, 134 | "dependencies": { 135 | "chai": { 136 | "version": "3.5.0", 137 | "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", 138 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", 139 | "dev": true, 140 | "requires": { 141 | "assertion-error": "^1.0.1", 142 | "deep-eql": "^0.1.3", 143 | "type-detect": "^1.0.0" 144 | } 145 | }, 146 | "deep-eql": { 147 | "version": "0.1.3", 148 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", 149 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", 150 | "dev": true, 151 | "requires": { 152 | "type-detect": "0.1.1" 153 | }, 154 | "dependencies": { 155 | "type-detect": { 156 | "version": "0.1.1", 157 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", 158 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", 159 | "dev": true 160 | } 161 | } 162 | }, 163 | "type-detect": { 164 | "version": "1.0.0", 165 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", 166 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", 167 | "dev": true 168 | } 169 | } 170 | }, 171 | "check-error": { 172 | "version": "1.0.2", 173 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 174 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 175 | "dev": true 176 | }, 177 | "co": { 178 | "version": "4.6.0", 179 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 180 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 181 | "dev": true 182 | }, 183 | "combined-stream": { 184 | "version": "1.0.6", 185 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", 186 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", 187 | "dev": true, 188 | "requires": { 189 | "delayed-stream": "~1.0.0" 190 | } 191 | }, 192 | "commander": { 193 | "version": "2.15.1", 194 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 195 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", 196 | "dev": true 197 | }, 198 | "concat-map": { 199 | "version": "0.0.1", 200 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 201 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 202 | "dev": true 203 | }, 204 | "core-util-is": { 205 | "version": "1.0.2", 206 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 207 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 208 | "dev": true 209 | }, 210 | "dashdash": { 211 | "version": "1.14.1", 212 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 213 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 214 | "dev": true, 215 | "requires": { 216 | "assert-plus": "^1.0.0" 217 | } 218 | }, 219 | "debug": { 220 | "version": "3.1.0", 221 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 222 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 223 | "dev": true, 224 | "requires": { 225 | "ms": "2.0.0" 226 | } 227 | }, 228 | "deep-eql": { 229 | "version": "3.0.1", 230 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 231 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 232 | "dev": true, 233 | "requires": { 234 | "type-detect": "^4.0.0" 235 | } 236 | }, 237 | "delayed-stream": { 238 | "version": "1.0.0", 239 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 240 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 241 | "dev": true 242 | }, 243 | "diff": { 244 | "version": "3.5.0", 245 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 246 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 247 | "dev": true 248 | }, 249 | "ecc-jsbn": { 250 | "version": "0.1.1", 251 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 252 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 253 | "dev": true, 254 | "optional": true, 255 | "requires": { 256 | "jsbn": "~0.1.0" 257 | } 258 | }, 259 | "escape-string-regexp": { 260 | "version": "1.0.5", 261 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 262 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 263 | "dev": true 264 | }, 265 | "extend": { 266 | "version": "3.0.2", 267 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 268 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 269 | "dev": true 270 | }, 271 | "extend-object": { 272 | "version": "1.0.0", 273 | "resolved": "https://registry.npmjs.org/extend-object/-/extend-object-1.0.0.tgz", 274 | "integrity": "sha1-QlFPhAFdE1bK9Rh5ad+yvBvaCCM=", 275 | "dev": true 276 | }, 277 | "extsprintf": { 278 | "version": "1.3.0", 279 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 280 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 281 | "dev": true 282 | }, 283 | "fast-deep-equal": { 284 | "version": "1.1.0", 285 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 286 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", 287 | "dev": true 288 | }, 289 | "fast-json-stable-stringify": { 290 | "version": "2.0.0", 291 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 292 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 293 | "dev": true 294 | }, 295 | "forever-agent": { 296 | "version": "0.6.1", 297 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 298 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 299 | "dev": true 300 | }, 301 | "form-data": { 302 | "version": "2.3.2", 303 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", 304 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", 305 | "dev": true, 306 | "requires": { 307 | "asynckit": "^0.4.0", 308 | "combined-stream": "1.0.6", 309 | "mime-types": "^2.1.12" 310 | } 311 | }, 312 | "fs.realpath": { 313 | "version": "1.0.0", 314 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 315 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 316 | "dev": true 317 | }, 318 | "get-func-name": { 319 | "version": "2.0.0", 320 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 321 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 322 | "dev": true 323 | }, 324 | "getpass": { 325 | "version": "0.1.7", 326 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 327 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 328 | "dev": true, 329 | "requires": { 330 | "assert-plus": "^1.0.0" 331 | } 332 | }, 333 | "glob": { 334 | "version": "7.1.2", 335 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 336 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 337 | "dev": true, 338 | "requires": { 339 | "fs.realpath": "^1.0.0", 340 | "inflight": "^1.0.4", 341 | "inherits": "2", 342 | "minimatch": "^3.0.4", 343 | "once": "^1.3.0", 344 | "path-is-absolute": "^1.0.0" 345 | } 346 | }, 347 | "growl": { 348 | "version": "1.10.5", 349 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 350 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 351 | "dev": true 352 | }, 353 | "har-schema": { 354 | "version": "2.0.0", 355 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 356 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 357 | "dev": true 358 | }, 359 | "har-validator": { 360 | "version": "5.0.3", 361 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", 362 | "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", 363 | "dev": true, 364 | "requires": { 365 | "ajv": "^5.1.0", 366 | "har-schema": "^2.0.0" 367 | } 368 | }, 369 | "has-flag": { 370 | "version": "3.0.0", 371 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 372 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 373 | "dev": true 374 | }, 375 | "he": { 376 | "version": "1.1.1", 377 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 378 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 379 | "dev": true 380 | }, 381 | "http-signature": { 382 | "version": "1.2.0", 383 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 384 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 385 | "dev": true, 386 | "requires": { 387 | "assert-plus": "^1.0.0", 388 | "jsprim": "^1.2.2", 389 | "sshpk": "^1.7.0" 390 | } 391 | }, 392 | "inflight": { 393 | "version": "1.0.6", 394 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 395 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 396 | "dev": true, 397 | "requires": { 398 | "once": "^1.3.0", 399 | "wrappy": "1" 400 | } 401 | }, 402 | "inherits": { 403 | "version": "2.0.3", 404 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 405 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 406 | "dev": true 407 | }, 408 | "is-typedarray": { 409 | "version": "1.0.0", 410 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 411 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 412 | "dev": true 413 | }, 414 | "isstream": { 415 | "version": "0.1.2", 416 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 417 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 418 | "dev": true 419 | }, 420 | "jsbn": { 421 | "version": "0.1.1", 422 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 423 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 424 | "dev": true, 425 | "optional": true 426 | }, 427 | "json-schema": { 428 | "version": "0.2.3", 429 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 430 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 431 | "dev": true 432 | }, 433 | "json-schema-traverse": { 434 | "version": "0.3.1", 435 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 436 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 437 | "dev": true 438 | }, 439 | "json-stringify-safe": { 440 | "version": "5.0.1", 441 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 442 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 443 | "dev": true 444 | }, 445 | "jsprim": { 446 | "version": "1.4.1", 447 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 448 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 449 | "dev": true, 450 | "requires": { 451 | "assert-plus": "1.0.0", 452 | "extsprintf": "1.3.0", 453 | "json-schema": "0.2.3", 454 | "verror": "1.10.0" 455 | } 456 | }, 457 | "mime-db": { 458 | "version": "1.35.0", 459 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", 460 | "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", 461 | "dev": true 462 | }, 463 | "mime-types": { 464 | "version": "2.1.19", 465 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", 466 | "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", 467 | "dev": true, 468 | "requires": { 469 | "mime-db": "~1.35.0" 470 | } 471 | }, 472 | "minimatch": { 473 | "version": "3.0.4", 474 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 475 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 476 | "dev": true, 477 | "requires": { 478 | "brace-expansion": "^1.1.7" 479 | } 480 | }, 481 | "minimist": { 482 | "version": "0.0.8", 483 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 484 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 485 | "dev": true 486 | }, 487 | "mkdirp": { 488 | "version": "0.5.1", 489 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 490 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 491 | "dev": true, 492 | "requires": { 493 | "minimist": "0.0.8" 494 | } 495 | }, 496 | "mocha": { 497 | "version": "5.2.0", 498 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", 499 | "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", 500 | "dev": true, 501 | "requires": { 502 | "browser-stdout": "1.3.1", 503 | "commander": "2.15.1", 504 | "debug": "3.1.0", 505 | "diff": "3.5.0", 506 | "escape-string-regexp": "1.0.5", 507 | "glob": "7.1.2", 508 | "growl": "1.10.5", 509 | "he": "1.1.1", 510 | "minimatch": "3.0.4", 511 | "mkdirp": "0.5.1", 512 | "supports-color": "5.4.0" 513 | } 514 | }, 515 | "ms": { 516 | "version": "2.0.0", 517 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 518 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 519 | "dev": true 520 | }, 521 | "oauth-sign": { 522 | "version": "0.8.2", 523 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 524 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", 525 | "dev": true 526 | }, 527 | "once": { 528 | "version": "1.4.0", 529 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 530 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 531 | "dev": true, 532 | "requires": { 533 | "wrappy": "1" 534 | } 535 | }, 536 | "path-is-absolute": { 537 | "version": "1.0.1", 538 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 539 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 540 | "dev": true 541 | }, 542 | "pathval": { 543 | "version": "1.1.0", 544 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 545 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", 546 | "dev": true 547 | }, 548 | "performance-now": { 549 | "version": "2.1.0", 550 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 551 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 552 | "dev": true 553 | }, 554 | "punycode": { 555 | "version": "1.4.1", 556 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 557 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 558 | "dev": true 559 | }, 560 | "q": { 561 | "version": "1.5.1", 562 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 563 | "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", 564 | "dev": true 565 | }, 566 | "qs": { 567 | "version": "6.5.2", 568 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 569 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 570 | "dev": true 571 | }, 572 | "request": { 573 | "version": "2.87.0", 574 | "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", 575 | "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", 576 | "dev": true, 577 | "requires": { 578 | "aws-sign2": "~0.7.0", 579 | "aws4": "^1.6.0", 580 | "caseless": "~0.12.0", 581 | "combined-stream": "~1.0.5", 582 | "extend": "~3.0.1", 583 | "forever-agent": "~0.6.1", 584 | "form-data": "~2.3.1", 585 | "har-validator": "~5.0.3", 586 | "http-signature": "~1.2.0", 587 | "is-typedarray": "~1.0.0", 588 | "isstream": "~0.1.2", 589 | "json-stringify-safe": "~5.0.1", 590 | "mime-types": "~2.1.17", 591 | "oauth-sign": "~0.8.2", 592 | "performance-now": "^2.1.0", 593 | "qs": "~6.5.1", 594 | "safe-buffer": "^5.1.1", 595 | "tough-cookie": "~2.3.3", 596 | "tunnel-agent": "^0.6.0", 597 | "uuid": "^3.1.0" 598 | } 599 | }, 600 | "request-debug": { 601 | "version": "0.2.0", 602 | "resolved": "https://registry.npmjs.org/request-debug/-/request-debug-0.2.0.tgz", 603 | "integrity": "sha1-/AVOyBcYGwTKQaBSwTb2HEirr3g=", 604 | "dev": true, 605 | "requires": { 606 | "stringify-clone": "^1.0.0" 607 | } 608 | }, 609 | "safe-buffer": { 610 | "version": "5.1.2", 611 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 612 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 613 | "dev": true 614 | }, 615 | "safer-buffer": { 616 | "version": "2.1.2", 617 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 618 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 619 | "dev": true 620 | }, 621 | "sshpk": { 622 | "version": "1.14.2", 623 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", 624 | "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", 625 | "dev": true, 626 | "requires": { 627 | "asn1": "~0.2.3", 628 | "assert-plus": "^1.0.0", 629 | "bcrypt-pbkdf": "^1.0.0", 630 | "dashdash": "^1.12.0", 631 | "ecc-jsbn": "~0.1.1", 632 | "getpass": "^0.1.1", 633 | "jsbn": "~0.1.0", 634 | "safer-buffer": "^2.0.2", 635 | "tweetnacl": "~0.14.0" 636 | } 637 | }, 638 | "stringify-clone": { 639 | "version": "1.1.1", 640 | "resolved": "https://registry.npmjs.org/stringify-clone/-/stringify-clone-1.1.1.tgz", 641 | "integrity": "sha1-MJojX7Ts/M19OI2+GLqQT6yvQzs=", 642 | "dev": true 643 | }, 644 | "supports-color": { 645 | "version": "5.4.0", 646 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 647 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 648 | "dev": true, 649 | "requires": { 650 | "has-flag": "^3.0.0" 651 | } 652 | }, 653 | "tough-cookie": { 654 | "version": "2.3.4", 655 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", 656 | "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", 657 | "dev": true, 658 | "requires": { 659 | "punycode": "^1.4.1" 660 | } 661 | }, 662 | "tunnel-agent": { 663 | "version": "0.6.0", 664 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 665 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 666 | "dev": true, 667 | "requires": { 668 | "safe-buffer": "^5.0.1" 669 | } 670 | }, 671 | "tv4": { 672 | "version": "1.3.0", 673 | "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", 674 | "integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM=", 675 | "dev": true 676 | }, 677 | "tweetnacl": { 678 | "version": "0.14.5", 679 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 680 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 681 | "dev": true, 682 | "optional": true 683 | }, 684 | "type-detect": { 685 | "version": "4.0.8", 686 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 687 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 688 | "dev": true 689 | }, 690 | "uuid": { 691 | "version": "3.3.2", 692 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 693 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 694 | "dev": true 695 | }, 696 | "verror": { 697 | "version": "1.10.0", 698 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 699 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 700 | "dev": true, 701 | "requires": { 702 | "assert-plus": "^1.0.0", 703 | "core-util-is": "1.0.2", 704 | "extsprintf": "^1.2.0" 705 | } 706 | }, 707 | "wrappy": { 708 | "version": "1.0.2", 709 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 710 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 711 | "dev": true 712 | } 713 | } 714 | } 715 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polyfill-io-feature-detection", 3 | "version": "1.1.14", 4 | "description": "Feature detection in the browser before loading polyfill using services like polyfill.io", 5 | "license": "MIT", 6 | "main": "index.js", 7 | "author": "Jose Quinto (https://blog.josequinto.com)", 8 | "scripts": { 9 | "pretest": "npm install", 10 | "test": "mocha test/node/detectBrowserUnsupportedFeatures.test.js", 11 | "pretestLoaders": "npm install", 12 | "testLoader": "mocha test/node/polyfillLoader.test.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/jquintozamora/polyfill-io-feature-detection" 17 | }, 18 | "keywords": [ 19 | "polyfill.io", 20 | "feature", 21 | "detection", 22 | "polyfill", 23 | "detect", 24 | "pre-detect", 25 | "supported", 26 | "browser" 27 | ], 28 | "devDependencies": { 29 | "chai": "4.1.2", 30 | "chakram": "1.5.0", 31 | "mocha": "5.2.0" 32 | }, 33 | "dependencies": {} 34 | } 35 | -------------------------------------------------------------------------------- /test/browser/sample.test.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = chai.assert; 3 | 4 | describe('Array', function() { 5 | it('should start empty', function() { 6 | var arr = []; 7 | 8 | assert.equal(arr.length, 0); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/browser/testRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha Tests 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /test/node/detectBrowserUnsupportedFeatures.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | Unit Tests for detectBrowserUnsupportedFeatures function 3 | */ 4 | 5 | 'use strict'; 6 | var expect = require('chai').expect; 7 | var polyfillLoader = require('./../../index.js'); 8 | 9 | describe('Browser Feature detection Tests for IE 11', function () { 10 | var warn, warnOutput = ''; 11 | 12 | before(function () { 13 | // runs before all tests in this block 14 | // Import IE11 window configs. 15 | window = require('./../utils/IE11.Config').configs(); 16 | }); 17 | 18 | // mocking or stubbing console is not needed, we could use this: https://github.com/mochajs/mocha/wiki/Mess-with-globals 19 | // restore console.warn 20 | var cleanup = function () { 21 | console.warn = warn; 22 | warnOutput = ""; 23 | }; 24 | beforeEach(function () { 25 | // store these functions to restore later because we are messing with them 26 | warn = console.warn; 27 | // our stub will concatenate any output to a string 28 | console.warn = function (s) { 29 | warnOutput += s; 30 | }; 31 | }); 32 | // restore after each test 33 | afterEach(cleanup); 34 | 35 | it('should detect Promise as unsupported feature', function () { 36 | var features = "Promise"; 37 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["Promise"]); 38 | }); 39 | 40 | it('should detect Array.isArray as supported feature', function () { 41 | var features = "Array.isArray"; 42 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq([]); 43 | }); 44 | 45 | it('should strip out more than one supported features', function () { 46 | var features = "Array.isArray,Date.now,Element.prototype.dataset,Object.defineProperties"; 47 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq([]); 48 | }); 49 | 50 | it('should return more than one unsupported features', function () { 51 | var features = "Array.from,Array.prototype.fill,AudioContext,Promise,Element.prototype.append,Math.trunc,Object.is,Symbol.iterator"; 52 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["Array.from", 53 | "Array.prototype.fill", 54 | "AudioContext", 55 | "Promise", 56 | "Element.prototype.append", 57 | "Math.trunc", 58 | "Object.is", 59 | "Symbol.iterator"]); 60 | try { 61 | expect(warnOutput).to.equal('[getDescendantProp] - Symbol property does not exists.'); 62 | } 63 | catch (e) { 64 | cleanup(); 65 | throw e; 66 | } 67 | }); 68 | 69 | it('should warn when not object exists getting the descendants of a complex object', function () { 70 | var features = "Symbol.iterator"; 71 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["Symbol.iterator"]); 72 | try { 73 | expect(warnOutput).to.equal('[getDescendantProp] - Symbol property does not exists.'); 74 | } 75 | catch (e) { 76 | cleanup(); 77 | throw e; 78 | } 79 | }); 80 | 81 | 82 | it('should warn when a feature can not be detected because has not JavaScript API', function () { 83 | var features = "~html5-elements"; 84 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq([]); 85 | try { 86 | expect(warnOutput).to.equal('Feature ~html5-elements can not be detected because it has not JavaScript API.'); 87 | } 88 | catch (e) { 89 | cleanup(); 90 | throw e; 91 | } 92 | }); 93 | 94 | 95 | it('should warn when a feature can not be detected because has not JavaScript API, but still detect other unsupported features', function () { 96 | var features = "Promise,~html5-elements"; 97 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["Promise"]); 98 | try { 99 | expect(warnOutput).to.equal('Feature ~html5-elements can not be detected because it has not JavaScript API.'); 100 | } 101 | catch (e) { 102 | cleanup(); 103 | throw e; 104 | } 105 | }); 106 | 107 | 108 | it('should warn when a feature can not be detected because it depends on Symbol', function () { 109 | var features = "Array.prototype.@@iterator"; 110 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq([]); 111 | try { 112 | expect(warnOutput).to.equal('Feature @@iterator can not be detected because it depends on Symbol.'); 113 | } 114 | catch (e) { 115 | cleanup(); 116 | throw e; 117 | } 118 | }); 119 | 120 | 121 | it('should warn when a feature can not be detected because it depends on Symbol, but still detect other unsupported features', function () { 122 | var features = "Promise,Array.prototype.@@iterator"; 123 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["Promise"]); 124 | try { 125 | expect(warnOutput).to.equal('Feature @@iterator can not be detected because it depends on Symbol.'); 126 | } 127 | catch (e) { 128 | cleanup(); 129 | throw e; 130 | } 131 | }); 132 | 133 | 134 | it('should add any random string as a unsupported feature. TODO: To check features in the list of available polyfills.', function () { 135 | // Available polyfills: https://github.com/Financial-Times/polyfill-service/blob/master/docs/assets/compat.json 136 | var features = "ramdom-String=+£$"; 137 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["ramdom-String=+£$"]); 138 | // Note that polyfill.io service will bring empty file when request the feature ramdom-String=+£$ 139 | }); 140 | 141 | it('should detect Intl.~locale.en-US as unsupported feature.', function () { 142 | // Available polyfills: https://github.com/Financial-Times/polyfill-service/blob/master/docs/assets/compat.json 143 | var features = "Intl.~locale.en-US"; 144 | expect(polyfillLoader.detectBrowserUnsupportedFeatures(features)).to.be.deep.eq(["Intl.~locale.en-US"]); 145 | }); 146 | 147 | 148 | 149 | }); 150 | -------------------------------------------------------------------------------- /test/node/polyfillLoader.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | Unit Tests for polyfillLoader function 3 | */ 4 | 5 | 'use strict'; 6 | var expect = require('chai').expect; 7 | var pf = require('./../../index.js'); 8 | var chakram = require('chakram'); 9 | 10 | describe('Polyfill Loader Tests for IE 11', function () { 11 | 12 | before(function () { 13 | // runs before all tests in this block 14 | // Import IE11 window configs. 15 | window = require('./../utils/IE11.Config').configs(); 16 | 17 | global.document = {}; 18 | document.createElement = function (tag) { return { src: "", onload: function () { }, onerror: function () { } }; }; 19 | document.head = {}; 20 | document.head.appendChild = function (obj) { 21 | setTimeout(function () { 22 | if (obj.src.indexOf("https://error") > -1) { 23 | obj.onerror(); 24 | } else { 25 | if (obj.onload) { 26 | obj.onload(); 27 | } else { 28 | obj.onerror(); 29 | } 30 | } 31 | }, 500); 32 | }; 33 | }); 34 | 35 | 36 | it('should call main with the polyfill url as a parameter', function (done) { 37 | var features = "Promise,fetch,Object.is"; 38 | function main(data) { 39 | expect(data).to.eq("https://cdn.polyfill.io/v2/polyfill.min.js?features=Promise,fetch,Object.is&flags=gated,always"); 40 | // this test is done, go to the next one 41 | done(); 42 | } 43 | pf.polyfillLoader({ 44 | "onCompleted": main, 45 | "features": features 46 | }); 47 | }); 48 | 49 | 50 | it('should call main with the polyfill url as a parameter filtered by only not supported features', function (done) { 51 | var features = "Promise,Date.now"; 52 | function main(data) { 53 | expect(data).to.eq("https://cdn.polyfill.io/v2/polyfill.min.js?features=Promise&flags=gated,always"); 54 | // this test is done, go to the next one 55 | done(); 56 | } 57 | pf.polyfillLoader({ 58 | "onCompleted": main, 59 | "features": features 60 | }); 61 | }); 62 | 63 | it('should call main with no parameters as all the features are supported by the browser', function (done) { 64 | var features = "Array.prototype.filter,Date.now"; 65 | function main(data) { 66 | expect(data).to.eq(undefined); 67 | // this test is done, go to the next one 68 | done(); 69 | } 70 | pf.polyfillLoader({ 71 | "onCompleted": main, 72 | "features": features 73 | }); 74 | }); 75 | 76 | it('should call my custom service if configured as parameter polyfillService', function (done) { 77 | var features = "Promise"; 78 | function main(data) { 79 | expect(data).to.eq('https://myservice?features=Promise&flags=gated,always'); 80 | // this test is done, go to the next one 81 | done(); 82 | } 83 | pf.polyfillLoader({ 84 | "onCompleted": main, 85 | "features": features, 86 | "polyfillService": "https://myservice" 87 | }); 88 | }); 89 | 90 | it('should call main with error parameter when failed to load the script', function (done) { 91 | var features = "Promise"; 92 | function main(data) { 93 | expect(data.toString()).to.eq((new Error('Failed to load script https://error?features=Promise&flags=gated,always')).toString()); 94 | // this test is done, go to the next one 95 | done(); 96 | } 97 | pf.polyfillLoader({ 98 | "onCompleted": main, 99 | "features": features, 100 | "polyfillService": "https://error" 101 | }); 102 | }); 103 | 104 | 105 | it("should have polyfill.io service enable on default and returning 200 status", function (done) { 106 | // this.timeout(5000); 107 | var features = "Promise,Date.now"; 108 | function main(data) { 109 | expect(data).to.eq("https://cdn.polyfill.io/v2/polyfill.min.js?features=Promise&flags=gated,always"); 110 | var Ie11UA = "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"; 111 | return chakram.get(data + "&ua=" + encodeURIComponent(Ie11UA)) 112 | .then(function (response) { 113 | chakram.expect(response).to.have.status(200); 114 | done(); 115 | }); 116 | } 117 | pf.polyfillLoader({ 118 | "onCompleted": main, 119 | "features": features 120 | }); 121 | }); 122 | 123 | }); 124 | -------------------------------------------------------------------------------- /test/utils/IE11.Config.js: -------------------------------------------------------------------------------- 1 | // Testing Configuration for IE 11 2 | // Source: https://polyfill.io/v2/docs/features/#feature-list 3 | // TODO: Add support to iterators 4 | 5 | exports.configs = function () { 6 | window = {}; 7 | window.Array = {}; 8 | //window.Array.from = function () { }; 9 | window.Array.isArray = function () { }; 10 | //window.Array.of = function () { }; 11 | //window.Array.prototype.@@iterator = function() {}; // no 12 | window.Array.prototype = {}; 13 | //window.Array.prototype.contains = function () { }; 14 | //window.Array.prototype.entries = function () { }; 15 | window.Array.prototype.every = function () { }; 16 | //window.Array.prototype.fill = function () { }; 17 | window.Array.prototype.filter = function () { }; 18 | //window.Array.prototype.find = function () { }; 19 | //window.Array.prototype.findIndex = function () { }; 20 | window.Array.prototype.forEach = function () { }; 21 | //window.Array.prototype.includes = function () { }; 22 | window.Array.prototype.indexOf = function () { }; 23 | //window.Array.prototype.keys = function () { }; 24 | window.Array.prototype.lastIndexOf = function () { }; 25 | window.Array.prototype.map = function () { }; 26 | window.Array.prototype.reduce = function () { }; 27 | window.Array.prototype.reduceRight = function () { }; 28 | window.Array.prototype.some = function () { }; 29 | //window.Array.prototype.values = function () { }; 30 | //window.AudioContext = function () { }; 31 | //window.CustomEvent = function () { }; 32 | //window.DOMTokenList = function () { }; 33 | //window.DOMTokenList.prototype.@@iterator = function() {}; 34 | window.Date = {}; 35 | window.Date.now = function () { }; 36 | window.Date.prototype = {}; 37 | window.Date.prototype.toISOString = function () { }; 38 | window.Document = function () { }; 39 | window.Element = function () { }; 40 | //window.Element.prototype.after = function () { }; 41 | //window.Element.prototype.append = function () { }; 42 | //window.Element.prototype.before = function () { }; 43 | //window.Element.prototype.classList = function () { }; 44 | //window.Element.prototype.cloneNode = function () { }; 45 | //window.Element.prototype.closest = function () { }; 46 | window.Element.prototype.dataset = function () { }; 47 | //window.Element.prototype.matches = function () { }; 48 | window.Element.prototype.placeholder = function () { }; 49 | //window.Element.prototype.prepend = function () { }; 50 | //window.Element.prototype.remove = function () { }; 51 | //window.Element.prototype.replaceWith = function () { }; 52 | window.Event = function () { }; 53 | window.Event.focusin = function () { }; 54 | window.Event.hashchange = function () { }; 55 | window.Function = {}; 56 | //window.Function.name = function () { }; 57 | window.Function.prototype = {}; 58 | window.Function.prototype.bind = function () { }; 59 | //window.HTMLCanvasElement = {}; 60 | //window.HTMLCanvasElement.protoype = {}; 61 | //window.HTMLCanvasElement.protoype.toBlob = function () { }; 62 | window.HTMLDocument = function () { }; 63 | //window.HTMLPictureElement = function () { }; 64 | //window.IntersectionObserver = function () { }; 65 | window.Intl = function () { }; 66 | window.Intl.Collator = function () { }; 67 | window.Intl.DateTimeFormat = function () { }; 68 | window.Intl.NumberFormat = function () { }; 69 | window.Intl.Collator.supportedLocalesOf = function (a) { return [] }; 70 | window.Intl.DateTimeFormat.supportedLocalesOf = function (a) { return []; }; 71 | window.Intl.NumberFormat.supportedLocalesOf = function (a) { return []; }; 72 | 73 | window.JSON = function () { }; 74 | //window.Map = function () { }; 75 | window.Math = {}; 76 | //window.Math.acosh = function () { }; 77 | //window.Math.asinh = function () { }; 78 | //window.Math.atanh = function () { }; 79 | //window.Math.cbrt = function () { }; 80 | //window.Math.clz32 = function () { }; 81 | //window.Math.cosh = function () { }; 82 | //window.Math.expm1 = function () { }; 83 | //window.Math.hypot = function () { }; 84 | //window.Math.imul = function () { }; 85 | //window.Math.log10 = function () { }; 86 | //window.Math.log1p = function () { }; 87 | //window.Math.log2 = function () { }; 88 | //window.Math.sign = function () { }; 89 | //window.Math.sinh = function () { }; 90 | //window.Math.tanh = function () { }; 91 | //window.Math.trunc = function () { }; 92 | window.Node = {}; 93 | window.Node.prototype = {}; 94 | //window.Node.prototype.contains = function () { }; 95 | //window.NodeList.prototype.@@iterator = function() {}; // no 96 | //window.Number = {}; 97 | //window.Number.MAX_SAFE_INTEGER = function () { }; 98 | //window.Number.MIN_SAFE_INTEGER = function () { }; 99 | //window.Number.isFinite = function () { }; 100 | //window.Number.isInteger = function () { }; 101 | //window.Number.isNaN = function () { }; 102 | window.Object = {}; 103 | //window.Object.assign = function () { }; 104 | window.Object.create = function () { }; 105 | window.Object.defineProperties = function () { }; 106 | window.Object.defineProperty = function () { }; 107 | window.Object.getOwnPropertyDescriptor = function () { }; 108 | window.Object.getOwnPropertyNames = function () { }; 109 | window.Object.getPrototypeOf = function () { }; 110 | //window.Object.is = function () { }; 111 | window.Object.keys = function () { }; 112 | window.Object.setPrototypeOf = function () { }; 113 | //window.Promise = function () { }; 114 | //window.Set = function () { }; 115 | window.String = {}; 116 | window.String.prototype = {}; 117 | //window.String.prototype.contains = function () { }; 118 | //window.String.prototype.endsWith = function () { }; 119 | //window.String.prototype.includes = function () { }; 120 | //window.String.prototype.repeat = function () { }; 121 | //window.String.prototype.startsWith = function () { }; 122 | window.String.prototype.trim = function () { }; 123 | // window.Symbol = function () { }; 124 | // window.Symbol.hasInstance = function () { }; 125 | // window.Symbol.isConcatSpreadable = function () { }; 126 | // window.Symbol.iterator = function () { }; 127 | // window.Symbol.match = function () { }; 128 | // window.Symbol.replace = function () { }; 129 | // window.Symbol.search = function () { }; 130 | // window.Symbol.species = function () { }; 131 | // window.Symbol.split = function () { }; 132 | // window.Symbol.toPrimitive = function () { }; 133 | // window.Symbol.toStringTag = function () { }; 134 | // window.Symbol.unscopables = function () { }; 135 | //window.URL = function () { }; 136 | //window.UserTiming = function () { }; 137 | //window.WeakMap = function () { }; 138 | //window.WeakSet = function () { }; 139 | window.XMLHttpRequest = function () { }; 140 | window.atob = function () { }; 141 | window.console = function () { }; 142 | window.console.assert = function () { }; 143 | window.console.clear = function () { }; 144 | window.console.count = function () { }; 145 | window.console.debug = function () { }; 146 | window.console.dir = function () { }; 147 | window.console.dirxml = function () { }; 148 | window.console.error = function () { }; 149 | //window.console.exception = function () { }; 150 | window.console.group = function () { }; 151 | window.console.groupCollapsed = function () { }; 152 | window.console.groupEnd = function () { }; 153 | window.console.info = function () { }; 154 | window.console.log = function () { }; 155 | //window.console.markTimeline = function () { }; 156 | //window.console.table = function () { }; 157 | window.console.time = function () { }; 158 | window.console.timeEnd = function () { }; 159 | //window.console.timeStamp = function () { }; 160 | //window.console.timeline = function () { }; 161 | //window.console.timelineEnd = function () { }; 162 | window.console.trace = function () { }; 163 | window.console.warn = function () { }; 164 | window.devicePixelRatio = function () { }; 165 | window.document = {}; 166 | //window.document.currentScript = function () { }; 167 | window.document.getElementsByClassName = function () { }; 168 | window.document.head = function () { }; 169 | window.document.querySelector = function () { }; 170 | window.document.visibilityState = function () { }; 171 | //window.fetch = function () { }; 172 | window.getComputedStyle = function () { }; 173 | window.localStorage = function () { }; 174 | window.location = {}; 175 | window.location.origin = function () { }; 176 | window.matchMedia = function () { }; 177 | window.navigator = {}; 178 | window.navigator.geolocation = function () { }; 179 | //window.navigator.sendBeacon = function () { }; 180 | window.performance = {}; 181 | window.performance.now = function () { }; 182 | window.requestAnimationFrame = function () { }; 183 | window.screen = {}; 184 | //window.screen.orientation = function () { }; 185 | window.setImmediate = function () { }; 186 | //window.~html5-elements = function() {}; // yes 187 | //window.~viewport = function() {}; // no 188 | 189 | return window; 190 | } -------------------------------------------------------------------------------- /test/utils/base.Config.js: -------------------------------------------------------------------------------- 1 | // Testing Configuration Template 2 | // Source: https://polyfill.io/v2/docs/features/#feature-list 3 | // TODO: Add support to iterators 4 | 5 | exports.configs = function () { 6 | window = {}; 7 | window.Array = {}; 8 | window.Array.from = function () { }; 9 | window.Array.isArray = function () { }; 10 | window.Array.of = function () { }; 11 | //window.Array.prototype.@@iterator = function() {}; 12 | window.Array.prototype = {}; 13 | window.Array.prototype.contains = function () { }; 14 | window.Array.prototype.entries = function () { }; 15 | window.Array.prototype.every = function () { }; 16 | window.Array.prototype.fill = function () { }; 17 | window.Array.prototype.filter = function () { }; 18 | window.Array.prototype.find = function () { }; 19 | window.Array.prototype.findIndex = function () { }; 20 | window.Array.prototype.forEach = function () { }; 21 | window.Array.prototype.includes = function () { }; 22 | window.Array.prototype.indexOf = function () { }; 23 | window.Array.prototype.keys = function () { }; 24 | window.Array.prototype.lastIndexOf = function () { }; 25 | window.Array.prototype.map = function () { }; 26 | window.Array.prototype.reduce = function () { }; 27 | window.Array.prototype.reduceRight = function () { }; 28 | window.Array.prototype.some = function () { }; 29 | window.Array.prototype.values = function () { }; 30 | window.AudioContext = function () { }; 31 | window.CustomEvent = function () { }; 32 | window.DOMTokenList = function () { }; 33 | //window.DOMTokenList.prototype.@@iterator = function() {}; 34 | window.Date = {}; 35 | window.Date.now = function () { }; 36 | window.Date.prototype = {}; 37 | window.Date.prototype.toISOString = function () { }; 38 | window.Document = function () { }; 39 | window.Element = function () { }; 40 | window.Element.prototype.after = function () { }; 41 | window.Element.prototype.append = function () { }; 42 | window.Element.prototype.before = function () { }; 43 | window.Element.prototype.classList = function () { }; 44 | window.Element.prototype.cloneNode = function () { }; 45 | window.Element.prototype.closest = function () { }; 46 | window.Element.prototype.dataset = function () { }; 47 | window.Element.prototype.matches = function () { }; 48 | window.Element.prototype.placeholder = function () { }; 49 | window.Element.prototype.prepend = function () { }; 50 | window.Element.prototype.remove = function () { }; 51 | window.Element.prototype.replaceWith = function () { }; 52 | window.Event = function () { }; 53 | window.Event.focusin = function () { }; 54 | window.Event.hashchange = function () { }; 55 | window.Function = {}; 56 | window.Function.name = function () { }; 57 | window.Function.prototype = {}; 58 | window.Function.prototype.bind = function () { }; 59 | window.HTMLCanvasElement = {}; 60 | window.HTMLCanvasElement.protoype = {}; 61 | window.HTMLCanvasElement.protoype.toBlob = function () { }; 62 | window.HTMLDocument = function () { }; 63 | window.HTMLPictureElement = function () { }; 64 | window.IntersectionObserver = function () { }; 65 | window.Intl = function () { }; 66 | window.Intl.Collator = function () { }; 67 | window.Intl.DateTimeFormat = function () { }; 68 | window.Intl.NumberFormat = function () { }; 69 | window.Intl.Collator.supportedLocalesOf = function (a) { return [] }; 70 | window.Intl.DateTimeFormat.supportedLocalesOf = function (a) { return []; }; 71 | window.Intl.NumberFormat.supportedLocalesOf = function (a) { return []; }; 72 | window.JSON = function () { }; 73 | window.Map = function () { }; 74 | window.Math = {}; 75 | window.Math.acosh = function () { }; 76 | window.Math.asinh = function () { }; 77 | window.Math.atanh = function () { }; 78 | window.Math.cbrt = function () { }; 79 | window.Math.clz32 = function () { }; 80 | window.Math.cosh = function () { }; 81 | window.Math.expm1 = function () { }; 82 | window.Math.hypot = function () { }; 83 | window.Math.imul = function () { }; 84 | window.Math.log10 = function () { }; 85 | window.Math.log1p = function () { }; 86 | window.Math.log2 = function () { }; 87 | window.Math.sign = function () { }; 88 | window.Math.sinh = function () { }; 89 | window.Math.tanh = function () { }; 90 | window.Math.trunc = function () { }; 91 | window.Node = {}; 92 | window.Node.prototype = {}; 93 | window.Node.prototype.contains = function () { }; 94 | //window.NodeList.prototype.@@iterator = function() {}; 95 | window.Number = {}; 96 | window.Number.MAX_SAFE_INTEGER = function () { }; 97 | window.Number.MIN_SAFE_INTEGER = function () { }; 98 | window.Number.isFinite = function () { }; 99 | window.Number.isInteger = function () { }; 100 | window.Number.isNaN = function () { }; 101 | window.Object = {}; 102 | window.Object.assign = function () { }; 103 | window.Object.create = function () { }; 104 | window.Object.defineProperties = function () { }; 105 | window.Object.defineProperty = function () { }; 106 | window.Object.getOwnPropertyDescriptor = function () { }; 107 | window.Object.getOwnPropertyNames = function () { }; 108 | window.Object.getPrototypeOf = function () { }; 109 | window.Object.is = function () { }; 110 | window.Object.keys = function () { }; 111 | window.Object.setPrototypeOf = function () { }; 112 | window.Promise = function () { }; 113 | window.Set = function () { }; 114 | window.String = {}; 115 | window.String.prototype = {}; 116 | window.String.prototype.contains = function () { }; 117 | window.String.prototype.endsWith = function () { }; 118 | window.String.prototype.includes = function () { }; 119 | window.String.prototype.repeat = function () { }; 120 | window.String.prototype.startsWith = function () { }; 121 | window.String.prototype.trim = function () { }; 122 | window.Symbol = function () { }; 123 | window.Symbol.hasInstance = function () { }; 124 | window.Symbol.isConcatSpreadable = function () { }; 125 | window.Symbol.iterator = function () { }; 126 | window.Symbol.match = function () { }; 127 | window.Symbol.replace = function () { }; 128 | window.Symbol.search = function () { }; 129 | window.Symbol.species = function () { }; 130 | window.Symbol.split = function () { }; 131 | window.Symbol.toPrimitive = function () { }; 132 | window.Symbol.toStringTag = function () { }; 133 | window.Symbol.unscopables = function () { }; 134 | window.URL = function () { }; 135 | window.UserTiming = function () { }; 136 | window.WeakMap = function () { }; 137 | window.WeakSet = function () { }; 138 | window.XMLHttpRequest = function () { }; 139 | window.atob = function () { }; 140 | window.console = function () { }; 141 | window.console.assert = function () { }; 142 | window.console.clear = function () { }; 143 | window.console.count = function () { }; 144 | window.console.debug = function () { }; 145 | window.console.dir = function () { }; 146 | window.console.dirxml = function () { }; 147 | window.console.error = function () { }; 148 | window.console.exception = function () { }; 149 | window.console.group = function () { }; 150 | window.console.groupCollapsed = function () { }; 151 | window.console.groupEnd = function () { }; 152 | window.console.info = function () { }; 153 | window.console.log = function () { }; 154 | window.console.markTimeline = function () { }; 155 | window.console.table = function () { }; 156 | window.console.time = function () { }; 157 | window.console.timeEnd = function () { }; 158 | window.console.timeStamp = function () { }; 159 | window.console.timeline = function () { }; 160 | window.console.timelineEnd = function () { }; 161 | window.console.trace = function () { }; 162 | window.console.warn = function () { }; 163 | window.devicePixelRatio = function () { }; 164 | window.document = {}; 165 | window.document.currentScript = function () { }; 166 | window.document.getElementsByClassName = function () { }; 167 | window.document.head = function () { }; 168 | window.document.querySelector = function () { }; 169 | window.document.visibilityState = function () { }; 170 | window.fetch = function () { }; 171 | window.getComputedStyle = function () { }; 172 | window.localStorage = function () { }; 173 | window.location = {}; 174 | window.location.origin = function () { }; 175 | window.matchMedia = function () { }; 176 | window.navigator = {}; 177 | window.navigator.geolocation = function () { }; 178 | window.navigator.sendBeacon = function () { }; 179 | window.performance = {}; 180 | window.performance.now = function () { }; 181 | window.requestAnimationFrame = function () { }; 182 | window.screen = {}; 183 | window.screen.orientation = function () { }; 184 | window.setImmediate = function () { }; 185 | //window.~html5-elements = function() {}; 186 | //window.~viewport = function() {}; 187 | 188 | return window; 189 | } --------------------------------------------------------------------------------