├── test ├── fixtures │ ├── cli │ │ ├── empty.js │ │ ├── a.js │ │ ├── c.coffee │ │ └── deep │ │ │ └── b.js │ ├── cli_parser │ │ ├── es6.js │ │ └── es5.js │ └── parser.js ├── test.polyfill-code.js ├── test.polyfill-reduce.js ├── test.polyfill-wrap.js ├── test.polyfill-scan.js ├── test.autopolyfiler.js └── test.cli.js ├── AUTHORS ├── .gitignore ├── benchmark ├── README.md └── scan │ ├── index.js │ └── assets │ └── require.min.js ├── images ├── favicon.ico ├── autopolyfiller.jpg ├── autopolyfiller.min.svg └── autopolyfiller.svg ├── .jshintignore ├── .travis.yml ├── bin └── autopolyfiller ├── .jscsrc ├── .editorconfig ├── .jshintrc ├── CHANGELOG.md ├── lib ├── polyfill-code │ └── index.js ├── polyfill-scan │ └── index.js ├── polyfill-wrap │ └── index.js ├── polyfill-reduce │ └── index.js └── cli.js ├── LICENSE ├── example_assets ├── index.css ├── index.js └── index.browserify.js ├── package.json ├── index.html ├── CONTRIBUTION.md ├── README.md └── index.js /test/fixtures/cli/empty.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/cli/a.js: -------------------------------------------------------------------------------- 1 | "".trim(); 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Mikhail Davydov 2 | -------------------------------------------------------------------------------- /test/fixtures/cli/c.coffee: -------------------------------------------------------------------------------- 1 | c = ''' 2 | 3 | ''' -------------------------------------------------------------------------------- /test/fixtures/cli/deep/b.js: -------------------------------------------------------------------------------- 1 | Object.keys({}); 2 | -------------------------------------------------------------------------------- /test/fixtures/cli_parser/es6.js: -------------------------------------------------------------------------------- 1 | [1, 2, 3].map(x => x * x); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | .DS_Store 4 | coverage 5 | -------------------------------------------------------------------------------- /benchmark/README.md: -------------------------------------------------------------------------------- 1 | # Benchmark 2 | 3 | Run using `node benchmark/scan` 4 | -------------------------------------------------------------------------------- /test/fixtures/cli_parser/es5.js: -------------------------------------------------------------------------------- 1 | [1, 2, 3].map(function (x) { 2 | return x * x; 3 | }); 4 | -------------------------------------------------------------------------------- /images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azproduction/autopolyfiller/HEAD/images/favicon.ico -------------------------------------------------------------------------------- /images/autopolyfiller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azproduction/autopolyfiller/HEAD/images/autopolyfiller.jpg -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | data 3 | benchmark/scan/assets 4 | example_assets/index.browserify.js 5 | test/fixtures 6 | coverage 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js:" 4 | - "0.10" 5 | - "0.12" 6 | 7 | matrix: 8 | allow_failures: 9 | - node_js: "0.12" 10 | 11 | branches: 12 | only: 13 | - master 14 | 15 | script: npm test && @npm run coverage_push || true 16 | -------------------------------------------------------------------------------- /bin/autopolyfiller: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | new (require('../lib/cli'))({ 3 | stdin: process.stdin, 4 | stdout: process.stdout, 5 | stderr: process.stderr, 6 | argv: process.argv, 7 | exit: process.exit, 8 | env: process.env 9 | }); 10 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "yandex", 3 | "excludeFiles": [ 4 | ".git/**", 5 | "node_modules/**", 6 | "coverage/**", 7 | "benchmark/scan/assets/**", 8 | "example_assets/index.browserify.js", 9 | "test/fixtures/**" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ; editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [GNUmakefile] 13 | indent_style = tab 14 | 15 | [package.json] 16 | indent_size = 2 17 | 18 | [.travis.yml] 19 | indent_size = 2 20 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "es5": false, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "immed": true, 6 | "latedef": true, 7 | "newcap": true, 8 | "noarg": true, 9 | "sub": true, 10 | "undef": true, 11 | "boss": true, 12 | "eqnull": true, 13 | "node": true, 14 | "jquery": true, 15 | "strict": false, 16 | "browser": true, 17 | "indent": 4, 18 | "maxerr": 5, 19 | "maxdepth": 2, 20 | "maxstatements": 12, 21 | "maxcomplexity": 5 22 | } 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Version 1.1.0: 2 | * considerably increased speed of polyfill scan by removing `grasp-equery` 3 | * added ability to `.include()` & `.exclude()` polyfills #6 4 | * improved polyfills scan. Now it can find square brackets expressions eg `""["trim"]()` #3 5 | * improved polyfills scan. Now it can find padded expressions eg `new this.Promise()` or `window.atob()` #4 6 | 7 | Version 1.0.10: 8 | * polyfills for `requestAnimationFrame()`, `cancelAnimationFrame()` 9 | * it uses semver to compare versions 10 | 11 | Version 1.0.9: 12 | * polyfills for `btoa()`, `atob()`, `matchMedia()` 13 | * polyfills scanner of polyfills code 14 | 15 | Version 1.0.0: 16 | * Initial release. 17 | -------------------------------------------------------------------------------- /benchmark/scan/index.js: -------------------------------------------------------------------------------- 1 | var glob = require('glob').sync; 2 | var read = require('fs').readFileSync; 3 | var scan = require('../../lib/polyfill-scan'); 4 | var Benchmark = require('benchmark'); 5 | 6 | var sources = glob(__dirname + '/assets/*.js').map(function (name) { 7 | return read(name, 'utf8'); 8 | }); 9 | 10 | var suite = new Benchmark.Suite(); 11 | 12 | suite.add('scan', function () { 13 | for (var i = 0, c = sources.length; i < c; i++) { 14 | scan(sources[i]); 15 | } 16 | }) 17 | .on('cycle', function (event) { 18 | console.log(String(event.target)); 19 | }) 20 | .on('complete', function () { 21 | console.log('Fastest is ' + this.filter('fastest').pluck('name')); 22 | }) 23 | .run({ 24 | async: true 25 | }); 26 | -------------------------------------------------------------------------------- /lib/polyfill-code/index.js: -------------------------------------------------------------------------------- 1 | var extend = require('node.extend'); 2 | var debug = require('debug')('polyfill:code'); 3 | 4 | var polyfillsCode = {}; 5 | 6 | /** 7 | * Returns crossbrowser polyfill code 8 | * 9 | * @param {string} polyfillName 10 | * @returns {string} 11 | */ 12 | function code(polyfillName) { 13 | debug('getting polyfill code for `%s`', polyfillName); 14 | var polyfillCode = polyfillsCode[polyfillName]; 15 | 16 | if (!polyfillCode) { 17 | throw new Error('Unknown feature: ' + polyfillName); 18 | } 19 | 20 | return polyfillCode; 21 | } 22 | 23 | /** 24 | * Adds polyfills code 25 | * 26 | * @param {object} newPolyfills 27 | */ 28 | function addSource(newPolyfills) { 29 | debug('adding custom polyfill'); 30 | extend(polyfillsCode, newPolyfills); 31 | } 32 | 33 | module.exports = code; 34 | module.exports.addSource = addSource; 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 Mikhail Davydov and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /test/test.polyfill-code.js: -------------------------------------------------------------------------------- 1 | /*global describe, it, beforeEach, afterEach*/ 2 | /*jshint expr:true*/ 3 | 4 | var code = require('../lib/polyfill-code'); 5 | var expect = require('chai').expect; 6 | 7 | describe('polyfill-code', function () { 8 | 9 | it('returns polyfill code', function () { 10 | expect(code('Object.keys')).to.match(/Object\.keys/); 11 | }); 12 | 13 | it('lazily loads polyfills', function () { 14 | expect(code('Window.prototype.requestAnimationFrame')).to.match(/requestAnimationFrame/); 15 | }); 16 | 17 | it('throws an error if required polyfill is not defined', function () { 18 | expect(function () { 19 | code('Object.pewpewOlolo'); 20 | }).to.throw(Error, /Unknown feature: Object.pewpewOlolo/); 21 | }); 22 | 23 | describe('.addSource', function () { 24 | 25 | it('defines new polyfills code', function () { 26 | var polyfillCode = '__MyPolyfill = function () {}'; 27 | 28 | code.addSource({ 29 | __MyPolyfill: polyfillCode 30 | }); 31 | 32 | expect(code('__MyPolyfill')).to.eql(polyfillCode); 33 | 34 | }); 35 | 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /example_assets/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 100%; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | header, 8 | section { 9 | width: 800px; 10 | margin: 0 auto; 11 | } 12 | 13 | textarea { 14 | width: 100%; 15 | max-width: 100%; 16 | height: 190px; 17 | font-size: 16px; 18 | font-family: "Consolas", "Courier New", monospace; 19 | } 20 | 21 | li { 22 | font-family: "Consolas", "Courier New", monospace; 23 | } 24 | 25 | textarea._small { 26 | height: 36px; 27 | } 28 | 29 | h1, 30 | h2 { 31 | font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif; 32 | font-weight: 200; 33 | } 34 | 35 | p { 36 | font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;; 37 | } 38 | 39 | button { 40 | border: solid transparent 30px; 41 | border-bottom-width: 0; 42 | border-top: solid 30px #bbb; 43 | width: 0; 44 | padding: 0; 45 | margin: 20px 0 0 -30px; 46 | height: 0; 47 | background: transparent; 48 | position: relative; 49 | display: inline-block; 50 | left: 50%; 51 | } 52 | 53 | button:active { 54 | top: 2px; 55 | } 56 | 57 | .main-title__image { 58 | height: 64px; 59 | vertical-align: middle; 60 | } 61 | 62 | .social-share { 63 | margin-top: 32px; 64 | text-align: center; 65 | } -------------------------------------------------------------------------------- /lib/polyfill-scan/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * polyfill-scan 3 | */ 4 | var acorn = require('acorn'); 5 | var debug = require('debug')('polyfill:scan'); 6 | 7 | var matchers = []; 8 | 9 | /** 10 | * 11 | * @param {Object} matcher 12 | * @param {Function} matcher.test 13 | */ 14 | function use(matcher) { 15 | debug('adding custom matcher'); 16 | matchers.push(matcher); 17 | } 18 | 19 | /** 20 | * @param {String} code 21 | * @param {Object} [parser] 22 | * @param {Function} parser.parse 23 | * @param {Object} [parserOptions] 24 | * @returns {String[]} list of polyfills 25 | */ 26 | function scan(code, parser, parserOptions) { 27 | parser = parser || acorn; 28 | debug('parsing code'); 29 | var ast = parser.parse(code, parserOptions); 30 | debug('parsing done'); 31 | 32 | debug('scanning for polyfills using %d matchers', matchers.length); 33 | var polyfills = matchers 34 | .reduce(function (polyfills, matcher) { 35 | return polyfills.concat(matcher.test(ast)); 36 | }, []) 37 | // Unique 38 | .reduce(function (polyfills, polyfill) { 39 | if (polyfills.indexOf(polyfill) === -1) { 40 | polyfills.push(polyfill); 41 | } 42 | return polyfills; 43 | }, []); 44 | debug('got %d polyfill(s)', polyfills.length); 45 | 46 | return polyfills; 47 | } 48 | 49 | module.exports = scan; 50 | module.exports.use = use; 51 | -------------------------------------------------------------------------------- /example_assets/index.js: -------------------------------------------------------------------------------- 1 | var autopolyfiller = require('../lib'); 2 | 3 | function $(sel) { 4 | return document.querySelector(sel); 5 | } 6 | 7 | setTimeout(function () { 8 | var $code = $('#code'); 9 | var $browsers = $('#browsers'); 10 | var $polyfills = $('#polyfills'); 11 | var $generateButton = $('#generate'); 12 | 13 | function generate() { 14 | console.time('Scan for polyfills'); 15 | try { 16 | var browsers = ($browsers.value || '').toLowerCase().split(',').map(function (string) { 17 | return string.trim(); 18 | }); 19 | 20 | var polyfills = autopolyfiller(browsers).add($code.value || '').polyfills; 21 | 22 | $polyfills.innerHTML = polyfills 23 | .map(function (polyfill) { 24 | return '
  • ' + 25 | '' + 26 | polyfill + 27 | '' + 28 | '
  • '; 29 | }).join(''); 30 | 31 | console.timeEnd('Scan for polyfills'); 32 | } catch (e) { 33 | console.timeEnd('Scan for polyfills'); 34 | console.error(e); 35 | } 36 | } 37 | 38 | $code.addEventListener('input', generate, false); 39 | $browsers.addEventListener('input', generate, false); 40 | $generateButton.addEventListener('click', generate, false); 41 | 42 | generate(); 43 | }, 0); 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "autopolyfiller", 3 | "description": "Precise polyfills. Like Autoprefixer, but for JavaScript polyfills", 4 | "keywords": [ 5 | "polyfill", 6 | "polyfills", 7 | "dom", 8 | "ecmascript", 9 | "ecmascript5", 10 | "ecmascript6", 11 | "postprocessor" 12 | ], 13 | "version": "1.6.1", 14 | "author": "Mikhail Davydov ", 15 | "contributors": [ 16 | { 17 | "name": "Mikhail Davydov", 18 | "email": "i@azproduction.ru" 19 | } 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "git://github.com/azproduction/autopolyfiller.git" 24 | }, 25 | "engines": { 26 | "node": ">= 0.8.0" 27 | }, 28 | "dependencies": { 29 | "acorn": "~0.11.0", 30 | "autopolyfiller-stable": "~1.0.2", 31 | "browserslist": "~0.1.0", 32 | "commander": "~2.1.0", 33 | "debug": "~0.7.4", 34 | "globule": "0.2.0", 35 | "minimatch": "^2.0.7", 36 | "mkdirp": "~0.3.5", 37 | "node.extend": "~1.0.9", 38 | "semver": "~2.2.1" 39 | }, 40 | "devDependencies": { 41 | "benchmark": "*", 42 | "browserify": "*", 43 | "chai": "*", 44 | "codeclimate-test-reporter": "~0.0.3", 45 | "coveralls": "*", 46 | "glob": "~3.2.9", 47 | "grasp-equery": "~0.2.0", 48 | "husky": "~0.5.1", 49 | "istanbul": "~0.2.11", 50 | "jscs": "^1.13.1", 51 | "jshint": "^2.7.0", 52 | "mocha": "~2.2.4", 53 | "mocha-istanbul": "*", 54 | "mock-utf8-stream": "*", 55 | "uglify-js": "*" 56 | }, 57 | "bin": { 58 | "autopolyfiller": "./bin/autopolyfiller" 59 | }, 60 | "files": [ 61 | "bin/", 62 | "lib/", 63 | "index.js" 64 | ], 65 | "scripts": { 66 | "test": "npm run lint && mocha -R spec", 67 | "lint": "jshint . && jscs . ", 68 | "coverage": "istanbul cover node_modules/.bin/_mocha --report html -- -R spec", 69 | "coverage_push": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && cat ./coverage/lcov.info | codeclimate || true", 70 | "precommit": "npm test", 71 | "benchmark": "node ./benchmark/scan" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/polyfill-wrap/index.js: -------------------------------------------------------------------------------- 1 | var extend = require('node.extend'); 2 | var debug = require('debug')('polyfill:wrap'); 3 | 4 | var polyfillsWrappers = {}; 5 | 6 | /** 7 | * Wraps code with conditional expression 8 | * 9 | * @param {string} code 10 | * @param {string} polyfillName 11 | * @returns {string} 12 | */ 13 | function wrapDefault(code, polyfillName) { 14 | debug('wrapping code of `%s` using default wrapper', polyfillName); 15 | var parts = polyfillName.split('.'); 16 | var expression = 'true'; 17 | 18 | if (parts.length === 1) { 19 | // Promise 20 | // typeof Promise === "undefined" 21 | expression = 'typeof ' + parts[0] + ' === "undefined"'; 22 | } else if (parts.length === 2) { 23 | // Object.keys 24 | // typeof Object !== "undefined" && !Object.keys 25 | expression = 'typeof ' + parts[0] + ' !== "undefined" && !' + parts[0] + '.' + parts[1]; 26 | } else if (parts[0] === 'Window' && parts[1] === 'prototype' && parts[2]) { 27 | // Window.prototype.JSON 28 | expression = 'typeof window.' + parts[2] + ' === "undefined"'; 29 | } else { 30 | // Array.prototype.map 31 | // !Array.prototype.map 32 | expression = '!' + polyfillName; 33 | } 34 | 35 | debug('got `%s` condition expression for `%s`', expression, polyfillName); 36 | return 'if (' + expression + ') {\n' + code + '\n}\n'; 37 | } 38 | 39 | /** 40 | * Wraps code with conditional expression 41 | * 42 | * @param {string} code 43 | * @param {string} polyfillName 44 | * @returns {string} 45 | */ 46 | function wrap(code, polyfillName) { 47 | var wrapper = polyfillsWrappers[polyfillName]; 48 | if (typeof wrapper !== 'object') { 49 | return wrapDefault(code, polyfillName); 50 | } 51 | 52 | return wrapper.before + code + wrapper.after; 53 | } 54 | 55 | /** 56 | * 57 | * @param {Object} wrappers 58 | * 59 | * @example 60 | * 61 | * .addWrapper({ 62 | * 'Promise': { 63 | * 'before': 'if (!window.Promise) {', 64 | * 'after': '}' 65 | * } 66 | * }); 67 | */ 68 | function addWrapper(wrappers) { 69 | extend(polyfillsWrappers, wrappers); 70 | } 71 | 72 | module.exports = wrap; 73 | module.exports.addWrapper = addWrapper; 74 | -------------------------------------------------------------------------------- /test/test.polyfill-reduce.js: -------------------------------------------------------------------------------- 1 | /*global describe, it, beforeEach, afterEach*/ 2 | /*jshint expr:true*/ 3 | 4 | var reduce = require('../lib/polyfill-reduce'); 5 | var browserslist = require('browserslist'); 6 | var expect = require('chai').expect; 7 | 8 | describe('polyfill-reduce', function () { 9 | 10 | it('excludes supported polyfills', function () { 11 | var polyfills = reduce(['Promise', 'String.prototype.trim', 'Object.create'], ['IE 11', 'Chrome 31']); 12 | expect(polyfills).to.eql(['Promise']); 13 | }); 14 | 15 | it('ignores undefined browsers', function () { 16 | browserslist.data.mychrome = { 17 | name: 'mychrome', 18 | released: ['37', '38', '39'], 19 | versions: ['37', '38', '39', '40'] 20 | }; 21 | var polyfills = reduce(['Promise', 'String.prototype.trim', 'Object.create'], ['mychrome 39']); 22 | delete browserslist.data.mychrome; 23 | 24 | expect(polyfills).to.eql([]); 25 | }); 26 | 27 | it('throws if browser or version is undefined', function () { 28 | expect(function () { 29 | reduce(['Promise', 'String.prototype.trim', 'Object.create'], ['mychrome 39']); 30 | }).to.throw(); 31 | 32 | expect(function () { 33 | reduce(['Promise', 'String.prototype.trim', 'Object.create'], ['Opera 1']); 34 | }).to.throw(); 35 | }); 36 | 37 | describe('.list', function () { 38 | 39 | it('returns list of all required polyfills', function () { 40 | expect(reduce.list()).to.be.instanceof(Array); 41 | }); 42 | 43 | }); 44 | 45 | describe('.support', function () { 46 | 47 | it('uses custom supports', function () { 48 | reduce.support({ 49 | Chrome: [{ 50 | only: '29', 51 | fill: '__PewpewOlolo' 52 | }] 53 | }); 54 | var polyfills = reduce(['__PewpewOlolo'], ['Chrome 30']); 55 | expect(polyfills).to.eql([]); 56 | }); 57 | 58 | it('can define new browsers', function () { 59 | reduce.support({ 60 | ChromePewpew: [{ 61 | only: '29', 62 | fill: '__PewpewOlolo' 63 | }] 64 | }); 65 | }); 66 | 67 | }); 68 | 69 | }); 70 | -------------------------------------------------------------------------------- /test/fixtures/parser.js: -------------------------------------------------------------------------------- 1 | exports.parse = function(code, options) { 2 | if (code !== 'array.map(x => x * x)') { 3 | throw new Error('Can not parse'); 4 | } 5 | 6 | if (options && typeof options !== 'object') { 7 | throw new Error('Bad options'); 8 | } 9 | 10 | return { 11 | "type": "Program", 12 | "body": [ 13 | { 14 | "type": "ExpressionStatement", 15 | "expression": { 16 | "type": "CallExpression", 17 | "callee": { 18 | "type": "MemberExpression", 19 | "computed": false, 20 | "object": { 21 | "type": "Identifier", 22 | "name": "array" 23 | }, 24 | "property": { 25 | "type": "Identifier", 26 | "name": "map" 27 | } 28 | }, 29 | "arguments": [ 30 | { 31 | "type": "ArrowFunctionExpression", 32 | "id": null, 33 | "params": [ 34 | { 35 | "type": "Identifier", 36 | "name": "x" 37 | } 38 | ], 39 | "defaults": [], 40 | "body": { 41 | "type": "BinaryExpression", 42 | "operator": "*", 43 | "left": { 44 | "type": "Identifier", 45 | "name": "x" 46 | }, 47 | "right": { 48 | "type": "Identifier", 49 | "name": "x" 50 | } 51 | }, 52 | "rest": null, 53 | "generator": false, 54 | "expression": true 55 | } 56 | ] 57 | } 58 | } 59 | ] 60 | }; 61 | }; 62 | -------------------------------------------------------------------------------- /test/test.polyfill-wrap.js: -------------------------------------------------------------------------------- 1 | /*global describe, it, beforeEach, afterEach*/ 2 | /*jshint expr:true*/ 3 | 4 | var wrap = require('../lib/polyfill-wrap'); 5 | var expect = require('chai').expect; 6 | 7 | describe('polyfill-wrap', function () { 8 | 9 | it('uses negative polyfill as expression if `polyfillName` is a prototype property', function () { 10 | var code = 'Array.prototype.every = function () {};'; 11 | var polyfillName = 'Array.prototype.every'; 12 | 13 | var wrappedCode = wrap(code, polyfillName); 14 | 15 | expect(wrappedCode).to.match(/Array\.prototype\.every = function \(\) \{\};/); 16 | expect(wrappedCode).to.match(/!Array\.prototype\.every/); 17 | }); 18 | 19 | it('uses window.Object as expression if `polyfillName` is a Window prototype property', function () { 20 | var code = 'Window.prototype.JSON = {};'; 21 | var polyfillName = 'Window.prototype.JSON'; 22 | 23 | var wrappedCode = wrap(code, polyfillName); 24 | 25 | expect(wrappedCode).to.match(/Window\.prototype\.JSON = \{\};/); 26 | expect(wrappedCode).to.match(/typeof window\.JSON === "undefined"/); 27 | }); 28 | 29 | it('uses typeof polyfill === "undefined" as expression if `polyfillName` is a single object', function () { 30 | var code = 'Promise = function () {};'; 31 | var polyfillName = 'Promise'; 32 | 33 | var wrappedCode = wrap(code, polyfillName); 34 | 35 | expect(wrappedCode).to.match(/Promise = function \(\) \{\};/); 36 | expect(wrappedCode).to.match(/typeof Promise === "undefined"/); 37 | }); 38 | 39 | it('uses complex expression if `polyfillName` is a static method polyfill', function () { 40 | var code = 'Object.keys = function () {};'; 41 | var polyfillName = 'Object.keys'; 42 | 43 | var wrappedCode = wrap(code, polyfillName); 44 | 45 | expect(wrappedCode).to.match(/Object.keys = function \(\) \{\};/); 46 | expect(wrappedCode).to.match(/typeof Object !== "undefined" && !Object.keys/); 47 | }); 48 | 49 | describe('.addWrapper', function () { 50 | it('declares special polyfill wrapper', function () { 51 | wrap.addWrapper({ 52 | __PewpewOlolo: { 53 | before: '', 54 | after: '' 55 | } 56 | }); 57 | 58 | var code = '__PewpewOlolo = function () {};'; 59 | var polyfillName = '__PewpewOlolo'; 60 | 61 | expect(wrap(code, polyfillName)).to.eql(code); 62 | }); 63 | }); 64 | 65 | }); 66 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Autopolyfiller — Precise polyfills 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 |

    Autopolyfiller — Precise polyfills

    18 |
    19 | 20 |
    21 |

    22 | 23 |

    24 | 34 | 35 |

    36 | 37 |

    38 | 39 | 40 | 41 | 42 |

    Required polyfills

    43 |
      44 | 45 |

      Polyfills code

      46 |

      It is not yet implemented in demo mode, but you can install Autopolyfiller and try it yourself.

      47 |
      $ npm i autopolyfiller -g
      48 | $ autopolyfiller js/**/*.js
      49 |
      50 | 51 | 61 | 62 | Fork me on GitHub 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /CONTRIBUTION.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | This document describes some points about contribution process for autopolyfiller package. 4 | 5 | The maintainer of the project is Mikhail Davydov (i@azproduction.ru). 6 | 7 | The project is being developed within community. Maintainer merges pull-requests, fixes critical bugs. 8 | 9 | ## Pull-requests 10 | 11 | If you fixed or added something useful to the project, you can send pull-request. 12 | It will be reviewed by maintainer and accepted, or commented for rework, or declined. 13 | 14 | ## Bugs 15 | 16 | If you found an error, mistype or any other flawback in the project, please report about it using github-issues. 17 | The more details you provide, the easier it can be reproduced and the faster can be fixed. 18 | Unfortunately, sometimes the bug can be only reproduced in your project or in your environment, 19 | so maintainers cannot reproduce it. In this case we believe you can fix the bug and send us the fix. 20 | 21 | ## Features 22 | 23 | It you've got an idea about a new feature, it's most likely that you have do implement it on your own. 24 | If you cannot implement the feature, but it is very important, you can add a task in github-issues, 25 | but expect it be declined by the maintainer. 26 | 27 | ## How to add a new polyfill 28 | 29 | - Write a polyfill's code 30 | - Name your polyfill 31 | - Write a AST matcher 32 | - Write a wrapper (optional) 33 | - Specify a set of invalid browsers 34 | - Write tests 35 | 36 | ### 1. Write a polyfill's code 37 | 38 | - It should be tested 39 | - Idially should have 100% code coverage 40 | - It should be without a condition wrapper 41 | - It should be roboust (full spec coverage is welcome) 42 | 43 | **Examples** 44 | 45 | ```js 46 | // GOOD 47 | String.prototype.trim = function () { 48 | return this.replace(/^\s+|\s+$/g, ''); 49 | }; 50 | ``` 51 | 52 | ```js 53 | // BAD 54 | if (!String.prototype.trim) { 55 | String.prototype.trim = function () { 56 | return this.replace(/^\s+|\s+$/g, ''); 57 | }; 58 | } 59 | ``` 60 | 61 | ### 2. Name your polyfill 62 | 63 | - It should be verbose (include prototype and a root object) 64 | 65 | **Examples** 66 | 67 | - `String.prototype.trim` - GOOD 68 | - `strtrim`, `trim`, `trim-fix` - BAD 69 | 70 | ### 3. Write a AST matcher 71 | 72 | - It should be simple 73 | - As fast as possible 74 | - It should cover edge cases like `Object['keys']()` 75 | 76 | You can use `grasp-equery` to greatly simplify your code. 77 | 78 | ```js 79 | var query = require('grasp-equery').query; 80 | /** 81 | * @param {Object} ast an esprima-style AST 82 | * @see An example of AST http://esprima.org/demo/parse.html?code=%27%27.trim() 83 | * @see Mozilla Parser API https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API 84 | * @see JavaScript AST Parser http://esprima.org/ 85 | * 86 | * @returns {String[]} array of polyfills name(s) or emply array 87 | */ 88 | function matcher(ast) { 89 | return query('_$.trim()', ast).length > 0 ? ['String.prototype.trim'] : []; 90 | } 91 | ``` 92 | 93 | ### 4. Write a conditional wrapper 94 | 95 | If a condition for polyfill is complex, you can write a wrapper. This condition specifies when polyfill shoul be applied. 96 | 97 | ```js 98 | /* BEFORE PART */if (!String.prototype.trim) { 99 | // There will be your polyfill's code 100 | /* AFTER PART */} 101 | ``` 102 | 103 | ### 5. Set of invalid browsers 104 | 105 | - http://caniuse.com/ 106 | - http://kangax.github.io/compat-table/es5/ 107 | 108 | ```js 109 | { 110 | 'Safari': [{ 111 | only: '4', 112 | fill: 'String.prototype.trim' 113 | }], 114 | 'Internet Explorer': [{ 115 | min: '6', 116 | max: '8', 117 | fill: 'String.prototype.trim' 118 | }] 119 | } 120 | ``` 121 | 122 | For more examples see https://github.com/jonathantneal/polyfill/blob/master/agent.js.json 123 | -------------------------------------------------------------------------------- /test/test.polyfill-scan.js: -------------------------------------------------------------------------------- 1 | /*global describe, it, beforeEach, afterEach*/ 2 | /*jshint expr:true*/ 3 | 4 | var scan = require('../lib/polyfill-scan'); 5 | var mockParser = require('./fixtures/parser'); 6 | var astQuery = require('grasp-equery').query; 7 | var expect = require('chai').expect; 8 | 9 | describe('polyfill-scan', function () { 10 | /* jshint maxstatements: 20 */ 11 | 12 | it('scans for prototype-based polyfills', function () { 13 | var polyfills = scan('"".trim();'); 14 | expect(polyfills).to.eql(['String.prototype.trim']); 15 | }); 16 | 17 | it('scans for prototype-based polyfills in deep statements', function () { 18 | var polyfills = scan('var x = a.b.c.d.e.f.g.trim();'); 19 | expect(polyfills).to.eql(['String.prototype.trim']); 20 | }); 21 | 22 | it('scans for prototype-based polyfills that called by call, apply or bind', function () { 23 | var polyfills = scan( 24 | '"".trim.call(" 1 ");' + 25 | '[].some.bind([], function () {});' 26 | ); 27 | expect(polyfills).to.eql(['String.prototype.trim', 'Function.prototype.bind', 'Array.prototype.some']); 28 | }); 29 | 30 | it('scans for static method polyfills', function () { 31 | var polyfills = scan('Object.create();Object.keys'); 32 | expect(polyfills).to.eql(['Object.create', 'Object.keys']); 33 | }); 34 | 35 | it('ignores deep expressions that mocks as static methods', function () { 36 | var polyfills = scan('My.Object.create();Oh.My.Object.create();'); 37 | expect(polyfills).to.eql([]); 38 | }); 39 | 40 | it('finds padded static methods', function () { 41 | var polyfills = scan('window.Object.create();'); 42 | expect(polyfills).to.eql(['Object.create']); 43 | }); 44 | 45 | it('finds square brackets static methods', function () { 46 | var polyfills = scan('window["Object"]["create"]();(JSON["parse"]);'); 47 | expect(polyfills).to.eql(['Object.create', 'Window.prototype.JSON']); 48 | }); 49 | 50 | it('scans for static method polyfills that called by call, apply or bind', function () { 51 | var polyfills = scan( 52 | 'Object.create.bind(null);' + 53 | 'JSON.parse.call(JSON, "{}");' 54 | ); 55 | expect(polyfills).to.eql(['Function.prototype.bind', 'Object.create', 'Window.prototype.JSON']); 56 | }); 57 | 58 | it('scans for constructor polyfills', function () { 59 | var polyfills = scan('new Promise();'); 60 | expect(polyfills).to.eql(['Promise']); 61 | }); 62 | 63 | it('scans for padded constructor polyfills', function () { 64 | var polyfills = scan('new window.Promise();'); 65 | expect(polyfills).to.eql(['Promise']); 66 | }); 67 | 68 | it('scans for global function polyfills', function () { 69 | var polyfills = scan( 70 | 'window.btoa();' + 71 | 'window.btoa.call();' + 72 | 73 | 'atob();' + 74 | 'atob.apply();' + 75 | 76 | 'this.btoa();' + 77 | 'this.btoa.call();' 78 | ); 79 | expect(polyfills).to.eql(['Window.prototype.base64']); 80 | }); 81 | 82 | it('returns unique polyfills', function () { 83 | var polyfills = scan('new Promise();new Promise();"".trim();"".trim();Object.create();Object.create();'); 84 | expect(polyfills).to.eql(['Promise', 'String.prototype.trim', 'Object.create']); 85 | }); 86 | 87 | it('uses custom parser', function () { 88 | var polyfills = scan('array.map(x => x * x)', mockParser); 89 | expect(polyfills).to.eql(['Array.prototype.map']); 90 | }); 91 | 92 | it('provides custom parser options', function () { 93 | expect(function () { 94 | scan('array.map(x => x * x)', mockParser, 42); 95 | }).to.throw(Error); 96 | 97 | expect(function () { 98 | scan('array.map(x => x * x)', mockParser, {}); 99 | }).to.not.throw(Error); 100 | }); 101 | 102 | describe('.use', function () { 103 | 104 | it('uses custom matches', function () { 105 | scan.use({ 106 | test: function (ast) { 107 | return astQuery('new PewpewOlolo(_$)', ast).length ? ['PewpewOlolo'] : []; 108 | } 109 | }); 110 | var polyfills = scan('new PewpewOlolo();'); 111 | expect(polyfills).to.eql(['PewpewOlolo']); 112 | }); 113 | 114 | }); 115 | 116 | }); 117 | -------------------------------------------------------------------------------- /lib/polyfill-reduce/index.js: -------------------------------------------------------------------------------- 1 | var browserslist = require('browserslist'); 2 | var debug = require('debug')('polyfill:reduce'); 3 | var semver = require('semver'); 4 | 5 | var polyFillSets = {}; 6 | 7 | // Autoprefixer browser code to polyfill agent name 8 | var browserMap = { 9 | ie: 'Internet Explorer', 10 | firefox: 'Firefox', 11 | chrome: 'Chrome', 12 | safari: 'Safari', 13 | opera: 'Opera', 14 | ios_saf: 'Safari iOS', 15 | android: 'Android' 16 | /*,'ie_mob': ''*/ 17 | }; 18 | 19 | var reBrowserAndVersion = /^(\w+) ([\d\.]+)$/; 20 | 21 | /** 22 | * 10 -> 10.0.0 23 | * 11.5 -> 11.5.0 24 | * 1.1.1 -> 1.1.1 25 | * 26 | * @param {string|number} version 27 | * @returns {string} 28 | */ 29 | function toSemver(version) { 30 | return String(version).split('.').concat(0, 0, 0).slice(0, 3).join('.'); 31 | } 32 | 33 | /** 34 | * @param {string} comparatorName 35 | * @param {string} a 36 | * @param {string} b 37 | * @returns {boolean} 38 | */ 39 | function cmp(comparatorName, a, b) { 40 | return semver[comparatorName](toSemver(a), toSemver(b)); 41 | } 42 | 43 | /** 44 | * 45 | * @param {String} browserCode 46 | * @param {String} version 47 | */ 48 | function polyFillsFor(browserCode, version) { 49 | var polyFillSet = polyFillSets[browserMap[browserCode]]; 50 | 51 | if (!polyFillSet) { 52 | return []; 53 | } 54 | 55 | return polyFillSet.reduce(function (polyfills, range) { 56 | var isMatches = 57 | // X === A 58 | (range.only && cmp('eq', version, range.only)) || 59 | // X >= A 60 | (range.min && !range.max && cmp('gte', version, range.min)) || 61 | // A <= X <= B 62 | (range.min && range.max && cmp('gte', version, range.min) && cmp('lte', version, range.max)) || 63 | // Always 64 | (!range.min && !range.max && !range.only); 65 | 66 | if (isMatches) { 67 | return polyfills.concat(range.fill.split(' ')); 68 | } 69 | 70 | return polyfills; 71 | }, []); 72 | } 73 | 74 | /** 75 | * 76 | * @param {String[]} polyfills List of polyfill names from polyfill-scan 77 | * @param {String[]|String} browsersRequest Autoprefixer-style list of browsers or versions 78 | * 79 | * @returns {String[]} reduced list of polyfills 80 | * 81 | * @example 82 | * 83 | * reduce(['JSON.parse'], ['Explorer 10', '> 5%']) 84 | * // [] 85 | */ 86 | function reduce(polyfills, browsersRequest) { 87 | var browsers = browserslist(browsersRequest.toString()); 88 | debug('%s are selected', browsers); 89 | 90 | var requiredPolyFills = browsers 91 | .reduce(function (requiredPolyFills, browserAndVersion) { 92 | var parts = browserAndVersion.match(reBrowserAndVersion); 93 | 94 | return requiredPolyFills.concat(polyFillsFor.apply(null, parts.slice(1, 3))); 95 | }, []) 96 | // Make unique and cast to hash 97 | .reduce(function (polyfills, polyfill) { 98 | polyfills[polyfill] = true; 99 | 100 | return polyfills; 101 | }, {}); 102 | 103 | return polyfills.filter(function (polyfill) { 104 | var shouldPolyFill = polyfill in requiredPolyFills; 105 | debug('%s `%s`', (shouldPolyFill ? 'keeping' : 'removing'), polyfill); 106 | return shouldPolyFill; 107 | }); 108 | } 109 | 110 | /** 111 | * @param {Object} polyfills 112 | */ 113 | function support(polyfills) { 114 | debug('adding custom supported polyfills'); 115 | Object.keys(polyfills).forEach(function (browser) { 116 | if (!polyFillSets[browser]) { 117 | polyFillSets[browser] = []; 118 | } 119 | 120 | polyFillSets[browser].push.apply(polyFillSets[browser], polyfills[browser]); 121 | }); 122 | } 123 | 124 | /** 125 | * @returns {String[]} list of all available polyfills 126 | */ 127 | function list() { 128 | return Object.keys(polyFillSets) 129 | // Collect all available polyfills 130 | .reduce(function (polyfills, browserName) { 131 | return polyFillSets[browserName].reduce(function (polyfills, sets) { 132 | return polyfills.concat(sets.fill.split(' ')); 133 | }, polyfills); 134 | }, []) 135 | // Unique 136 | .reduce(function (polyfills, polyfill) { 137 | if (polyfills.indexOf(polyfill) === -1) { 138 | polyfills.push(polyfill); 139 | } 140 | return polyfills; 141 | }, []); 142 | } 143 | 144 | module.exports = reduce; 145 | module.exports.support = support; 146 | module.exports.list = list; 147 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ⚠️ This repo is no longer maintained. 2 | 3 | As replacement use https://github.com/zloirock/core-js 4 | 5 | ---- 6 | 7 | # Autopolyfiller — Precise polyfills 8 | 9 | [![NPM Version](https://img.shields.io/npm/v/autopolyfiller.svg)](https://npmjs.org/package/autopolyfiller) [![Build Status](https://img.shields.io/travis/azproduction/autopolyfiller.svg)](https://travis-ci.org/azproduction/autopolyfiller) [![Coverage Status](https://img.shields.io/coveralls/azproduction/autopolyfiller.svg)](https://coveralls.io/r/azproduction/autopolyfiller) [![Code Climate](https://img.shields.io/codeclimate/github/azproduction/autopolyfiller.svg)](https://codeclimate.com/github/azproduction/autopolyfiller) [![Dependency Status](https://img.shields.io/gemnasium/azproduction/autopolyfiller.svg)](https://gemnasium.com/azproduction/autopolyfiller) 10 | 11 | This is like [Autoprefixer](https://github.com/ai/autoprefixer), but for JavaScript polyfills. It scans your code and applies only required polyfills. [Live example](http://azproduction.github.io/autopolyfiller). 12 | 13 | Assume you code is `Object.keys(window)`. `Object.keys` polyfill is required to run it [in any browser](http://kangax.github.io/es5-compat-table/#Object.keys) (include IE7). On the other hand this code can be executed on iOS 7 Safari without any polyfills. AutoPolyfiller knows about ES5 and ES6 features and their support in browsers. It can help you to write cutting-edge JavaScript without thinking about ES shims and shivs. 14 | 15 | How it works. Step by step: 16 | 17 | 1. Using AST matchers, it scans your code and finds all polyfills 18 | 2. If target browsers are specified, then it reduces the list of polyfills according to the "feature database" 19 | 3. It generates polyfills code, using [polyfills database](https://github.com/azproduction/polyfill), which precisely fixes only required features 20 | 21 | Limitations: 22 | 23 | * Right now it supports only safe and cross-browser [polyfills from ES5](https://github.com/azproduction/polyfill), but you can add your own (see examples). 24 | * It can have a false-positives for some cases. For instance, autopolyfiller thinks that `$('div').map()` is call of `Array.prototype.map`. But you can exclude false-positives (see examples). 25 | 26 | It will not work if: 27 | 28 | * You are `eval`ing code with polyfills. Eg `eval('Object.keys(this)')` 29 | * You are doing something odd. Eg `Object['k' + 'eys']()` 30 | 31 | ## Installation 32 | 33 | `autopolyfiller` can be installed using `npm`: 34 | 35 | ``` 36 | npm install autopolyfiller 37 | ``` 38 | 39 | ## CLI Example 40 | 41 | ``` 42 | $ autopolyfiller lib/**/*.js -b "Explorer 7, Chrome >= 10" 43 | $ cat lib/*.js | autopolyfiller 44 | ``` 45 | 46 | ## Grunt, Gulp, Enb tasks, and Webpack loader 47 | 48 | * [grunt-autopolyfiller](https://github.com/azproduction/grunt-autopolyfiller/) - Grunt task for autopolyfiller. 49 | * [gulp-autopolyfiller](https://github.com/azproduction/gulp-autopolyfiller/) - Gulp task for autopolyfiller. 50 | * [enb-autopolyfiller](https://github.com/enb-make/enb-autopolyfiller/) - Enb task for autopolyfiller. 51 | * [autopolyfiller-loader](https://github.com/deepsweet/autopolyfiller-loader) - Webpack loader for autopolyfiller. 52 | 53 | ## Example 54 | 55 | ```js 56 | // Polyfills + Code 57 | require('autopolyfiller')().add(code) + code; 58 | ``` 59 | 60 | **List of polyfills without browsers filtering** 61 | 62 | ```js 63 | var autopolyfiller = require('autopolyfiller'); 64 | 65 | autopolyfiller() 66 | .add('"".trim();') 67 | .polyfills; 68 | // ['String.prototype.trim'] 69 | ``` 70 | 71 | **Filtering using Autoprefixer-style [browser matchers](https://github.com/ai/browserslist#queries)** 72 | 73 | ```js 74 | var autopolyfiller = require('autopolyfiller'); 75 | 76 | autopolyfiller('IE 11', 'Chrome >= 31') 77 | .add('"".trim();Object.create();new Promise()') 78 | .polyfills; 79 | // ['Promise'] 80 | ``` 81 | 82 | **Default autoprefixer browsers** 83 | 84 | ```js 85 | var autopolyfiller = require('autopolyfiller'), 86 | autoprefixer = require('autopolyfiller'); 87 | 88 | autopolyfiller(autoprefixer.default) 89 | .add('new Promise();') 90 | .polyfills; 91 | // ['Promise'] 92 | ``` 93 | 94 | **Excluding/including polyfills** 95 | 96 | ```js 97 | var autopolyfiller = require('autopolyfiller'); 98 | 99 | autopolyfiller() 100 | .exclude(['Promise']) 101 | .include(['String.prototype.trim']) 102 | // All Array polyfills 103 | .include(['Array.*']) 104 | .add('new My.Promise();') 105 | .polyfills; 106 | // ['String.prototype.trim'] 107 | ``` 108 | 109 | **Using custom parser** 110 | 111 | ```js 112 | var autopolyfiller = require('autopolyfiller'); 113 | 114 | autopolyfiller() 115 | .withParser('acorn@0.11.0', {ecmaVersion: 6}) 116 | .add('array.map(x => x * x)') 117 | .polyfills; 118 | // ['Array.prototype.map'] 119 | ``` 120 | 121 | **Adding your own polyfills** 122 | 123 | ```js 124 | var query = require('grasp-equery').query; 125 | var autopolyfiller = require('autopolyfiller'); 126 | 127 | autopolyfiller.use({ 128 | // AST tree pattern matching 129 | // It may "grep" multiply polyfills 130 | test: function (ast) { 131 | return query('Object.newFeature(_$)', ast).length > 0 ? ['Object.newFeature'] : []; 132 | }, 133 | 134 | // Your polyfills code 135 | polyfill: { 136 | 'Object.newFeature': 'Object.newFeature = function () {};' 137 | }, 138 | 139 | // This list means "apply this feature to the " 140 | // For more examples see https://github.com/jonathantneal/polyfill/blob/master/agent.js.json 141 | support: { 142 | // For chrome 29 only apply Object.newFeature polyfill 143 | 'Chrome': [{ 144 | only: '29', 145 | fill: 'Object.newFeature' 146 | }] 147 | }, 148 | 149 | // This is optional. By default autopolyfiller will use 150 | // polyfill's name to generate condition's code: 151 | wrapper: { 152 | 'Object.newFeature': { 153 | 'before': 'if (!("newFeature" in Object)) {', 154 | 'after': '}' 155 | } 156 | } 157 | }); 158 | 159 | autopolyfiller() 160 | .add('Object.create();Object.newFeature();') 161 | .polyfills; 162 | // ['Object.create', 'Object.newFeature'] 163 | 164 | autopolyfiller() 165 | .add('Object.newFeature();') 166 | .toString(); 167 | // if (!("newFeature" in Object)) { 168 | // Object.newFeature = function () {}; 169 | // } 170 | 171 | autopolyfiller('Chrome >= 20') 172 | .add('Object.create();Object.newFeature();') 173 | .polyfills; 174 | // [] 175 | ``` 176 | 177 | ## Handling polyfills issues 178 | 179 | Right now Autopolyfiller aggreagates existing sources of polyfills. If you have any issues related to a polyfill code itself, please, add an issue or a pull request to the [jonathantneal/polyfill](https://github.com/jonathantneal/polyfill). 180 | 181 | Here is how to temporary workaround, while your issue being resolved: 182 | ```js 183 | var autopolyfiller = require('autopolyfiller'); 184 | 185 | autopolyfiller.use({ 186 | polyfill: { 187 | 'Function.prototype.bind': 'fixed code (!Function.prototype.bind)' 188 | } 189 | }); 190 | ``` 191 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | var Command = require('commander').Command; 2 | var fs = require('fs'); 3 | var mkdirp = require('mkdirp').sync; 4 | var format = require('util').format; 5 | var path = require('path'); 6 | var globule = require('globule'); 7 | var autopolyfiller = require('..'); 8 | 9 | var noop = function () {}; 10 | 11 | /** 12 | * @param {Object} process 13 | * @param {Stream} process.stdin 14 | * @param {Stream} process.stdout 15 | * @param {Stream} process.stderr 16 | * @param {Array} process.argv 17 | * @param {Function} process.exit 18 | * @param {Object} [process.env] 19 | * @param {Function} [done] 20 | */ 21 | function AutoPolyFillerCli(process, done) { 22 | this.process = process; 23 | this.program = this.createProgram(); 24 | this.polyfiller = this.createPolyFiller(); 25 | this.done = function (status) { 26 | (done || noop)(status); 27 | this.done = noop; 28 | }.bind(this); 29 | 30 | this.run(this.process.stdin.isTTY); 31 | } 32 | 33 | AutoPolyFillerCli.prototype = { 34 | _list: function (browsers) { 35 | return browsers.split(',').map(function (browser) { 36 | return browser.trim(); 37 | }); 38 | }, 39 | 40 | log: function () { 41 | if (!this.program.verbose) { 42 | return; 43 | } 44 | 45 | this.process.stdout.write(format.apply(null, arguments) + '\n'); 46 | }, 47 | 48 | _logHelp: function (message) { 49 | this.process.stdout.write(message + '\n'); 50 | }, 51 | 52 | getOutput: function () { 53 | var output = this.program.output; 54 | switch (output) { 55 | case 'STDOUT': 56 | return this.process.stdout; 57 | case 'STDERR': 58 | return this.process.stderr; 59 | default: 60 | mkdirp(path.dirname(output)); 61 | return fs.createWriteStream(output); 62 | } 63 | }, 64 | 65 | createPolyFiller: function () { 66 | var browsers = this.program.browsers; 67 | var excludedPolyfills = this.program.exclude; 68 | var includedPolyfills = this.program.include; 69 | 70 | this.log((function () { 71 | if (!browsers.length) { 72 | return 'Generating polyfills for all browsers'; 73 | } 74 | return 'Generating polyfills for' + [''].concat(browsers).join('\n * '); 75 | })()); 76 | 77 | if (includedPolyfills.length) { 78 | this.log('Adding extra polyfills: ' + [''].concat(includedPolyfills).join('\n * ')); 79 | } 80 | 81 | if (excludedPolyfills.length) { 82 | this.log('Ignoring polyfills: ' + [''].concat(excludedPolyfills).join('\n * ')); 83 | } 84 | 85 | return autopolyfiller(browsers) 86 | .withParser(this.program.parser, this.program.parserOptions) 87 | .exclude(excludedPolyfills) 88 | .include(includedPolyfills); 89 | }, 90 | 91 | createProgram: function () { 92 | return new Command() 93 | .version(require('../package.json').version) 94 | .usage('[options] ') 95 | .option('-o, --output ', 'set output file', 'STDOUT') 96 | .option('-b, --browsers ', 'generate polyfills for these browsers', this._list.bind(this), []) 97 | .option('-x, --exclude ', 'exclude these polyfills', this._list.bind(this), []) 98 | .option('-i, --include ', 'include these polyfills', this._list.bind(this), []) 99 | .option('-p, --parser ', 'specifies JavaScript parser (node module)', require, null) 100 | .option( 101 | '-P, --parser-options ', 102 | 'custom parser options (valid json object)', 103 | JSON.parse.bind(JSON), 104 | void 0 105 | ) 106 | .option('-v, --verbose', 'verbose output') 107 | .on('--help', function () { 108 | this._logHelp([ 109 | ' Examples:', 110 | '', 111 | ' $ echo "Object.keys({})" | autopolyfiller', 112 | ' $ autopolyfiller -o polyfills.js script.js', 113 | ' $ autopolyfiller -o polyfills.js -i Promise -x Array.prototype.map script.js', 114 | ' $ autopolyfiller -b "last 1 version, > 1%, Explorer 7" lib/*.js vendors/**/*.js', 115 | ' $ autopolyfiller lib/*.js !lib/lodash.js', 116 | ' $ autopolyfiller -p acorn -P \'{"ecmaVersion":6}\' lib/*.js', 117 | '' 118 | ].join('\n')); 119 | }.bind(this)) 120 | .parse(this.process.argv); 121 | }, 122 | 123 | addFile: function (fileContents, filePath) { 124 | try { 125 | this.polyfiller.add(fileContents); 126 | } catch (e) { 127 | this.process.stderr.write(format('Error while adding file from %s: %s', filePath, e) + '\n'); 128 | this.done(new Error(String(e))); 129 | this.process.exit(1); 130 | } 131 | }, 132 | 133 | addPatterns: function (patterns) { 134 | this.log('Globbing files %s', [''].concat(patterns).join('\n * ')); 135 | var files = globule.find(patterns); 136 | 137 | this.log('Got %d file(s)', files.length); 138 | files.forEach(function (file) { 139 | this.log('Reading file %s', file); 140 | this.addFile(fs.readFileSync(file, 'utf8'), file); 141 | }.bind(this)); 142 | }, 143 | 144 | readStdin: function (cb) { 145 | var buff = ''; 146 | this.process.stdin.resume(); 147 | this.process.stdin.setEncoding('utf8'); 148 | this.process.stdin.on('data', function (data) { 149 | buff += data; 150 | }); 151 | this.process.stdin.on('end', function () { 152 | cb(null, buff); 153 | }); 154 | }, 155 | 156 | writePolyFills: function () { 157 | var output = this.program.output; 158 | var polyfills = this.polyfiller.polyfills; 159 | 160 | this.log((function () { 161 | if (!polyfills.length) { 162 | return 'Polyfills are not required'; 163 | } 164 | return 'Got ' + polyfills.length + ' polyfills for' + 165 | [''].concat(polyfills).join('\n * '); 166 | })()); 167 | 168 | this.log('Writing %d polyfills to %s', polyfills.length, output); 169 | this.getOutput().write(this.polyfiller.toString(), 'utf8', this.done.bind(this)); 170 | }, 171 | 172 | run: function (isTTY) { 173 | if (isTTY) { 174 | if (!this.program.args.length) { 175 | this._logHelp(this.program.helpInformation()); 176 | this.program.emit('--help'); 177 | this.done(null); 178 | } else { 179 | this.addPatterns(this.program.args); 180 | this.writePolyFills(); 181 | } 182 | } else { 183 | this.readStdin(function (error, fileContents) { 184 | this.addFile(fileContents, 'STDIN'); 185 | this.writePolyFills(); 186 | }.bind(this)); 187 | } 188 | } 189 | }; 190 | 191 | module.exports = AutoPolyFillerCli; 192 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var acorn = require('acorn'); 2 | var assert = require('assert'); 3 | var scan = require('./lib/polyfill-scan'); 4 | var reduce = require('./lib/polyfill-reduce'); 5 | var wrap = require('./lib/polyfill-wrap'); 6 | var minimatch = require('minimatch'); 7 | var code = require('./lib/polyfill-code'); 8 | var stablePolyfills = require('autopolyfiller-stable'); 9 | var polyfillNames = Object.keys(stablePolyfills.polyfill); 10 | 11 | /** 12 | * 13 | * @param {Object} options 14 | * @param {String[]} [options.browsers] Autoprefixer style list of browsers 15 | * @constructor 16 | * 17 | * @example 18 | * 19 | * new AutoPolyFiller({ 20 | * browsers: ['IE 11', 'Chrome >= 31'] 21 | * }) 22 | * .withParser(require('esprima-fb')) 23 | * .exclude(['Object.create']) 24 | * .include(['Array.prototype.map']) 25 | * .add('"".trim();Object.create();new Promise();') 26 | * .polyfills; 27 | * // ['Promise', 'Array.prototype.map'] 28 | */ 29 | function AutoPolyFiller(options) { 30 | this.browsers = options.browsers; 31 | this.polyfills = []; 32 | this.excluedPolyfills = []; 33 | this.parserOptions = void 0; 34 | this.parser = acorn; 35 | } 36 | 37 | AutoPolyFiller.prototype = { 38 | /** 39 | * Scans `code` for polyfills 40 | * 41 | * @param {String} code 42 | * @returns {String[]} 43 | * @private 44 | */ 45 | _scan: function (code) { 46 | var polyfills = scan(code, this.parser, this.parserOptions); 47 | 48 | // Do not reduce if no browsers 49 | if (this.browsers && this.browsers.length === 0) { 50 | return polyfills; 51 | } 52 | return reduce(polyfills, this.browsers); 53 | }, 54 | 55 | /** 56 | * Scans for polyfills in code of each polyfills 57 | * 58 | * @param {String[]} polyfills list of polyfills names 59 | * @returns {String[]} list contains non unique polyfills 60 | * @private 61 | */ 62 | _scanForPolyfillsOfPolyfills: function (polyfills) { 63 | var hasIterated = {}; 64 | 65 | var iteratePolyfills = function (polyfills, polyfillName) { 66 | // Already scanned this polyfill 67 | if (hasIterated.hasOwnProperty(polyfillName)) { 68 | return polyfills; 69 | } 70 | hasIterated[polyfillName] = true; 71 | 72 | polyfills = polyfills.concat(this._scan(code(polyfillName))); 73 | 74 | return polyfills.concat(polyfills.reduce(iteratePolyfills, [])); 75 | }.bind(this); 76 | 77 | return polyfills.reduce(iteratePolyfills, []); 78 | }, 79 | 80 | /** 81 | * Inspects given `code` for polyfills 82 | * @param {String} code javascipt code 83 | * @returns {AutoPolyFiller} 84 | */ 85 | add: function (code) { 86 | var polyfills = this._scan(code); 87 | var polyfillsOfPolyfills = this._scanForPolyfillsOfPolyfills(polyfills); 88 | 89 | this.include(polyfills.concat(polyfillsOfPolyfills)); 90 | 91 | return this; 92 | }, 93 | 94 | /** 95 | * 96 | * @returns {string} code that polyfills all listed functions 97 | */ 98 | toString: function () { 99 | return this.polyfills.map(function (polyfillName) { 100 | var polyfillCode = code(polyfillName); 101 | return wrap(polyfillCode, polyfillName); 102 | }).join(''); 103 | }, 104 | 105 | /** 106 | * Checks if `polyfill` is not in a `excluedPolyfills` list 107 | * 108 | * @param {String} polyfill 109 | * @returns {Boolean} 110 | * @private 111 | */ 112 | _isPolyfillIncluded: function (polyfill) { 113 | return this.excluedPolyfills.indexOf(polyfill) === -1; 114 | }, 115 | 116 | /** 117 | * Adds `polyfills` to the list of required polyfills 118 | * 119 | * @param {String[]} polyfills 120 | * @returns {AutoPolyFiller} 121 | */ 122 | include: function (polyfills) { 123 | this.polyfills = this.polyfills 124 | .concat(polyfills) 125 | 126 | // If any of the patterns contain '*', add all of the matching 127 | // polyfills 128 | .reduce(function (polyfills, polyfill) { 129 | if (polyfill.indexOf('*') > -1) { 130 | var matches = polyfillNames.filter(function (name) { 131 | return minimatch(name, polyfill); 132 | }); 133 | return polyfills.concat(matches); 134 | } 135 | polyfills.push(polyfill); 136 | 137 | return polyfills; 138 | }, []) 139 | 140 | // Filter ignored polyfills 141 | .filter(this._isPolyfillIncluded.bind(this)) 142 | 143 | // Make unique polyfills 144 | .reduce(function (polyfills, polyfill) { 145 | if (polyfills.indexOf(polyfill) === -1) { 146 | polyfills.push(polyfill); 147 | } 148 | 149 | return polyfills; 150 | }, []); 151 | 152 | return this; 153 | }, 154 | 155 | /** 156 | * Ignores `polyfills`, excluded their code from result 157 | * 158 | * @param {String[]} polyfills 159 | * @returns {AutoPolyFiller} 160 | */ 161 | exclude: function (polyfills) { 162 | this.excluedPolyfills.push.apply(this.excluedPolyfills, polyfills); 163 | 164 | // Filter ignored polyfills 165 | this.polyfills = this.polyfills 166 | .filter(this._isPolyfillIncluded.bind(this)); 167 | 168 | return this; 169 | }, 170 | 171 | /** 172 | * Overrides default parser 173 | * 174 | * @param {Object} parser 175 | * @param {Object} parser.parse 176 | * @param {Object} [parserOptions] 177 | * @returns {AutoPolyFiller} 178 | */ 179 | withParser: function (parser, parserOptions) { 180 | this.parserOptions = parserOptions; 181 | 182 | if (parser) { 183 | assert(typeof parser.parse === 'function', 'parser should have a `parse` method'); 184 | this.parser = parser; 185 | } 186 | 187 | return this; 188 | } 189 | }; 190 | 191 | /** 192 | * Polyfill interface 193 | * 194 | * @example 195 | * 196 | * polyfiller('IE 11', 'Chrome >= 31') 197 | * .add('"".trim();Object.create();new Promise()') 198 | * .polyfills; 199 | * // ['Promise'] 200 | */ 201 | function create() { 202 | var browsers = arguments.length >= 1 ? [].slice.call(arguments, 0) : []; 203 | 204 | if (browsers.length === 1 && browsers[0] instanceof Array) { 205 | browsers = browsers[0]; 206 | } 207 | 208 | return new AutoPolyFiller({ 209 | browsers: browsers 210 | }); 211 | } 212 | 213 | /** 214 | * Customizes polyfills 215 | * 216 | * @param {Object} options 217 | * @param {Function} [options.test] 218 | * @param {Object} [options.support] 219 | * @param {Object} [options.polyfill] 220 | * @param {Object} [options.wrapper] 221 | */ 222 | function use(options) { 223 | if (options.test) { 224 | scan.use({ 225 | test: options.test 226 | }); 227 | } 228 | 229 | if (options.support) { 230 | reduce.support(options.support); 231 | } 232 | 233 | if (options.polyfill) { 234 | code.addSource(options.polyfill); 235 | } 236 | 237 | if (options.wrapper) { 238 | wrap.addWrapper(options.wrapper); 239 | } 240 | } 241 | 242 | use(stablePolyfills); 243 | 244 | module.exports = create; 245 | module.exports.use = use; 246 | -------------------------------------------------------------------------------- /images/autopolyfiller.min.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/test.autopolyfiler.js: -------------------------------------------------------------------------------- 1 | /*global describe, it, beforeEach, afterEach*/ 2 | /*jshint expr:true*/ 3 | 4 | var autopolyfiller = require('..'); 5 | var astQuery = require('grasp-equery').query; 6 | var expect = require('chai').expect; 7 | 8 | var reLocalPolyfills = /^__/; 9 | 10 | describe('autopolyfiller', function () { 11 | 12 | it('accepts browsers as ...rest parameter', function () { 13 | var polyfills = autopolyfiller('IE 11', 'Chrome >= 31').add('"".trim();').polyfills; 14 | 15 | expect(polyfills).to.eql([]); 16 | }); 17 | 18 | it('accepts browsers as array parameter', function () { 19 | var polyfills = autopolyfiller(['IE 11', 'Chrome >= 31']).add('"".trim();').polyfills; 20 | 21 | expect(polyfills).to.eql([]); 22 | }); 23 | 24 | describe('.add', function () { 25 | 26 | it('stores unique polyfills', function () { 27 | var polyfills = autopolyfiller('IE 7').add('"".trim();').add('"".trim();').polyfills; 28 | 29 | expect(polyfills).to.eql(['String.prototype.trim']); 30 | }); 31 | 32 | it('keeps all polyfills if no browsers passed', function () { 33 | var polyfills = autopolyfiller().add('"".trim();').add('Object.keys();').polyfills; 34 | 35 | expect(polyfills).to.eql(['String.prototype.trim', 'Object.keys']); 36 | }); 37 | 38 | it('scans polyfills for extra polyfills', function () { 39 | var polyfills = autopolyfiller().add('Object.defineProperties();').polyfills; 40 | 41 | expect(polyfills).to.eql(['Object.defineProperties', 'Object.defineProperty']); 42 | }); 43 | 44 | it('scans polyfills for extra polyfills recursively', function () { 45 | autopolyfiller.use({ 46 | test: function (ast) { 47 | return astQuery('__.recursively(_$)', ast).length ? ['PewPew.prototype.recursively'] : []; 48 | }, 49 | support: { 50 | Opera: [{ 51 | only: '11.5', 52 | fill: 'PewPew.prototype.recursively' 53 | }] 54 | }, 55 | polyfill: { 56 | 'PewPew.prototype.recursively': 'Object.defineProperties(' + 57 | 'PewPew.prototype, {' + 58 | 'myTemporary: function(){}' + 59 | '}' + 60 | ');' 61 | } 62 | }); 63 | var polyfills = autopolyfiller('Opera 11.5').add('"".recursively();').polyfills; 64 | 65 | expect(polyfills).to.eql([ 66 | 'PewPew.prototype.recursively', 67 | 'Object.defineProperties', 68 | 'Object.defineProperty' 69 | ]); 70 | }); 71 | }); 72 | 73 | describe('.use', function () { 74 | 75 | it('registers matchers, support, wrappers and polyfills', function () { 76 | autopolyfiller.use({ 77 | test: function (ast) { 78 | return astQuery('__.ololo(_$)', ast).length ? ['PewPew.prototype.ololo'] : []; 79 | }, 80 | support: { 81 | Chrome: [{ 82 | only: '19', 83 | fill: 'PewPew.prototype.ololo' 84 | }] 85 | }, 86 | polyfill: { 87 | 'PewPew.prototype.ololo': 'PewPew.prototype.ololo = {};' 88 | }, 89 | wrapper: { 90 | 'PewPew.prototype.ololo': { 91 | before: 'if (!PewPew.prototype.ololo) {', 92 | after: '}' 93 | } 94 | } 95 | }); 96 | 97 | var polyfills = autopolyfiller('Chrome 19').add('"".ololo();').polyfills; 98 | 99 | expect(polyfills).to.eql(['PewPew.prototype.ololo']); 100 | }); 101 | 102 | it('ignores absent parameters', function () { 103 | autopolyfiller.use({}); 104 | }); 105 | 106 | }); 107 | 108 | describe('.toString', function () { 109 | 110 | it('returnes polyfills code as string', function () { 111 | var code = 'PewPew.prototype.test = {};'; 112 | 113 | autopolyfiller.use({ 114 | test: function (ast) { 115 | return astQuery('__.test(_$)', ast).length ? ['PewPew.prototype.test'] : []; 116 | }, 117 | support: { 118 | Chrome: [{ 119 | only: '19', 120 | fill: 'PewPew.prototype.test' 121 | }] 122 | }, 123 | polyfill: { 124 | 'PewPew.prototype.test': code 125 | } 126 | }); 127 | 128 | var polyfillsCode = autopolyfiller('Chrome 19').add('"".test();').toString(); 129 | 130 | expect(polyfillsCode).to.have.string(code); 131 | }); 132 | 133 | it('wraps code with conditional expression', function () { 134 | var polyfills = autopolyfiller('IE 7').add('"".trim();').toString(); 135 | 136 | expect(polyfills).to.match(/String\.prototype\.trim/); 137 | expect(polyfills).to.match(/!String\.prototype\.trim/); 138 | }); 139 | 140 | }); 141 | 142 | describe('.include', function () { 143 | 144 | it('includes extra polyfills', function () { 145 | var polyfills = autopolyfiller() 146 | .include(['Promise']) 147 | .add('"".trim();') 148 | .polyfills; 149 | 150 | expect(polyfills).to.eql(['Promise', 'String.prototype.trim']); 151 | }); 152 | 153 | it('filters against list of excluded polyfills', function () { 154 | var polyfills = autopolyfiller() 155 | .exclude(['Promise']) 156 | .include(['Promise']) 157 | .add('"".trim();') 158 | .exclude(['String.prototype.trim']) 159 | .polyfills; 160 | 161 | expect(polyfills).to.eql([]); 162 | }); 163 | 164 | it('adds unique polyfills', function () { 165 | var polyfills = autopolyfiller() 166 | .include(['String.prototype.trim', 'String.prototype.trim']) 167 | .add('"".trim();') 168 | .polyfills; 169 | 170 | expect(polyfills).to.eql(['String.prototype.trim']); 171 | }); 172 | 173 | it('accepts wildcards', function () { 174 | var polyfills = autopolyfiller() 175 | .include(['Array.*']) 176 | .polyfills; 177 | 178 | expect(polyfills.length).to.be.above(0); 179 | }); 180 | 181 | }); 182 | 183 | describe('.exclude', function () { 184 | 185 | it('adds exclued polyfills to the `excluedPolyfills` list', function () { 186 | var excluedPolyfills = autopolyfiller() 187 | .exclude(['Promise']) 188 | .add('"".trim();') 189 | .excluedPolyfills; 190 | 191 | expect(excluedPolyfills).to.eql(['Promise']); 192 | }); 193 | 194 | it('removes non required polyfills', function () { 195 | var polyfills = autopolyfiller() 196 | .exclude(['Promise']) 197 | .include(['Promise', 'Object.keys']) 198 | .exclude(['Object.keys', 'Array.prototype.map']) 199 | .add('"".trim();[].map(function () {});') 200 | .exclude(['String.prototype.trim']) 201 | .polyfills; 202 | 203 | expect(polyfills).to.eql([]); 204 | }); 205 | 206 | }); 207 | 208 | describe('.withParser', function () { 209 | it('overriders default parser and parser options', function () { 210 | var myParser = { 211 | parse: function () { 212 | 213 | } 214 | }; 215 | 216 | var myParserOptions = {}; 217 | 218 | var instance = autopolyfiller() 219 | .withParser(myParser, myParserOptions); 220 | 221 | expect(instance.parser).to.eql(myParser); 222 | expect(instance.parserOptions).to.eql(myParserOptions); 223 | }); 224 | 225 | it('throws in case of invalid parser', function () { 226 | expect(function () { 227 | autopolyfiller().withParser({}); 228 | }).to.throw(Error); 229 | }); 230 | }); 231 | 232 | }); 233 | -------------------------------------------------------------------------------- /images/autopolyfiller.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /benchmark/scan/assets/require.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS 2.1.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | var requirejs,require,define; 7 | (function(W){function D(b){return M.call(b)==="[object Function]"}function E(b){return M.call(b)==="[object Array]"}function t(b,c){if(b){var d;for(d=0;d-1;d-=1)if(b[d]&&c(b[d],d,b))break}}function A(b,c){for(var d in b)if(b.hasOwnProperty(d)&&c(b[d],d))break}function O(b,c,d,g){c&&A(c,function(c,j){if(d||!F.call(b,j))g&&typeof c!=="string"?(b[j]||(b[j]={}),O(b[j],c,d,g)):b[j]=c});return b}function r(b,c){return function(){return c.apply(b, 8 | arguments)}}function X(b){if(!b)return b;var c=W;t(b.split("."),function(b){c=c[b]});return c}function G(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;if(d)c.originalError=d;return c}function ba(){if(H&&H.readyState==="interactive")return H;N(document.getElementsByTagName("script"),function(b){if(b.readyState==="interactive")return H=b});return H}var g,s,u,y,q,B,H,I,Y,Z,ca=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,da=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, 9 | $=/\.js$/,ea=/^\.\//;s=Object.prototype;var M=s.toString,F=s.hasOwnProperty,fa=Array.prototype.splice,v=!!(typeof window!=="undefined"&&navigator&&document),aa=!v&&typeof importScripts!=="undefined",ga=v&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/,R=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",w={},n={},P=[],J=!1;if(typeof define==="undefined"){if(typeof requirejs!=="undefined"){if(D(requirejs))return;n=requirejs;requirejs=void 0}typeof require!=="undefined"&& 10 | !D(require)&&(n=require,require=void 0);g=requirejs=function(b,c,d,p){var i,j="_";!E(b)&&typeof b!=="string"&&(i=b,E(c)?(b=c,c=d,d=p):b=[]);if(i&&i.context)j=i.context;(p=w[j])||(p=w[j]=g.s.newContext(j));i&&p.configure(i);return p.require(b,c,d)};g.config=function(b){return g(b)};g.nextTick=typeof setTimeout!=="undefined"?function(b){setTimeout(b,4)}:function(b){b()};require||(require=g);g.version="2.1.1";g.jsExtRegExp=/^\/|:|\?|\.js$/;g.isBrowser=v;s=g.s={contexts:w,newContext:function(b){function c(a, 11 | f,x){var e,m,b,c,d,h,i,g=f&&f.split("/");e=g;var j=k.map,l=j&&j["*"];if(a&&a.charAt(0)===".")if(f){e=k.pkgs[f]?g=[f]:g.slice(0,g.length-1);f=a=e.concat(a.split("/"));for(e=0;f[e];e+=1)if(m=f[e],m===".")f.splice(e,1),e-=1;else if(m==="..")if(e===1&&(f[2]===".."||f[0]===".."))break;else e>0&&(f.splice(e-1,2),e-=2);e=k.pkgs[f=a[0]];a=a.join("/");e&&a===f+"/"+e.main&&(a=f)}else a.indexOf("./")===0&&(a=a.substring(2));if(x&&(g||l)&&j){f=a.split("/");for(e=f.length;e>0;e-=1){b=f.slice(0,e).join("/");if(g)for(m= 12 | g.length;m>0;m-=1)if(x=j[g.slice(0,m).join("/")])if(x=x[b]){c=x;d=e;break}if(c)break;!h&&l&&l[b]&&(h=l[b],i=e)}!c&&h&&(c=h,d=i);c&&(f.splice(0,d,c),a=f.join("/"))}return a}function d(a){v&&t(document.getElementsByTagName("script"),function(f){if(f.getAttribute("data-requiremodule")===a&&f.getAttribute("data-requirecontext")===h.contextName)return f.parentNode.removeChild(f),!0})}function p(a){var f=k.paths[a];if(f&&E(f)&&f.length>1)return d(a),f.shift(),h.require.undef(a),h.require([a]),!0}function i(a){var f, 13 | b=a?a.indexOf("!"):-1;b>-1&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function j(a,f,b,e){var m,K,d=null,g=f?f.name:null,j=a,l=!0,k="";a||(l=!1,a="_@r"+(M+=1));a=i(a);d=a[0];a=a[1];d&&(d=c(d,g,e),K=o[d]);a&&(d?k=K&&K.normalize?K.normalize(a,function(a){return c(a,g,e)}):c(a,g,e):(k=c(a,g,e),a=i(k),d=a[0],k=a[1],b=!0,m=h.nameToUrl(k)));b=d&&!K&&!b?"_unnormalized"+(N+=1):"";return{prefix:d,name:k,parentMap:f,unnormalized:!!b,url:m,originalName:j,isDefine:l,id:(d?d+"!"+k:k)+b}}function n(a){var f= 14 | a.id,b=l[f];b||(b=l[f]=new h.Module(a));return b}function q(a,f,b){var e=a.id,m=l[e];if(F.call(o,e)&&(!m||m.defineEmitComplete))f==="defined"&&b(o[e]);else n(a).on(f,b)}function z(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(t(b,function(f){if(f=l[f])f.error=a,f.events.error&&(e=!0,f.emit("error",a))}),!e)g.onError(a)}function s(){P.length&&(fa.apply(C,[C.length-1,0].concat(P)),P=[])}function u(a,f,b){var e=a.map.id;a.error?a.emit("error",a.error):(f[e]=!0,t(a.depMaps,function(e,c){var d=e.id, 15 | g=l[d];g&&!a.depMatched[c]&&!b[d]&&(f[d]?(a.defineDep(c,o[d]),a.check()):u(g,f,b))}),b[e]=!0)}function w(){var a,f,b,e,m=(b=k.waitSeconds*1E3)&&h.startTime+b<(new Date).getTime(),c=[],g=[],i=!1,j=!0;if(!S){S=!0;A(l,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||g.push(b),!b.error))if(!b.inited&&m)p(f)?i=e=!0:(c.push(f),d(f));else if(!b.inited&&b.fetched&&a.isDefine&&(i=!0,!a.prefix))return j=!1});if(m&&c.length)return b=G("timeout","Load timeout for modules: "+c,null,c),b.contextName=h.contextName, 16 | z(b);j&&t(g,function(a){u(a,{},{})});if((!m||e)&&i)if((v||aa)&&!T)T=setTimeout(function(){T=0;w()},50);S=!1}}function y(a){n(j(a[0],null,!0)).init(a[1],a[2])}function B(a){var a=a.currentTarget||a.srcElement,b=h.onScriptLoad;a.detachEvent&&!R?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=h.onScriptError;a.detachEvent&&!R||a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function I(){var a;for(s();C.length;)if(a=C.shift(),a[0]=== 17 | null)return z(G("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));else y(a)}var S,U,h,L,T,k={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},shim:{},map:{},config:{}},l={},V={},C=[],o={},Q={},M=1,N=1;L={require:function(a){return a.require?a.require:a.require=h.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=o[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return k.config&& 18 | k.config[a.map.id]||{}},exports:o[a.map.id]}}};U=function(a){this.events=V[a.id]||{};this.map=a;this.shim=k.shim[a.id];this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};U.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=r(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}}, 19 | defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;h.startTime=(new Date).getTime();var a=this.map;if(this.shim)h.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],r(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;Q[a]||(Q[a]=!0,h.load(this.map.id,a))},check:function(){if(this.enabled&& 20 | !this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,m=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(this.depCount<1&&!this.defined){if(D(m)){if(this.events.error)try{e=h.execCb(c,m,b,e)}catch(d){a=d}else e=h.execCb(c,m,b,e);if(this.map.isDefine)if((b=this.module)&&b.exports!==void 0&&b.exports!==this.exports)e=b.exports;else if(e===void 0&&this.usingExports)e=this.exports;if(a)return a.requireMap=this.map, 21 | a.requireModules=[this.map.id],a.requireType="define",z(this.error=a)}else e=m;this.exports=e;if(this.map.isDefine&&!this.ignore&&(o[c]=e,g.onResourceLoad))g.onResourceLoad(h,this.map,this.depMaps);delete l[c];this.defined=!0}this.defining=!1;if(this.defined&&!this.defineEmitted)this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=j(a.prefix);this.depMaps.push(d);q(d,"defined",r(this,function(e){var m, 22 | d;d=this.map.name;var x=this.map.parentMap?this.map.parentMap.name:null,i=h.makeRequire(a.parentMap,{enableBuildCallback:!0,skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,x,!0)})||""),e=j(a.prefix+"!"+d,this.map.parentMap),q(e,"defined",r(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=l[e.id]){this.depMaps.push(e);if(this.events.error)d.on("error",r(this,function(a){this.emit("error",a)}));d.enable()}}else m=r(this, 23 | function(a){this.init([],function(){return a},null,{enabled:!0})}),m.error=r(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];A(l,function(a){a.map.id.indexOf(b+"_unnormalized")===0&&delete l[a.map.id]});z(a)}),m.fromText=r(this,function(b,e){var f=a.name,c=j(f),d=J;e&&(b=e);d&&(J=!1);n(c);try{g.exec(b)}catch(x){throw Error("fromText eval for "+f+" failed: "+x);}d&&(J=!0);this.depMaps.push(c);h.completeLoad(f);i([f],m)}),e.load(a.name,i,m,k)}));h.enable(d,this);this.pluginMaps[d.id]= 24 | d},enable:function(){this.enabling=this.enabled=!0;t(this.depMaps,r(this,function(a,b){var c,e;if(typeof a==="string"){a=j(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=L[a.id]){this.depExports[b]=c(this);return}this.depCount+=1;q(a,"defined",r(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&q(a,"error",this.errback)}c=a.id;e=l[c];!L[c]&&e&&!e.enabled&&h.enable(a,this)}));A(this.pluginMaps,r(this,function(a){var b=l[a.id];b&&!b.enabled&& 25 | h.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){t(this.events[a],function(a){a(b)});a==="error"&&delete this.events[a]}};h={config:k,contextName:b,registry:l,defined:o,urlFetched:Q,defQueue:C,Module:U,makeModuleMap:j,nextTick:g.nextTick,configure:function(a){a.baseUrl&&a.baseUrl.charAt(a.baseUrl.length-1)!=="/"&&(a.baseUrl+="/");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};A(a,function(a,b){e[b]? 26 | b==="map"?O(k[b],a,!0,!0):O(k[b],a,!0):k[b]=a});if(a.shim)A(a.shim,function(a,b){E(a)&&(a={deps:a});if(a.exports&&!a.exportsFn)a.exportsFn=h.makeShimExports(a);c[b]=a}),k.shim=c;if(a.packages)t(a.packages,function(a){a=typeof a==="string"?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ea,"").replace($,"")}}),k.pkgs=b;A(l,function(a,b){if(!a.inited&&!a.map.unnormalized)a.map=j(b)});if(a.deps||a.callback)h.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b; 27 | a.init&&(b=a.init.apply(W,arguments));return b||X(a.exports)}},makeRequire:function(a,f){function d(e,c,i){var k,p;if(f.enableBuildCallback&&c&&D(c))c.__requireJsBuild=!0;if(typeof e==="string"){if(D(c))return z(G("requireargs","Invalid require call"),i);if(a&&L[e])return L[e](l[a.id]);if(g.get)return g.get(h,e,a);k=j(e,a,!1,!0);k=k.id;return!F.call(o,k)?z(G("notloaded",'Module name "'+k+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):o[k]}I();h.nextTick(function(){I();p= 28 | n(j(null,a));p.skipMap=f.skipMap;p.init(e,c,i,{enabled:!0});w()});return d}f=f||{};O(d,{isBrowser:v,toUrl:function(b){var d=b.lastIndexOf("."),f=null;d!==-1&&(f=b.substring(d,b.length),b=b.substring(0,d));return h.nameToUrl(c(b,a&&a.id,!0),f)},defined:function(b){b=j(b,a,!1,!0).id;return F.call(o,b)},specified:function(b){b=j(b,a,!1,!0).id;return F.call(o,b)||F.call(l,b)}});if(!a)d.undef=function(b){s();var c=j(b,a,!0),d=l[b];delete o[b];delete Q[c.url];delete V[b];if(d){if(d.events.defined)V[b]= 29 | d.events;delete l[b]}};return d},enable:function(a){l[a.id]&&n(a).enable()},completeLoad:function(a){var b,c,d=k.shim[a]||{},g=d.exports;for(s();C.length;){c=C.shift();if(c[0]===null){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);y(c)}c=l[a];if(!b&&!o[a]&&c&&!c.inited)if(k.enforceDefine&&(!g||!X(g)))if(p(a))return;else return z(G("nodefine","No define call for "+a,null,[a]));else y([a,d.deps||[],d.exportsFn]);w()},nameToUrl:function(a,b){var c,d,i,h,j,l;if(g.jsExtRegExp.test(a))h=a+(b||"");else{c= 30 | k.paths;d=k.pkgs;h=a.split("/");for(j=h.length;j>0;j-=1)if(l=h.slice(0,j).join("/"),i=d[l],l=c[l]){E(l)&&(l=l[0]);h.splice(0,j,l);break}else if(i){c=a===i.name?i.location+"/"+i.main:i.location;h.splice(0,j,c);break}h=h.join("/");h+=b||(/\?/.test(h)?"":".js");h=(h.charAt(0)==="/"||h.match(/^[\w\+\.\-]+:/)?"":k.baseUrl)+h}return k.urlArgs?h+((h.indexOf("?")===-1?"?":"&")+k.urlArgs):h},load:function(a,b){g.load(h,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if(a.type=== 31 | "load"||ga.test((a.currentTarget||a.srcElement).readyState))H=null,a=B(a),h.completeLoad(a.id)},onScriptError:function(a){var b=B(a);if(!p(b.id))return z(G("scripterror","Script error",a,[b.id]))}};h.require=h.makeRequire();return h}};g({});t(["toUrl","undef","defined","specified"],function(b){g[b]=function(){var c=w._;return c.require[b].apply(c,arguments)}});if(v&&(u=s.head=document.getElementsByTagName("head")[0],y=document.getElementsByTagName("base")[0]))u=s.head=y.parentNode;g.onError=function(b){throw b; 32 | };g.load=function(b,c,d){var g=b&&b.config||{},i;if(v)return i=g.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),i.type=g.scriptType||"text/javascript",i.charset="utf-8",i.async=!0,i.setAttribute("data-requirecontext",b.contextName),i.setAttribute("data-requiremodule",c),i.attachEvent&&!(i.attachEvent.toString&&i.attachEvent.toString().indexOf("[native code")<0)&&!R?(J=!0,i.attachEvent("onreadystatechange",b.onScriptLoad)):(i.addEventListener("load", 33 | b.onScriptLoad,!1),i.addEventListener("error",b.onScriptError,!1)),i.src=d,I=i,y?u.insertBefore(i,y):u.appendChild(i),I=null,i;else aa&&(importScripts(d),b.completeLoad(c))};v&&N(document.getElementsByTagName("script"),function(b){if(!u)u=b.parentNode;if(q=b.getAttribute("data-main")){if(!n.baseUrl)B=q.split("/"),Y=B.pop(),Z=B.length?B.join("/")+"/":"./",n.baseUrl=Z,q=Y;q=q.replace($,"");n.deps=n.deps?n.deps.concat(q):[q];return!0}});define=function(b,c,d){var g,i;typeof b!=="string"&&(d=c,c=b,b= 34 | null);E(c)||(d=c,c=[]);!c.length&&D(d)&&d.length&&(d.toString().replace(ca,"").replace(da,function(b,d){c.push(d)}),c=(d.length===1?["require"]:["require","exports","module"]).concat(c));if(J&&(g=I||ba()))b||(b=g.getAttribute("data-requiremodule")),i=w[g.getAttribute("data-requirecontext")];(i?i.defQueue:P).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(n)}})(this); 35 | -------------------------------------------------------------------------------- /test/test.cli.js: -------------------------------------------------------------------------------- 1 | /*global describe, it, beforeEach, afterEach*/ 2 | /*jshint expr:true, maxstatements:50*/ 3 | 4 | var join = require('path').join; 5 | var fs = require('fs'); 6 | var stream = require('mock-utf8-stream'); 7 | var cliJs = join(__dirname, '..', 'lib', 'cli.js'); 8 | var cliBin = join(__dirname, '..', 'bin', 'autopolyfiller'); 9 | var AutoPolyFillerCli = require(cliJs); 10 | var expect = require('chai').expect; 11 | 12 | var TEMPORARY_FILE = join(__dirname, 'fixtures/cli/tmp/pf.js'); 13 | 14 | describe('cli', function () { 15 | var stdout; 16 | var stdin; 17 | var stderr; 18 | var exit; 19 | 20 | beforeEach(function () { 21 | stdout = new stream.MockWritableStream(); 22 | stdout.write = function (data, encoding, cb) { 23 | this.emit('data', data); 24 | cb && cb(); 25 | }; 26 | stderr = new stream.MockWritableStream(); 27 | stderr.write = function (data, encoding, cb) { 28 | this.emit('data', data); 29 | cb && cb(); 30 | }; 31 | stdin = new stream.MockReadableStream(); 32 | stdin.isTTY = true; 33 | exit = function (status) { 34 | exit.status = status; 35 | }; 36 | }); 37 | 38 | afterEach(function () { 39 | if (fs.existsSync(TEMPORARY_FILE)) { 40 | fs.unlinkSync(TEMPORARY_FILE); 41 | } 42 | }); 43 | 44 | it('ignores missing callback', function () { 45 | new AutoPolyFillerCli({ 46 | stdin: stdin, 47 | stdout: stdout, 48 | stderr: stderr, 49 | exit: exit, 50 | argv: [ 51 | 'node', 52 | cliBin 53 | ] 54 | }); 55 | }); 56 | 57 | it('prints help if no files were passed', function (done) { 58 | stdout.startCapture(); 59 | 60 | new AutoPolyFillerCli({ 61 | stdin: stdin, 62 | stdout: stdout, 63 | stderr: stderr, 64 | exit: exit, 65 | argv: [ 66 | 'node', 67 | cliBin 68 | ] 69 | }, function () { 70 | expect(stdout.capturedData).to.match(/Options/); 71 | expect(stdout.capturedData).to.match(/Usage/); 72 | expect(stdout.capturedData).to.match(/Examples/); 73 | done(); 74 | }); 75 | }); 76 | 77 | it('accepts STDIN', function (done) { 78 | stdout.startCapture(); 79 | stdin.isTTY = false; 80 | 81 | new AutoPolyFillerCli({ 82 | stdin: stdin, 83 | stdout: stdout, 84 | stderr: stderr, 85 | exit: exit, 86 | argv: [ 87 | 'node', 88 | cliBin 89 | ] 90 | }, function () { 91 | expect(stdout.capturedData).to.match(/String.prototype.trim/); 92 | done(); 93 | }); 94 | 95 | setTimeout(function () { 96 | stdin.emit('data', fs.readFileSync(__dirname + '/fixtures/cli/a.js')); 97 | stdin.emit('end'); 98 | }, 0); 99 | }); 100 | 101 | it('exit process with code 1 if content of input file is bad', function (done) { 102 | stderr.startCapture(); 103 | 104 | new AutoPolyFillerCli({ 105 | stdin: stdin, 106 | stdout: stdout, 107 | stderr: stderr, 108 | exit: exit, 109 | argv: [ 110 | 'node', 111 | cliBin, 112 | 'test/fixtures/cli/c.coffee' 113 | ] 114 | }, function (error) { 115 | setTimeout(function () { 116 | expect(stderr.capturedData).to.match(/Error while adding file from/); 117 | expect(exit.status).to.eql(1); 118 | expect(error).to.be.instanceof(Error); 119 | done(); 120 | }, 0); 121 | }); 122 | }); 123 | 124 | it('exit process with code 1 if content of STDIN is bad', function (done) { 125 | stderr.startCapture(); 126 | stdin.isTTY = false; 127 | 128 | new AutoPolyFillerCli({ 129 | stdin: stdin, 130 | stdout: stdout, 131 | stderr: stderr, 132 | exit: exit, 133 | argv: [ 134 | 'node', 135 | cliBin 136 | ] 137 | }, function (error) { 138 | setTimeout(function () { 139 | expect(stderr.capturedData).to.match(/Error while adding file from STDIN/); 140 | expect(exit.status).to.eql(1); 141 | expect(error).to.be.instanceof(Error); 142 | done(); 143 | }, 0); 144 | }); 145 | 146 | setTimeout(function () { 147 | stdin.emit('data', 'var var throw;'); 148 | stdin.emit('end'); 149 | }, 0); 150 | }); 151 | 152 | describe('', function () { 153 | 154 | it('can be list of files', function (done) { 155 | stdout.startCapture(); 156 | 157 | new AutoPolyFillerCli({ 158 | stdin: stdin, 159 | stdout: stdout, 160 | stderr: stderr, 161 | exit: exit, 162 | argv: [ 163 | 'node', 164 | cliBin, 165 | 'test/fixtures/cli/a.js', 166 | 'test/fixtures/cli/deep/b.js' 167 | ] 168 | }, function () { 169 | expect(stdout.capturedData).to.match(/String.prototype.trim/); 170 | expect(stdout.capturedData).to.match(/Object.keys/); 171 | done(); 172 | }); 173 | }); 174 | 175 | it('can be glob(s)', function (done) { 176 | stdout.startCapture(); 177 | 178 | new AutoPolyFillerCli({ 179 | stdin: stdin, 180 | stdout: stdout, 181 | stderr: stderr, 182 | exit: exit, 183 | argv: [ 184 | 'node', 185 | cliBin, 186 | 'test/fixtures/cli/**/*.js' 187 | ] 188 | }, function () { 189 | expect(stdout.capturedData).to.match(/String.prototype.trim/); 190 | expect(stdout.capturedData).to.match(/Object.keys/); 191 | done(); 192 | }); 193 | }); 194 | 195 | it('can be negative glob(s)', function (done) { 196 | stdout.startCapture(); 197 | 198 | new AutoPolyFillerCli({ 199 | stdin: stdin, 200 | stdout: stdout, 201 | stderr: stderr, 202 | exit: exit, 203 | argv: [ 204 | 'node', 205 | cliBin, 206 | 'test/fixtures/cli/**/*.js', 207 | '!test/fixtures/cli/deep/*.js' 208 | ] 209 | }, function () { 210 | expect(stdout.capturedData).to.match(/String.prototype.trim/); 211 | expect(stdout.capturedData).to.not.match(/Object.keys/); 212 | done(); 213 | }); 214 | }); 215 | 216 | }); 217 | 218 | describe('-v, --verbose', function () { 219 | 220 | it('prints verbose process log to stdout', function (done) { 221 | stdout.startCapture(); 222 | 223 | new AutoPolyFillerCli({ 224 | stdin: stdin, 225 | stdout: stdout, 226 | stderr: stderr, 227 | exit: exit, 228 | argv: [ 229 | 'node', 230 | cliBin, 231 | '-v', 232 | '-b', 233 | 'Explorer 7', 234 | 'test/fixtures/cli/a.js' 235 | ] 236 | }, function () { 237 | expect(stdout.capturedData).to.match(/Generating polyfills for/); 238 | expect(stdout.capturedData).to.match(/Globbing files/); 239 | expect(stdout.capturedData).to.match(/Got 1 file/); 240 | expect(stdout.capturedData).to.match(/Got 1 polyfills for/); 241 | expect(stdout.capturedData).to.match(/Writing 1 polyfills to STDOUT/); 242 | done(); 243 | }); 244 | }); 245 | 246 | it('silent if not passed', function (done) { 247 | stdout.startCapture(); 248 | 249 | new AutoPolyFillerCli({ 250 | stdin: stdin, 251 | stdout: stdout, 252 | stderr: stderr, 253 | exit: exit, 254 | argv: [ 255 | 'node', 256 | cliBin, 257 | 'test/fixtures/cli/empty.js' 258 | ] 259 | }, function () { 260 | expect(stdout.capturedData).to.be.empty; 261 | done(); 262 | }); 263 | }); 264 | 265 | }); 266 | 267 | describe('-o, --output ', function () { 268 | 269 | it('prints polyfills to STDOUT by default', function (done) { 270 | stdout.startCapture(); 271 | 272 | new AutoPolyFillerCli({ 273 | stdin: stdin, 274 | stdout: stdout, 275 | stderr: stderr, 276 | exit: exit, 277 | argv: [ 278 | 'node', 279 | cliBin, 280 | 'test/fixtures/cli/a.js' 281 | ] 282 | }, function () { 283 | expect(stdout.capturedData).to.match(/String.prototype.trim/); 284 | done(); 285 | }); 286 | }); 287 | 288 | it('prints polyfills to STDERR if passed', function (done) { 289 | stderr.startCapture(); 290 | 291 | new AutoPolyFillerCli({ 292 | stdin: stdin, 293 | stdout: stdout, 294 | stderr: stderr, 295 | exit: exit, 296 | argv: [ 297 | 'node', 298 | cliBin, 299 | '-o', 300 | 'STDERR', 301 | 'test/fixtures/cli/a.js' 302 | ] 303 | }, function () { 304 | expect(stderr.capturedData).to.match(/String.prototype.trim/); 305 | done(); 306 | }); 307 | }); 308 | 309 | it('prints polyfills to file if file passed', function (done) { 310 | 311 | new AutoPolyFillerCli({ 312 | stdin: stdin, 313 | stdout: stdout, 314 | stderr: stderr, 315 | exit: exit, 316 | argv: [ 317 | 'node', 318 | cliBin, 319 | '-o', 320 | TEMPORARY_FILE, 321 | 'test/fixtures/cli/a.js' 322 | ] 323 | }, function () { 324 | expect(fs.readFileSync(TEMPORARY_FILE, 'utf8')).to.match(/String.prototype.trim/); 325 | done(); 326 | }); 327 | }); 328 | 329 | }); 330 | 331 | describe('-b, --browsers', function () { 332 | 333 | it('reduces polyfills against required browsers', function (done) { 334 | stdout.startCapture(); 335 | 336 | new AutoPolyFillerCli({ 337 | stdin: stdin, 338 | stdout: stdout, 339 | stderr: stderr, 340 | exit: exit, 341 | argv: [ 342 | 'node', 343 | cliBin, 344 | '-b', 345 | 'Chrome 30', 346 | 'test/fixtures/cli/**/*.js' 347 | ] 348 | }, function () { 349 | expect(stdout.capturedData).to.be.empty; 350 | done(); 351 | }); 352 | }); 353 | 354 | it('can be comma separated list of browsers', function (done) { 355 | stdout.startCapture(); 356 | 357 | new AutoPolyFillerCli({ 358 | stdin: stdin, 359 | stdout: stdout, 360 | stderr: stderr, 361 | exit: exit, 362 | argv: [ 363 | 'node', 364 | cliBin, 365 | '-b', 366 | 'Explorer 8, Opera 12', 367 | 'test/fixtures/cli/**/*.js' 368 | ] 369 | }, function () { 370 | expect(stdout.capturedData).to.match(/String.prototype.trim/); 371 | expect(stdout.capturedData).to.match(/Object.keys/); 372 | done(); 373 | }); 374 | }); 375 | 376 | }); 377 | 378 | describe('-x, --exclude ', function () { 379 | 380 | it('ignores listed polyfills', function (done) { 381 | stdout.startCapture(); 382 | 383 | new AutoPolyFillerCli({ 384 | stdin: stdin, 385 | stdout: stdout, 386 | stderr: stderr, 387 | exit: exit, 388 | argv: [ 389 | 'node', 390 | cliBin, 391 | '-x', 392 | 'String.prototype.trim', 393 | 'test/fixtures/cli/**/*.js' 394 | ] 395 | }, function () { 396 | expect(stdout.capturedData).to.match(/Object.keys/); 397 | done(); 398 | }); 399 | }); 400 | 401 | it('can be comma separated list of polyfills', function (done) { 402 | stdout.startCapture(); 403 | 404 | new AutoPolyFillerCli({ 405 | stdin: stdin, 406 | stdout: stdout, 407 | stderr: stderr, 408 | exit: exit, 409 | argv: [ 410 | 'node', 411 | cliBin, 412 | '-x', 413 | 'String.prototype.trim, Object.keys', 414 | 'test/fixtures/cli/**/*.js' 415 | ] 416 | }, function () { 417 | expect(stdout.capturedData).to.be.empty; 418 | done(); 419 | }); 420 | }); 421 | 422 | }); 423 | 424 | describe('-i, --include ', function () { 425 | 426 | it('adds extra polyfills', function (done) { 427 | stdout.startCapture(); 428 | 429 | new AutoPolyFillerCli({ 430 | stdin: stdin, 431 | stdout: stdout, 432 | stderr: stderr, 433 | exit: exit, 434 | argv: [ 435 | 'node', 436 | cliBin, 437 | '-i', 438 | 'Promise', 439 | 'test/fixtures/cli/**/*.js' 440 | ] 441 | }, function () { 442 | expect(stdout.capturedData).to.match(/Promise/); 443 | done(); 444 | }); 445 | }); 446 | 447 | it('can be comma separated list of polyfills', function (done) { 448 | stdout.startCapture(); 449 | 450 | new AutoPolyFillerCli({ 451 | stdin: stdin, 452 | stdout: stdout, 453 | stderr: stderr, 454 | exit: exit, 455 | argv: [ 456 | 'node', 457 | cliBin, 458 | '-i', 459 | 'Promise, Array.prototype.map', 460 | 'test/fixtures/cli/**/*.js' 461 | ] 462 | }, function () { 463 | expect(stdout.capturedData).to.match(/Promise/); 464 | expect(stdout.capturedData).to.match(/Array\.prototype\.map/); 465 | done(); 466 | }); 467 | }); 468 | 469 | }); 470 | 471 | describe('-p, --parser ', function () { 472 | it('overrides existing parser', function (done) { 473 | stdout.startCapture(); 474 | 475 | new AutoPolyFillerCli({ 476 | stdin: stdin, 477 | stdout: stdout, 478 | stderr: stderr, 479 | exit: exit, 480 | argv: [ 481 | 'node', 482 | cliBin, 483 | '-v', 484 | '-p', 485 | 'acorn', 486 | 'test/fixtures/cli_parser/es5.js' 487 | ] 488 | }, function () { 489 | expect(stdout.capturedData).to.match(/Array\.prototype\.map/); 490 | done(); 491 | }); 492 | }); 493 | }); 494 | 495 | describe('-P, --parser-options ', function () { 496 | it('overrides parser options', function (done) { 497 | stdout.startCapture(); 498 | 499 | new AutoPolyFillerCli({ 500 | stdin: stdin, 501 | stdout: stdout, 502 | stderr: stderr, 503 | exit: exit, 504 | argv: [ 505 | 'node', 506 | cliBin, 507 | '-v', 508 | '-P', 509 | '{"ecmaVersion":6}', 510 | 'test/fixtures/cli_parser/es6.js' 511 | ] 512 | }, function () { 513 | expect(stdout.capturedData).to.match(/Array\.prototype\.map/); 514 | done(); 515 | }); 516 | }); 517 | }); 518 | }); 519 | -------------------------------------------------------------------------------- /example_assets/index.browserify.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o"+''+polyfill+""+""}).join("");console.timeEnd("Scan for polyfills")}catch(e){console.timeEnd("Scan for polyfills");console.error(e)}}$code.addEventListener("input",generate,false);$browsers.addEventListener("input",generate,false);$generateButton.addEventListener("click",generate,false);generate()},0)},{"../lib":2}],2:[function(require,module,exports){var scan=require("./polyfill-scan"),reduce=require("./polyfill-reduce"),wrap=require("./polyfill-wrap"),code=require("./polyfill-code");function AutoPolyFiller(options){this.browsers=options.browsers;this.polyfills=[];this.excluedPolyfills=[]}AutoPolyFiller.prototype={_scan:function(code){var polyfills=scan(code);if(this.browsers&&this.browsers.length===0){return polyfills}return reduce(polyfills,this.browsers)},_scanForPolyfillsOfPolyfills:function(polyfills){var hasIterated={};var iteratePolyfills=function(polyfills,polyfillName){if(hasIterated.hasOwnProperty(polyfillName)){return polyfills}hasIterated[polyfillName]=true;polyfills=polyfills.concat([]||this._scan(code(polyfillName)));return polyfills.concat(polyfills.reduce(iteratePolyfills,[]))}.bind(this);return polyfills.reduce(iteratePolyfills,[])},add:function(code){var polyfills=this._scan(code),polyfillsOfPolyfills=this._scanForPolyfillsOfPolyfills(polyfills);this.include(polyfills.concat(polyfillsOfPolyfills));return this},toString:function(){return this.polyfills.map(function(polyfillName){var polyfillCode=code(polyfillName);return wrap(polyfillCode,polyfillName)}).join("")},_isPolyfillIncluded:function(polyfill){return this.excluedPolyfills.indexOf(polyfill)===-1},include:function(polyfills){this.polyfills=this.polyfills.concat(polyfills).filter(this._isPolyfillIncluded.bind(this)).reduce(function(polyfills,polyfill){if(polyfills.indexOf(polyfill)===-1){polyfills.push(polyfill)}return polyfills},[]);return this},exclude:function(polyfills){this.excluedPolyfills.push.apply(this.excluedPolyfills,polyfills);this.polyfills=this.polyfills.filter(this._isPolyfillIncluded.bind(this));return this}};module.exports=function(){var browsers=1<=arguments.length?[].slice.call(arguments,0):[];if(browsers.length===1&&browsers[0]instanceof Array){browsers=browsers[0]}return new AutoPolyFiller({browsers:browsers})};module.exports.use=function(config){if(config.test){scan.use({test:config.test})}if(config.support){reduce.support(config.support)}if(config.polyfill){code.addSource(config.polyfill)}if(config.wrapper){wrap.addWrapper(config.wrapper)}}},{"./polyfill-code":3,"./polyfill-reduce":7,"./polyfill-scan":9,"./polyfill-wrap":15}],3:[function(require,module,exports){(function(__dirname){var polyfill=require("polyfill"),extend=require("node.extend"),fs=require("fs"),debug=require("debug")("polyfill:code");debug("defining polyfills getters");var polyfillsCode=polyfill.source;fs.readdirSync&&fs.readdirSync(__dirname+"/source").forEach(function(fileName){var polyfillName=fileName.replace(/\.js$/,"");polyfillsCode.__defineGetter__(polyfillName,function(){var code=fs.readFileSync(__dirname+"/source/"+fileName,"utf8");delete polyfillsCode[polyfillName];polyfillsCode[polyfillName]=code;return code})});debug("got %d polyfills",Object.keys(polyfillsCode).length);function code(polyfillName){debug("getting polyfill code for `%s`",polyfillName);var polyfillCode=polyfillsCode[polyfillName];if(!polyfillCode){throw new Error("Unknown feature: "+polyfillName)}return polyfillCode}function addSource(newPolyfills){debug("adding custom polyfill");extend(polyfillsCode,newPolyfills)}module.exports=code;module.exports.addSource=addSource}).call(this,"/../lib/polyfill-code")},{debug:24,fs:21,"node.extend":26,polyfill:32}],4:[function(require,module,exports){function propertyValue(property){if(property.type==="Identifier"){return property.name}else if(property.type==="Literal"){return property.value}}module.exports=function(ast){var chain=[];while(ast){if(ast.type==="Identifier"){chain.unshift(ast.name);return chain}if(ast.type!=="MemberExpression"){return chain}var value=propertyValue(ast.property);if(typeof value==="undefined"){return chain}chain.unshift(value);ast=ast.object}return chain}},{}],5:[function(require,module,exports){var quotemeta=require("quotemeta");var functionMethods=["call","apply","bind"];var padding=["window","this"];var propertySeparator=quotemeta(".");var types={"static":function(options){var objects=options.objects||{};var methods=Object.keys(objects).map(function(object){return object+propertySeparator+"(?:"+objects[object].join("|")+")"});var rx=new RegExp("^"+"(?:(?:"+padding.join("|")+")"+propertySeparator+")?"+"("+methods.join("|")+")"+"(?:"+propertySeparator+"(?:"+functionMethods.join("|")+"))*"+"$");return function(code){return(code.match(rx)||0)[1]}},method:function(options){var methods=options.methods||[];var rx=new RegExp("^"+"(?:[^"+propertySeparator+"]*"+propertySeparator+")*"+"("+methods.join("|")+")"+"(?:"+propertySeparator+"(?:"+functionMethods.join("|")+"))*"+"$");return function(code){return(code.match(rx)||0)[1]}},global:function(options){var methods=options.methods||[];var rx=new RegExp("^"+"(?:(?:"+padding.join("|")+")"+propertySeparator+")?"+"("+methods.join("|")+")"+"(?:"+propertySeparator+"(?:"+functionMethods.join("|")+"))*"+"$");return function(code){return(code.match(rx)||0)[1]}},constructor:function(options){var constructors=options.constructors||[];var rx=new RegExp("^"+"(?:(?:"+padding.join("|")+")"+propertySeparator+")?"+"("+constructors.join("|")+")"+"$");return function(code){return(code.match(rx)||0)[1]}}};module.exports=function(type,options){return types[type](options)}},{quotemeta:34}],6:[function(require,module,exports){module.exports={"Opera Mini":[{fill:"Promise Window.prototype.requestAnimationFrame"}],"Opera Mobile":[{fill:"Promise"},{min:"10",max:"12.1",fill:"Window.prototype.requestAnimationFrame"}],Opera:[{fill:"Promise"},{min:"9",max:"12.1",fill:"Window.prototype.requestAnimationFrame"}],Android:[{fill:"Promise"},{min:"2",max:"4.3",fill:"Window.prototype.requestAnimationFrame"}],BlackBerry:[{fill:"Promise Window.prototype.requestAnimationFrame"}],"Chrome iOS":[{fill:"Promise Window.prototype.requestAnimationFrame"}],"Safari iOS":[{fill:"Promise"},{min:"3",max:"6.1",fill:"Window.prototype.requestAnimationFrame"}],Chrome:[{fill:"Promise"},{min:"4",max:"23",fill:"Window.prototype.requestAnimationFrame"}],"Internet Explorer":[{fill:"Promise"},{min:"6",max:"9",fill:"Window.prototype.requestAnimationFrame"}],Firefox:[{fill:"Promise"},{min:"2",max:"22",fill:"Window.prototype.requestAnimationFrame"}],Safari:[{fill:"Promise"},{min:"3",max:"6",fill:"Window.prototype.requestAnimationFrame"}]}},{}],7:[function(require,module,exports){var Browsers=require("autoprefixer/lib/browsers"),browsersData=require("autoprefixer/data/browsers"),debug=require("debug")("polyfill:reduce"),polyfill=require("polyfill"),semver=require("semver");var polyFillSets=polyfill.agent.js;var browserMap={opera:"Opera",android:"Android",bb:"BlackBerry",ios:"Safari iOS",chrome:"Chrome",ie:"Internet Explorer",ff:"Firefox",safari:"Safari"};var reBrowserAndVersion=/^(\w+) ([\d\.]+)$/;function toSemver(version){return String(version).split(".").concat(0,0,0).slice(0,3).join(".")}function cmp(comparatorName,a,b){return semver[comparatorName](toSemver(a),toSemver(b))}function polyFillsFor(browserCode,version){var polyFillSet=polyFillSets[browserMap[browserCode]];if(!polyFillSet){return[]}return polyFillSet.reduce(function(polyfills,range){var isMatches=range.only&&cmp("eq",version,range.only)||range.min&&!range.max&&cmp("gte",version,range.min)||range.min&&range.max&&cmp("gte",version,range.min)&&cmp("lte",version,range.max)||!range.min&&!range.max&&!range.only;if(isMatches){return polyfills.concat(range.fill.split(" "))}return polyfills},[])}function reduce(polyfills,browsersRequest){var browsers=new Browsers(browsersData,browsersRequest).selected;debug("%s are selected",browsers);var requiredPolyFills=browsers.reduce(function(requiredPolyFills,browserAndVersion){var parts=browserAndVersion.match(reBrowserAndVersion);return requiredPolyFills.concat(polyFillsFor.apply(null,parts.slice(1,3)))},[]).reduce(function(polyfills,polyfill){polyfills[polyfill]=true;return polyfills},{});return polyfills.filter(function(polyfill){var shouldPolyFill=polyfill in requiredPolyFills;debug("%s `%s`",shouldPolyFill?"keeping":"removing",polyfill);return shouldPolyFill})}function support(polyfills){debug("adding custom supported polyfills");Object.keys(polyfills).forEach(function(browser){if(!polyFillSets[browser]){polyFillSets[browser]=[]}polyFillSets[browser].push.apply(polyFillSets[browser],polyfills[browser])})}function list(){return Object.keys(polyFillSets).reduce(function(polyfills,browserName){return polyFillSets[browserName].reduce(function(polyfills,sets){return polyfills.concat(sets.fill.split(" "))},polyfills)},[]).reduce(function(polyfills,polyfill){if(polyfills.indexOf(polyfill)===-1){polyfills.push(polyfill)}return polyfills},[])}support(require("./data/index.json"));module.exports=reduce;module.exports.support=support;module.exports.list=list},{"./data/index.json":6,"autoprefixer/data/browsers":18,"autoprefixer/lib/browsers":19,debug:24,polyfill:32,semver:35}],8:[function(require,module,exports){var traverse=require("estraverse").traverse;module.exports=function(ast){var expressions=[];traverse(ast,{enter:function(node){if(node.type==="MemberExpression"||node.type==="Identifier"){expressions.push(node)}}});return expressions}},{estraverse:25}],9:[function(require,module,exports){var parse=require("acorn").parse,debug=require("debug")("polyfill:scan");debug("loading matchers");var matchers=require("./matchers");debug("%d matchers are loaded",matchers.length);function use(matcher){debug("adding custom matcher");matchers.push(matcher)}function scan(code){debug("parsing code");var ast=parse(code);debug("parsing done");debug("scanning for polyfills using %d matchers",matchers.length);var polyfills=matchers.reduce(function(polyfills,matcher){return polyfills.concat(matcher.test(ast))},[]).reduce(function(polyfills,polyfill){if(polyfills.indexOf(polyfill)===-1){polyfills.push(polyfill)}return polyfills},[]);debug("got %d polyfill(s)",polyfills.length);return polyfills}module.exports=scan;module.exports.use=use},{"./matchers":12,acorn:17,debug:24}],10:[function(require,module,exports){var foldExpression=require("../../polyfill-expression-fold");var grepExpressions=require("../grep-expression");var matcher=require("../../polyfill-expression-matcher");var constructors={WeakMap:"WeakMap",Symbol:"Symbol",Set:"Set",Proxy:"Proxy",Promise:"Promise",Map:"Map"};var testConstructor=matcher("constructor",{constructors:Object.keys(constructors)});exports.test=function(ast){return grepExpressions(ast).map(foldExpression).reduce(function(polyfills,list){var polyfill=constructors[testConstructor(list.join("."))];if(polyfill){polyfills.push(polyfill)}return polyfills},[])}},{"../../polyfill-expression-fold":4,"../../polyfill-expression-matcher":5,"../grep-expression":8}],11:[function(require,module,exports){var foldExpression=require("../../polyfill-expression-fold");var grepExpressions=require("../grep-expression");var matcher=require("../../polyfill-expression-matcher");var globalFunctions={btoa:"Window.prototype.base64",atob:"Window.prototype.base64",matchMedia:"Window.prototype.matchMedia",requestAnimationFrame:"Window.prototype.requestAnimationFrame",cancelAnimationFrame:"Window.prototype.requestAnimationFrame"};var testMethod=matcher("global",{methods:Object.keys(globalFunctions)});exports.test=function(ast){return grepExpressions(ast).map(foldExpression).reduce(function(polyfills,list){var polyfill=globalFunctions[testMethod(list.join("."))];if(polyfill){polyfills.push(polyfill)}return polyfills},[])}},{"../../polyfill-expression-fold":4,"../../polyfill-expression-matcher":5,"../grep-expression":8}],12:[function(require,module,exports){module.exports=[require("./constructor"),require("./method"),require("./static"),require("./global")]},{"./constructor":10,"./global":11,"./method":13,"./static":14}],13:[function(require,module,exports){var foldExpression=require("../../polyfill-expression-fold");var grepExpressions=require("../grep-expression");var matcher=require("../../polyfill-expression-matcher");var methods={every:"Array.prototype.every",fill:"Array.prototype.fill",filter:"Array.prototype.filter",find:"Array.prototype.find",findIndex:"Array.prototype.findIndex",forEach:"Array.prototype.forEach",indexOf:"Array.prototype.indexOf",lastIndexOf:"Array.prototype.lastIndexOf",map:"Array.prototype.map",reduce:"Array.prototype.reduce",reduceRight:"Array.prototype.reduceRight",some:"Array.prototype.some",toISOString:"Date.prototype.toISOString",bind:"Function.prototype.bind",clz:"Number.prototype.clz",codePointAt:"String.prototype.codePointAt",contains:"String.prototype.contains",endsWith:"String.prototype.endsWith",repeat:"String.prototype.repeat",startsWith:"String.prototype.startsWith",toArray:"String.prototype.toArray",trim:"String.prototype.trim"};var testMethod=matcher("method",{methods:Object.keys(methods)});exports.test=function(ast){return grepExpressions(ast).map(foldExpression).reduce(function(polyfills,list){var polyfill=methods[testMethod(list.join("."))];if(polyfill){polyfills.push(polyfill)}return polyfills},[])}},{"../../polyfill-expression-fold":4,"../../polyfill-expression-matcher":5,"../grep-expression":8}],14:[function(require,module,exports){var foldExpression=require("../../polyfill-expression-fold");var grepExpressions=require("../grep-expression");var matcher=require("../../polyfill-expression-matcher");var statics={Array:{from:"Array.from",isArray:"Array.isArray",of:"Array.of"},Date:{now:"Date.now"},JSON:{parse:"Window.prototype.JSON",stringify:"Window.prototype.JSON"},Math:{acosh:"Math.acosh",asinh:"Math.asinh",atanh:"Math.atanh",cosh:"Math.cosh",expm1:"Math.expm1",fround:"Math.fround",hypot:"Math.hypot",imul:"Math.imul",log10:"Math.log10",log1p:"Math.log1p",log2:"Math.log2",sign:"Math.sign",sinh:"Math.sinh",tanh:"Math.tanh",trunc:"Math.trunc"},Number:{isFinite:"Number.isFinite",isInteger:"Number.isInteger",isNaN:"Number.isNaN",toInteger:"Number.toInteger"},Object:{assign:"Object.assign",create:"Object.create",defineProperties:"Object.defineProperties",defineProperty:"Object.defineProperty",freeze:"Object.freeze",getOwnPropertyDescriptor:"Object.getOwnPropertyDescriptor",getOwnPropertyDescriptors:"Object.getOwnPropertyDescriptors",getOwnPropertyNames:"Object.getOwnPropertyNames",getPropertyDescriptor:"Object.getPropertyDescriptor",getPropertyNames:"Object.getPropertyNames",getPrototypeOf:"Object.getPrototypeOf",is:"Object.is",isExtensible:"Object.isExtensible",isFrozen:"Object.isFrozen",isSealed:"Object.isSealed",keys:"Object.keys",observe:"Object.observe",preventExtensions:"Object.preventExtensions",seal:"Object.seal",setPrototypeOf:"Object.setPrototypeOf"}};var testStatic=matcher("static",{objects:Object.keys(statics).reduce(function(objects,object){objects[object]=Object.keys(statics[object]);return objects},{})});var expressionToPolyfillMap=Object.keys(statics).reduce(function(map,object){return Object.keys(statics[object]).reduce(function(map,method){map[object+"."+method]=statics[object][method];return map},map)},{});exports.test=function(ast){return grepExpressions(ast).map(foldExpression).reduce(function(polyfills,list){var polyfill=expressionToPolyfillMap[testStatic(list.join("."))];if(polyfill){polyfills.push(polyfill)}return polyfills},[])}},{"../../polyfill-expression-fold":4,"../../polyfill-expression-matcher":5,"../grep-expression":8}],15:[function(require,module,exports){var extend=require("node.extend"),debug=require("debug")("polyfill:wrap");var polyfillsWrappers=require("./wrappers");function wrapDefault(code,polyfillName){debug("wrapping code of `%s` using default wrapper",polyfillName);var parts=polyfillName.split("."),expression="true";if(parts.length===1){expression="typeof "+parts[0]+' === "undefined"'}else if(parts.length===2){expression="typeof "+parts[0]+' === "undefined" || '+parts[0]+" && !"+parts[0]+"."+parts[1]}else if(parts[0]==="Window"&&parts[1]==="prototype"&&parts[2]){expression="typeof window."+parts[2]+' === "undefined"'}else{expression="!"+polyfillName}debug("got `%s` condition expression for `%s`",expression,polyfillName);return"if ("+expression+") {\n"+code+"\n}\n"}function wrap(code,polyfillName){var wrapper=polyfillsWrappers[polyfillName];if(typeof wrapper!=="object"){return wrapDefault(code,polyfillName)}return wrapper.before+code+wrapper.after}function addWrapper(wrappers){extend(polyfillsWrappers,wrappers)}module.exports=wrap;module.exports.addWrapper=addWrapper},{"./wrappers":16,debug:24,"node.extend":26}],16:[function(require,module,exports){module.exports={"Window.prototype.base64":{before:"if (typeof window.atob === 'undefined' || typeof window.btoa === 'undefined') {\n",after:"\n}\n"},"Navigator.prototype.geolocation":{before:"if (typeof navigator.geolocation === 'undefined') {\n",after:"\n}\n"},"Window.prototype.requestAnimationFrame":{before:"",after:""}}},{}],17:[function(require,module,exports){(function(root,mod){if(typeof exports=="object"&&typeof module=="object")return mod(exports);if(typeof define=="function"&&define.amd)return define(["exports"],mod);mod(root.acorn||(root.acorn={}))})(this,function(exports){"use strict";exports.version="0.4.1";var options,input,inputLen,sourceFile;exports.parse=function(inpt,opts){input=String(inpt);inputLen=input.length;setOptions(opts);initTokenState();return parseTopLevel(options.program)};var defaultOptions=exports.defaultOptions={ecmaVersion:5,strictSemicolons:false,allowTrailingCommas:true,forbidReserved:false,locations:false,onComment:null,ranges:false,program:null,sourceFile:null,directSourceFile:null};function setOptions(opts){options=opts||{};for(var opt in defaultOptions)if(!Object.prototype.hasOwnProperty.call(options,opt))options[opt]=defaultOptions[opt];sourceFile=options.sourceFile||null}var getLineInfo=exports.getLineInfo=function(input,offset){for(var line=1,cur=0;;){lineBreak.lastIndex=cur;var match=lineBreak.exec(input);if(match&&match.index3){cats.sort(function(a,b){return b.length-a.length});f+="switch(str.length){";for(var i=0;i=170&&nonASCIIidentifierStart.test(String.fromCharCode(code))};var isIdentifierChar=exports.isIdentifierChar=function(code){if(code<48)return code===36;if(code<58)return true;if(code<65)return false;if(code<91)return true;if(code<97)return code===95;if(code<123)return true;return code>=170&&nonASCIIidentifier.test(String.fromCharCode(code))};function line_loc_t(){this.line=tokCurLine;this.column=tokPos-tokLineStart}function initTokenState(){tokCurLine=1;tokPos=tokLineStart=0;tokRegexpAllowed=true;skipSpace()}function finishToken(type,val){tokEnd=tokPos;if(options.locations)tokEndLoc=new line_loc_t;tokType=type;skipSpace();tokVal=val;tokRegexpAllowed=type.beforeExpr}function skipBlockComment(){var startLoc=options.onComment&&options.locations&&new line_loc_t;var start=tokPos,end=input.indexOf("*/",tokPos+=2);if(end===-1)raise(tokPos-2,"Unterminated comment");tokPos=end+2;if(options.locations){lineBreak.lastIndex=start;var match;while((match=lineBreak.exec(input))&&match.index8&&ch<14){++tokPos}else if(ch===47){var next=input.charCodeAt(tokPos+1);if(next===42){skipBlockComment()}else if(next===47){skipLineComment()}else break}else if(ch===160){++tokPos}else if(ch>=5760&&nonASCIIwhitespace.test(String.fromCharCode(ch))){++tokPos}else{break}}}function readToken_dot(){var next=input.charCodeAt(tokPos+1);if(next>=48&&next<=57)return readNumber(true);++tokPos;return finishToken(_dot)}function readToken_slash(){var next=input.charCodeAt(tokPos+1);if(tokRegexpAllowed){++tokPos;return readRegexp()}if(next===61)return finishOp(_assign,2);return finishOp(_slash,1)}function readToken_mult_modulo(){var next=input.charCodeAt(tokPos+1);if(next===61)return finishOp(_assign,2);return finishOp(_multiplyModulo,1)}function readToken_pipe_amp(code){var next=input.charCodeAt(tokPos+1);if(next===code)return finishOp(code===124?_logicalOR:_logicalAND,2);if(next===61)return finishOp(_assign,2);return finishOp(code===124?_bitwiseOR:_bitwiseAND,1)}function readToken_caret(){var next=input.charCodeAt(tokPos+1);if(next===61)return finishOp(_assign,2);return finishOp(_bitwiseXOR,1)}function readToken_plus_min(code){var next=input.charCodeAt(tokPos+1);if(next===code){if(next==45&&input.charCodeAt(tokPos+2)==62&&newline.test(input.slice(lastEnd,tokPos))){tokPos+=3;skipLineComment();skipSpace();return readToken()}return finishOp(_incDec,2)}if(next===61)return finishOp(_assign,2);return finishOp(_plusMin,1)}function readToken_lt_gt(code){var next=input.charCodeAt(tokPos+1);var size=1;if(next===code){size=code===62&&input.charCodeAt(tokPos+2)===62?3:2;if(input.charCodeAt(tokPos+size)===61)return finishOp(_assign,size+1);return finishOp(_bitShift,size)}if(next==33&&code==60&&input.charCodeAt(tokPos+2)==45&&input.charCodeAt(tokPos+3)==45){tokPos+=4;skipLineComment();skipSpace();return readToken()}if(next===61)size=input.charCodeAt(tokPos+2)===61?3:2;return finishOp(_relational,size)}function readToken_eq_excl(code){var next=input.charCodeAt(tokPos+1);if(next===61)return finishOp(_equality,input.charCodeAt(tokPos+2)===61?3:2);return finishOp(code===61?_eq:_prefix,1)}function getTokenFromCode(code){switch(code){case 46:return readToken_dot();case 40:++tokPos;return finishToken(_parenL);case 41:++tokPos;return finishToken(_parenR);case 59:++tokPos;return finishToken(_semi);case 44:++tokPos;return finishToken(_comma);case 91:++tokPos;return finishToken(_bracketL);case 93:++tokPos;return finishToken(_bracketR);case 123:++tokPos;return finishToken(_braceL);case 125:++tokPos;return finishToken(_braceR);case 58:++tokPos;return finishToken(_colon);case 63:++tokPos;return finishToken(_question);case 48:var next=input.charCodeAt(tokPos+1);if(next===120||next===88)return readHexNumber();case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return readNumber(false);case 34:case 39:return readString(code);case 47:return readToken_slash(code);case 37:case 42:return readToken_mult_modulo();case 124:case 38:return readToken_pipe_amp(code);case 94:return readToken_caret();case 43:case 45:return readToken_plus_min(code);case 60:case 62:return readToken_lt_gt(code);case 61:case 33:return readToken_eq_excl(code);case 126:return finishOp(_prefix,1)}return false}function readToken(forceRegexp){if(!forceRegexp)tokStart=tokPos;else tokPos=tokStart+1;if(options.locations)tokStartLoc=new line_loc_t;if(forceRegexp)return readRegexp();if(tokPos>=inputLen)return finishToken(_eof);var code=input.charCodeAt(tokPos);if(isIdentifierStart(code)||code===92)return readWord();var tok=getTokenFromCode(code);if(tok===false){var ch=String.fromCharCode(code); 2 | if(ch==="\\"||nonASCIIidentifierStart.test(ch))return readWord();raise(tokPos,"Unexpected character '"+ch+"'")}return tok}function finishOp(type,size){var str=input.slice(tokPos,tokPos+size);tokPos+=size;finishToken(type,str)}function readRegexp(){var content="",escaped,inClass,start=tokPos;for(;;){if(tokPos>=inputLen)raise(start,"Unterminated regular expression");var ch=input.charAt(tokPos);if(newline.test(ch))raise(start,"Unterminated regular expression");if(!escaped){if(ch==="[")inClass=true;else if(ch==="]"&&inClass)inClass=false;else if(ch==="/"&&!inClass)break;escaped=ch==="\\"}else escaped=false;++tokPos}var content=input.slice(start,tokPos);++tokPos;var mods=readWord1();if(mods&&!/^[gmsiy]*$/.test(mods))raise(start,"Invalid regexp flag");return finishToken(_regexp,new RegExp(content,mods))}function readInt(radix,len){var start=tokPos,total=0;for(var i=0,e=len==null?Infinity:len;i=97)val=code-97+10;else if(code>=65)val=code-65+10;else if(code>=48&&code<=57)val=code-48;else val=Infinity;if(val>=radix)break;++tokPos;total=total*radix+val}if(tokPos===start||len!=null&&tokPos-start!==len)return null;return total}function readHexNumber(){tokPos+=2;var val=readInt(16);if(val==null)raise(tokStart+2,"Expected hexadecimal number");if(isIdentifierStart(input.charCodeAt(tokPos)))raise(tokPos,"Identifier directly after number");return finishToken(_num,val)}function readNumber(startsWithDot){var start=tokPos,isFloat=false,octal=input.charCodeAt(tokPos)===48;if(!startsWithDot&&readInt(10)===null)raise(start,"Invalid number");if(input.charCodeAt(tokPos)===46){++tokPos;readInt(10);isFloat=true}var next=input.charCodeAt(tokPos);if(next===69||next===101){next=input.charCodeAt(++tokPos);if(next===43||next===45)++tokPos;if(readInt(10)===null)raise(start,"Invalid number");isFloat=true}if(isIdentifierStart(input.charCodeAt(tokPos)))raise(tokPos,"Identifier directly after number");var str=input.slice(start,tokPos),val;if(isFloat)val=parseFloat(str);else if(!octal||str.length===1)val=parseInt(str,10);else if(/[89]/.test(str)||strict)raise(start,"Invalid number");else val=parseInt(str,8);return finishToken(_num,val)}function readString(quote){tokPos++;var out="";for(;;){if(tokPos>=inputLen)raise(tokStart,"Unterminated string constant");var ch=input.charCodeAt(tokPos);if(ch===quote){++tokPos;return finishToken(_string,out)}if(ch===92){ch=input.charCodeAt(++tokPos);var octal=/^[0-7]+/.exec(input.slice(tokPos,tokPos+3));if(octal)octal=octal[0];while(octal&&parseInt(octal,8)>255)octal=octal.slice(0,-1);if(octal==="0")octal=null;++tokPos;if(octal){if(strict)raise(tokPos-2,"Octal literal in strict mode");out+=String.fromCharCode(parseInt(octal,8));tokPos+=octal.length-1}else{switch(ch){case 110:out+="\n";break;case 114:out+="\r";break;case 120:out+=String.fromCharCode(readHexChar(2));break;case 117:out+=String.fromCharCode(readHexChar(4));break;case 85:out+=String.fromCharCode(readHexChar(8));break;case 116:out+=" ";break;case 98:out+="\b";break;case 118:out+=" ";break;case 102:out+="\f";break;case 48:out+="\x00";break;case 13:if(input.charCodeAt(tokPos)===10)++tokPos;case 10:if(options.locations){tokLineStart=tokPos;++tokCurLine}break;default:out+=String.fromCharCode(ch);break}}}else{if(ch===13||ch===10||ch===8232||ch===8233)raise(tokStart,"Unterminated string constant");out+=String.fromCharCode(ch);++tokPos}}}function readHexChar(len){var n=readInt(16,len);if(n===null)raise(tokStart,"Bad character escape sequence");return n}var containsEsc;function readWord1(){containsEsc=false;var word,first=true,start=tokPos;for(;;){var ch=input.charCodeAt(tokPos);if(isIdentifierChar(ch)){if(containsEsc)word+=input.charAt(tokPos);++tokPos}else if(ch===92){if(!containsEsc)word=input.slice(start,tokPos);containsEsc=true;if(input.charCodeAt(++tokPos)!=117)raise(tokPos,"Expecting Unicode escape sequence \\uXXXX");++tokPos;var esc=readHexChar(4);var escStr=String.fromCharCode(esc);if(!escStr)raise(tokPos-1,"Invalid Unicode escape");if(!(first?isIdentifierStart(esc):isIdentifierChar(esc)))raise(tokPos-4,"Invalid Unicode escape");word+=escStr}else{break}first=false}return containsEsc?word:input.slice(start,tokPos)}function readWord(){var word=readWord1();var type=_name;if(!containsEsc){if(isKeyword(word))type=keywordTypes[word];else if(options.forbidReserved&&(options.ecmaVersion===3?isReservedWord3:isReservedWord5)(word)||strict&&isStrictReservedWord(word))raise(tokStart,"The keyword '"+word+"' is reserved")}return finishToken(type,word)}function next(){lastStart=tokStart;lastEnd=tokEnd;lastEndLoc=tokEndLoc;readToken()}function setStrict(strct){strict=strct;tokPos=lastEnd;if(options.locations){while(tokPos=5&&stmt.type==="ExpressionStatement"&&stmt.expression.type==="Literal"&&stmt.expression.value==="use strict"}function eat(type){if(tokType===type){next();return true}}function canInsertSemicolon(){return!options.strictSemicolons&&(tokType===_eof||tokType===_braceR||newline.test(input.slice(lastEnd,tokStart)))}function semicolon(){if(!eat(_semi)&&!canInsertSemicolon())unexpected()}function expect(type){if(tokType===type)next();else unexpected()}function unexpected(){raise(tokStart,"Unexpected token")}function checkLVal(expr){if(expr.type!=="Identifier"&&expr.type!=="MemberExpression")raise(expr.start,"Assigning to rvalue");if(strict&&expr.type==="Identifier"&&isStrictBadIdWord(expr.name))raise(expr.start,"Assigning to "+expr.name+" in strict mode")}function parseTopLevel(program){lastStart=lastEnd=tokPos;if(options.locations)lastEndLoc=new line_loc_t;inFunction=strict=null;labels=[];readToken();var node=program||startNode(),first=true;if(!program)node.body=[];while(tokType!==_eof){var stmt=parseStatement();node.body.push(stmt);if(first&&isUseStrict(stmt))setStrict(true);first=false}return finishNode(node,"Program")}var loopLabel={kind:"loop"},switchLabel={kind:"switch"};function parseStatement(){if(tokType===_slash||tokType===_assign&&tokVal=="/=")readToken(true);var starttype=tokType,node=startNode();switch(starttype){case _break:case _continue:next();var isBreak=starttype===_break;if(eat(_semi)||canInsertSemicolon())node.label=null;else if(tokType!==_name)unexpected();else{node.label=parseIdent();semicolon()}for(var i=0;iminPrec){var node=startNodeFrom(left);node.left=left;node.operator=tokVal;var op=tokType;next();node.right=parseExprOp(parseMaybeUnary(),prec,noIn);var exprNode=finishNode(node,op===_logicalOR||op===_logicalAND?"LogicalExpression":"BinaryExpression");return parseExprOp(exprNode,minPrec,noIn)}}return left}function parseMaybeUnary(){if(tokType.prefix){var node=startNode(),update=tokType.isUpdate;node.operator=tokVal;node.prefix=true;tokRegexpAllowed=true;next();node.argument=parseMaybeUnary();if(update)checkLVal(node.argument);else if(strict&&node.operator==="delete"&&node.argument.type==="Identifier")raise(node.start,"Deleting local variable in strict mode");return finishNode(node,update?"UpdateExpression":"UnaryExpression")}var expr=parseExprSubscripts();while(tokType.postfix&&!canInsertSemicolon()){var node=startNodeFrom(expr);node.operator=tokVal;node.prefix=false;node.argument=expr;checkLVal(expr);next();expr=finishNode(node,"UpdateExpression")}return expr}function parseExprSubscripts(){return parseSubscripts(parseExprAtom())}function parseSubscripts(base,noCalls){if(eat(_dot)){var node=startNodeFrom(base);node.object=base;node.property=parseIdent(true);node.computed=false;return parseSubscripts(finishNode(node,"MemberExpression"),noCalls)}else if(eat(_bracketL)){var node=startNodeFrom(base);node.object=base;node.property=parseExpression();node.computed=true;expect(_bracketR);return parseSubscripts(finishNode(node,"MemberExpression"),noCalls)}else if(!noCalls&&eat(_parenL)){var node=startNodeFrom(base);node.callee=base;node.arguments=parseExprList(_parenR,false);return parseSubscripts(finishNode(node,"CallExpression"),noCalls)}else return base}function parseExprAtom(){switch(tokType){case _this:var node=startNode();next();return finishNode(node,"ThisExpression");case _name:return parseIdent();case _num:case _string:case _regexp:var node=startNode();node.value=tokVal;node.raw=input.slice(tokStart,tokEnd);next();return finishNode(node,"Literal");case _null:case _true:case _false:var node=startNode();node.value=tokType.atomValue;node.raw=tokType.keyword;next();return finishNode(node,"Literal");case _parenL:var tokStartLoc1=tokStartLoc,tokStart1=tokStart;next();var val=parseExpression();val.start=tokStart1;val.end=tokEnd;if(options.locations){val.loc.start=tokStartLoc1;val.loc.end=tokEndLoc}if(options.ranges)val.range=[tokStart1,tokEnd];expect(_parenR);return val;case _bracketL:var node=startNode();next();node.elements=parseExprList(_bracketR,true,true);return finishNode(node,"ArrayExpression");case _braceL:return parseObj();case _function:var node=startNode();next();return parseFunction(node,false);case _new:return parseNew();default:unexpected()}}function parseNew(){var node=startNode();next();node.callee=parseSubscripts(parseExprAtom(),true);if(eat(_parenL))node.arguments=parseExprList(_parenR,false);else node.arguments=empty;return finishNode(node,"NewExpression")}function parseObj(){var node=startNode(),first=true,sawGetSet=false;node.properties=[];next();while(!eat(_braceR)){if(!first){expect(_comma);if(options.allowTrailingCommas&&eat(_braceR))break}else first=false;var prop={key:parsePropertyName()},isGetSet=false,kind;if(eat(_colon)){prop.value=parseExpression(true);kind=prop.kind="init"}else if(options.ecmaVersion>=5&&prop.key.type==="Identifier"&&(prop.key.name==="get"||prop.key.name==="set")){isGetSet=sawGetSet=true;kind=prop.kind=prop.key.name;prop.key=parsePropertyName();if(tokType!==_parenL)unexpected();prop.value=parseFunction(startNode(),false)}else unexpected();if(prop.key.type==="Identifier"&&(strict||sawGetSet)){for(var i=0;i=0)for(var j=0;j (\d+(\.\d+)?)%$/,select:function(popularity){return this.browsers(function(data){return data.versions.filter(function(version,i){return data.popularity[i]>popularity})})}},newerThen:{regexp:/^(\w+) (>=?)\s*([\d\.]+)/,select:function(browser,sign,version){var data,filter;data=this.byName(browser);version=parseFloat(version);if(sign===">"){filter=function(v){return v>version}}else if(sign===">="){filter=function(v){return v>=version}}return data.versions.filter(filter).map(function(v){return""+data.name+" "+v})}},esr:{regexp:/^(firefox|ff|fx) esr$/i,select:function(){return["ff 24"]}},direct:{regexp:/^(\w+) ([\d\.]+)$/,select:function(browser,version){var data,first,last;data=this.byName(browser);version=parseFloat(version);last=data.future?data.future[0]:data.versions[0];first=data.versions[data.versions.length-1];if(version>last){version=last}else if(version=15){return"-webkit-"}else{return this.data[name].prefix}};Browsers.prototype.isSelected=function(browser){return this.selected.indexOf(browser)!==-1};Browsers.prototype.byName=function(name){var data;name=name.toLowerCase();name=this.aliases[name]||name;data=this.data[name];if(!data){utils.error("Unknown browser "+browser)}data.name=name;return data};return Browsers}();module.exports=Browsers}).call(this)},{"../data/browsers":18,"./utils":20}],20:[function(require,module,exports){(function(){module.exports={error:function(text){var err;err=new Error(text);err.autoprefixer=true;throw err},uniq:function(array){var filtered,i,_i,_len;filtered=[];for(_i=0,_len=array.length;_i<_len;_i++){i=array[_i];if(filtered.indexOf(i)===-1){filtered.push(i)}}return filtered},removeNote:function(string){if(string.indexOf(" ")===-1){return string}else{return string.split(" ")[0]}},escapeRegexp:function(string){return string.replace(/[.?*+\^\$\[\]\\(){}|\-]/g,"\\$&")},regexp:function(word,escape){if(escape==null){escape=true}if(escape){word=this.escapeRegexp(word)}return RegExp("(^|[\\s,(])("+word+"($|[\\s(,]))","gi")}}}).call(this)},{}],21:[function(require,module,exports){},{}],22:[function(require,module,exports){var process=module.exports={};process.nextTick=function(){var canSetImmediate=typeof window!=="undefined"&&window.setImmediate;var canPost=typeof window!=="undefined"&&window.postMessage&&window.addEventListener;if(canSetImmediate){return function(f){return window.setImmediate(f)}}if(canPost){var queue=[];window.addEventListener("message",function(ev){var source=ev.source;if((source===window||source===null)&&ev.data==="process-tick"){ev.stopPropagation();if(queue.length>0){var fn=queue.shift();fn()}}},true);return function nextTick(fn){queue.push(fn);window.postMessage("process-tick","*")}}return function nextTick(fn){setTimeout(fn,0)}}();process.title="browser";process.browser=true;process.env={};process.argv=[];function noop(){}process.on=noop;process.once=noop;process.off=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")}},{}],23:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i=hour)return(ms/hour).toFixed(1)+"h";if(ms>=min)return(ms/min).toFixed(1)+"m";if(ms>=sec)return(ms/sec|0)+"s";return ms+"ms"};debug.enabled=function(name){for(var i=0,len=debug.skips.length;i>>1;current=i+diff;if(func(array[current])){len=diff}else{i=current+1;len-=diff+1}}return i}function lowerBound(array,func){var diff,len,i,current;len=array.length;i=0;while(len){diff=len>>>1;current=i+diff;if(func(array[current])){i=current+1;len-=diff+1}else{len=diff}}return i}ignoreJSHintError(lowerBound);VisitorKeys={AssignmentExpression:["left","right"],ArrayExpression:["elements"],ArrayPattern:["elements"],ArrowFunctionExpression:["params","defaults","rest","body"],BlockStatement:["body"],BinaryExpression:["left","right"],BreakStatement:["label"],CallExpression:["callee","arguments"],CatchClause:["param","body"],ClassBody:["body"],ClassDeclaration:["id","body","superClass"],ClassExpression:["id","body","superClass"],ConditionalExpression:["test","consequent","alternate"],ContinueStatement:["label"],DebuggerStatement:[],DirectiveStatement:[],DoWhileStatement:["body","test"],EmptyStatement:[],ExpressionStatement:["expression"],ForStatement:["init","test","update","body"],ForInStatement:["left","right","body"],FunctionDeclaration:["id","params","defaults","rest","body"],FunctionExpression:["id","params","defaults","rest","body"],Identifier:[],IfStatement:["test","consequent","alternate"],Literal:[],LabeledStatement:["label","body"],LogicalExpression:["left","right"],MemberExpression:["object","property"],MethodDefinition:["key","value"],NewExpression:["callee","arguments"],ObjectExpression:["properties"],ObjectPattern:["properties"],Program:["body"],Property:["key","value"],ReturnStatement:["argument"],SequenceExpression:["expressions"],SwitchStatement:["discriminant","cases"],SwitchCase:["test","consequent"],ThisExpression:[],ThrowStatement:["argument"],TryStatement:["block","handlers","handler","guardedHandlers","finalizer"],UnaryExpression:["argument"],UpdateExpression:["argument"],VariableDeclaration:["declarations"],VariableDeclarator:["id","init"],WhileStatement:["test","body"],WithStatement:["object","body"],YieldExpression:["argument"]};BREAK={};SKIP={};VisitorOption={Break:BREAK,Skip:SKIP};function Reference(parent,key){this.parent=parent;this.key=key}Reference.prototype.replace=function replace(node){this.parent[this.key]=node};function Element(node,path,wrap,ref){this.node=node;this.path=path;this.wrap=wrap;this.ref=ref}function Controller(){}Controller.prototype.path=function path(){var i,iz,j,jz,result,element;function addToPath(result,path){if(isArray(path)){for(j=0,jz=path.length;j=0){key=candidates[current];candidate=node[key];if(!candidate){continue}if(!isArray(candidate)){worklist.push(new Element(candidate,key,null,null));continue}current2=candidate.length;while((current2-=1)>=0){if(!candidate[current2]){continue}if((nodeType===Syntax.ObjectExpression||nodeType===Syntax.ObjectPattern)&&"properties"===candidates[current]){element=new Element(candidate[current2],[key,current2],"Property",null)}else{element=new Element(candidate[current2],[key,current2],null,null)}worklist.push(element)}}}}};Controller.prototype.replace=function replace(root,visitor){var worklist,leavelist,node,nodeType,target,element,current,current2,candidates,candidate,sentinel,outer,key;this.__initialize(root,visitor);sentinel={};worklist=this.__worklist;leavelist=this.__leavelist;outer={root:root};element=new Element(root,null,null,new Reference(outer,"root"));worklist.push(element);leavelist.push(element);while(worklist.length){element=worklist.pop();if(element===sentinel){element=leavelist.pop();target=this.__execute(visitor.leave,element);if(target!==undefined&&target!==BREAK&&target!==SKIP){element.ref.replace(target)}if(this.__state===BREAK||target===BREAK){return outer.root}continue}target=this.__execute(visitor.enter,element);if(target!==undefined&&target!==BREAK&&target!==SKIP){element.ref.replace(target);element.node=target}if(this.__state===BREAK||target===BREAK){return outer.root}node=element.node;if(!node){continue}worklist.push(sentinel);leavelist.push(element);if(this.__state===SKIP||target===SKIP){continue}nodeType=element.wrap||node.type;candidates=VisitorKeys[nodeType];current=candidates.length;while((current-=1)>=0){key=candidates[current];candidate=node[key];if(!candidate){continue}if(!isArray(candidate)){worklist.push(new Element(candidate,key,null,new Reference(node,key)));continue}current2=candidate.length;while((current2-=1)>=0){if(!candidate[current2]){continue}if(nodeType===Syntax.ObjectExpression&&"properties"===candidates[current]){element=new Element(candidate[current2],[key,current2],"Property",new Reference(candidate,current2))}else{element=new Element(candidate[current2],[key,current2],null,new Reference(candidate,current2))}worklist.push(element)}}}return outer.root};function traverse(root,visitor){var controller=new Controller;return controller.traverse(root,visitor)}function replace(root,visitor){var controller=new Controller;return controller.replace(root,visitor)}function extendCommentRange(comment,tokens){var target;target=upperBound(tokens,function search(token){return token.range[0]>comment.range[0]});comment.extendedRange=[comment.range[0],comment.range[1]];if(target!==tokens.length){comment.extendedRange[1]=tokens[target].range[0]}target-=1;if(target>=0){comment.extendedRange[0]=tokens[target].range[1]}return comment}function attachComments(tree,providedComments,tokens){var comments=[],comment,len,i,cursor;if(!tree.range){throw new Error("attachComments needs range information")}if(!tokens.length){if(providedComments.length){for(i=0,len=providedComments.length;inode.range[0]){break}if(comment.extendedRange[1]===node.range[0]){if(!node.leadingComments){node.leadingComments=[]}node.leadingComments.push(comment);comments.splice(cursor,1)}else{cursor+=1}}if(cursor===comments.length){return VisitorOption.Break}if(comments[cursor].extendedRange[0]>node.range[1]){return VisitorOption.Skip}}});cursor=0;traverse(tree,{leave:function(node){var comment;while(cursornode.range[1]){return VisitorOption.Skip}}});return tree}exports.version="1.3.3-dev";exports.Syntax=Syntax;exports.traverse=traverse;exports.replace=replace;exports.attachComments=attachComments;exports.VisitorKeys=VisitorKeys;exports.VisitorOption=VisitorOption;exports.Controller=Controller})},{}],26:[function(require,module,exports){module.exports=require("./lib/extend")},{"./lib/extend":27}],27:[function(require,module,exports){var is=require("is");function extend(){var target=arguments[0]||{};var i=1;var length=arguments.length;var deep=false;var options,name,src,copy,copy_is_array,clone;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2}if(typeof target!=="object"&&!is.fn(target)){target={}}for(;i=0};is.boolean=function(value){return"[object Boolean]"===toString.call(value)};is["false"]=function(value){return is.boolean(value)&&(value===false||value.valueOf()===false)};is["true"]=function(value){return is.boolean(value)&&(value===true||value.valueOf()===true)};is.date=function(value){return"[object Date]"===toString.call(value)};is.element=function(value){return value!==undefined&&typeof HTMLElement!=="undefined"&&value instanceof HTMLElement&&value.nodeType===1};is.error=function(value){return"[object Error]"===toString.call(value)};is.fn=is["function"]=function(value){var isAlert=typeof window!=="undefined"&&value===window.alert;return isAlert||"[object Function]"===toString.call(value)};is.number=function(value){return"[object Number]"===toString.call(value)};is.infinite=function(value){return value===Infinity||value===-Infinity};is.decimal=function(value){return is.number(value)&&!isActualNaN(value)&&!is.infinite(value)&&value%1!==0};is.divisibleBy=function(value,n){var isDividendInfinite=is.infinite(value);var isDivisorInfinite=is.infinite(n);var isNonZeroNumber=is.number(value)&&!isActualNaN(value)&&is.number(n)&&!isActualNaN(n)&&n!==0;return isDividendInfinite||isDivisorInfinite||isNonZeroNumber&&value%n===0};is.int=function(value){return is.number(value)&&!isActualNaN(value)&&value%1===0};is.maximum=function(value,others){if(isActualNaN(value)){throw new TypeError("NaN is not a valid value")}else if(!is.arraylike(others)){throw new TypeError("second argument must be array-like")}var len=others.length;while(--len>=0){if(value=0){if(value>others[len]){return false}}return true};is.nan=function(value){return!is.number(value)||value!==value};is.even=function(value){return is.infinite(value)||is.number(value)&&value===value&&value%2===0};is.odd=function(value){return is.infinite(value)||is.number(value)&&value===value&&value%2!==0};is.ge=function(value,other){if(isActualNaN(value)||isActualNaN(other)){throw new TypeError("NaN is not a valid value")}return!is.infinite(value)&&!is.infinite(other)&&value>=other};is.gt=function(value,other){if(isActualNaN(value)||isActualNaN(other)){throw new TypeError("NaN is not a valid value")}return!is.infinite(value)&&!is.infinite(other)&&value>other};is.le=function(value,other){if(isActualNaN(value)||isActualNaN(other)){throw new TypeError("NaN is not a valid value")}return!is.infinite(value)&&!is.infinite(other)&&value<=other};is.lt=function(value,other){if(isActualNaN(value)||isActualNaN(other)){throw new TypeError("NaN is not a valid value")}return!is.infinite(value)&&!is.infinite(other)&&value=start&&value<=finish};is.object=function(value){return value&&"[object Object]"===toString.call(value)};is.hash=function(value){return is.object(value)&&value.constructor===Object&&!value.nodeType&&!value.setInterval};is.regexp=function(value){return"[object RegExp]"===toString.call(value)};is.string=function(value){return"[object String]"===toString.call(value)}},{}],29:[function(require,module,exports){module.exports={"Opera Mini":[{fill:"audio:not([controls]) main subline"}],"Opera Mobile":[{fill:"audio:not([controls]) main subline"}],Opera:[{min:"10",max:"11.64",fill:"details figure main subline summary"},{min:"10",max:"10.63",fill:"audio[controls] article aside canvas figcaption figure footer header hgroup nav section template"},{min:"15",fill:"subline"}],Android:[{fill:"main subline"}],BlackBerry:[{fill:"main subline"}],"Chrome iOS":[{fill:"audio:not([controls]) main subline"}],"Safari iOS":[{fill:"audio:not([controls]) main subline"}],Chrome:[{fill:"abbr[title] subline"}],"Internet Explorer":[{min:"6",fill:"details main subline summary"},{min:"6",max:"9",fill:"article aside figcaption figure footer header hgroup img legend mark nav section template _textarea"},{min:"6",max:"8",fill:"_audio canvas -ms-placeholder video"},{min:"6",max:"7",fill:"button dd dl form h1 h2 h3 h4 h5 h6 input _legend menu ol p _pre select ul"},{only:"6",fill:"_abbr _code _kbd _samp"},{min:"7",max:"9",fill:"[hidden] abbr[title]"},{only:"7",fill:'_button _input[type="button"] _input[type="checkbox"] _input[type="radio"] _input[type="reset"] _input[type="submit"]'},{min:"8",max:"9",fill:'input[type="checkbox"] input[type="radio"]'},{only:"9",fill:"audio:not([controls]) svg:not(:root)"},{only:"10",fill:"img"}],Firefox:[{min:"3",fill:"details summary subline"},{min:"3",max:"20",fill:"main"},{min:"3",max:"3.6",fill:"audio article aside b canvas figcaption figure footer header hgroup __legend nav section strong video"}],Safari:[{min:"3",fill:"main subline"},{min:"3",max:"5.1",fill:"abbr[title] article aside audio canvas code details dfn figcaption figure footer header hgroup kbd nav pre samp section summary video"}]}},{}],30:[function(require,module,exports){module.exports={"Opera Mini":[{fill:"Window.prototype.matchMedia Element.prototype.matches.o Element.prototype.mutation"}],"Opera Mobile":[{min:"10",max:"12",fill:"Window.prototype.matchMedia"},{fill:"Element.prototype.matches.o"}],Opera:[{only:"11.5",fill:"Object.defineProperty Object.defineProperties"},{min:"11.5",max:"12.1",fill:"Window.prototype.matchMedia Element.prototype.matches.o Element.prototype.mutation"},{only:"15",fill:"Navigator.prototype.geolocation"},{min:"15",fill:"Element.prototype.matches.webkit Element.prototype.mutation.blink"}],Android:[{min:"2.1",max:"2.3",fill:"Window.prototype.matchMedia"},{fill:"Element.prototype.matches.webkit Element.prototype.mutation"}],BlackBerry:[{only:"7",fill:"Window.prototype.matchMedia"},{fill:"Element.prototype.matches.webkit Element.prototype.mutation"}],"Chrome iOS":[{fill:"Element.prototype.matches.webkit Element.prototype.mutation"}],"Safari iOS":[{max:"4.3",fill:"Object.defineProperty Object.defineProperties"},{fill:"Window.prototype.devicePixelRatio.iossafari6 Element.prototype.matches.webkit Element.prototype.mutation"}],Chrome:[{fill:"Element.prototype.matches.webkit Element.prototype.mutation.blink"}],"Internet Explorer":[{min:"6",max:"7",fill:"Object.create.ie7 Object.defineProperty.ie7 Object.defineProperties Object.getPrototypeOf Object.keys Object.getOwnPropertyNames Date.prototype.toISOString Date.now Array.isArray Function.prototype.bind String.prototype.trim Array.prototype.every Array.prototype.filter Array.prototype.forEach Array.prototype.indexOf Array.prototype.lastIndexOf Array.prototype.map Array.prototype.reduce Array.prototype.reduceRight Array.prototype.some Window.polyfill.ie7 Window.prototype.base64 Window.prototype.devicePixelRatio.ie7 Window.prototype.DOMTokenList Window.prototype.Event.ie8 Window.prototype.Event.ie8.DOMContentLoaded Window.prototype.Event.hashchange Window.prototype.getComputedStyle.ie8 Window.prototype.JSON Window.prototype.localStorage.ie7 Window.prototype.matchMedia Window.prototype.viewport.ie7 Window.prototype.XMLHttpRequest.ie7 Window.prototype.XMLHttpRequest.ie8 Navigator.prototype.geolocation Element.prototype.classList.ie7 Element.prototype.matches Element.prototype.mutation Element.prototype.placeholder.ie7 Window.polyfill.ie7.init"},{only:"8",fill:"Object.create Object.defineProperty.ie8 Object.defineProperties Object.getPrototypeOf Object.keys Object.getOwnPropertyNames Date.prototype.toISOString Date.now Array.isArray Function.prototype.bind String.prototype.trim Array.prototype.every Array.prototype.filter Array.prototype.forEach Array.prototype.indexOf Array.prototype.lastIndexOf Array.prototype.map Array.prototype.reduce Array.prototype.reduceRight Array.prototype.some Window.polyfill.ie8 Window.prototype.base64 Window.prototype.devicePixelRatio.ie8 Window.prototype.DOMTokenList Window.prototype.Event.ie8 Window.prototype.Event.ie8.DOMContentLoaded Window.prototype.getComputedStyle.ie8 Window.prototype.matchMedia Window.prototype.viewport Window.prototype.XMLHttpRequest.ie8 Navigator.prototype.geolocation HTMLDocument.prototype.head Element.prototype.classList Element.prototype.matches Element.prototype.mutation Element.prototype.placeholder Window.polyfill.ie8.init"},{min:"9",max:"10",fill:"Window.prototype.Event Window.prototype.CustomEvent Window.prototype.scroll HTMLDocument"},{only:"9",fill:"Window.prototype.base64 Window.prototype.DOMTokenList Window.prototype.matchMedia Element.prototype.classList"},{min:"9",fill:"Element.prototype.matches.ms Element.prototype.mutation"}],Firefox:[{only:"3.6",fill:"Object.create Object.defineProperty Object.defineProperties Object.getPrototypeOf Object.keys Object.getOwnPropertyNames Array.isArray Function.prototype.bind"},{min:"3.6",max:"5",fill:"Window.prototype.Event Window.prototype.CustomEvent Window.prototype.matchMedia Window.prototype.Event.firefox5"},{min:"3.6",fill:"Element.prototype.matches.moz Element.prototype.mutation Window.prototype.Event.focus"}],Safari:[{only:"4",fill:"Array.isArray Object.create Object.defineProperty Object.defineProperties Object.getOwnPropertyNames Object.getPrototypeOf Object.keys Function.prototype.bind String.prototype.trim Window.polyfill.safari4 Window.prototype.DOMTokenList Window.prototype.Event Window.prototype.CustomEvent Window.prototype.Event.hashchange Navigator.prototype.geolocation HTMLDocument.prototype.head Element.prototype.classList"},{min:"5",max:"5.1",fill:"Function.prototype.bind"},{min:"4",max:"5",fill:"Window.prototype.matchMedia"},{min:"4",fill:"Window.prototype.devicePixelRatio.safari6 Element.prototype.matches.webkit Element.prototype.mutation"}]}},{}],31:[function(require,module,exports){module.exports={"Opera Mini":["\\sOpera\\sMini\\/(\\d+\\.?\\d*)"],"Opera Mobile":["\\sOpera\\sMobi\\/.+?Version\\/(\\d+\\.?\\d*)"],Opera:["\\sOPR\\/(\\d+\\.?\\d*)","^Opera\\/.+?Version\\/(\\d+\\.?\\d*)","\\sOpera\\s(\\d+\\.?\\d*)"],Android:["\\sAndroid\\s(\\d+\\.?\\d*)"],BlackBerry:["\\(BB\\d+\\.?\\d*;.+?\\sVersion\\/(\\d+\\.?\\d*)","\\(BlackBerry;.+?\\sVersion\\/(\\d+\\.?\\d*)"],"Chrome iOS":["\\sCriOS\\/(\\d+\\.?\\d*)"],"Safari iOS":["\\(iPad.+?\\Version\\/(\\d+\\.?\\d*).+?\\sSafari\\/","\\(iPhone.+?\\Version\\/(\\d+\\.?\\d*).+?\\sSafari\\/","iPhone\\sOS\\s(\\d+)"],Chrome:["\\sChrome\\/(\\d+\\.?\\d*)"],"Internet Explorer":["\\sTrident\\/.+?rv[:\\s](\\d+\\.?\\d*)","\\sMSIE\\s(\\d+\\.?\\d*)"],Firefox:["\\s[Ff]irefox[\\/\\s\\(\\/]?(\\d+\\.?\\d*)"],Safari:["\\sVersion\\/(\\d+\\.?\\d*).+?Safari\\/[\\d\\.]+$"]}},{}],32:[function(require,module,exports){(function(__dirname){var fs=require("fs");var join=require("path").join;exports.agent={js:require("./agent.js.json"),css:require("./agent.css.json")};exports.useragent=require("./agent.json");exports.normalize=require("./normalize.json");var source=exports.source={};var sourceFolder=join(__dirname,"source");fs.readdirSync&&fs.readdirSync(sourceFolder).forEach(function(filename){if(filename[0]===".")return;source[filename.replace(/\.js$/,"")]=fs.readFileSync(join(sourceFolder,filename),"utf8")})}).call(this,"/../node_modules/polyfill")},{"./agent.css.json":29,"./agent.js.json":30,"./agent.json":31,"./normalize.json":33,fs:21,path:23}],33:[function(require,module,exports){module.exports={"[hidden] template":"display: none","_abbr abbr[title]":"border-bottom: 1px dotted","article aside details figcaption figure footer header hgroup main nav section subhead summary":"display: block",_audio:"clip: rect(0 0 0 0); position: absolute","audio[controls] canvas video":"display: inline-block","audio:not([controls])":"height: 0","b strong":"font-weight: bold",'_button _input[type="button"] _input[type="reset"] _input[type="submit"]':"overflow: visible","button figure form input select textarea":"margin: 0","code kbd pre samp":"font-family: monospace serif; font-size: 1em","_code _kbd _pre _samp":'font-family: "Courier New" monospace',dd:"margin: 0 0 0 40px",dfn:"font-style: italic","dl h3 menu ol p _pre ul":"margin: 1em 0",h1:"font-size: 2em; margin: .67em 0",h2:"font-size: 1.5em; margin: .83em 0",h3:"font-size: 1.17em",h4:"font-size: 1em; margin: 1.33em 0",h5:"font-size: .83em; margin: 1.67em 0",h6:"font-size: .67em; margin: 2.33em 0",'_input[type="checkbox"] _input[type="radio"]':"height: 13px; width: 13px",'input[type="checkbox"] input[type="radio"]':"box-sizing: border-box; padding: 0","img legend":"border: 0",_legend:"margin-left: -7px",__legend:"white-space: normal",mark:"background: #FF0; color: #000","menu ol ul":"padding: 0 0 0 40px","-ms-placeholder":"color: #777",pre:"font-size: .9em","svg:not(:root)":"overflow: hidden",_textarea:"overflow: auto"}},{}],34:[function(require,module,exports){module.exports=function(str){return String(str).replace(/(\W)/g,"\\$1")}},{}],35:[function(require,module,exports){(function(exports){if(typeof module==="object"&&module.exports===exports)exports=module.exports=SemVer;exports.SEMVER_SPEC_VERSION="2.0.0";var re=exports.re=[];var src=exports.src=[];var R=0;var NUMERICIDENTIFIER=R++;src[NUMERICIDENTIFIER]="0|[1-9]\\d*";var NUMERICIDENTIFIERLOOSE=R++;src[NUMERICIDENTIFIERLOOSE]="[0-9]+";var NONNUMERICIDENTIFIER=R++;src[NONNUMERICIDENTIFIER]="\\d*[a-zA-Z-][a-zA-Z0-9-]*";var MAINVERSION=R++;src[MAINVERSION]="("+src[NUMERICIDENTIFIER]+")\\."+"("+src[NUMERICIDENTIFIER]+")\\."+"("+src[NUMERICIDENTIFIER]+")";var MAINVERSIONLOOSE=R++;src[MAINVERSIONLOOSE]="("+src[NUMERICIDENTIFIERLOOSE]+")\\."+"("+src[NUMERICIDENTIFIERLOOSE]+")\\."+"("+src[NUMERICIDENTIFIERLOOSE]+")";var PRERELEASEIDENTIFIER=R++;src[PRERELEASEIDENTIFIER]="(?:"+src[NUMERICIDENTIFIER]+"|"+src[NONNUMERICIDENTIFIER]+")";var PRERELEASEIDENTIFIERLOOSE=R++;src[PRERELEASEIDENTIFIERLOOSE]="(?:"+src[NUMERICIDENTIFIERLOOSE]+"|"+src[NONNUMERICIDENTIFIER]+")";var PRERELEASE=R++;src[PRERELEASE]="(?:-("+src[PRERELEASEIDENTIFIER]+"(?:\\."+src[PRERELEASEIDENTIFIER]+")*))";var PRERELEASELOOSE=R++;src[PRERELEASELOOSE]="(?:-?("+src[PRERELEASEIDENTIFIERLOOSE]+"(?:\\."+src[PRERELEASEIDENTIFIERLOOSE]+")*))";var BUILDIDENTIFIER=R++;src[BUILDIDENTIFIER]="[0-9A-Za-z-]+";var BUILD=R++;src[BUILD]="(?:\\+("+src[BUILDIDENTIFIER]+"(?:\\."+src[BUILDIDENTIFIER]+")*))";var FULL=R++;var FULLPLAIN="v?"+src[MAINVERSION]+src[PRERELEASE]+"?"+src[BUILD]+"?";src[FULL]="^"+FULLPLAIN+"$";var LOOSEPLAIN="[v=\\s]*"+src[MAINVERSIONLOOSE]+src[PRERELEASELOOSE]+"?"+src[BUILD]+"?";var LOOSE=R++;src[LOOSE]="^"+LOOSEPLAIN+"$";var GTLT=R++;src[GTLT]="((?:<|>)?=?)";var XRANGEIDENTIFIERLOOSE=R++;src[XRANGEIDENTIFIERLOOSE]=src[NUMERICIDENTIFIERLOOSE]+"|x|X|\\*";var XRANGEIDENTIFIER=R++;src[XRANGEIDENTIFIER]=src[NUMERICIDENTIFIER]+"|x|X|\\*";var XRANGEPLAIN=R++;src[XRANGEPLAIN]="[v=\\s]*("+src[XRANGEIDENTIFIER]+")"+"(?:\\.("+src[XRANGEIDENTIFIER]+")"+"(?:\\.("+src[XRANGEIDENTIFIER]+")"+"(?:("+src[PRERELEASE]+")"+")?)?)?";var XRANGEPLAINLOOSE=R++;src[XRANGEPLAINLOOSE]="[v=\\s]*("+src[XRANGEIDENTIFIERLOOSE]+")"+"(?:\\.("+src[XRANGEIDENTIFIERLOOSE]+")"+"(?:\\.("+src[XRANGEIDENTIFIERLOOSE]+")"+"(?:("+src[PRERELEASELOOSE]+")"+")?)?)?";var XRANGE=R++;src[XRANGE]="^"+src[GTLT]+"\\s*"+src[XRANGEPLAIN]+"$";var XRANGELOOSE=R++;src[XRANGELOOSE]="^"+src[GTLT]+"\\s*"+src[XRANGEPLAINLOOSE]+"$";var LONETILDE=R++;src[LONETILDE]="(?:~>?)";var TILDETRIM=R++;src[TILDETRIM]="(\\s*)"+src[LONETILDE]+"\\s+";re[TILDETRIM]=new RegExp(src[TILDETRIM],"g");var tildeTrimReplace="$1~";var TILDE=R++;src[TILDE]="^"+src[LONETILDE]+src[XRANGEPLAIN]+"$";var TILDELOOSE=R++;src[TILDELOOSE]="^"+src[LONETILDE]+src[XRANGEPLAINLOOSE]+"$";var LONECARET=R++;src[LONECARET]="(?:\\^)";var CARETTRIM=R++;src[CARETTRIM]="(\\s*)"+src[LONECARET]+"\\s+";re[CARETTRIM]=new RegExp(src[CARETTRIM],"g");var caretTrimReplace="$1^";var CARET=R++;src[CARET]="^"+src[LONECARET]+src[XRANGEPLAIN]+"$";var CARETLOOSE=R++;src[CARETLOOSE]="^"+src[LONECARET]+src[XRANGEPLAINLOOSE]+"$";var COMPARATORLOOSE=R++;src[COMPARATORLOOSE]="^"+src[GTLT]+"\\s*("+LOOSEPLAIN+")$|^$";var COMPARATOR=R++;src[COMPARATOR]="^"+src[GTLT]+"\\s*("+FULLPLAIN+")$|^$";var COMPARATORTRIM=R++;src[COMPARATORTRIM]="(\\s*)"+src[GTLT]+"\\s*("+LOOSEPLAIN+"|"+src[XRANGEPLAIN]+")";re[COMPARATORTRIM]=new RegExp(src[COMPARATORTRIM],"g");var comparatorTrimReplace="$1$2$3";var HYPHENRANGE=R++;src[HYPHENRANGE]="^\\s*("+src[XRANGEPLAIN]+")"+"\\s+-\\s+"+"("+src[XRANGEPLAIN]+")"+"\\s*$";var HYPHENRANGELOOSE=R++;src[HYPHENRANGELOOSE]="^\\s*("+src[XRANGEPLAINLOOSE]+")"+"\\s+-\\s+"+"("+src[XRANGEPLAINLOOSE]+")"+"\\s*$";var STAR=R++;src[STAR]="(<|>)?=?\\s*\\*";for(var i=0;i'};SemVer.prototype.toString=function(){return this.version};SemVer.prototype.compare=function(other){if(!(other instanceof SemVer))other=new SemVer(other,this.loose);return this.compareMain(other)||this.comparePre(other)};SemVer.prototype.compareMain=function(other){if(!(other instanceof SemVer))other=new SemVer(other,this.loose);return compareIdentifiers(this.major,other.major)||compareIdentifiers(this.minor,other.minor)||compareIdentifiers(this.patch,other.patch)};SemVer.prototype.comparePre=function(other){if(!(other instanceof SemVer))other=new SemVer(other,this.loose);if(this.prerelease.length&&!other.prerelease.length)return-1;else if(!this.prerelease.length&&other.prerelease.length)return 1;else if(!this.prerelease.lenth&&!other.prerelease.length)return 0;var i=0;do{var a=this.prerelease[i];var b=other.prerelease[i];if(a===undefined&&b===undefined)return 0;else if(b===undefined)return 1;else if(a===undefined)return-1;else if(a===b)continue;else return compareIdentifiers(a,b)}while(++i)};SemVer.prototype.inc=function(release){switch(release){case"major":this.major++; 4 | this.minor=-1;case"minor":this.minor++;this.patch=-1;case"patch":this.patch++;this.prerelease=[];break;case"prerelease":if(this.prerelease.length===0)this.prerelease=[0];else{var i=this.prerelease.length;while(--i>=0){if(typeof this.prerelease[i]==="number"){this.prerelease[i]++;i=-2}}if(i===-1)this.prerelease.push(0)}break;default:throw new Error("invalid increment argument: "+release)}this.format();return this};exports.inc=inc;function inc(version,release,loose){try{return new SemVer(version,loose).inc(release).version}catch(er){return null}}exports.compareIdentifiers=compareIdentifiers;var numeric=/^[0-9]+$/;function compareIdentifiers(a,b){var anum=numeric.test(a);var bnum=numeric.test(b);if(anum&&bnum){a=+a;b=+b}return anum&&!bnum?-1:bnum&&!anum?1:ab?1:0}exports.rcompareIdentifiers=rcompareIdentifiers;function rcompareIdentifiers(a,b){return compareIdentifiers(b,a)}exports.compare=compare;function compare(a,b,loose){return new SemVer(a,loose).compare(b)}exports.compareLoose=compareLoose;function compareLoose(a,b){return compare(a,b,true)}exports.rcompare=rcompare;function rcompare(a,b,loose){return compare(b,a,loose)}exports.sort=sort;function sort(list,loose){return list.sort(function(a,b){return exports.compare(a,b,loose)})}exports.rsort=rsort;function rsort(list,loose){return list.sort(function(a,b){return exports.rcompare(a,b,loose)})}exports.gt=gt;function gt(a,b,loose){return compare(a,b,loose)>0}exports.lt=lt;function lt(a,b,loose){return compare(a,b,loose)<0}exports.eq=eq;function eq(a,b,loose){return compare(a,b,loose)===0}exports.neq=neq;function neq(a,b,loose){return compare(a,b,loose)!==0}exports.gte=gte;function gte(a,b,loose){return compare(a,b,loose)>=0}exports.lte=lte;function lte(a,b,loose){return compare(a,b,loose)<=0}exports.cmp=cmp;function cmp(a,op,b,loose){var ret;switch(op){case"===":ret=a===b;break;case"!==":ret=a!==b;break;case"":case"=":case"==":ret=eq(a,b,loose);break;case"!=":ret=neq(a,b,loose);break;case">":ret=gt(a,b,loose);break;case">=":ret=gte(a,b,loose);break;case"<":ret=lt(a,b,loose);break;case"<=":ret=lte(a,b,loose);break;default:throw new TypeError("Invalid operator: "+op)}return ret}exports.Comparator=Comparator;function Comparator(comp,loose){if(comp instanceof Comparator){if(comp.loose===loose)return comp;else comp=comp.value}if(!(this instanceof Comparator))return new Comparator(comp,loose);this.loose=loose;this.parse(comp);if(this.semver===ANY)this.value="";else this.value=this.operator+this.semver.version}var ANY={};Comparator.prototype.parse=function(comp){var r=this.loose?re[COMPARATORLOOSE]:re[COMPARATOR];var m=comp.match(r);if(!m)throw new TypeError("Invalid comparator: "+comp);this.operator=m[1];if(!m[2])this.semver=ANY;else{this.semver=new SemVer(m[2],this.loose);if(this.operator==="<"&&!this.semver.prerelease.length){this.semver.prerelease=["0"];this.semver.format()}}};Comparator.prototype.inspect=function(){return''};Comparator.prototype.toString=function(){return this.value};Comparator.prototype.test=function(version){return this.semver===ANY?true:cmp(version,this.operator,this.semver,this.loose)};exports.Range=Range;function Range(range,loose){if(range instanceof Range&&range.loose===loose)return range;if(!(this instanceof Range))return new Range(range,loose);this.loose=loose;this.raw=range;this.set=range.split(/\s*\|\|\s*/).map(function(range){return this.parseRange(range.trim())},this).filter(function(c){return c.length});if(!this.set.length){throw new TypeError("Invalid SemVer Range: "+range)}this.format()}Range.prototype.inspect=function(){return''};Range.prototype.format=function(){this.range=this.set.map(function(comps){return comps.join(" ").trim()}).join("||").trim();return this.range};Range.prototype.toString=function(){return this.range};Range.prototype.parseRange=function(range){var loose=this.loose;range=range.trim();var hr=loose?re[HYPHENRANGELOOSE]:re[HYPHENRANGE];range=range.replace(hr,hyphenReplace);range=range.replace(re[COMPARATORTRIM],comparatorTrimReplace);range=range.replace(re[TILDETRIM],tildeTrimReplace);range=range.replace(re[CARETTRIM],caretTrimReplace);range=range.split(/\s+/).join(" ");var compRe=loose?re[COMPARATORLOOSE]:re[COMPARATOR];var set=range.split(" ").map(function(comp){return parseComparator(comp,loose)}).join(" ").split(/\s+/);if(this.loose){set=set.filter(function(comp){return!!comp.match(compRe)})}set=set.map(function(comp){return new Comparator(comp,loose)});return set};exports.toComparators=toComparators;function toComparators(range,loose){return new Range(range,loose).set.map(function(comp){return comp.map(function(c){return c.value}).join(" ").trim().split(" ")})}function parseComparator(comp,loose){comp=replaceCarets(comp,loose);comp=replaceTildes(comp,loose);comp=replaceXRanges(comp,loose);comp=replaceStars(comp,loose);return comp}function isX(id){return!id||id.toLowerCase()==="x"||id==="*"}function replaceTildes(comp,loose){return comp.trim().split(/\s+/).map(function(comp){return replaceTilde(comp,loose)}).join(" ")}function replaceTilde(comp,loose){var r=loose?re[TILDELOOSE]:re[TILDE];return comp.replace(r,function(_,M,m,p,pr){var ret;if(isX(M))ret="";else if(isX(m))ret=">="+M+".0.0-0 <"+(+M+1)+".0.0-0";else if(isX(p))ret=">="+M+"."+m+".0-0 <"+M+"."+(+m+1)+".0-0";else if(pr){if(pr.charAt(0)!=="-")pr="-"+pr;ret=">="+M+"."+m+"."+p+pr+" <"+M+"."+(+m+1)+".0-0"}else ret=">="+M+"."+m+"."+p+"-0"+" <"+M+"."+(+m+1)+".0-0";return ret})}function replaceCarets(comp,loose){return comp.trim().split(/\s+/).map(function(comp){return replaceCaret(comp,loose)}).join(" ")}function replaceCaret(comp,loose){var r=loose?re[CARETLOOSE]:re[CARET];return comp.replace(r,function(_,M,m,p,pr){var ret;if(isX(M))ret="";else if(isX(m))ret=">="+M+".0.0-0 <"+(+M+1)+".0.0-0";else if(isX(p)){if(M==="0")ret=">="+M+"."+m+".0-0 <"+M+"."+(+m+1)+".0-0";else ret=">="+M+"."+m+".0-0 <"+(+M+1)+".0.0-0"}else if(pr){if(pr.charAt(0)!=="-")pr="-"+pr;if(M==="0"){if(m==="0")ret="="+M+"."+m+"."+p+pr;else ret=">="+M+"."+m+"."+p+pr+" <"+M+"."+(+m+1)+".0-0"}else ret=">="+M+"."+m+"."+p+pr+" <"+(+M+1)+".0.0-0"}else{if(M==="0"){if(m==="0")ret="="+M+"."+m+"."+p;else ret=">="+M+"."+m+"."+p+"-0"+" <"+M+"."+(+m+1)+".0-0"}else ret=">="+M+"."+m+"."+p+"-0"+" <"+(+M+1)+".0.0-0"}return ret})}function replaceXRanges(comp,loose){return comp.split(/\s+/).map(function(comp){return replaceXRange(comp,loose)}).join(" ")}function replaceXRange(comp,loose){comp=comp.trim();var r=loose?re[XRANGELOOSE]:re[XRANGE];return comp.replace(r,function(ret,gtlt,M,m,p,pr){var xM=isX(M);var xm=xM||isX(m);var xp=xm||isX(p);var anyX=xp;if(gtlt==="="&&anyX)gtlt="";if(gtlt&&anyX){if(xM)M=0;if(xm)m=0;if(xp)p=0;if(gtlt===">"){gtlt=">=";if(xM){}else if(xm){M=+M+1;m=0;p=0}else if(xp){m=+m+1;p=0}}ret=gtlt+M+"."+m+"."+p+"-0"}else if(xM){ret="*"}else if(xm){ret=">="+M+".0.0-0 <"+(+M+1)+".0.0-0"}else if(xp){ret=">="+M+"."+m+".0-0 <"+M+"."+(+m+1)+".0-0"}return ret})}function replaceStars(comp,loose){return comp.trim().replace(re[STAR],"")}function hyphenReplace($0,from,fM,fm,fp,fpr,fb,to,tM,tm,tp,tpr,tb){if(isX(fM))from="";else if(isX(fm))from=">="+fM+".0.0-0";else if(isX(fp))from=">="+fM+"."+fm+".0-0";else from=">="+from;if(isX(tM))to="";else if(isX(tm))to="<"+(+tM+1)+".0.0-0";else if(isX(tp))to="<"+tM+"."+(+tm+1)+".0-0";else if(tpr)to="<="+tM+"."+tm+"."+tp+"-"+tpr;else to="<="+to;return(from+" "+to).trim()}Range.prototype.test=function(version){if(!version)return false;for(var i=0;i",loose)}exports.outside=outside;function outside(version,range,hilo,loose){version=new SemVer(version,loose);range=new Range(range,loose);var gtfn,ltefn,ltfn,comp,ecomp;switch(hilo){case">":gtfn=gt;ltefn=lte;ltfn=lt;comp=">";ecomp=">=";break;case"<":gtfn=lt;ltefn=gte;ltfn=gt;comp="<";ecomp="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(satisfies(version,range,loose)){return false}for(var i=0;i