Lock the prototype of an object
by Joe Pea
JavaScript
// lockPrototype.js /////////////////////////////////////////////////////
const oldSetPrototypeOf = Object.setPrototypeOf
const lockedObjects = new WeakSet
Object.setPrototypeOf = function(obj, proto) {
if (lockedObjects.has(obj))
throw new TypeError("#<Object>'s prototype is locked.")
oldSetPrototypeOf.call(Object, obj, proto)
}
const __proto__descriptor = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__')
Object.defineProperty(Object.prototype, '__proto__', {
...__proto__descriptor,
set(proto) {
if (lockedObjects.has(this))
throw new TypeError("#<Object>'s prototype is locked.")
__proto__descriptor.set.call(this, proto)
},
})
/*export*/ function lockPrototype(obj) {
if (typeof obj !== "object" && typeof obj !== "function")
return obj
lockedObjects.add(obj)
}
// test.js //////////////////////////////////////////////////////////////
// import {lockPrototype} from './lockPrototype'
const a = {}
const b = {}
const c = {}
const proto = { n: 5 }
lockPrototype(b)
lockPrototype(c)
Object.setPrototypeOf(a, proto) // works fine
console.log('a.n', a.n) // 5
setTimeout(() => {
console.log('b.n:', b.n) // undefined
setTimeout(() => {
console.log('c.n', c.n) // undefined
})
c.__proto__ = proto // throws
})
Object.setPrototypeOf(b, proto) // throws