AOSSIE-Org / AOSSIE-Org/IndexedDB-Import-Export
[BUG]: Silent Data Loss for Supported IndexedDB Structured Clone Types (Set, Map, ArrayBuffer, etc.)
- 主要言語
- YAML
- スター
- 7
- フォーク
- 3
- 平均マージ
- 3日 55分
- マージ済み PR(30日)
- 8
説明
### Bug Description
The library's stated goal is to provide an export format that "preserves data types that `JSON.stringify` normally corrupts." Currently, the custom `serialize()` function only handles `Uint8Array`, `bigint`, and `Date`.
However, the native **IndexedDB Structured Clone algorithm** supports many more complex types natively, including `Set`, `Map`, `ArrayBuffer`, and other TypedArrays (like `Uint16Array`, `Float32Array`).
Because these objects fail the `isPlainObject` check inside `src/serialization/index.ts`, they bypass the recursive serialization block and are passed back to the user unchanged. When the user eventually runs `JSON.stringify()` on the export data, these types are silently corrupted (e.g., converted into empty `{}` objects). When importing this backup, the original data is permanently lost and replaced with empty objects.
### Steps to Reproduce
1. Create an IndexedDB store that contains a `Set`, `Map`, or `ArrayBuffer`.
2. Export the database using `exportDB()`.
3. Stringify the backup using `JSON.stringify()`.
4. Parse and import the backup using `importDB()`.
5. Observe that the `Set`, `Map`, and `ArrayBuffer` data has been replaced by empty objects `{}`.
### Logs and Screenshots
Here is a minimal reproduction using a Vitest test script:
```typescript
import { describe, it, expect } from 'vitest';
import { serialize, deserialize } from '../src/serialization/index.js';
describe('Unsupported type serialization', () => {
it('corrupts Set, Map, and ArrayBuffer via JSON.stringify', () => {
const data = {
mySet: new Set([1, 2, 3]),
myMap: new Map([['a', 1]]),
myBuffer: new Uint16Array([1, 2, 3]).buffer, // ArrayBuffer
};
const serialized = serialize(data);
const jsonStr = JSON.stringify(serialized);
const parsed = JSON.parse(jsonStr);
const restored = deserialize(parsed);
console.log("Restored:", restored);
expect(restored).not.toEqual(data); // Fails, data is corrupted
});
});
```
**Test Output:**
```javascript
Restored: [Object: null prototype] {
mySet: [Object: null prototype] {},
myMap: [Object: null prototype] {},
myBuffer: [Object: null prototype] {}
}
```
### Environment Details
- **OS:** All
- **Browser:** All
- **Node.js:** >=20
### Impact
High - Major feature is broken
### Recommended Fix
Expand the `SERIALIZATION_TAGS` and add serialization/deserialization branches for standard Structured Clone types:
1. **`Set`**: Convert to `[...value]` and tag as `"set"`.
2. **`Map`**: Convert to `[...value.entries()]` and tag as `"map"`.
3. **`ArrayBuffer`**: Convert to `Uint8Array` -> Base64 and tag as `"buffer"`.
### Code of Conduct
- [x] I have joined the Discord server and will post updates there
- [x] I have searched existing issues to avoid duplicates
コントリビューションガイド
評価
この issue はまだ評価されていません。