Last active
May 6, 2021 03:52
-
-
Save svidgen/2afd1c6d954ff354ffec898cf5b3d845 to your computer and use it in GitHub Desktop.
example of the new observe/infect/curse implementation i'll be using in my DOM lib
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Infects an object with a multi-cast property and method "mirroring". | |
| * | |
| * ``` | |
| * observe(source, ['property_a', 'property_b', 'method_a']).mirror(target); | |
| * ``` | |
| * | |
| * The `target` object will be invoked with the same calls/values as those | |
| * made against the `source` on the listed properties and methods -- or | |
| * ALL enumerable properties and methods if non are given. | |
| * | |
| * The only way to stop mirroring is to shatter the mirror: | |
| * | |
| * ``` | |
| * const mirror = observe(source, [...]).mirror(target); | |
| * | |
| * // later. | |
| * mirror.shatter(); | |
| * ``` | |
| */ | |
| function observe(o, props) { | |
| if (typeof(props) === 'undefined') { | |
| props = allPropertyNamesOf(o); | |
| } else if (typeof(props) != 'Array') { | |
| props = [props]; | |
| } else { | |
| props = distinct(props); | |
| } | |
| o.__callbacks = o.__callbacks || {}; | |
| o.__targets = o.__targets || []; | |
| props.forEach(function(p) { | |
| if (p === '__callbacks') return; | |
| if (p === '__targets') return; | |
| if (typeof(o.__callbacks[p]) === 'function') return; | |
| o.__callbacks[p] = callback(o, p); | |
| if (typeof(o[p]) === 'function') { | |
| const _originalFunction = o[p].bind(o); | |
| o[p] = (...args) => { | |
| try { | |
| const rv = _originalFunction(...args); | |
| o.__callbacks[p](...args); | |
| return rv; | |
| } catch (err) { | |
| throw err; | |
| } | |
| }; | |
| } else { | |
| var innerValue = o[p]; | |
| Object.defineProperty(o, p, { | |
| set: function(v) { | |
| innerValue = v; | |
| o.__callbacks[p](v); | |
| }, | |
| get: function() { | |
| return innerValue; | |
| } | |
| }); | |
| // also initialize the value on the mirrored object. | |
| o.__callbacks[p](o[p]) | |
| } | |
| }); | |
| return { | |
| mirror: target => { | |
| o.__targets.indexOf(target) < 0 && o.__targets.push(target); | |
| return { | |
| shatter: () => { | |
| o.__targets.splice(o.__targets.indexOf(target), 1); | |
| } | |
| }; | |
| } | |
| }; | |
| }; | |
| function callback(s, name) { | |
| return (...args) => { | |
| s.__targets.forEach(target => { | |
| try { | |
| if (typeof(target[name]) === 'function') { | |
| target[name](...args); | |
| } else { | |
| target[name] = args[0]; | |
| } | |
| } catch (err) { | |
| console.error(`${err}: Could not invoke ${name} on target`); | |
| console.log('target =', target); | |
| } | |
| }); | |
| }; | |
| }; | |
| function distinct(items) { | |
| return [...(new Set([...items]))]; | |
| }; | |
| function allPropertyNamesOf(o) { | |
| var props = Object.getOwnPropertyNames(o); | |
| for (; o != null; o = Object.getPrototypeOf(o)) { | |
| props = [...props, ...Object.getOwnPropertyNames(o)]; | |
| } | |
| return distinct(props); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var source = {a: '123'}; | |
| var target = {}; | |
| var mirror = observe(source).mirror(target); | |
| source.a = '456'; | |
| console.log(target); | |
| mirror.shatter(); | |
| source.a = '789'; | |
| console.log(target); | |
| source = {f: (a) => console.log('logged form source', a)}; | |
| target1 = {f: (a) => console.log('logged form target1', a)}; | |
| target2 = {f: (a) => console.log('logged form target2', a)}; | |
| target3 = {f: (a) => console.log('logged form target3', a)}; | |
| var mirror1 = observe(source).mirror(target1); | |
| var mirror2 = observe(source).mirror(target2); | |
| var mirror3 = observe(source).mirror(target3); | |
| source.f('u'); | |
| mirror1.shatter(); | |
| mirror2.shatter(); | |
| mirror3.shatter(); | |
| source = {a: 123}; | |
| target = {a: v => console.log('detected change', v)}; | |
| mirror = observe(source).mirror(target); | |
| source.a += 1; | |
| mirror.shatter(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {a: "456"} | |
| {a: "456"} | |
| logged form source u | |
| logged form target1 u | |
| logged form target2 u | |
| logged form target3 u | |
| detected change 124 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment