UNPKG

6.76 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.createCachedDescriptors = createCachedDescriptors;
7exports.createUncachedDescriptors = createUncachedDescriptors;
8exports.createDescriptor = createDescriptor;
9
10function _gensync() {
11 const data = require("gensync");
12
13 _gensync = function () {
14 return data;
15 };
16
17 return data;
18}
19
20var _files = require("./files");
21
22var _item = require("./item");
23
24var _caching = require("./caching");
25
26var _resolveTargets = require("./resolve-targets");
27
28function isEqualDescriptor(a, b) {
29 return a.name === b.name && a.value === b.value && a.options === b.options && a.dirname === b.dirname && a.alias === b.alias && a.ownPass === b.ownPass && (a.file && a.file.request) === (b.file && b.file.request) && (a.file && a.file.resolved) === (b.file && b.file.resolved);
30}
31
32function* handlerOf(value) {
33 return value;
34}
35
36function optionsWithResolvedBrowserslistConfigFile(options, dirname) {
37 if (typeof options.browserslistConfigFile === "string") {
38 options.browserslistConfigFile = (0, _resolveTargets.resolveBrowserslistConfigFile)(options.browserslistConfigFile, dirname);
39 }
40
41 return options;
42}
43
44function createCachedDescriptors(dirname, options, alias) {
45 const {
46 plugins,
47 presets,
48 passPerPreset
49 } = options;
50 return {
51 options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
52 plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => handlerOf([]),
53 presets: presets ? () => createCachedPresetDescriptors(presets, dirname)(alias)(!!passPerPreset) : () => handlerOf([])
54 };
55}
56
57function createUncachedDescriptors(dirname, options, alias) {
58 let plugins;
59 let presets;
60 return {
61 options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
62
63 *plugins() {
64 if (!plugins) {
65 plugins = yield* createPluginDescriptors(options.plugins || [], dirname, alias);
66 }
67
68 return plugins;
69 },
70
71 *presets() {
72 if (!presets) {
73 presets = yield* createPresetDescriptors(options.presets || [], dirname, alias, !!options.passPerPreset);
74 }
75
76 return presets;
77 }
78
79 };
80}
81
82const PRESET_DESCRIPTOR_CACHE = new WeakMap();
83const createCachedPresetDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
84 const dirname = cache.using(dir => dir);
85 return (0, _caching.makeStrongCacheSync)(alias => (0, _caching.makeStrongCache)(function* (passPerPreset) {
86 const descriptors = yield* createPresetDescriptors(items, dirname, alias, passPerPreset);
87 return descriptors.map(desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc));
88 }));
89});
90const PLUGIN_DESCRIPTOR_CACHE = new WeakMap();
91const createCachedPluginDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
92 const dirname = cache.using(dir => dir);
93 return (0, _caching.makeStrongCache)(function* (alias) {
94 const descriptors = yield* createPluginDescriptors(items, dirname, alias);
95 return descriptors.map(desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc));
96 });
97});
98const DEFAULT_OPTIONS = {};
99
100function loadCachedDescriptor(cache, desc) {
101 const {
102 value,
103 options = DEFAULT_OPTIONS
104 } = desc;
105 if (options === false) return desc;
106 let cacheByOptions = cache.get(value);
107
108 if (!cacheByOptions) {
109 cacheByOptions = new WeakMap();
110 cache.set(value, cacheByOptions);
111 }
112
113 let possibilities = cacheByOptions.get(options);
114
115 if (!possibilities) {
116 possibilities = [];
117 cacheByOptions.set(options, possibilities);
118 }
119
120 if (possibilities.indexOf(desc) === -1) {
121 const matches = possibilities.filter(possibility => isEqualDescriptor(possibility, desc));
122
123 if (matches.length > 0) {
124 return matches[0];
125 }
126
127 possibilities.push(desc);
128 }
129
130 return desc;
131}
132
133function* createPresetDescriptors(items, dirname, alias, passPerPreset) {
134 return yield* createDescriptors("preset", items, dirname, alias, passPerPreset);
135}
136
137function* createPluginDescriptors(items, dirname, alias) {
138 return yield* createDescriptors("plugin", items, dirname, alias);
139}
140
141function* createDescriptors(type, items, dirname, alias, ownPass) {
142 const descriptors = yield* _gensync().all(items.map((item, index) => createDescriptor(item, dirname, {
143 type,
144 alias: `${alias}$${index}`,
145 ownPass: !!ownPass
146 })));
147 assertNoDuplicates(descriptors);
148 return descriptors;
149}
150
151function* createDescriptor(pair, dirname, {
152 type,
153 alias,
154 ownPass
155}) {
156 const desc = (0, _item.getItemDescriptor)(pair);
157
158 if (desc) {
159 return desc;
160 }
161
162 let name;
163 let options;
164 let value = pair;
165
166 if (Array.isArray(value)) {
167 if (value.length === 3) {
168 [value, options, name] = value;
169 } else {
170 [value, options] = value;
171 }
172 }
173
174 let file = undefined;
175 let filepath = null;
176
177 if (typeof value === "string") {
178 if (typeof type !== "string") {
179 throw new Error("To resolve a string-based item, the type of item must be given");
180 }
181
182 const resolver = type === "plugin" ? _files.loadPlugin : _files.loadPreset;
183 const request = value;
184 ({
185 filepath,
186 value
187 } = yield* resolver(value, dirname));
188 file = {
189 request,
190 resolved: filepath
191 };
192 }
193
194 if (!value) {
195 throw new Error(`Unexpected falsy value: ${String(value)}`);
196 }
197
198 if (typeof value === "object" && value.__esModule) {
199 if (value.default) {
200 value = value.default;
201 } else {
202 throw new Error("Must export a default export when using ES6 modules.");
203 }
204 }
205
206 if (typeof value !== "object" && typeof value !== "function") {
207 throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`);
208 }
209
210 if (filepath !== null && typeof value === "object" && value) {
211 throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`);
212 }
213
214 return {
215 name,
216 alias: filepath || alias,
217 value,
218 options,
219 dirname,
220 ownPass,
221 file
222 };
223}
224
225function assertNoDuplicates(items) {
226 const map = new Map();
227
228 for (const item of items) {
229 if (typeof item.value !== "function") continue;
230 let nameMap = map.get(item.value);
231
232 if (!nameMap) {
233 nameMap = new Set();
234 map.set(item.value, nameMap);
235 }
236
237 if (nameMap.has(item.name)) {
238 const conflicts = items.filter(i => i.value === item.value);
239 throw new Error([`Duplicate plugin/preset detected.`, `If you'd like to use two separate instances of a plugin,`, `they need separate names, e.g.`, ``, ` plugins: [`, ` ['some-plugin', {}],`, ` ['some-plugin', {}, 'some unique name'],`, ` ]`, ``, `Duplicates detected are:`, `${JSON.stringify(conflicts, null, 2)}`].join("\n"));
240 }
241
242 nameMap.add(item.name);
243 }
244}
\No newline at end of file