UNPKG

9.71 kBJavaScriptView Raw
1/*
2 @license
3 Rollup.js v2.62.1
4 Sun, 13 Feb 2022 23:06:06 GMT - commit 159f1d7f9506bdd1266d9324efd48b2ec30f5f22
5
6
7 https://github.com/rollup/rollup
8
9 Released under the MIT License.
10*/
11'use strict';
12
13const path = require('path');
14const rollup = require('./rollup.js');
15const mergeOptions = require('./mergeOptions.js');
16const require$$2 = require('os');
17const index = require('./index.js');
18require('crypto');
19require('fs');
20require('events');
21require('util');
22require('stream');
23
24function _interopNamespaceDefault(e) {
25 const n = Object.create(null);
26 if (e) {
27 for (const k in e) {
28 n[k] = e[k];
29 }
30 }
31 n.default = e;
32 return n;
33}
34
35const path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
36
37class FileWatcher {
38 constructor(task, chokidarOptions) {
39 this.transformWatchers = new Map();
40 this.chokidarOptions = chokidarOptions;
41 this.task = task;
42 this.watcher = this.createWatcher(null);
43 }
44 close() {
45 this.watcher.close();
46 for (const watcher of this.transformWatchers.values()) {
47 watcher.close();
48 }
49 }
50 unwatch(id) {
51 this.watcher.unwatch(id);
52 const transformWatcher = this.transformWatchers.get(id);
53 if (transformWatcher) {
54 this.transformWatchers.delete(id);
55 transformWatcher.close();
56 }
57 }
58 watch(id, isTransformDependency) {
59 if (isTransformDependency) {
60 const watcher = this.transformWatchers.get(id) || this.createWatcher(id);
61 watcher.add(id);
62 this.transformWatchers.set(id, watcher);
63 }
64 else {
65 this.watcher.add(id);
66 }
67 }
68 createWatcher(transformWatcherId) {
69 const task = this.task;
70 const isLinux = require$$2.platform() === 'linux';
71 const isTransformDependency = transformWatcherId !== null;
72 const handleChange = (id, event) => {
73 const changedId = transformWatcherId || id;
74 if (isLinux) {
75 // unwatching and watching fixes an issue with chokidar where on certain systems,
76 // a file that was unlinked and immediately recreated would create a change event
77 // but then no longer any further events
78 watcher.unwatch(changedId);
79 watcher.add(changedId);
80 }
81 task.invalidate(changedId, { event, isTransformDependency });
82 };
83 const watcher = index.chokidar
84 .watch([], this.chokidarOptions)
85 .on('add', id => handleChange(id, 'create'))
86 .on('change', id => handleChange(id, 'update'))
87 .on('unlink', id => handleChange(id, 'delete'));
88 return watcher;
89 }
90}
91
92const eventsRewrites = {
93 create: {
94 create: 'buggy',
95 delete: null,
96 update: 'create'
97 },
98 delete: {
99 create: 'update',
100 delete: 'buggy',
101 update: 'buggy'
102 },
103 update: {
104 create: 'buggy',
105 delete: 'delete',
106 update: 'update'
107 }
108};
109class Watcher {
110 constructor(configs, emitter) {
111 this.buildDelay = 0;
112 this.buildTimeout = null;
113 this.invalidatedIds = new Map();
114 this.rerun = false;
115 this.running = true;
116 this.emitter = emitter;
117 emitter.close = this.close.bind(this);
118 this.tasks = configs.map(config => new Task(this, config));
119 this.buildDelay = configs.reduce((buildDelay, { watch }) => watch && typeof watch.buildDelay === 'number'
120 ? Math.max(buildDelay, watch.buildDelay)
121 : buildDelay, this.buildDelay);
122 process.nextTick(() => this.run());
123 }
124 close() {
125 if (this.buildTimeout)
126 clearTimeout(this.buildTimeout);
127 for (const task of this.tasks) {
128 task.close();
129 }
130 this.emitter.emit('close');
131 this.emitter.removeAllListeners();
132 }
133 invalidate(file) {
134 if (file) {
135 const prevEvent = this.invalidatedIds.get(file.id);
136 const event = prevEvent ? eventsRewrites[prevEvent][file.event] : file.event;
137 if (event === 'buggy') {
138 //TODO: throws or warn? Currently just ignore, uses new event
139 this.invalidatedIds.set(file.id, file.event);
140 }
141 else if (event === null) {
142 this.invalidatedIds.delete(file.id);
143 }
144 else {
145 this.invalidatedIds.set(file.id, event);
146 }
147 }
148 if (this.running) {
149 this.rerun = true;
150 return;
151 }
152 if (this.buildTimeout)
153 clearTimeout(this.buildTimeout);
154 this.buildTimeout = setTimeout(() => {
155 this.buildTimeout = null;
156 for (const [id, event] of this.invalidatedIds.entries()) {
157 this.emitter.emit('change', id, { event });
158 }
159 this.invalidatedIds.clear();
160 this.emitter.emit('restart');
161 this.run();
162 }, this.buildDelay);
163 }
164 async run() {
165 this.running = true;
166 this.emitter.emit('event', {
167 code: 'START'
168 });
169 for (const task of this.tasks) {
170 await task.run();
171 }
172 this.running = false;
173 this.emitter.emit('event', {
174 code: 'END'
175 });
176 if (this.rerun) {
177 this.rerun = false;
178 this.invalidate();
179 }
180 }
181}
182class Task {
183 constructor(watcher, config) {
184 this.cache = { modules: [] };
185 this.watchFiles = [];
186 this.closed = false;
187 this.invalidated = true;
188 this.watched = new Set();
189 this.watcher = watcher;
190 this.skipWrite = Boolean(config.watch && config.watch.skipWrite);
191 this.options = mergeOptions.mergeOptions(config);
192 this.outputs = this.options.output;
193 this.outputFiles = this.outputs.map(output => {
194 if (output.file || output.dir)
195 return path__namespace.resolve(output.file || output.dir);
196 return undefined;
197 });
198 const watchOptions = this.options.watch || {};
199 this.filter = rollup.createFilter(watchOptions.include, watchOptions.exclude);
200 this.fileWatcher = new FileWatcher(this, {
201 ...watchOptions.chokidar,
202 disableGlobbing: true,
203 ignoreInitial: true
204 });
205 }
206 close() {
207 this.closed = true;
208 this.fileWatcher.close();
209 }
210 invalidate(id, details) {
211 this.invalidated = true;
212 if (details.isTransformDependency) {
213 for (const module of this.cache.modules) {
214 if (module.transformDependencies.indexOf(id) === -1)
215 continue;
216 // effective invalidation
217 module.originalCode = null;
218 }
219 }
220 this.watcher.invalidate({ event: details.event, id });
221 }
222 async run() {
223 if (!this.invalidated)
224 return;
225 this.invalidated = false;
226 const options = {
227 ...this.options,
228 cache: this.cache
229 };
230 const start = Date.now();
231 this.watcher.emitter.emit('event', {
232 code: 'BUNDLE_START',
233 input: this.options.input,
234 output: this.outputFiles
235 });
236 let result = null;
237 try {
238 result = await rollup.rollupInternal(options, this.watcher.emitter);
239 if (this.closed) {
240 return;
241 }
242 this.updateWatchedFiles(result);
243 this.skipWrite || (await Promise.all(this.outputs.map(output => result.write(output))));
244 this.watcher.emitter.emit('event', {
245 code: 'BUNDLE_END',
246 duration: Date.now() - start,
247 input: this.options.input,
248 output: this.outputFiles,
249 result
250 });
251 }
252 catch (error) {
253 if (!this.closed) {
254 if (Array.isArray(error.watchFiles)) {
255 for (const id of error.watchFiles) {
256 this.watchFile(id);
257 }
258 }
259 if (error.id) {
260 this.cache.modules = this.cache.modules.filter(module => module.id !== error.id);
261 }
262 }
263 this.watcher.emitter.emit('event', {
264 code: 'ERROR',
265 error,
266 result
267 });
268 }
269 }
270 updateWatchedFiles(result) {
271 const previouslyWatched = this.watched;
272 this.watched = new Set();
273 this.watchFiles = result.watchFiles;
274 this.cache = result.cache;
275 for (const id of this.watchFiles) {
276 this.watchFile(id);
277 }
278 for (const module of this.cache.modules) {
279 for (const depId of module.transformDependencies) {
280 this.watchFile(depId, true);
281 }
282 }
283 for (const id of previouslyWatched) {
284 if (!this.watched.has(id)) {
285 this.fileWatcher.unwatch(id);
286 }
287 }
288 }
289 watchFile(id, isTransformDependency = false) {
290 if (!this.filter(id))
291 return;
292 this.watched.add(id);
293 if (this.outputFiles.some(file => file === id)) {
294 throw new Error('Cannot import the generated bundle');
295 }
296 // this is necessary to ensure that any 'renamed' files
297 // continue to be watched following an error
298 this.fileWatcher.watch(id, isTransformDependency);
299 }
300}
301
302exports.Task = Task;
303exports.Watcher = Watcher;
304//# sourceMappingURL=watch.js.map