Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parcel 2: Asset methods #2335

Merged
merged 2 commits into from
Dec 2, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions packages/core/core/src/Asset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// @flow
import type {
Asset as IAsset,
TransformerResult,
DependencyOptions,
Dependency,
FilePath,
File,
Environment,
JSONObject,
AST,
AssetOutput
} from '@parcel/types';
import md5 from '@parcel/utils/md5';
import config from '@parcel/utils/config';
import createDependency from './createDependency';

type AssetOptions = {
id?: string,
hash?: string,
filePath: FilePath,
type: string,
code?: string,
ast?: ?AST,
dependencies?: Array<Dependency>,
connectedFiles?: Array<File>,
output?: AssetOutput,
env: Environment,
meta?: JSONObject
};

export default class Asset implements IAsset {
id: string;
hash: string;
filePath: FilePath;
type: string;
code: string;
ast: ?AST;
dependencies: Array<Dependency>;
connectedFiles: Array<File>;
output: AssetOutput;
env: Environment;
meta: JSONObject;

constructor(options: AssetOptions) {
this.id =
options.id ||
md5(options.filePath + options.type + JSON.stringify(options.env));
this.hash = options.hash || '';
this.filePath = options.filePath;
this.type = options.type;
this.code = options.code || (options.output ? options.output.code : '');
this.ast = options.ast || null;
this.dependencies = options.dependencies
? options.dependencies.slice()
: [];
this.connectedFiles = options.connectedFiles
? options.connectedFiles.slice()
: [];
this.output = options.output || {code: this.code};
this.env = options.env;
this.meta = options.meta || {};
}

toJSON(): AssetOptions {
// Exclude `code` and `ast` from cache
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to also set code to null when the asset is finalized in TransformerRunner? I noticed these fields are getting removed when the asset is stringified going into the cache, but that's not what is passed back on a cache miss run, so some "code" is being stored in memory in the graph.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. That's true, although when run in the worker farm the assets are converted to JSON to pass over the IPC back to the main process.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I guess it wouldn't be every cache miss, just the cache misses before the workers warm up. Still probably better to guarantee it's removed once finalized though.

return {
id: this.id,
hash: this.hash,
filePath: this.filePath,
type: this.type,
dependencies: this.dependencies,
connectedFiles: this.connectedFiles,
output: this.output,
env: this.env,
meta: this.meta
};
}

addDependency(opts: DependencyOptions) {
let dep = createDependency(
{
...opts,
env: mergeEnvironment(this.env, opts.env)
},
this.filePath
);

this.dependencies.push(dep);
return dep.id;
}

async addConnectedFile(file: File) {
if (!file.hash) {
file.hash = await md5.file(file.filePath);
}

this.connectedFiles.push(file);
}

createChildAsset(result: TransformerResult) {
let code = result.code || (result.output && result.output.code) || '';
let opts: AssetOptions = {
hash: this.hash || md5(code),
filePath: this.filePath,
type: result.type,
code,
ast: result.ast,
env: mergeEnvironment(this.env, result.env),
dependencies: this.dependencies,
connectedFiles: this.connectedFiles,
meta: Object.assign({}, this.meta, result.meta)
};

let asset = new Asset(opts);

if (result.dependencies) {
for (let dep of result.dependencies) {
asset.addDependency(dep);
}
}

if (result.connectedFiles) {
for (let file of result.connectedFiles) {
asset.addConnectedFile(file);
}
}

return asset;
}

async getOutput() {
return this.output;
}

async getConfig(filePaths: Array<FilePath>) {
return config.load(filePaths);
}

async getPackage() {
return {
name: 'foo',
version: '1.2.3'
};
}
}

function mergeEnvironment(a: Environment, b: ?Environment): Environment {
return Object.assign({}, a, b);
}
21 changes: 11 additions & 10 deletions packages/core/core/src/AssetGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
} from '@parcel/types';
import path from 'path';
import md5 from '@parcel/utils/md5';
import createDependency from './createDependency';

export const nodeFromRootDir = (rootDir: string) => ({
id: rootDir,
Expand All @@ -21,9 +22,7 @@ export const nodeFromRootDir = (rootDir: string) => ({
});

export const nodeFromDep = (dep: Dependency) => ({
id: md5(
`${dep.sourcePath}:${dep.moduleSpecifier}:${JSON.stringify(dep.env)}`
),
id: dep.id,
type: 'dependency',
value: dep
});
Expand Down Expand Up @@ -104,11 +103,15 @@ export default class AssetGraph extends Graph {
let depNodes = [];
for (let entry of entries) {
for (let target of targets) {
let node = nodeFromDep({
sourcePath: path.resolve(rootDir, 'index'),
moduleSpecifier: entry,
env: target.env
});
let node = nodeFromDep(
createDependency(
{
moduleSpecifier: entry,
env: target.env
},
path.resolve(rootDir, 'index')
)
);

depNodes.push(node);
}
Expand Down Expand Up @@ -182,9 +185,7 @@ export default class AssetGraph extends Graph {
let removedFiles = getFilesFromGraph(removed);

for (let assetNode of assetNodes) {
// TODO: dep should already have sourcePath
let depNodes = assetNode.value.dependencies.map(dep => {
dep.sourcePath = req.filePath;
return nodeFromDep(dep);
});
let {removed, added} = this.replaceNodesConnectedTo(assetNode, depNodes);
Expand Down
5 changes: 2 additions & 3 deletions packages/core/core/src/Graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,8 @@ export default class Graph {

edgesToRemove = edgesToRemove.filter(edge => edge.to !== toNode.id);

let edge = edgesBefore.find(edge => edge.to === toNode.id);
if (!edge) {
edge = {from: fromNode.id, to: toNode.id};
let edge = {from: fromNode.id, to: toNode.id};
if (!this.hasEdge(edge)) {
this.addEdge(edge);
added.addEdge(edge);
}
Expand Down
Loading