const parseJson = require('parse-json');
|
const { cachePrefix } = require('.');
|
|
class ParityRoot {
|
constructor() {
|
this.children = [];
|
}
|
|
add(name) {
|
const bits = new ParityCache(name);
|
this.children.push(bits);
|
return bits;
|
}
|
|
verify() {
|
const firstChild = this.children[0];
|
if (!this.children.some(child => child.root)) {
|
return true;
|
}
|
for (const child of this.children) {
|
if (!child.verify()) {
|
this.reason = {
|
cache: child,
|
cacheName: child.name,
|
cacheReason: child.reason,
|
message: `Cache ${child.name} is not complete. ${
|
child.reason.message
|
}`,
|
};
|
return false;
|
}
|
if (child !== firstChild && child.root.token !== firstChild.root.token) {
|
this.reason = {
|
firstCache: firstChild,
|
firstCacheName: firstChild.name,
|
firstCacheReason: firstChild.reason,
|
secondCache: child,
|
secondCacheName: child.name,
|
secondCacheReason: child.reason,
|
|
message: `Cache ${firstChild.name} and ${child.name} disagree.`,
|
};
|
return false;
|
}
|
}
|
return true;
|
}
|
}
|
|
class ParityCache {
|
constructor(name) {
|
this.name = name;
|
this.root = null;
|
this.bits = {};
|
|
this.reason = null;
|
}
|
|
add(_token) {
|
const token = ParityToken.fromJson(_token);
|
if (token.isRoot) {
|
this.root = token;
|
}
|
this.bits[token.id] = token;
|
}
|
|
verify() {
|
if (this.root === null) {
|
this.reason = {
|
message: 'Root compilation not found.',
|
};
|
return false;
|
}
|
|
for (const id of this.root.ids) {
|
if (typeof this.bits[id] === 'undefined') {
|
this.reason = {
|
message: `Compilation '${id}' not found.`,
|
};
|
return false;
|
} else if (this.root.token !== this.bits[id].token) {
|
this.reason = {
|
message: `Root and '${id}' compilation disagree.`,
|
};
|
return false;
|
}
|
}
|
|
return true;
|
}
|
}
|
|
const createParityToken = (id, ids = null) => {
|
const token = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c =>
|
c === 'x'
|
? ((Math.random() * 16) | 0).toString(16)
|
: (((Math.random() * 4) | 0) + 8).toString(16),
|
);
|
|
return new ParityToken(id, token, ids);
|
};
|
|
class ParityToken {
|
constructor(id, token, ids = null) {
|
this.id = id;
|
this.token = token;
|
|
this.isRoot = ids !== null;
|
this.ids = ids;
|
}
|
|
static fromCompilation(compilation) {
|
let parentCompilation = compilation;
|
while (parentCompilation.compiler.parentCompilation) {
|
parentCompilation = parentCompilation.compiler.parentCompilation;
|
}
|
|
if (!parentCompilation.__hardSource_parityToken) {
|
parentCompilation.__hardSource_parityToken = createParityToken(
|
cachePrefix(parentCompilation),
|
[],
|
);
|
}
|
|
if (compilation !== parentCompilation) {
|
return parentCompilation.__hardSource_parityToken.createChild(
|
cachePrefix(compilation),
|
);
|
}
|
return parentCompilation.__hardSource_parityToken;
|
}
|
|
static fromJson(json) {
|
return new ParityToken(json.id, json.token, json.ids);
|
}
|
|
createChild(id) {
|
this.ids.push(id);
|
|
return new ParityToken(id, this.token);
|
}
|
|
toJSON() {
|
return {
|
type: 'CacheParityToken',
|
id: this.id,
|
ids: this.ids,
|
token: this.token,
|
};
|
}
|
}
|
|
const parseIfString = item => {
|
if (typeof item === 'string') {
|
return parseJson(item);
|
}
|
return item;
|
};
|
|
const parityCacheFromCache = (name, parityRoot, cache) => {
|
const parityCache = parityRoot.add(name);
|
if (cache.__hardSource_parityToken_root) {
|
const rootCompilation = parseIfString(cache.__hardSource_parityToken_root);
|
parityCache.add(rootCompilation);
|
rootCompilation.ids.forEach(id => {
|
if (cache[`__hardSource_parityToken_${id}`]) {
|
parityCache.add(parseIfString(cache[`__hardSource_parityToken_${id}`]));
|
}
|
});
|
}
|
};
|
|
const pushParityWriteOps = (compilation, ops) => {
|
if (compilation.compiler.parentCompilation) {
|
ops.push({
|
key: `__hardSource_parityToken_${cachePrefix(compilation)}`,
|
value: JSON.stringify(ParityToken.fromCompilation(compilation)),
|
});
|
} else {
|
ops.push({
|
key: `__hardSource_parityToken_root`,
|
value: JSON.stringify(ParityToken.fromCompilation(compilation)),
|
});
|
}
|
};
|
|
module.exports = {
|
ParityRoot,
|
ParityCache,
|
ParityToken,
|
|
parityCacheFromCache,
|
pushParityWriteOps,
|
};
|