Harden dictionary cache reading (avoid Function constructor)
Summary
Replace the current approach that evaluates cache files using the Function constructor with a safer, simpler JSON-based format and reader. Provide a seamless migration path from the existing export default {...}; format to JSON, and add tests to cover read/write and migration scenarios.
Motivation
- Using
new Function(...) to evaluate a cache file is unnecessarily risky and harder to maintain.
- A plain JSON cache improves safety, tooling compatibility, and clarity.
- Migration can be implemented without breaking users by auto-detecting and converting the old format upon first write.
Current behavior
- File:
packages/compiler/src/lib/lcp/cache.ts
- The cache writer writes
export default { ... }; and the reader strips that header and evaluates the remainder with new Function(...).
- This requires executing code to read the cache and is not ideal.
Proposed changes
-
Change cache file format to JSON
- Write cache as JSON to a
.json file (for example, lingo-cache.json), or keep the current filename but ensure pure JSON content.
- Read cache with
JSON.parse.
-
Backward-compatible migration
- Detect the legacy format that starts with
export default.
- Parse legacy content by converting it to an object without executing code (e.g., using a minimal, safe transform and
JSON.parse if possible, or a strict parser), then immediately re-write the cache in the new JSON format.
- Consider logging a one-time info message when migration occurs (guarded by a debug flag).
-
Tests
- Add tests that cover:
- Reading/writing the new JSON cache format.
- Migrating from an existing legacy
export default {...}; cache file to the new JSON format.
- Ensuring no data loss and deterministic formatting (stable key ordering already exists in writer code).
Affected files (initial)
packages/compiler/src/lib/lcp/cache.ts (read/write and format logic)
- Potentially references to
LCP_DICTIONARY_FILE_NAME if the extension changes (packages/compiler/src/_const)
- New tests near
packages/compiler/src/lib/lcp/ (or existing test suite location)
Can I start working on it? Maintainers [@vrcprl @maxprilutskiy @sumitsaurabh927 @davidturnbull ..]
Harden dictionary cache reading (avoid Function constructor)
Summary
Replace the current approach that evaluates cache files using the Function constructor with a safer, simpler JSON-based format and reader. Provide a seamless migration path from the existing
export default {...};format to JSON, and add tests to cover read/write and migration scenarios.Motivation
new Function(...)to evaluate a cache file is unnecessarily risky and harder to maintain.Current behavior
packages/compiler/src/lib/lcp/cache.tsexport default { ... };and the reader strips that header and evaluates the remainder withnew Function(...).Proposed changes
Change cache file format to JSON
.jsonfile (for example,lingo-cache.json), or keep the current filename but ensure pure JSON content.JSON.parse.Backward-compatible migration
export default.JSON.parseif possible, or a strict parser), then immediately re-write the cache in the new JSON format.Tests
export default {...};cache file to the new JSON format.Affected files (initial)
packages/compiler/src/lib/lcp/cache.ts(read/write and format logic)LCP_DICTIONARY_FILE_NAMEif the extension changes (packages/compiler/src/_const)packages/compiler/src/lib/lcp/(or existing test suite location)Can I start working on it? Maintainers [@vrcprl @maxprilutskiy @sumitsaurabh927 @davidturnbull ..]