1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Moved arrow callback functions to named functions

Separated arrow callback functions into named functions to avoid re-creating
the functions at runtime.
This commit is contained in:
Cyber Gsus 2021-06-10 12:00:40 +02:00
parent a04dff4d10
commit bc32f2d21f

View File

@ -161,47 +161,49 @@ export class ReadWriteProxy {
// Reads the data asynchronously, fails if verify() fails // Reads the data asynchronously, fails if verify() fails
readAsync() { readAsync() {
// Start read request
return (
this.app.storage
.readFileAsync(this.filename)
// Decrypt data (if its encrypted)
// @ts-ignore
.then(rawData => {
if (rawData == null) {
// So, the file has not been found, use default data
return JSON.stringify(compressObject(this.getDefaultData()));
}
if (rawData.startsWith(compressionPrefix)) { /**
const decompressed = decompressX64(rawData.substr(compressionPrefix.length)); * Decompresses raw data through `decompressX64`
if (!decompressed) { * Fails if decompression failed or
// LZ string decompression failure * data is too small.
return Promise.reject("bad-content / decompression-failed"); * @param {string} data
} * @returns {Promise<string>}
if (decompressed.length < 40) { */
// String too short const decompressRaw = data => {
return Promise.reject("bad-content / payload-too-small"); const decompressed = decompressX64(data.substr(compressionPrefix.length));
} if (!decompressed) return Promise.reject("bad-content / decompression-failed");
return Promise.resolve(decompressed);
};
// Compare stored checksum with actual checksum /**
const checksum = decompressed.substring(0, 40); * Verifies the checksum and returns the payload.
const jsonString = decompressed.substr(40); * Fails if the payload is too small to contain the checksum
* or the checksums don't match.
*
* @param {string} data
* @returns {Promise<string>}
*/
const verifyChecksum = data => {
if (data.length < 40) return Promise.reject("bad-content / payload-too-small");
const checksum = data.substr(0, 40);
const payload = data.substr(40);
const saltedPayload = payload + salt;
const desiredChecksum = checksum.startsWith(CRC_PREFIX) ? computeCrc(saltedPayload) : sha1(saltedPayload);
if (desiredChecksum !== checksum) return Promise.reject(`bad-content / checksum-mismatch: ${desiredChecksum} vs ${checksum} `);
return Promise.resolve(payload);
};
const desiredChecksum = checksum.startsWith(CRC_PREFIX) /**
? computeCrc(jsonString + salt) * Tries to parse the JSON data.
: sha1(jsonString + salt); * Logs and fails if the parser failed.
*
if (desiredChecksum !== checksum) { * @param {string} jsonString
// Checksum mismatch * @returns {Promise<any>}
return Promise.reject( */
"bad-content / checksum-mismatch: " + desiredChecksum + " vs " + checksum const tryParseJSON = jsonString => {
);
}
// Parse JSON
try { try {
return JSON.parse(jsonString); const parsedData = JSON.parse(jsonString);
return Promise.resolve(parsedData);
} catch (ex) { } catch (ex) {
logger.error( logger.error(
"Failed to parse file content of", "Failed to parse file content of",
@ -214,88 +216,141 @@ export class ReadWriteProxy {
); );
throw new Error("invalid-serialized-data"); throw new Error("invalid-serialized-data");
} }
};
} /**
* Tries to decompress the data.
* Fails if data is not compressed
* and code is in production.
*
* @param {string} rawData
* @returns {Promise<string>}
*/
const tryDecompress = rawData => {
if (rawData.startsWith(compressionPrefix)) return decompressRaw(rawData);
if (!G_IS_DEV) return Promise.reject("bad-content / missing-compression");
return Promise.resolve(rawData);
};
if (!G_IS_DEV) { /**
return Promise.reject("bad-content / missing-compression"); * Checks for errors during file read.
} * If the file was not found, it will not fail
return rawData; * and instead return default data.
}) *
// Check for errors during read * @param {FILE_NOT_FOUND | string} err
.catch(err => { * @returns {Promise<object>}
*/
const onReadError = err => {
if (err === FILE_NOT_FOUND) { if (err === FILE_NOT_FOUND) {
logger.log("File not found, using default data"); logger.log("File not found, using default data");
// File not found or unreadable, assume default file
return Promise.resolve(this.getDefaultData()); return Promise.resolve(this.getDefaultData());
} }
return Promise.reject(`file-error: ${err}`);
};
return Promise.reject("file-error: " + err); /**
}) * Verifies basic structure of the data
* through `internalVerifyBasicStructure`.
*
* @param {any} contents
* @returns {Promise<any>}
*/
const verifyBasicStructure = contents => {
const verifyResult = this.internalVerifyBasicStructure(contents);
if (verifyResult.isBad()) return Promise.reject(`verify-failed: ${verifyResult.reason}`);
return Promise.resolve(contents);
};
/**
* Checks the version and migrates if required.
* Fails if the version required for the data is newer
* or migration failed.
*
* @param {any} contents
* @returns {Promise<any>}
*/
const checkVersionAndMigrate = contents => {
const currentVersion = this.getCurrentVersion();
if (contents.version > currentVersion) return Promise.reject("stored-data-is-newer");
if (contents.version < currentVersion) {
logger.log(
`Trying to migrate data object from version ${contents.version} to ${currentVersion}`
);
const migrationResult = this.migrate(contents); // modify in place
if (migrationResult.isBad()) {
return Promise.reject(`migration-failed: ${migrationResult.reason}`);
}
}
return Promise.resolve(contents);
}
/**
* Verifies contents once they've been version-matched
* and migrated if needed, through `internalVerifyEntry`.
* Fails if such method fails.
*
* @param {any} contents
* @returns {Promise<any>}
*/
const verifyEntry = contents => {
const verifyResult = this.internalVerifyEntry(contents);
if (!verifyResult.result) {
logger.error(
`Read invalid data from ${this.filename}, reason: ${verifyResult.reason}, contents: ${contents}`
);
return Promise.reject(`invalid-data: ${verifyResult.reason}`);
}
return Promise.resolve(contents);
};
/**
* Stores the verified data.
*
* @param {any} contents
* @returns {any}
*/
const storeContents = contents => {
this.currentData = contents;
logger.log("📄 Read data with version", this.currentData.version, "from", this.filename);
return contents;
};
/**
* Generic handler for any failure.
*
* @param {any} err
* @returns {Promise<void>}
*/
const genericOnFail = err => Promise.reject(`Failed to read ${this.filename}: ${err}`);
// Start read request
return (
this.app.storage
.readFileAsync(this.filename)
// Decrypt data (if its encrypted)
// @ts-ignore
.then(rawData => tryDecompress(rawData).then(verifyChecksum).then(tryParseJSON))
// Check for errors during read
.catch(onReadError)
// Decompress // Decompress
.then(decompressObject) .then(decompressObject)
// Verify basic structure // Verify basic structure
.then(contents => { .then(verifyBasicStructure)
const result = this.internalVerifyBasicStructure(contents);
if (!result.isGood()) {
return Promise.reject("verify-failed: " + result.reason);
}
return contents;
})
// Check version and migrate if required // Check version and migrate if required
.then(contents => { .then(checkVersionAndMigrate)
if (contents.version > this.getCurrentVersion()) {
return Promise.reject("stored-data-is-newer");
}
if (contents.version < this.getCurrentVersion()) {
logger.log(
"Trying to migrate data object from version",
contents.version,
"to",
this.getCurrentVersion()
);
const migrationResult = this.migrate(contents); // modify in place
if (migrationResult.isBad()) {
return Promise.reject("migration-failed: " + migrationResult.reason);
}
}
return contents;
})
// Verify // Verify
.then(contents => { .then(verifyEntry)
const verifyResult = this.internalVerifyEntry(contents);
if (!verifyResult.result) {
logger.error(
"Read invalid data from",
this.filename,
"reason:",
verifyResult.reason,
"contents:",
contents
);
return Promise.reject("invalid-data: " + verifyResult.reason);
}
return contents;
})
// Store // Store
.then(contents => { .then(storeContents)
this.currentData = contents;
logger.log("📄 Read data with version", this.currentData.version, "from", this.filename);
return contents;
})
// Catchall // Catchall
.catch(err => { .catch(genericOnFail)
return Promise.reject("Failed to read " + this.filename + ": " + err);
})
); );
} }