line_push/node_modules/hard-source-webpack-plugin/lib/util/parity.js
2022-07-21 03:28:35 +00:00

195 lines
4.5 KiB
JavaScript

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,
};