Skip to content

Commit

Permalink
feature: transform dependencies (#1203), watcher fixes #2280, #2281
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford authored and lukastaegert committed Jun 20, 2018
1 parent 9dc91c7 commit 1b18909
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 85 deletions.
6 changes: 5 additions & 1 deletion src/Module.ts
Expand Up @@ -182,6 +182,7 @@ export default class Module {
private esTreeAst: ESTree.Program;
private magicString: MagicString;
private needsTreeshakingPass: boolean = false;
private transformDependencies: string[];

constructor(graph: Graph, id: string) {
this.id = id;
Expand Down Expand Up @@ -219,12 +220,14 @@ export default class Module {
originalSourcemap,
ast,
sourcemapChain,
resolvedIds
resolvedIds,
transformDependencies
}: ModuleJSON) {
this.code = code;
this.originalCode = originalCode;
this.originalSourcemap = originalSourcemap;
this.sourcemapChain = sourcemapChain;
this.transformDependencies = transformDependencies;

timeStart('generate ast', 3);

Expand Down Expand Up @@ -640,6 +643,7 @@ export default class Module {
return {
id: this.id,
dependencies: this.dependencies.map(module => module.id),
transformDependencies: this.transformDependencies,
code: this.code,
originalCode: this.originalCode,
originalSourcemap: this.originalSourcemap,
Expand Down
1 change: 1 addition & 0 deletions src/rollup/types.d.ts
Expand Up @@ -56,6 +56,7 @@ export interface SourceDescription {
export interface ModuleJSON {
id: string;
dependencies: string[];
transformDependencies: string[];
code: string;
originalCode: string;
originalSourcemap: RawSourceMap | void;
Expand Down
10 changes: 10 additions & 0 deletions src/utils/transform.ts
Expand Up @@ -13,6 +13,7 @@ import {
} from '../rollup/types';
import error from './error';
import getCodeFrame from './getCodeFrame';
import { dirname, resolve } from './path';

function augmentCodeLocation<T extends RollupError | RollupWarning>({
object,
Expand Down Expand Up @@ -104,6 +105,7 @@ export default function transform(
let ast = <Program>source.ast;

let promise = Promise.resolve(source.code);
let transformDependencies: string[];

plugins.forEach(plugin => {
if (!plugin.transform) return;
Expand All @@ -128,6 +130,13 @@ export default function transform(
result.map = JSON.parse(result.map);
}

if (Array.isArray(result.dependencies)) {
if (!transformDependencies) transformDependencies = [];
for (const dep of result.dependencies) {
transformDependencies.push(resolve(dirname(id), dep));
}
}

if (result.map && typeof result.map.mappings === 'string') {
result.map.mappings = decode(result.map.mappings);
}
Expand Down Expand Up @@ -157,6 +166,7 @@ export default function transform(
return promise.then(code => {
return {
code,
transformDependencies,
originalCode,
originalSourcemap,
ast: <ESTree.Program>ast,
Expand Down
92 changes: 55 additions & 37 deletions src/watch/fileWatchers.ts
Expand Up @@ -11,52 +11,43 @@ export function addTask(
id: string,
task: Task,
chokidarOptions: WatchOptions,
chokidarOptionsHash: string
chokidarOptionsHash: string,
isTransformDependency: boolean
) {
if (!watchers.has(chokidarOptionsHash)) watchers.set(chokidarOptionsHash, new Map());
const group = watchers.get(chokidarOptionsHash);

if (!group.has(id)) {
const watcher = new FileWatcher(id, chokidarOptions, () => {
group.delete(id);
});

if (watcher.fileExists) {
group.set(id, watcher);
} else {
return;
}
const watcher = group.get(id) || new FileWatcher(id, chokidarOptions, group);
if (!watcher.fileExists) {
if (isTransformDependency) throw new Error(`Transform dependency ${id} does not exist.`);
} else {
watcher.addTask(task, isTransformDependency);
}

group.get(id).tasks.add(task);
}

export function deleteTask(id: string, target: Task, chokidarOptionsHash: string) {
const group = watchers.get(chokidarOptionsHash);

const watcher = group.get(id);
if (watcher) {
watcher.tasks.delete(target);

if (watcher.tasks.size === 0) {
watcher.close();
group.delete(id);
}
}
if (watcher) watcher.deleteTask(target, group);
}

export default class FileWatcher {
fileExists: boolean;
fsWatcher: FSWatcher | fs.FSWatcher;
tasks: Set<Task>;
fileExists: boolean;
private id: string;
private tasks: Set<Task>;
private transformDependencyTasks: Set<Task>;

constructor(id: string, chokidarOptions: WatchOptions, dispose: () => void) {
constructor(id: string, chokidarOptions: WatchOptions, group: Map<string, FileWatcher>) {
this.id = id;
this.tasks = new Set();
this.transformDependencyTasks = new Set();

let data: string;
let modifiedTime: number;

try {
fs.statSync(id);
const stats = fs.statSync(id);
modifiedTime = +stats.mtime;
this.fileExists = true;
} catch (err) {
if (err.code === 'ENOENT') {
Expand All @@ -71,16 +62,23 @@ export default class FileWatcher {

const handleWatchEvent = (event: string) => {
if (event === 'rename' || event === 'unlink') {
this.fsWatcher.close();
this.trigger();
dispose();
this.close();
group.delete(id);
this.trigger(id);
} else {
// this is necessary because we get duplicate events...
const contents = fs.readFileSync(id, 'utf-8');
if (contents !== data) {
data = contents;
this.trigger();
let stats: fs.Stats;
try {
stats = fs.statSync(id);
} catch (err) {
if (err.code === 'ENOENT') {
modifiedTime = -1;
this.trigger(id);
return;
}
throw err;
}
// debounce
if (+stats.mtime - modifiedTime > 15) this.trigger(id);
}
};

Expand All @@ -89,15 +87,35 @@ export default class FileWatcher {
} else {
this.fsWatcher = fs.watch(id, opts, handleWatchEvent);
}

group.set(id, this);
}

addTask(task: Task, isTransformDependency = false) {
if (isTransformDependency) this.transformDependencyTasks.add(task);
else this.tasks.add(task);
}

deleteTask(task: Task, group: Map<string, FileWatcher>) {
let deleted = this.tasks.delete(task);
deleted = this.transformDependencyTasks.delete(task) || deleted;

if (deleted && this.tasks.size === 0 && this.transformDependencyTasks.size === 0) {
group.delete(this.id);
this.close();
}
}

close() {
this.fsWatcher.close();
}

trigger() {
trigger(id: string) {
this.tasks.forEach(task => {
task.makeDirty();
task.invalidate(id, false);
});
this.transformDependencyTasks.forEach(task => {
task.invalidate(id, true);
});
}
}

0 comments on commit 1b18909

Please sign in to comment.