Answer the Core Question First
When a backup contains both :simple and :advanced compiled artifacts and no source‑maps, the only reliable way to confirm that the restored runtime behaves the same as the original is to use deterministic, data‑centric validation rather than decompilation. In practice this means:
- Running a suite of unit or integration tests that exercise the backup logic and compare output checksums or serialized representations.
- Using a stable serialization format (e.g., JSON) and a cryptographic hash (SHA‑256) to capture the exact state of the data structures after each operation.
- Ensuring that the same environment (Node.js version, Closure Compiler version, externs, and any runtime flags) is used for both the original build and the restore.
Why Decompilation Is Unreliable
Advanced builds rename symbols, inline functions, and remove dead code. Without source‑maps the mapping from runtime identifiers back to source names is lost, and property names used in interop may have been mangled. Even a perfect decompiler will produce code that is syntactically correct but semantically different from the original if externs were omitted or if the code relied on dynamic property access.
Practical Verification Steps
- Capture a Baseline
Run the original application, serialize the critical data structures (e.g., the backup payload), and compute a SHA‑256 hash:
const data = serializeBackup();
const hash = crypto.createHash('sha256').update(JSON.stringify(data)).digest('hex');
console.log('Baseline hash:', hash);
- Restore and Re‑serialize
After restoring from the backup, run the same serialization routine on the in‑memory data and compute a new hash.
- Compare Hashes
If the hashes match, the semantics of the data are preserved. A mismatch indicates that either the restoration process altered the data or that the compiled artifacts behaved differently during runtime.
- Run Targeted Tests
Execute any domain‑specific tests that check invariants (e.g., checksum of a file list, integrity of immutable maps). These tests provide additional confidence that the restored state behaves as expected.
- Optional Property‑Name Verification
For :advanced builds, verify that any externally exposed property names (e.g., API keys, event names) match expected strings. If externs were omitted, missing properties will surface as runtime errors.
Documented Strategy?
There is no official ClojureScript or Closure Compiler document that prescribes a decompilation‑based validation workflow for mixed optimization levels. The community consensus is to rely on deterministic tests and checksum comparison, as described above.
What Diagnostic Detail Could Change the Recommendation?
Does the backup archive include the original ClojureScript source files (or a copy of the shadow-cljs.edn / project.clj configuration)? If so, you could compare the source hash against the runtime hash to detect any inadvertent changes introduced by the compiler. If not, the checksum‑based approach remains the only practical method.