Read the source and its declared rule
The original input is a parsed plain JSON object with an own __proto__ member. Object.assign into a normal empty object follows its target setter behaviour and can replace that target’s prototype. The corrected local construction uses Object.fromEntries to create own data properties.
| Record | Input JSON |
|---|---|
| Base input | {"raw":"{\"__proto__\":{\"mark\":\"changed\"},\"label\":\"A\"}"} |
Compare the actual paths
The bad target loses the own member and inherits mark changed. Good output has own keys __proto__ and label, with no inherited mark. This fixture changes only its fresh local target.
| Path | Output JSON |
|---|---|
| Misleading path | {"ownKeys":["label"],"prototypeMark":"changed","ownData":[["label","A"]]} |
| Corrected path | {"ownKeys":["__proto__","label"],"prototypeMark":null,"ownData":[["__proto__",{"mark":"changed"}],["label","A"]]} |
import {DatabaseSync} from 'node:sqlite';
import {TextDecoder} from 'node:util';
import {inflateSync} from 'node:zlib';
import {posix} from 'node:path';
import {createHash} from 'node:crypto';
const rows=(db,sql)=>db.prepare(sql).all().map(r=>({...r}));
const failed=(action)=>{try{action();return null;}catch(e){return {code:e.errcode??e.code??e.name};}};
import assert from 'node:assert/strict';
const run=function run(i,corrected=true){
const parsed=JSON.parse(i.raw);const object=corrected?Object.fromEntries(Object.entries(parsed)):Object.assign({},parsed);
return {ownKeys:Object.keys(object),prototypeMark:Object.getPrototypeOf(object).mark??null,ownData:Object.entries(object)};
};
const cases=[{"label":"misleading base","input":{"raw":"{\"__proto__\":{\"mark\":\"changed\"},\"label\":\"A\"}"},"expected":{"ownKeys":["label"],"prototypeMark":"changed","ownData":[["label","A"]]},"corrected":false},{"label":"corrected base","input":{"raw":"{\"__proto__\":{\"mark\":\"changed\"},\"label\":\"A\"}"},"expected":{"ownKeys":["__proto__","label"],"prototypeMark":null,"ownData":[["__proto__",{"mark":"changed"}],["label","A"]]},"corrected":true},{"label":"constructor remains own data","input":{"raw":"{\"constructor\":\"C\"}"},"expected":{"ownKeys":["constructor"],"prototypeMark":null,"ownData":[["constructor","C"]]},"corrected":true},{"label":"text proto member remains data","input":{"raw":"{\"__proto__\":\"P\"}"},"expected":{"ownKeys":["__proto__"],"prototypeMark":null,"ownData":[["__proto__","P"]]},"corrected":true}];
for(const test of cases){
const actual=run(test.input,test.corrected);
assert.deepEqual(actual,test.expected,test.label);
console.log(test.label,actual);
}
Check boundaries before the next load
constructor and a text-valued __proto__ remain ordinary own data in the corrected path.
| Case | Input JSON | Expected output JSON |
|---|---|---|
| Own constructor member | {"raw":"{\"constructor\":\"C\"}"} | {"ownKeys":["constructor"],"prototypeMark":null,"ownData":[["constructor","C"]]} |
| Text-valued proto member | {"raw":"{\"__proto__\":\"P\"}"} | {"ownKeys":["__proto__"],"prototypeMark":null,"ownData":[["__proto__","P"]]} |
Should __proto__ disappear from accepted source data?
Show the worked answer
No. The chosen contract preserves it as an own member without allowing it to replace the object prototype.