Last active
April 1, 2016 01:59
-
-
Save axefrog/5a89fcb4c56bfee0bb94 to your computer and use it in GitHub Desktop.
An idea I was playing around with for improving the way sources are passed around in Cycle.js. I since discarded the approach after the discussion at https://github.com/cyclejs/core/issues/284
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
| export function upgradeSources(sources) { | |
| const sourceKeys = Array.from(Object.keys(sources)); | |
| const cleanSources = sources => sourceKeys | |
| .reduce((acc, key) => (acc[key] = sources[key], acc), {}); | |
| function withCustom(baseSources, customSources) { | |
| const cleanedSources = cleanSources(baseSources); | |
| const nextSources = Object.assign({}, cleanedSources, customSources); | |
| return augment(nextSources, cleanedSources); | |
| } | |
| function augment(nextSources, cleanedSources) { | |
| let augmentedSources = Object.assign({ | |
| sanitize: function() { | |
| return augment(cleanSources(this)); | |
| }, | |
| with: function(custom) { | |
| return withCustom(this, custom); | |
| } | |
| }, nextSources); | |
| return Object.assign(augmentedSources, {sources: augmentedSources}); | |
| } | |
| return augment(sources); | |
| } |
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
| import {assert} from 'chai'; | |
| import {upgradeSources} from './index'; | |
| import {inspect} from 'common/utils/testing'; // eslint-disable-line no-unused-vars | |
| describe('upgradeSources()', () => { | |
| function component({x, y, z, sources}) { | |
| } | |
| function widget({x, y, z, sources}) { | |
| } | |
| function main({x, sources}) { | |
| // const b = a.with({y: 2}); | |
| return { | |
| a: [ | |
| component(sources.with({x: 3})) | |
| ] | |
| }; | |
| } | |
| it('should return an augmented clone of the sources object', () => { | |
| const sources = {a: 1, b: 2}; | |
| const upgradedSources = upgradeSources(sources); | |
| assert.notEqual(sources, upgradedSources); | |
| assert.property(sources, 'a', 'The original sources object was modified: property "a" is missing'); | |
| assert.property(sources, 'b', 'The original sources object was modified: property "b" is missing'); | |
| assert.strictEqual(sources.a, 1, 'The original sources object was modified: property "a" has the wrong value'); | |
| assert.strictEqual(sources.b, 2, 'The original sources object was modified: property "b" has the wrong value'); | |
| assert.property(upgradedSources, 'a', 'The upgraded sources object is missing property "a"'); | |
| assert.property(upgradedSources, 'b', 'The upgraded sources object is missing property "b"'); | |
| assert.equal(upgradedSources.a, sources.a, 'The upgraded sources object should have the same value for "a" as the original sources object'); | |
| assert.equal(upgradedSources.b, sources.b, 'The upgraded sources object should have the same value for "b" as the original sources object'); | |
| assert.isFunction(upgradedSources.with); | |
| assert.isFunction(upgradedSources.sanitize); | |
| assert.equal(upgradedSources, upgradedSources.sources); | |
| }); | |
| describe('#with()', () => { | |
| it('should return a clone of the basic sources object, augmented with additional properties and functions', () => { | |
| const sources = {a: 1, b: 2}; | |
| const upgradedSources = upgradeSources(sources); | |
| const custom = {m: 3, n: 4}; | |
| const customizedSources = upgradedSources.with(custom); | |
| assert.notEqual(upgradedSources, customizedSources); | |
| assert.equal(customizedSources, customizedSources.sources); | |
| assert.property(customizedSources, 'a'); | |
| assert.property(customizedSources, 'b'); | |
| assert.property(customizedSources, 'm'); | |
| assert.property(customizedSources, 'n'); | |
| assert.equal(customizedSources.a, upgradedSources.a); | |
| assert.equal(customizedSources.b, upgradedSources.b); | |
| assert.equal(customizedSources.m, custom.m); | |
| assert.equal(customizedSources.n, custom.n); | |
| assert.isFunction(customizedSources.with); | |
| assert.isFunction(customizedSources.sanitize); | |
| }); | |
| it('should omit custom properties added by a previous call to with()', () => { | |
| const sources = {a: 1, b: 2}; | |
| const upgradedSources = upgradeSources(sources); | |
| const custom1 = {m: 3, n: 4}; | |
| const customizedSources1 = upgradedSources.with(custom1); | |
| const custom2 = {q: 8, s: 9}; | |
| const customizedSources2 = customizedSources1.with(custom2); | |
| assert.notEqual(customizedSources2, customizedSources1); | |
| assert.property(customizedSources2, 'a'); | |
| assert.property(customizedSources2, 'b'); | |
| assert.property(customizedSources2, 'q'); | |
| assert.property(customizedSources2, 's'); | |
| assert.notProperty(customizedSources2, 'm'); | |
| assert.notProperty(customizedSources2, 'n'); | |
| assert.equal(customizedSources2.a, customizedSources1.a); | |
| assert.equal(customizedSources2.b, customizedSources1.b); | |
| assert.equal(customizedSources2.m, custom2.m); | |
| assert.equal(customizedSources2.n, custom2.n); | |
| assert.isFunction(customizedSources2.with); | |
| assert.isFunction(customizedSources2.sanitize); | |
| }); | |
| it('should preserve the derived state of core driver sources, in order to account for isolation', () => { | |
| function fakeIsolate(sources) { | |
| return Object.assign({}, sources, 'a' in sources ? {a: sources.a*100} : {}); | |
| } | |
| const sources = {a:2, b:3}; | |
| const upgradedSources = upgradeSources(sources); | |
| const isolatedSources = fakeIsolate(upgradedSources); | |
| const customizedSources = isolatedSources.with({m: 7}); | |
| const customizedSources2 = isolatedSources.with({n: 8}); | |
| assert.equal(customizedSources.a, sources.a*100); | |
| assert.equal(customizedSources.b, sources.b); | |
| assert.equal(customizedSources2.a, sources.a*100); | |
| assert.equal(customizedSources2.b, sources.b); | |
| assert.equal(customizedSources2.n, 8); | |
| }); | |
| }); | |
| describe('#sanitize()', () => { | |
| it('should return an identical result to calling `with({})`', () => { | |
| const sources = {a: 1, b: 2}; | |
| const upgradedSources = upgradeSources(sources); | |
| const custom = {m: 3, n: 4}; | |
| const customizedSources = upgradedSources.with(custom); | |
| const sanitizedSources = customizedSources.sanitize(); | |
| const decustomizedSources = customizedSources.with({}); | |
| assert.property(sanitizedSources, 'a'); | |
| assert.property(sanitizedSources, 'b'); | |
| assert.notProperty(sanitizedSources, 'm'); | |
| assert.notProperty(sanitizedSources, 'n'); | |
| assert.isFunction(sanitizedSources.with); | |
| assert.isFunction(sanitizedSources.sanitize); | |
| assert.property(decustomizedSources, 'a'); | |
| assert.property(decustomizedSources, 'b'); | |
| assert.notProperty(decustomizedSources, 'm'); | |
| assert.notProperty(decustomizedSources, 'n'); | |
| assert.isFunction(decustomizedSources.with); | |
| assert.isFunction(decustomizedSources.sanitize); | |
| }); | |
| }); | |
| // function run(sources) { | |
| // const sources = {x: 1}; | |
| // return main(upgradeSources(sources)); | |
| // } | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment