|
|
|
"use strict";
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
|
value: true
|
|
|
|
});
|
|
|
|
exports.nodeFromDep = nodeFromDep;
|
|
|
|
exports.nodeFromAssetGroup = nodeFromAssetGroup;
|
|
|
|
exports.nodeFromAsset = nodeFromAsset;
|
|
|
|
exports.nodeFromEntrySpecifier = nodeFromEntrySpecifier;
|
|
|
|
exports.nodeFromEntryFile = nodeFromEntryFile;
|
|
|
|
exports.default = void 0;
|
|
|
|
|
|
|
|
function _assert() {
|
|
|
|
const data = _interopRequireDefault(require("assert"));
|
|
|
|
|
|
|
|
_assert = function () {
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash() {
|
|
|
|
const data = require("@parcel/hash");
|
|
|
|
|
|
|
|
_hash = function () {
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _utils() {
|
|
|
|
const data = require("@parcel/utils");
|
|
|
|
|
|
|
|
_utils = function () {
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _nullthrows() {
|
|
|
|
const data = _interopRequireDefault(require("nullthrows"));
|
|
|
|
|
|
|
|
_nullthrows = function () {
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _graph() {
|
|
|
|
const data = require("@parcel/graph");
|
|
|
|
|
|
|
|
_graph = function () {
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
var _Dependency = require("./Dependency");
|
|
|
|
|
|
|
|
var _projectPath = require("./projectPath");
|
|
|
|
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
|
|
|
|
function nodeFromDep(dep) {
|
|
|
|
return {
|
|
|
|
id: dep.id,
|
|
|
|
type: 'dependency',
|
|
|
|
value: dep,
|
|
|
|
deferred: false,
|
|
|
|
excluded: false,
|
|
|
|
usedSymbolsDown: new Set(),
|
|
|
|
usedSymbolsUp: new Set(),
|
|
|
|
usedSymbolsDownDirty: true,
|
|
|
|
usedSymbolsUpDirtyDown: true,
|
|
|
|
usedSymbolsUpDirtyUp: true
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function nodeFromAssetGroup(assetGroup) {
|
|
|
|
var _assetGroup$code, _assetGroup$pipeline, _assetGroup$query;
|
|
|
|
|
|
|
|
return {
|
|
|
|
id: (0, _hash().hashString)((0, _projectPath.fromProjectPathRelative)(assetGroup.filePath) + assetGroup.env.id + String(assetGroup.isSource) + String(assetGroup.sideEffects) + ((_assetGroup$code = assetGroup.code) !== null && _assetGroup$code !== void 0 ? _assetGroup$code : '') + ':' + ((_assetGroup$pipeline = assetGroup.pipeline) !== null && _assetGroup$pipeline !== void 0 ? _assetGroup$pipeline : '') + ':' + ((_assetGroup$query = assetGroup.query) !== null && _assetGroup$query !== void 0 ? _assetGroup$query : '')),
|
|
|
|
type: 'asset_group',
|
|
|
|
value: assetGroup,
|
|
|
|
usedSymbolsDownDirty: true
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function nodeFromAsset(asset) {
|
|
|
|
return {
|
|
|
|
id: asset.id,
|
|
|
|
type: 'asset',
|
|
|
|
value: asset,
|
|
|
|
usedSymbols: new Set(),
|
|
|
|
usedSymbolsDownDirty: true,
|
|
|
|
usedSymbolsUpDirty: true
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function nodeFromEntrySpecifier(entry) {
|
|
|
|
return {
|
|
|
|
id: 'entry_specifier:' + (0, _projectPath.fromProjectPathRelative)(entry),
|
|
|
|
type: 'entry_specifier',
|
|
|
|
value: entry
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function nodeFromEntryFile(entry) {
|
|
|
|
return {
|
|
|
|
id: 'entry_file:' + (0, _utils().hashObject)(entry),
|
|
|
|
type: 'entry_file',
|
|
|
|
value: entry
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
class AssetGraph extends _graph().ContentGraph {
|
|
|
|
constructor(opts) {
|
|
|
|
if (opts) {
|
|
|
|
let {
|
|
|
|
hash,
|
|
|
|
symbolPropagationRan,
|
|
|
|
...rest
|
|
|
|
} = opts;
|
|
|
|
super(rest);
|
|
|
|
this.hash = hash;
|
|
|
|
this.symbolPropagationRan = symbolPropagationRan;
|
|
|
|
} else {
|
|
|
|
super();
|
|
|
|
this.setRootNodeId(this.addNode({
|
|
|
|
id: '@@root',
|
|
|
|
type: 'root',
|
|
|
|
value: null
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
this.envCache = new Map();
|
|
|
|
this.symbolPropagationRan = false;
|
|
|
|
} // $FlowFixMe[prop-missing]
|
|
|
|
|
|
|
|
|
|
|
|
static deserialize(opts) {
|
|
|
|
return new AssetGraph(opts);
|
|
|
|
} // $FlowFixMe[prop-missing]
|
|
|
|
|
|
|
|
|
|
|
|
serialize() {
|
|
|
|
return { ...super.serialize(),
|
|
|
|
hash: this.hash,
|
|
|
|
symbolPropagationRan: this.symbolPropagationRan
|
|
|
|
};
|
|
|
|
} // Deduplicates Environments by making them referentially equal
|
|
|
|
|
|
|
|
|
|
|
|
normalizeEnvironment(input) {
|
|
|
|
let {
|
|
|
|
id,
|
|
|
|
context
|
|
|
|
} = input.env;
|
|
|
|
let idAndContext = `${id}-${context}`;
|
|
|
|
let env = this.envCache.get(idAndContext);
|
|
|
|
|
|
|
|
if (env) {
|
|
|
|
input.env = env;
|
|
|
|
} else {
|
|
|
|
this.envCache.set(idAndContext, input.env);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setRootConnections({
|
|
|
|
entries,
|
|
|
|
assetGroups
|
|
|
|
}) {
|
|
|
|
let nodes = [];
|
|
|
|
|
|
|
|
if (entries) {
|
|
|
|
for (let entry of entries) {
|
|
|
|
let node = nodeFromEntrySpecifier(entry);
|
|
|
|
nodes.push(node);
|
|
|
|
}
|
|
|
|
} else if (assetGroups) {
|
|
|
|
nodes.push(...assetGroups.map(assetGroup => nodeFromAssetGroup(assetGroup)));
|
|
|
|
}
|
|
|
|
|
|
|
|
this.replaceNodeIdsConnectedTo((0, _nullthrows().default)(this.rootNodeId), nodes.map(node => this.addNode(node)));
|
|
|
|
}
|
|
|
|
|
|
|
|
addNode(node) {
|
|
|
|
this.hash = null;
|
|
|
|
let existing = this.getNodeByContentKey(node.id);
|
|
|
|
|
|
|
|
if (existing != null) {
|
|
|
|
(0, _assert().default)(existing.type === node.type); // $FlowFixMe[incompatible-type] Checked above
|
|
|
|
// $FlowFixMe[prop-missing]
|
|
|
|
|
|
|
|
existing.value = node.value;
|
|
|
|
let existingId = this.getNodeIdByContentKey(node.id);
|
|
|
|
this.updateNode(existingId, existing);
|
|
|
|
return existingId;
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.addNodeByContentKey(node.id, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
removeNode(nodeId) {
|
|
|
|
this.hash = null;
|
|
|
|
this.onNodeRemoved && this.onNodeRemoved(nodeId); // This needs to mark all connected nodes that doesn't become orphaned
|
|
|
|
// due to replaceNodesConnectedTo to make sure that the symbols of
|
|
|
|
// nodes from which at least one parent was removed are updated.
|
|
|
|
|
|
|
|
let node = (0, _nullthrows().default)(this.getNode(nodeId));
|
|
|
|
|
|
|
|
if (this.isOrphanedNode(nodeId) && node.type === 'dependency') {
|
|
|
|
let children = this.getNodeIdsConnectedFrom(nodeId).map(id => (0, _nullthrows().default)(this.getNode(id)));
|
|
|
|
|
|
|
|
for (let n of children) {
|
|
|
|
(0, _assert().default)(n.type === 'asset_group' || n.type === 'asset');
|
|
|
|
n.usedSymbolsDownDirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.removeNode(nodeId);
|
|
|
|
}
|
|
|
|
|
|
|
|
resolveEntry(entry, resolved, correspondingRequest) {
|
|
|
|
let entrySpecifierNodeId = this.getNodeIdByContentKey(nodeFromEntrySpecifier(entry).id);
|
|
|
|
let entrySpecifierNode = (0, _nullthrows().default)(this.getNode(entrySpecifierNodeId));
|
|
|
|
(0, _assert().default)(entrySpecifierNode.type === 'entry_specifier');
|
|
|
|
entrySpecifierNode.correspondingRequest = correspondingRequest;
|
|
|
|
this.replaceNodeIdsConnectedTo(entrySpecifierNodeId, resolved.map(file => this.addNode(nodeFromEntryFile(file))));
|
|
|
|
}
|
|
|
|
|
|
|
|
resolveTargets(entry, targets, correspondingRequest) {
|
|
|
|
let depNodes = targets.map(target => {
|
|
|
|
let node = nodeFromDep( // The passed project path is ignored in this case, because there is no `loc`
|
|
|
|
(0, _Dependency.createDependency)('', {
|
|
|
|
specifier: (0, _projectPath.fromProjectPathRelative)(entry.filePath),
|
|
|
|
specifierType: 'esm',
|
|
|
|
// ???
|
|
|
|
pipeline: target.pipeline,
|
|
|
|
target: target,
|
|
|
|
env: target.env,
|
|
|
|
isEntry: true,
|
|
|
|
needsStableName: true,
|
|
|
|
symbols: target.env.isLibrary ? new Map([['*', {
|
|
|
|
local: '*',
|
|
|
|
isWeak: true,
|
|
|
|
loc: null
|
|
|
|
}]]) : undefined
|
|
|
|
}));
|
|
|
|
|
|
|
|
if (node.value.env.isLibrary) {
|
|
|
|
// in library mode, all of the entry's symbols are "used"
|
|
|
|
node.usedSymbolsDown.add('*');
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
});
|
|
|
|
let entryNodeId = this.getNodeIdByContentKey(nodeFromEntryFile(entry).id);
|
|
|
|
let entryNode = (0, _nullthrows().default)(this.getNode(entryNodeId));
|
|
|
|
(0, _assert().default)(entryNode.type === 'entry_file');
|
|
|
|
entryNode.correspondingRequest = correspondingRequest;
|
|
|
|
this.replaceNodeIdsConnectedTo(entryNodeId, depNodes.map(node => this.addNode(node)));
|
|
|
|
}
|
|
|
|
|
|
|
|
resolveDependency(dependency, assetGroup, correspondingRequest) {
|
|
|
|
let depNodeId = this.getNodeIdByContentKey(dependency.id);
|
|
|
|
let depNode = (0, _nullthrows().default)(this.getNode(depNodeId));
|
|
|
|
(0, _assert().default)(depNode.type === 'dependency');
|
|
|
|
depNode.correspondingRequest = correspondingRequest;
|
|
|
|
|
|
|
|
if (!assetGroup) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let assetGroupNode = nodeFromAssetGroup(assetGroup);
|
|
|
|
let existing = this.getNodeByContentKey(assetGroupNode.id);
|
|
|
|
|
|
|
|
if (existing != null) {
|
|
|
|
(0, _assert().default)(existing.type === 'asset_group');
|
|
|
|
assetGroupNode.value.canDefer = assetGroupNode.value.canDefer && existing.value.canDefer;
|
|
|
|
}
|
|
|
|
|
|
|
|
let assetGroupNodeId = this.addNode(assetGroupNode);
|
|
|
|
this.replaceNodeIdsConnectedTo(this.getNodeIdByContentKey(dependency.id), [assetGroupNodeId]);
|
|
|
|
this.replaceNodeIdsConnectedTo(depNodeId, [assetGroupNodeId]);
|
|
|
|
}
|
|
|
|
|
|
|
|
shouldVisitChild(nodeId, childNodeId) {
|
|
|
|
let node = (0, _nullthrows().default)(this.getNode(nodeId));
|
|
|
|
let childNode = (0, _nullthrows().default)(this.getNode(childNodeId));
|
|
|
|
|
|
|
|
if (node.type !== 'dependency' || childNode.type !== 'asset_group' || childNode.deferred === false) {
|
|
|
|
return true;
|
|
|
|
} // Node types are proved above
|
|
|
|
|
|
|
|
|
|
|
|
let dependencyNode = node;
|
|
|
|
let assetGroupNode = childNode;
|
|
|
|
let {
|
|
|
|
sideEffects,
|
|
|
|
canDefer = true
|
|
|
|
} = assetGroupNode.value;
|
|
|
|
let dependency = dependencyNode.value;
|
|
|
|
let dependencyPreviouslyDeferred = dependencyNode.hasDeferred;
|
|
|
|
let assetGroupPreviouslyDeferred = assetGroupNode.deferred;
|
|
|
|
let defer = this.shouldDeferDependency(dependency, sideEffects, canDefer);
|
|
|
|
dependencyNode.hasDeferred = defer;
|
|
|
|
assetGroupNode.deferred = defer;
|
|
|
|
|
|
|
|
if (!dependencyPreviouslyDeferred && defer) {
|
|
|
|
this.markParentsWithHasDeferred(nodeId);
|
|
|
|
} else if (assetGroupPreviouslyDeferred && !defer) {
|
|
|
|
this.unmarkParentsWithHasDeferred(childNodeId);
|
|
|
|
}
|
|
|
|
|
|
|
|
return !defer;
|
|
|
|
} // Dependency: mark parent Asset <- AssetGroup with hasDeferred true
|
|
|
|
|
|
|
|
|
|
|
|
markParentsWithHasDeferred(nodeId) {
|
|
|
|
this.traverseAncestors(nodeId, (traversedNodeId, _, actions) => {
|
|
|
|
let traversedNode = (0, _nullthrows().default)(this.getNode(traversedNodeId));
|
|
|
|
|
|
|
|
if (traversedNode.type === 'asset') {
|
|
|
|
traversedNode.hasDeferred = true;
|
|
|
|
} else if (traversedNode.type === 'asset_group') {
|
|
|
|
traversedNode.hasDeferred = true;
|
|
|
|
actions.skipChildren();
|
|
|
|
} else if (nodeId !== traversedNodeId) {
|
|
|
|
actions.skipChildren();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} // AssetGroup: update hasDeferred of all parent Dependency <- Asset <- AssetGroup
|
|
|
|
|
|
|
|
|
|
|
|
unmarkParentsWithHasDeferred(nodeId) {
|
|
|
|
this.traverseAncestors(nodeId, (traversedNodeId, ctx, actions) => {
|
|
|
|
let traversedNode = (0, _nullthrows().default)(this.getNode(traversedNodeId));
|
|
|
|
|
|
|
|
if (traversedNode.type === 'asset') {
|
|
|
|
let hasDeferred = this.getNodeIdsConnectedFrom(traversedNodeId).some(childNodeId => {
|
|
|
|
let childNode = (0, _nullthrows().default)(this.getNode(childNodeId));
|
|
|
|
return childNode.hasDeferred == null ? false : childNode.hasDeferred;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!hasDeferred) {
|
|
|
|
delete traversedNode.hasDeferred;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
hasDeferred
|
|
|
|
};
|
|
|
|
} else if (traversedNode.type === 'asset_group' && nodeId !== traversedNodeId) {
|
|
|
|
if (!(ctx !== null && ctx !== void 0 && ctx.hasDeferred)) {
|
|
|
|
delete traversedNode.hasDeferred;
|
|
|
|
}
|
|
|
|
|
|
|
|
actions.skipChildren();
|
|
|
|
} else if (traversedNode.type === 'dependency') {
|
|
|
|
traversedNode.hasDeferred = false;
|
|
|
|
} else if (nodeId !== traversedNodeId) {
|
|
|
|
actions.skipChildren();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} // Defer transforming this dependency if it is marked as weak, there are no side effects,
|
|
|
|
// no re-exported symbols are used by ancestor dependencies and the re-exporting asset isn't
|
|
|
|
// using a wildcard and isn't an entry (in library mode).
|
|
|
|
// This helps with performance building large libraries like `lodash-es`, which re-exports
|
|
|
|
// a huge number of functions since we can avoid even transforming the files that aren't used.
|
|
|
|
|
|
|
|
|
|
|
|
shouldDeferDependency(dependency, sideEffects, canDefer) {
|
|
|
|
let defer = false;
|
|
|
|
let dependencySymbols = dependency.symbols;
|
|
|
|
|
|
|
|
if (dependencySymbols && [...dependencySymbols].every(([, {
|
|
|
|
isWeak
|
|
|
|
}]) => isWeak) && sideEffects === false && canDefer && !dependencySymbols.has('*')) {
|
|
|
|
let depNodeId = this.getNodeIdByContentKey(dependency.id);
|
|
|
|
let depNode = this.getNode(depNodeId);
|
|
|
|
(0, _assert().default)(depNode);
|
|
|
|
let assets = this.getNodeIdsConnectedTo(depNodeId);
|
|
|
|
let symbols = new Map([...dependencySymbols].map(([key, val]) => [val.local, key]));
|
|
|
|
(0, _assert().default)(assets.length === 1);
|
|
|
|
let firstAsset = (0, _nullthrows().default)(this.getNode(assets[0]));
|
|
|
|
(0, _assert().default)(firstAsset.type === 'asset');
|
|
|
|
let resolvedAsset = firstAsset.value;
|
|
|
|
let deps = this.getIncomingDependencies(resolvedAsset);
|
|
|
|
defer = deps.every(d => d.symbols && !(d.env.isLibrary && d.isEntry) && !d.symbols.has('*') && ![...d.symbols.keys()].some(symbol => {
|
|
|
|
var _resolvedAsset$symbol, _resolvedAsset$symbol2;
|
|
|
|
|
|
|
|
if (!resolvedAsset.symbols) return true;
|
|
|
|
let assetSymbol = (_resolvedAsset$symbol = resolvedAsset.symbols) === null || _resolvedAsset$symbol === void 0 ? void 0 : (_resolvedAsset$symbol2 = _resolvedAsset$symbol.get(symbol)) === null || _resolvedAsset$symbol2 === void 0 ? void 0 : _resolvedAsset$symbol2.local;
|
|
|
|
return assetSymbol != null && symbols.has(assetSymbol);
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
return defer;
|
|
|
|
}
|
|
|
|
|
|
|
|
resolveAssetGroup(assetGroup, assets, correspondingRequest) {
|
|
|
|
this.normalizeEnvironment(assetGroup);
|
|
|
|
let assetGroupNode = nodeFromAssetGroup(assetGroup);
|
|
|
|
assetGroupNode = this.getNodeByContentKey(assetGroupNode.id);
|
|
|
|
|
|
|
|
if (!assetGroupNode) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
(0, _assert().default)(assetGroupNode.type === 'asset_group');
|
|
|
|
assetGroupNode.correspondingRequest = correspondingRequest;
|
|
|
|
let assetsByKey = new Map();
|
|
|
|
|
|
|
|
for (let asset of assets) {
|
|
|
|
if (asset.uniqueKey != null) {
|
|
|
|
assetsByKey.set(asset.uniqueKey, asset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let dependentAssetKeys = new Set();
|
|
|
|
|
|
|
|
for (let asset of assets) {
|
|
|
|
for (let dep of asset.dependencies.values()) {
|
|
|
|
if (assetsByKey.has(dep.specifier)) {
|
|
|
|
dependentAssetKeys.add(dep.specifier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let assetObjects = [];
|
|
|
|
let assetNodeIds = [];
|
|
|
|
|
|
|
|
for (let asset of assets) {
|
|
|
|
this.normalizeEnvironment(asset);
|
|
|
|
let isDirect = !dependentAssetKeys.has(asset.uniqueKey);
|
|
|
|
let dependentAssets = [];
|
|
|
|
|
|
|
|
for (let dep of asset.dependencies.values()) {
|
|
|
|
let dependentAsset = assetsByKey.get(dep.specifier);
|
|
|
|
|
|
|
|
if (dependentAsset) {
|
|
|
|
dependentAssets.push(dependentAsset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let id = this.addNode(nodeFromAsset(asset));
|
|
|
|
assetObjects.push({
|
|
|
|
assetNodeId: id,
|
|
|
|
dependentAssets
|
|
|
|
});
|
|
|
|
|
|
|
|
if (isDirect) {
|
|
|
|
assetNodeIds.push(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.replaceNodeIdsConnectedTo(this.getNodeIdByContentKey(assetGroupNode.id), assetNodeIds);
|
|
|
|
|
|
|
|
for (let {
|
|
|
|
assetNodeId,
|
|
|
|
dependentAssets
|
|
|
|
} of assetObjects) {
|
|
|
|
// replaceNodesConnectedTo has merged the value into the existing node, retrieve
|
|
|
|
// the actual current node.
|
|
|
|
let assetNode = (0, _nullthrows().default)(this.getNode(assetNodeId));
|
|
|
|
(0, _assert().default)(assetNode.type === 'asset');
|
|
|
|
this.resolveAsset(assetNode, dependentAssets);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resolveAsset(assetNode, dependentAssets) {
|
|
|
|
let depNodeIds = [];
|
|
|
|
let depNodesWithAssets = [];
|
|
|
|
|
|
|
|
for (let dep of assetNode.value.dependencies.values()) {
|
|
|
|
this.normalizeEnvironment(dep);
|
|
|
|
let depNode = nodeFromDep(dep);
|
|
|
|
let existing = this.getNodeByContentKey(depNode.id);
|
|
|
|
|
|
|
|
if ((existing === null || existing === void 0 ? void 0 : existing.type) === 'dependency' && existing.value.resolverMeta != null) {
|
|
|
|
depNode.value.meta = { ...depNode.value.meta,
|
|
|
|
...existing.value.resolverMeta
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
let dependentAsset = dependentAssets.find(a => a.uniqueKey === dep.specifier);
|
|
|
|
|
|
|
|
if (dependentAsset) {
|
|
|
|
depNode.complete = true;
|
|
|
|
depNodesWithAssets.push([depNode, nodeFromAsset(dependentAsset)]);
|
|
|
|
}
|
|
|
|
|
|
|
|
depNode.value.sourceAssetType = assetNode.value.type;
|
|
|
|
depNodeIds.push(this.addNode(depNode));
|
|
|
|
}
|
|
|
|
|
|
|
|
assetNode.usedSymbolsDownDirty = true;
|
|
|
|
this.replaceNodeIdsConnectedTo(this.getNodeIdByContentKey(assetNode.id), depNodeIds);
|
|
|
|
|
|
|
|
for (let [depNode, dependentAssetNode] of depNodesWithAssets) {
|
|
|
|
let depAssetNodeId = this.addNode(dependentAssetNode);
|
|
|
|
this.replaceNodeIdsConnectedTo(this.getNodeIdByContentKey(depNode.id), [depAssetNodeId]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getIncomingDependencies(asset) {
|
|
|
|
let nodeId = this._contentKeyToNodeId.get(asset.id);
|
|
|
|
|
|
|
|
if (!nodeId) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
let assetGroupIds = this.getNodeIdsConnectedTo(nodeId);
|
|
|
|
let dependencies = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < assetGroupIds.length; i++) {
|
|
|
|
let assetGroupId = assetGroupIds[i]; // Sometimes assets are connected directly to dependencies
|
|
|
|
// rather than through an asset group. This happens due to
|
|
|
|
// inline dependencies on assets via uniqueKey. See resolveAsset.
|
|
|
|
|
|
|
|
let node = this.getNode(assetGroupId);
|
|
|
|
|
|
|
|
if ((node === null || node === void 0 ? void 0 : node.type) === 'dependency') {
|
|
|
|
dependencies.push(node.value);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let assetIds = this.getNodeIdsConnectedTo(assetGroupId);
|
|
|
|
|
|
|
|
for (let j = 0; j < assetIds.length; j++) {
|
|
|
|
let node = this.getNode(assetIds[j]);
|
|
|
|
|
|
|
|
if (!node || node.type !== 'dependency') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dependencies.push(node.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dependencies;
|
|
|
|
}
|
|
|
|
|
|
|
|
traverseAssets(visit, startNodeId) {
|
|
|
|
return this.filteredTraverse(nodeId => {
|
|
|
|
let node = (0, _nullthrows().default)(this.getNode(nodeId));
|
|
|
|
return node.type === 'asset' ? node.value : null;
|
|
|
|
}, visit, startNodeId);
|
|
|
|
}
|
|
|
|
|
|
|
|
getEntryAssetGroupNodes() {
|
|
|
|
let entryNodes = [];
|
|
|
|
this.traverse((nodeId, _, actions) => {
|
|
|
|
let node = (0, _nullthrows().default)(this.getNode(nodeId));
|
|
|
|
|
|
|
|
if (node.type === 'asset_group') {
|
|
|
|
entryNodes.push(node);
|
|
|
|
actions.skipChildren();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return entryNodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
getEntryAssets() {
|
|
|
|
let entries = [];
|
|
|
|
this.traverseAssets((asset, ctx, traversal) => {
|
|
|
|
entries.push(asset);
|
|
|
|
traversal.skipChildren();
|
|
|
|
});
|
|
|
|
return entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
getHash() {
|
|
|
|
if (this.hash != null) {
|
|
|
|
return this.hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
let hash = new (_hash().Hash)(); // TODO: sort??
|
|
|
|
|
|
|
|
this.traverse(nodeId => {
|
|
|
|
let node = (0, _nullthrows().default)(this.getNode(nodeId));
|
|
|
|
|
|
|
|
if (node.type === 'asset') {
|
|
|
|
hash.writeString((0, _nullthrows().default)(node.value.outputHash));
|
|
|
|
} else if (node.type === 'dependency' && node.value.target) {
|
|
|
|
hash.writeString(JSON.stringify(node.value.target));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.hash = hash.finish();
|
|
|
|
return this.hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.default = AssetGraph;
|