<div dir="ltr"><div><div><div>You can just do:<br><br></div><span style="font-family:monospace,monospace">const proxy = new Proxy(obj, {<br></span></div><span style="font-family:monospace,monospace">   set() { throw new Error(); },<br>   defineProperty() { throw new Error();},<br></span></div><div><span style="font-family:monospace,monospace">   deleteProperty() { throw new Error(); }<br></span></div><div><div><span style="font-family:monospace,monospace">})<br></span><div><div><span style="font-family:monospace,monospace">
</span><div><span style="font-family:monospace,monospace"></span></div><div><font face="georgia, serif" color="#000000"><span style="font-family:monospace,monospace">this.emit('some:event', proxy)</span><br><br><br></font></div>

Though, it seems like an exotic use case.<br></div></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Feb 19, 2018 at 8:56 PM, /#!/JoePea <span dir="ltr"><<a href="mailto:joe@trusktr.io" target="_blank">joe@trusktr.io</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif;font-size:small;color:rgb(0,0,0);display:inline">​</div><font face="georgia, serif" color="#000000">I think the ability to unfreeze an object can be useful.</font><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">For example, suppose we have a library that emits events:</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000">this.emit('some:event', this.obj)</font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">Maybe we want to try to prevent external listeners from modifying the event payload without having to clone `this.obj`, otherwise cloning can cause "jank" from GC during animations that should be smooth.</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">So, what if there was a way to unfreeze an object in the scope in which the object was frozen?</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000">Object.freeze(obj) // instead of cloning</font></div><div><font face="georgia, serif" color="#000000">this.emit('some:event', this.obj) // recommend all listeners to be synchronous, and not modify the payload later</font></div><div><font face="georgia, serif" color="#000000">Object.unfreeze(this.obj) // in the same scope</font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">or maybe it return an unfreeze function:</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000">const unfreeze = Object.freeze(obj) // instead of cloning</font></div><div><font face="georgia, serif" color="#000000">this.emit('some:event', this.obj) // recommend all listeners to be synchronous, and not modify the payload later</font></div><div><font face="georgia, serif" color="#000000">unfreeze(this.obj) // only code that is given the unfreeze function can call it, similar to resolve/reject functions with Promises</font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">or maybe it is more similar to setTimeout and setInterval:</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000">const frozenKey = Object.freeze(obj) // instead of cloning</font></div><div><font face="georgia, serif" color="#000000">this.emit('some:event', this.obj) // recommend all listeners to be synchronous, and not modify the payload later</font></div><div><font face="georgia, serif" color="#000000">Object.unfreeze(frozenKey) // only code that is given the key can unfreeze the object associated with the key</font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">It seems like there can be opportunity for this to be optimized, so that it can be faster than cloning. For example, this uses more memory and causes GC:</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000">this.emit('some:event', { ...this.obj }) // creates a new object</font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">Could the performance benefit make it worth it to have a way to unfreeze objects?</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">Another use case is unlocking things only when used in certain places, as a "guard". In the following example, the only way to set the X rotation value is with the setter, which enforces that certain logic will fire, rather than someone from the outside modifying the readable state not using the setter:</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">import Privates from 'somewhere'</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">// a private cache, using WeakMap internally</font></div><div><font face="georgia, serif" color="#000000">const _ = new Privates</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">class ThingThatRotates {</font></div><div><font face="georgia, serif" color="#000000">    constructor() {</font></div><div><font face="georgia, serif" color="#000000">        this.rotation = { x: 0, y: 0, z: 0 }</font></div><div><font face="georgia, serif" color="#000000">        _(this).frozen = Object.freeze(this.rotation)</font></div><div><font face="georgia, serif" color="#000000">        // ...</font></div><div><font face="georgia, serif" color="#000000">    }</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">    get rotateX() { return this.rotation.x }</font></div><div><font face="georgia, serif" color="#000000">    set rotateX(val) {</font></div><div><font face="georgia, serif" color="#000000">        this.<wbr>doSomethingImportantWithTheVal<wbr>ue(val)</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">        // unlock here, so that the value can only be set with this setter.</font></div><div><font face="georgia, serif" color="#000000">        Object.unfreeze(_(this).<wbr>frozen)</font></div><div><font face="georgia, serif" color="#000000">        this.rotation.x = val</font></div><div><font face="georgia, serif" color="#000000">        _(this).frozen = Object.freeze(this.rotation)</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">        this.emitAnEventWithTheValue(<wbr>val)</font></div><div><font face="georgia, serif" color="#000000">        this.etc(val)</font></div><div><font face="georgia, serif" color="#000000">    }</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">    // ...</font></div><div><font face="georgia, serif" color="#000000">}</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">I know, I can probably just keep `rotation` in the private cache, but then it isn't readable. Maybe I want that to be readable as a convenient shortcut. F.e.</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```js</font></div><div><font face="georgia, serif" color="#000000">// outside code</font></div><div><font face="georgia, serif" color="#000000">const r = new ThingThatRotates</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">// X rotation might be animated by some other tool</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">const {x, y, z} = r.rotation // for convenience, no cloning involved.</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">```</font></div><div><font face="georgia, serif" color="#000000"><br></font></div><div><font face="georgia, serif" color="#000000">This is a completely contrived example I just made up right now. I can probably think of more. It seems like it could be good for performance in cases where we don't want modification from the outside...</font></div><span class="HOEnZb"><font color="#888888"><br><br>/#!/JoePea</font></span></div>
<br>______________________________<wbr>_________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/<wbr>listinfo/es-discuss</a><br>
<br></blockquote></div><br></div>