Skip to content

Commit

Permalink
Add types for AssetGraph nodes and restrict AssetGraph to them
Browse files Browse the repository at this point in the history
  • Loading branch information
wbinnssmith committed Mar 12, 2019
1 parent 291b881 commit f1220a9
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 28 deletions.
58 changes: 36 additions & 22 deletions packages/core/core/src/AssetGraph.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
// @flow

import Graph from './Graph';
import type {
Asset,
AssetGraph as IAssetGraph,
AssetGraphNode,
Bundle,
CacheEntry,
Dependency as IDependency,
DependencyNode,
File,
FilePath,
FileNode,
Graph as IGraph,
GraphTraversalCallback,
Node,
NodeId,
Target,
TransformerRequest
} from '@parcel/types';

import invariant from 'assert';
import Graph from './Graph';
import {md5FromString} from '@parcel/utils/src/md5';
import Dependency from './Dependency';

Expand Down Expand Up @@ -47,19 +53,23 @@ export const nodeFromAsset = (asset: Asset) => ({
value: asset
});

const getFileNodesFromGraph = (graph: Graph<Node>): Array<Node> => {
return Array.from(graph.nodes.values()).filter(
(node: any) => node.type === 'file'
);
const getFileNodesFromGraph = (
graph: IGraph<AssetGraphNode>
): Array<FileNode> => {
// $FlowFixMe Flow can't refine on filter https://github.com/facebook/flow/issues/1414
return Array.from(graph.nodes.values()).filter(node => node.type === 'file');
};
const getFilesFromGraph = (graph: Graph<Node>): Array<File> => {
const getFilesFromGraph = (graph: IGraph<AssetGraphNode>): Array<File> => {
return getFileNodesFromGraph(graph).map(node => node.value);
};
const getDepNodesFromGraph = (graph: Graph<Node>): Array<Node> => {
const getDepNodesFromGraph = (
graph: IGraph<AssetGraphNode>
): Array<DependencyNode> => {
// $FlowFixMe Flow can't refine on filter https://github.com/facebook/flow/issues/1414
return Array.from(graph.nodes.values()).filter(
(node: any) => node.type === 'dependency'
node => node.type === 'dependency'
);
};

Expand All @@ -69,7 +79,7 @@ type DepUpdates = {|
|};

type FileUpdates = {|
newDeps: Array<Dependency>,
newDeps: Array<IDependency>,
addedFiles: Array<File>,
removedFiles: Array<File>
|};
Expand All @@ -89,9 +99,10 @@ type AssetGraphOpts = {|
* * A dependency node should have an edge to exactly one file node
* * A file node can have one to many edges to asset nodes which can have zero to many edges dependency nodes
*/
export default class AssetGraph extends Graph<Node> {
incompleteNodes: Map<NodeId, Node> = new Map();
invalidNodes: Map<NodeId, Node> = new Map();
export default class AssetGraph extends Graph<AssetGraphNode>
implements IAssetGraph {
incompleteNodes: Map<NodeId, AssetGraphNode> = new Map();
invalidNodes: Map<NodeId, AssetGraphNode> = new Map();

initializeGraph({
entries,
Expand Down Expand Up @@ -133,7 +144,7 @@ export default class AssetGraph extends Graph<Node> {
}
}

removeNode(node: Node): this {
removeNode(node: AssetGraphNode): this {
this.incompleteNodes.delete(node.id);
return super.removeNode(node);
}
Expand Down Expand Up @@ -169,7 +180,7 @@ export default class AssetGraph extends Graph<Node> {
req: TransformerRequest,
cacheEntry: CacheEntry
): FileUpdates {
let newDepNodes: Array<Node> = [];
let newDepNodes: Array<DependencyNode> = [];

let requestNode = nodeFromTransformerRequest(req);
this.incompleteNodes.delete(requestNode.id);
Expand Down Expand Up @@ -212,7 +223,7 @@ export default class AssetGraph extends Graph<Node> {
return {newDeps, addedFiles, removedFiles};
}

invalidateNode(node: Node) {
invalidateNode(node: AssetGraphNode) {
this.invalidNodes.set(node.id, node);
}

Expand All @@ -236,7 +247,10 @@ export default class AssetGraph extends Graph<Node> {
return [];
}

return this.getNodesConnectedFrom(node).map(node => node.value);
return this.getNodesConnectedFrom(node).map(node => {
invariant(node.type === 'dependency');
return node.value;
});
}

getDependencyResolution(dep: IDependency): ?Asset {
Expand All @@ -245,10 +259,10 @@ export default class AssetGraph extends Graph<Node> {
return null;
}

let res = null;
let res: ?Asset = null;
this.traverse((node, ctx, traversal) => {
if (node.type === 'asset' || node.type === 'asset_reference') {
res = (node.value: Asset);
res = node.value;
traversal.stop();
}
}, depNode);
Expand All @@ -257,9 +271,9 @@ export default class AssetGraph extends Graph<Node> {
}

traverseAssets(
visit: GraphTraversalCallback<Asset, Node>,
startNode: ?Node
): ?Node {
visit: GraphTraversalCallback<Asset, AssetGraphNode>,
startNode: ?AssetGraphNode
): ?AssetGraphNode {
return this.traverse((node, ...args) => {
if (node.type === 'asset') {
return visit(node.value, ...args);
Expand Down
43 changes: 41 additions & 2 deletions packages/core/types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,43 @@ export type GraphTraversalCallback<TNode, TContext> = (

export type NodeId = string;

export type AssetNode = {|id: string, type: 'asset', value: Asset|};
export type AssetReferenceNode = {|
id: string,
type: 'asset_reference',
value: Asset
|};

export type BundleGroupNode = {|
id: string,
type: 'bundle_group',
value: BundleGroup
|};

export type DependencyNode = {|
id: string,
type: 'dependency',
value: Dependency
|};

export type FileNode = {|id: string, type: 'file', value: File|};
export type RootNode = {|id: string, type: 'root', value: string | null|};

export type TransformerRequestNode = {|
id: string,
type: 'transformer_request',
value: TransformerRequest
|};

export type AssetGraphNode =
| AssetNode
| AssetReferenceNode
| BundleGroupNode
| DependencyNode
| FileNode
| RootNode
| TransformerRequestNode;

export type Edge = {|
from: NodeId,
to: NodeId
Expand All @@ -308,8 +345,10 @@ export interface Graph<TNode: Node> {
}

// TODO: what do we want to expose here?
export interface AssetGraph extends Graph<Node> {
traverseAssets(visit: GraphTraversalCallback<Asset, Node>): ?Node;
export interface AssetGraph extends Graph<AssetGraphNode> {
traverseAssets(
visit: GraphTraversalCallback<Asset, AssetGraphNode>
): ?AssetGraphNode;
createBundle(asset: Asset): Bundle;
getTotalSize(asset?: Asset): number;
getEntryAssets(): Array<Asset>;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/types/unsafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export type AST = {|

export interface Node {
id: string;
type?: string;
+type?: string;
value: any;
}
11 changes: 8 additions & 3 deletions packages/runtimes/js/src/JSRuntime.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// @flow

import type {BundleGroup} from '@parcel/types';

import {Runtime} from '@parcel/plugin';
import path from 'path';

Expand Down Expand Up @@ -36,9 +39,11 @@ export default new Runtime({
return;
}

let bundleGroups = Array.from(bundle.assetGraph.nodes.values()).filter(
n => n.type === 'bundle_group'
);
// $FlowFixMe Flow can't refine on filter https://github.com/facebook/flow/issues/1414
let bundleGroups: Array<BundleGroup> = Array.from(
bundle.assetGraph.nodes.values()
).filter(n => n.type === 'bundle_group');

for (let bundleGroup of bundleGroups) {
// Ignore deps with native loaders, e.g. workers.
if (bundleGroup.value.dependency.isURL) {
Expand Down

0 comments on commit f1220a9

Please sign in to comment.