mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-30 17:40:53 -07:00
fix(electron): allow patch downgrades in the runtime guard
- Compare only major and minor versions, so same-minor patch downgrades are allowed - Keep blocking Electron minor and major downgrades before Yomitan storage loads - Add tests for patch downgrades, minor downgrades and Electron 42 reopening a 43 profile - Document the new rules and the SubMiner-dev profile workaround in troubleshooting
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
type: fixed
|
type: fixed
|
||||||
area: dictionary
|
area: dictionary
|
||||||
|
|
||||||
- Upgraded the desktop runtime to Electron 43.7.2 and added profile guards that block unsupported runtimes and Electron downgrades before Yomitan storage is loaded.
|
- Upgraded the desktop runtime to Electron 43.7.2 and added profile guards that block unsupported runtimes and Electron major or minor downgrades before Yomitan storage is loaded. Patch downgrades within the same major and minor version are allowed.
|
||||||
- Development launches now use a separate `SubMiner-dev` profile unless production-profile access is explicitly requested.
|
- Development launches now use a separate `SubMiner-dev` profile unless production-profile access is explicitly requested.
|
||||||
- Automatic character-dictionary changes now stop when a previously non-empty Yomitan profile suddenly reports zero dictionaries.
|
- Automatic character-dictionary changes now stop when a previously non-empty Yomitan profile suddenly reports zero dictionaries.
|
||||||
|
|||||||
@@ -69,7 +69,9 @@ Word boundaries come from Yomitan's parser. Some splits will be wrong, since Jap
|
|||||||
|
|
||||||
## "Electron downgrade blocked" or "Unsupported Electron runtime"
|
## "Electron downgrade blocked" or "Unsupported Electron runtime"
|
||||||
|
|
||||||
SubMiner refuses to load Yomitan storage when the current Electron major does not match the app build, or when the profile was previously opened by a newer Electron version. Launch the packaged app or use the repository's `bun run dev` command. Do not delete the runtime safety record to force an older Electron version to open the profile.
|
SubMiner refuses to load Yomitan storage when the current Electron major does not match the app build, or when the profile was previously opened by a newer Electron major or minor version. Patch downgrades within the same major and minor version are allowed, such as `43.7.3` to `43.7.2`. Downgrades from `43.7.x` to `43.6.x`, or from Electron 43 to 42, are blocked. Launch the packaged app or use the repository's `bun run dev` command. Do not delete the runtime safety record to force an older major or minor version to open the profile.
|
||||||
|
|
||||||
|
Older SubMiner builds without this guard cannot enforce the safety record. When testing Electron 43 before returning to an older Electron 42 build, use the separate `SubMiner-dev` profile described in [development](/development#run-locally) so the older build never opens the upgraded profile.
|
||||||
|
|
||||||
## "Yomitan reported zero dictionaries after previously reporting ..."
|
## "Yomitan reported zero dictionaries after previously reporting ..."
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ test('runtime guard blocks a profile downgrade before rewriting its safety recor
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('runtime guard blocks a downgrade within the supported Electron major', () => {
|
test('runtime guard blocks a minor downgrade even when the patch is higher', () => {
|
||||||
withTempDir((userDataPath) => {
|
withTempDir((userDataPath) => {
|
||||||
const statePath = path.join(userDataPath, 'electron-runtime.json');
|
const statePath = path.join(userDataPath, 'electron-runtime.json');
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
@@ -107,7 +107,7 @@ test('runtime guard blocks a downgrade within the supported Electron major', ()
|
|||||||
);
|
);
|
||||||
|
|
||||||
const result = enforceElectronRuntimeGuard({
|
const result = enforceElectronRuntimeGuard({
|
||||||
electronVersion: '43.3.0',
|
electronVersion: '43.3.99',
|
||||||
userDataPath,
|
userDataPath,
|
||||||
supportedElectronMajor: 43,
|
supportedElectronMajor: 43,
|
||||||
});
|
});
|
||||||
@@ -123,6 +123,60 @@ test('runtime guard blocks a downgrade within the supported Electron major', ()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('runtime guard allows a patch downgrade while preserving minor downgrade protection', () => {
|
||||||
|
withTempDir((userDataPath) => {
|
||||||
|
const statePath = path.join(userDataPath, 'electron-runtime.json');
|
||||||
|
fs.writeFileSync(
|
||||||
|
statePath,
|
||||||
|
JSON.stringify({ highestElectronMajor: 43, lastElectronVersion: '43.7.3' }),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = enforceElectronRuntimeGuard({
|
||||||
|
electronVersion: '43.7.2',
|
||||||
|
userDataPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(result.ok, true);
|
||||||
|
const updatedState = fs.readFileSync(statePath, 'utf8');
|
||||||
|
assert.deepEqual(JSON.parse(updatedState), {
|
||||||
|
highestElectronMajor: 43,
|
||||||
|
lastElectronVersion: '43.7.2',
|
||||||
|
});
|
||||||
|
|
||||||
|
const minorDowngrade = enforceElectronRuntimeGuard({
|
||||||
|
electronVersion: '43.6.99',
|
||||||
|
userDataPath,
|
||||||
|
});
|
||||||
|
assert.equal(minorDowngrade.ok, false);
|
||||||
|
if (minorDowngrade.ok) return;
|
||||||
|
assert.equal(minorDowngrade.title, 'Electron downgrade blocked');
|
||||||
|
assert.equal(fs.readFileSync(statePath, 'utf8'), updatedState);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('runtime guard blocks an Electron 42 build from reopening an Electron 43 profile', () => {
|
||||||
|
withTempDir((userDataPath) => {
|
||||||
|
const statePath = path.join(userDataPath, 'electron-runtime.json');
|
||||||
|
const previousState = JSON.stringify({
|
||||||
|
highestElectronMajor: 43,
|
||||||
|
lastElectronVersion: '43.7.2',
|
||||||
|
});
|
||||||
|
fs.writeFileSync(statePath, previousState, 'utf8');
|
||||||
|
|
||||||
|
const result = enforceElectronRuntimeGuard({
|
||||||
|
electronVersion: '42.11.8',
|
||||||
|
userDataPath,
|
||||||
|
supportedElectronMajor: 42,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(result.ok, false);
|
||||||
|
if (result.ok) return;
|
||||||
|
assert.equal(result.title, 'Electron downgrade blocked');
|
||||||
|
assert.equal(fs.readFileSync(statePath, 'utf8'), previousState);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('runtime guard fails closed when its safety record is malformed', () => {
|
test('runtime guard fails closed when its safety record is malformed', () => {
|
||||||
withTempDir((userDataPath) => {
|
withTempDir((userDataPath) => {
|
||||||
const statePath = path.join(userDataPath, 'electron-runtime.json');
|
const statePath = path.join(userDataPath, 'electron-runtime.json');
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ function parseElectronVersion(version: string): ParsedElectronVersion | null {
|
|||||||
return { major, minor, patch };
|
return { major, minor, patch };
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareElectronVersions(
|
function compareElectronMajorMinorVersions(
|
||||||
left: ParsedElectronVersion,
|
left: ParsedElectronVersion,
|
||||||
right: ParsedElectronVersion,
|
right: ParsedElectronVersion,
|
||||||
): number {
|
): number {
|
||||||
return left.major - right.major || left.minor - right.minor || left.patch - right.patch;
|
return left.major - right.major || left.minor - right.minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readRuntimeState(statePath: string): ValidatedElectronRuntimeState | null {
|
function readRuntimeState(statePath: string): ValidatedElectronRuntimeState | null {
|
||||||
@@ -129,7 +129,7 @@ export function enforceElectronRuntimeGuard(options: {
|
|||||||
if (
|
if (
|
||||||
previousState &&
|
previousState &&
|
||||||
(currentVersion.major < previousState.state.highestElectronMajor ||
|
(currentVersion.major < previousState.state.highestElectronMajor ||
|
||||||
compareElectronVersions(currentVersion, previousState.version) < 0)
|
compareElectronMajorMinorVersions(currentVersion, previousState.version) < 0)
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
@@ -139,7 +139,7 @@ export function enforceElectronRuntimeGuard(options: {
|
|||||||
`The current runtime is Electron ${options.electronVersion}.`,
|
`The current runtime is Electron ${options.electronVersion}.`,
|
||||||
`Runtime safety record: ${statePath}.`,
|
`Runtime safety record: ${statePath}.`,
|
||||||
'',
|
'',
|
||||||
'Opening Chromium storage with an older Electron version can destroy Yomitan dictionaries. Upgrade SubMiner before using this profile.',
|
'Opening Chromium storage with an older Electron major or minor version can destroy Yomitan dictionaries. Upgrade SubMiner before using this profile. Patch downgrades within the same major and minor version are allowed.',
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
statePath,
|
statePath,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user