Summary
src/cmdSwitches.js ends with:
for (const k in c) {
app.commandLine.appendSwitch(k.replace('--', ''), c[k].join(','));
}
Chromium's CommandLine stores switches in a map keyed by name, and appendSwitch runs after argv has already been parsed, so OpenAsar's value replaces the user's entirely. Since both the base and perf presets always define --disable-features, any --disable-features a user passes on the command line is dropped without warning.
Evidence
Isolated in a bare Electron 42.11.1, using EnableDrDc (see #254) as the payload because its effect is unmistakable: the GPU process dies three times and acceleration is lost.
appendSwitch (what OpenAsar does) |
argv (what the user passes) |
Result |
--enable-features=EnableDrDc, no disable-features |
--disable-features=EnableDrDc |
user's value survives, D3D11 |
--enable-features=EnableDrDc plus --disable-features=Vulkan |
--disable-features=EnableDrDc |
overwritten, exit_code=34 |
The first row is the control: when OpenAsar does not set --disable-features at all, the user's value works fine and takes precedence over --enable-features. The second row is what actually happens in practice, because the presets always set it.
Why it matters
It removes the obvious escape hatch. A user hitting a bad flag cannot work around it from the command line, and gets no indication that their switch was ignored, which is a large part of why #254 took so long to pin down. customFlags in settings.json works, but it is far less discoverable.
Suggested fix
Feed argv's feature lists into the same merge instead of letting them be overwritten:
module.exports = () => {
- const flags = ('base,' + (oaConfig.cmdPreset || 'perf')).split(',').reduce((a, x) => a.concat(presets[x]?.split(' ')), (oaConfig.customFlags ?? '').split(' '));
+ const userFeatures = process.argv.filter(x => x.startsWith('--enable-features=') || x.startsWith('--disable-features='));
+
+ const flags = ('base,' + (oaConfig.cmdPreset || 'perf')).split(',').reduce((a, x) => a.concat(presets[x]?.split(' ')), userFeatures.concat((oaConfig.customFlags ?? '').split(' ')));
Verified against the real cmdSwitches.js: with the patch, --disable-features=Foo on the command line produces --disable-features=Foo,WinRetrieveSuggestionsOnlyOnDemand,…,Vulkan instead of being discarded.
Aside
While testing this I noticed the config UI offers a balanced option that writes cmdPreset: 'balanced', but presets has no such key, so presets[x]?.split(' ') contributes nothing and balanced silently resolves to base only. Possibly intended, but the optional chaining also means a typo in cmdPreset fails the same silent way.
Summary
src/cmdSwitches.jsends with:Chromium's
CommandLinestores switches in a map keyed by name, andappendSwitchruns afterargvhas already been parsed, so OpenAsar's value replaces the user's entirely. Since both thebaseandperfpresets always define--disable-features, any--disable-featuresa user passes on the command line is dropped without warning.Evidence
Isolated in a bare Electron 42.11.1, using
EnableDrDc(see #254) as the payload because its effect is unmistakable: the GPU process dies three times and acceleration is lost.appendSwitch(what OpenAsar does)argv(what the user passes)--enable-features=EnableDrDc, nodisable-features--disable-features=EnableDrDc--enable-features=EnableDrDcplus--disable-features=Vulkan--disable-features=EnableDrDcexit_code=34The first row is the control: when OpenAsar does not set
--disable-featuresat all, the user's value works fine and takes precedence over--enable-features. The second row is what actually happens in practice, because the presets always set it.Why it matters
It removes the obvious escape hatch. A user hitting a bad flag cannot work around it from the command line, and gets no indication that their switch was ignored, which is a large part of why #254 took so long to pin down.
customFlagsinsettings.jsonworks, but it is far less discoverable.Suggested fix
Feed
argv's feature lists into the same merge instead of letting them be overwritten:module.exports = () => { - const flags = ('base,' + (oaConfig.cmdPreset || 'perf')).split(',').reduce((a, x) => a.concat(presets[x]?.split(' ')), (oaConfig.customFlags ?? '').split(' ')); + const userFeatures = process.argv.filter(x => x.startsWith('--enable-features=') || x.startsWith('--disable-features=')); + + const flags = ('base,' + (oaConfig.cmdPreset || 'perf')).split(',').reduce((a, x) => a.concat(presets[x]?.split(' ')), userFeatures.concat((oaConfig.customFlags ?? '').split(' ')));Verified against the real
cmdSwitches.js: with the patch,--disable-features=Fooon the command line produces--disable-features=Foo,WinRetrieveSuggestionsOnlyOnDemand,…,Vulkaninstead of being discarded.Aside
While testing this I noticed the config UI offers a
balancedoption that writescmdPreset: 'balanced', butpresetshas no such key, sopresets[x]?.split(' ')contributes nothing andbalancedsilently resolves tobaseonly. Possibly intended, but the optional chaining also means a typo incmdPresetfails the same silent way.