You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					308 lines
				
				9.8 KiB
			
		
		
			
		
	
	
					308 lines
				
				9.8 KiB
			| 
											3 years ago
										 | /* | ||
|  |   @license | ||
|  | 	Rollup.js v2.79.1 | ||
|  | 	Thu, 22 Sep 2022 04:55:29 GMT - commit 69ff4181e701a0fe0026d0ba147f31bc86beffa8 | ||
|  | 
 | ||
|  | 	https://github.com/rollup/rollup
 | ||
|  | 
 | ||
|  | 	Released under the MIT License. | ||
|  | */ | ||
|  | 'use strict'; | ||
|  | 
 | ||
|  | Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
|  | 
 | ||
|  | const require$$0 = require('path'); | ||
|  | const process = require('process'); | ||
|  | const rollup = require('./rollup.js'); | ||
|  | const mergeOptions = require('./mergeOptions.js'); | ||
|  | const require$$2 = require('os'); | ||
|  | const index = require('./index.js'); | ||
|  | require('perf_hooks'); | ||
|  | require('crypto'); | ||
|  | require('fs'); | ||
|  | require('events'); | ||
|  | require('util'); | ||
|  | require('stream'); | ||
|  | 
 | ||
|  | class FileWatcher { | ||
|  |     constructor(task, chokidarOptions) { | ||
|  |         this.transformWatchers = new Map(); | ||
|  |         this.chokidarOptions = chokidarOptions; | ||
|  |         this.task = task; | ||
|  |         this.watcher = this.createWatcher(null); | ||
|  |     } | ||
|  |     close() { | ||
|  |         this.watcher.close(); | ||
|  |         for (const watcher of this.transformWatchers.values()) { | ||
|  |             watcher.close(); | ||
|  |         } | ||
|  |     } | ||
|  |     unwatch(id) { | ||
|  |         this.watcher.unwatch(id); | ||
|  |         const transformWatcher = this.transformWatchers.get(id); | ||
|  |         if (transformWatcher) { | ||
|  |             this.transformWatchers.delete(id); | ||
|  |             transformWatcher.close(); | ||
|  |         } | ||
|  |     } | ||
|  |     watch(id, isTransformDependency) { | ||
|  |         var _a; | ||
|  |         if (isTransformDependency) { | ||
|  |             const watcher = (_a = this.transformWatchers.get(id)) !== null && _a !== void 0 ? _a : this.createWatcher(id); | ||
|  |             watcher.add(id); | ||
|  |             this.transformWatchers.set(id, watcher); | ||
|  |         } | ||
|  |         else { | ||
|  |             this.watcher.add(id); | ||
|  |         } | ||
|  |     } | ||
|  |     createWatcher(transformWatcherId) { | ||
|  |         const task = this.task; | ||
|  |         const isLinux = require$$2.platform() === 'linux'; | ||
|  |         const isTransformDependency = transformWatcherId !== null; | ||
|  |         const handleChange = (id, event) => { | ||
|  |             const changedId = transformWatcherId || id; | ||
|  |             if (isLinux) { | ||
|  |                 // unwatching and watching fixes an issue with chokidar where on certain systems,
 | ||
|  |                 // a file that was unlinked and immediately recreated would create a change event
 | ||
|  |                 // but then no longer any further events
 | ||
|  |                 watcher.unwatch(changedId); | ||
|  |                 watcher.add(changedId); | ||
|  |             } | ||
|  |             task.invalidate(changedId, { event, isTransformDependency }); | ||
|  |         }; | ||
|  |         const watcher = index.chokidar | ||
|  |             .watch([], this.chokidarOptions) | ||
|  |             .on('add', id => handleChange(id, 'create')) | ||
|  |             .on('change', id => handleChange(id, 'update')) | ||
|  |             .on('unlink', id => handleChange(id, 'delete')); | ||
|  |         return watcher; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | const eventsRewrites = { | ||
|  |     create: { | ||
|  |         create: 'buggy', | ||
|  |         delete: null, | ||
|  |         update: 'create' | ||
|  |     }, | ||
|  |     delete: { | ||
|  |         create: 'update', | ||
|  |         delete: 'buggy', | ||
|  |         update: 'buggy' | ||
|  |     }, | ||
|  |     update: { | ||
|  |         create: 'buggy', | ||
|  |         delete: 'delete', | ||
|  |         update: 'update' | ||
|  |     } | ||
|  | }; | ||
|  | class Watcher { | ||
|  |     constructor(configs, emitter) { | ||
|  |         this.buildDelay = 0; | ||
|  |         this.buildTimeout = null; | ||
|  |         this.invalidatedIds = new Map(); | ||
|  |         this.rerun = false; | ||
|  |         this.running = true; | ||
|  |         this.emitter = emitter; | ||
|  |         emitter.close = this.close.bind(this); | ||
|  |         this.tasks = configs.map(config => new Task(this, config)); | ||
|  |         this.buildDelay = configs.reduce((buildDelay, { watch }) => watch && typeof watch.buildDelay === 'number' | ||
|  |             ? Math.max(buildDelay, watch.buildDelay) | ||
|  |             : buildDelay, this.buildDelay); | ||
|  |         process.nextTick(() => this.run()); | ||
|  |     } | ||
|  |     async close() { | ||
|  |         if (this.buildTimeout) | ||
|  |             clearTimeout(this.buildTimeout); | ||
|  |         for (const task of this.tasks) { | ||
|  |             task.close(); | ||
|  |         } | ||
|  |         await this.emitter.emitAndAwait('close'); | ||
|  |         this.emitter.removeAllListeners(); | ||
|  |     } | ||
|  |     invalidate(file) { | ||
|  |         if (file) { | ||
|  |             const prevEvent = this.invalidatedIds.get(file.id); | ||
|  |             const event = prevEvent ? eventsRewrites[prevEvent][file.event] : file.event; | ||
|  |             if (event === 'buggy') { | ||
|  |                 //TODO: throws or warn? Currently just ignore, uses new event
 | ||
|  |                 this.invalidatedIds.set(file.id, file.event); | ||
|  |             } | ||
|  |             else if (event === null) { | ||
|  |                 this.invalidatedIds.delete(file.id); | ||
|  |             } | ||
|  |             else { | ||
|  |                 this.invalidatedIds.set(file.id, event); | ||
|  |             } | ||
|  |         } | ||
|  |         if (this.running) { | ||
|  |             this.rerun = true; | ||
|  |             return; | ||
|  |         } | ||
|  |         if (this.buildTimeout) | ||
|  |             clearTimeout(this.buildTimeout); | ||
|  |         this.buildTimeout = setTimeout(async () => { | ||
|  |             this.buildTimeout = null; | ||
|  |             try { | ||
|  |                 await Promise.all([...this.invalidatedIds].map(([id, event]) => this.emitter.emitAndAwait('change', id, { event }))); | ||
|  |                 this.invalidatedIds.clear(); | ||
|  |                 this.emitter.emit('restart'); | ||
|  |                 this.emitter.removeAwaited(); | ||
|  |                 this.run(); | ||
|  |             } | ||
|  |             catch (error) { | ||
|  |                 this.invalidatedIds.clear(); | ||
|  |                 this.emitter.emit('event', { | ||
|  |                     code: 'ERROR', | ||
|  |                     error, | ||
|  |                     result: null | ||
|  |                 }); | ||
|  |                 this.emitter.emit('event', { | ||
|  |                     code: 'END' | ||
|  |                 }); | ||
|  |             } | ||
|  |         }, this.buildDelay); | ||
|  |     } | ||
|  |     async run() { | ||
|  |         this.running = true; | ||
|  |         this.emitter.emit('event', { | ||
|  |             code: 'START' | ||
|  |         }); | ||
|  |         for (const task of this.tasks) { | ||
|  |             await task.run(); | ||
|  |         } | ||
|  |         this.running = false; | ||
|  |         this.emitter.emit('event', { | ||
|  |             code: 'END' | ||
|  |         }); | ||
|  |         if (this.rerun) { | ||
|  |             this.rerun = false; | ||
|  |             this.invalidate(); | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | class Task { | ||
|  |     constructor(watcher, config) { | ||
|  |         this.cache = { modules: [] }; | ||
|  |         this.watchFiles = []; | ||
|  |         this.closed = false; | ||
|  |         this.invalidated = true; | ||
|  |         this.watched = new Set(); | ||
|  |         this.watcher = watcher; | ||
|  |         this.skipWrite = Boolean(config.watch && config.watch.skipWrite); | ||
|  |         this.options = mergeOptions.mergeOptions(config); | ||
|  |         this.outputs = this.options.output; | ||
|  |         this.outputFiles = this.outputs.map(output => { | ||
|  |             if (output.file || output.dir) | ||
|  |                 return require$$0.resolve(output.file || output.dir); | ||
|  |             return undefined; | ||
|  |         }); | ||
|  |         const watchOptions = this.options.watch || {}; | ||
|  |         this.filter = rollup.createFilter(watchOptions.include, watchOptions.exclude); | ||
|  |         this.fileWatcher = new FileWatcher(this, { | ||
|  |             ...watchOptions.chokidar, | ||
|  |             disableGlobbing: true, | ||
|  |             ignoreInitial: true | ||
|  |         }); | ||
|  |     } | ||
|  |     close() { | ||
|  |         this.closed = true; | ||
|  |         this.fileWatcher.close(); | ||
|  |     } | ||
|  |     invalidate(id, details) { | ||
|  |         this.invalidated = true; | ||
|  |         if (details.isTransformDependency) { | ||
|  |             for (const module of this.cache.modules) { | ||
|  |                 if (!module.transformDependencies.includes(id)) | ||
|  |                     continue; | ||
|  |                 // effective invalidation
 | ||
|  |                 module.originalCode = null; | ||
|  |             } | ||
|  |         } | ||
|  |         this.watcher.invalidate({ event: details.event, id }); | ||
|  |     } | ||
|  |     async run() { | ||
|  |         if (!this.invalidated) | ||
|  |             return; | ||
|  |         this.invalidated = false; | ||
|  |         const options = { | ||
|  |             ...this.options, | ||
|  |             cache: this.cache | ||
|  |         }; | ||
|  |         const start = Date.now(); | ||
|  |         this.watcher.emitter.emit('event', { | ||
|  |             code: 'BUNDLE_START', | ||
|  |             input: this.options.input, | ||
|  |             output: this.outputFiles | ||
|  |         }); | ||
|  |         let result = null; | ||
|  |         try { | ||
|  |             result = await rollup.rollupInternal(options, this.watcher.emitter); | ||
|  |             if (this.closed) { | ||
|  |                 return; | ||
|  |             } | ||
|  |             this.updateWatchedFiles(result); | ||
|  |             this.skipWrite || (await Promise.all(this.outputs.map(output => result.write(output)))); | ||
|  |             this.watcher.emitter.emit('event', { | ||
|  |                 code: 'BUNDLE_END', | ||
|  |                 duration: Date.now() - start, | ||
|  |                 input: this.options.input, | ||
|  |                 output: this.outputFiles, | ||
|  |                 result | ||
|  |             }); | ||
|  |         } | ||
|  |         catch (error) { | ||
|  |             if (!this.closed) { | ||
|  |                 if (Array.isArray(error.watchFiles)) { | ||
|  |                     for (const id of error.watchFiles) { | ||
|  |                         this.watchFile(id); | ||
|  |                     } | ||
|  |                 } | ||
|  |                 if (error.id) { | ||
|  |                     this.cache.modules = this.cache.modules.filter(module => module.id !== error.id); | ||
|  |                 } | ||
|  |             } | ||
|  |             this.watcher.emitter.emit('event', { | ||
|  |                 code: 'ERROR', | ||
|  |                 error, | ||
|  |                 result | ||
|  |             }); | ||
|  |         } | ||
|  |     } | ||
|  |     updateWatchedFiles(result) { | ||
|  |         const previouslyWatched = this.watched; | ||
|  |         this.watched = new Set(); | ||
|  |         this.watchFiles = result.watchFiles; | ||
|  |         this.cache = result.cache; | ||
|  |         for (const id of this.watchFiles) { | ||
|  |             this.watchFile(id); | ||
|  |         } | ||
|  |         for (const module of this.cache.modules) { | ||
|  |             for (const depId of module.transformDependencies) { | ||
|  |                 this.watchFile(depId, true); | ||
|  |             } | ||
|  |         } | ||
|  |         for (const id of previouslyWatched) { | ||
|  |             if (!this.watched.has(id)) { | ||
|  |                 this.fileWatcher.unwatch(id); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  |     watchFile(id, isTransformDependency = false) { | ||
|  |         if (!this.filter(id)) | ||
|  |             return; | ||
|  |         this.watched.add(id); | ||
|  |         if (this.outputFiles.some(file => file === id)) { | ||
|  |             throw new Error('Cannot import the generated bundle'); | ||
|  |         } | ||
|  |         // this is necessary to ensure that any 'renamed' files
 | ||
|  |         // continue to be watched following an error
 | ||
|  |         this.fileWatcher.watch(id, isTransformDependency); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | exports.Task = Task; | ||
|  | exports.Watcher = Watcher; | ||
|  | //# sourceMappingURL=watch.js.map
 |