UNPKG

6.65 kBJavaScriptView Raw
1'use strict';
2
3var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
4 return typeof obj;
5} : function (obj) {
6 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
7};
8
9var es5 = require('../caniuse/es5');
10var es6 = require('../caniuse/es6');
11
12var browserVersions = require('./browserVersions');
13var getVersions = browserVersions.getVersions;
14var pid = browserVersions.parseId;
15
16function polyfillNeeded(browsers, versions, testCase) {
17 var _iteratorNormalCompletion = true;
18 var _didIteratorError = false;
19 var _iteratorError = undefined;
20
21 try {
22 var _loop = function _loop() {
23 var entry = _step.value;
24
25 var browser = entry[0];
26 var target = entry[1];
27 var versionList = versions.get(browser);
28
29 // If the version demanded version is greater than the highest one in the list, just skip it
30 if (!versionList || target.version > versionList[0].version) {
31 return 'continue';
32 }
33
34 var test = testCase.res[target.id];
35
36 // If there is no result for the current test, look if there should be one
37 // for lower versions
38 if (typeof test === 'undefined') {
39 var closestVersion = 0;
40 var closestId = Object.keys(testCase.res).reduce(function (closest, id) {
41 if (id.indexOf(browser) !== 0) {
42 return closest;
43 }
44
45 var v = pid(id).version;
46 if (v < target.version && v > closestVersion) {
47 closestVersion = v;
48 return id;
49 }
50 });
51
52 if (!closestId || testCase.res[closestId] !== true) {
53 return {
54 v: true
55 };
56 }
57
58 // if the test is not really passed
59 // Just return true as the browser needs a polyfill for the feature
60 } else if (test !== true) {
61 return {
62 v: true
63 };
64 }
65 };
66
67 for (var _iterator = browsers.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
68 var _ret = _loop();
69
70 switch (_ret) {
71 case 'continue':
72 continue;
73
74 default:
75 if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
76 }
77 }
78
79 // If none of the tests already returned true, it means no polyfill is needed, so return false
80 } catch (err) {
81 _didIteratorError = true;
82 _iteratorError = err;
83 } finally {
84 try {
85 if (!_iteratorNormalCompletion && _iterator.return) {
86 _iterator.return();
87 }
88 } finally {
89 if (_didIteratorError) {
90 throw _iteratorError;
91 }
92 }
93 }
94
95 return false;
96}
97
98module.exports = function filterFeatures(features, versions) {
99 var dbBrowsers = getVersions(versions);
100
101 return features.filter(function (feature) {
102 var split = feature.split('.');
103 var obj = split[0];
104 var method = split[1] || '';
105
106 // Start by checking ES 5
107 var test = null;
108 es5.tests.some(function (t) {
109 if (!new RegExp('^' + obj).test(t.name)) {
110 return false;
111 }
112
113 if (t.subtests) {
114 // Otherwise search for a matching sub test
115 var _iteratorNormalCompletion2 = true;
116 var _didIteratorError2 = false;
117 var _iteratorError2 = undefined;
118
119 try {
120 for (var _iterator2 = t.subtests[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
121 var sub = _step2.value;
122
123 if (sub.name.replace('.prototype.', '.') === feature) {
124 test = sub;
125 return true;
126 }
127 }
128 } catch (err) {
129 _didIteratorError2 = true;
130 _iteratorError2 = err;
131 } finally {
132 try {
133 if (!_iteratorNormalCompletion2 && _iterator2.return) {
134 _iterator2.return();
135 }
136 } finally {
137 if (_didIteratorError2) {
138 throw _iteratorError2;
139 }
140 }
141 }
142 } else if (t.name.replace('.prototype.', '.') === feature) {
143 test = t;
144 return true;
145 }
146 });
147
148 if (test) {
149 return polyfillNeeded(dbBrowsers.parsed, dbBrowsers.es5, test);
150 }
151
152 // If feature was not a es5 feature then test es6
153 es6.tests.some(function (t) {
154 // We only look at 'built-ins' or 'built-in extensions' and only if it is
155 // concerning the current Object
156 if (['built-ins', 'built-in extensions'].indexOf(t.category) < 0 || !new RegExp('^' + obj).test(t.name) || t.category === 'built-in extensions' && !method) {
157 return false;
158 }
159
160 if (!method) {
161 // If there is a 'basic functionality' sub category, just examine that test
162 if (t.subtests['basic functionality']) {
163 test = t.subtests['basic functionality'];
164 return true;
165 }
166
167 // Examine all tests if there is no 'basic functionality' sub category
168 test = Object.keys(t.subtests).map(function (sub) {
169 return t.subtests[sub];
170 });
171 return true;
172 }
173
174 // Otherwise search for a matching sub test
175 var _iteratorNormalCompletion3 = true;
176 var _didIteratorError3 = false;
177 var _iteratorError3 = undefined;
178
179 try {
180 for (var _iterator3 = t.subtests[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
181 var sub = _step3.value;
182
183 if (sub.name.replace('.prototype.', '.') === feature) {
184 test = sub;
185 return true;
186 }
187 }
188 } catch (err) {
189 _didIteratorError3 = true;
190 _iteratorError3 = err;
191 } finally {
192 try {
193 if (!_iteratorNormalCompletion3 && _iterator3.return) {
194 _iterator3.return();
195 }
196 } finally {
197 if (_didIteratorError3) {
198 throw _iteratorError3;
199 }
200 }
201 }
202 });
203
204 // If it is an array of tests see if polyfill would be needed for one of them
205 if (Array.isArray(test)) {
206 return test.some(function (t) {
207 return polyfillNeeded(dbBrowsers.parsed, dbBrowsers.es6, t);
208 });
209 }
210
211 // If it is just one, then see if the polyfill would be needed for the feature
212 if (test) {
213 return polyfillNeeded(dbBrowsers.parsed, dbBrowsers.es6, test);
214 }
215
216 // If no test was found in the caniuse db then leave it in the list, so the
217 // browser can perform the test
218 return true;
219 });
220};