computed values

pull/31/head
Rich-Harris 8 years ago
parent 8bce418b25
commit 9ff58cdb41

@ -20,7 +20,8 @@
"one-var": [ 2, "never" ], "one-var": [ 2, "never" ],
"prefer-arrow-callback": 2, "prefer-arrow-callback": 2,
"prefer-const": [ 2, { "destructuring": "all" } ], "prefer-const": [ 2, { "destructuring": "all" } ],
"arrow-spacing": 2 "arrow-spacing": 2,
"no-inner-declarations": 0
}, },
"env": { "env": {
"es6": true, "es6": true,

@ -47,7 +47,7 @@ export default function generate ( parsed, template ) {
code.overwrite( defaultExport.start, defaultExport.declaration.start, `const template = ` ); code.overwrite( defaultExport.start, defaultExport.declaration.start, `const template = ` );
defaultExport.declaration.properties.forEach( prop => { defaultExport.declaration.properties.forEach( prop => {
templateProperties[ prop.key.name ] = true; templateProperties[ prop.key.name ] = prop.value;
}); });
} }
} }
@ -353,6 +353,49 @@ export default function generate ( parsed, template ) {
renderers.push( createRenderer( current ) ); renderers.push( createRenderer( current ) );
const setStatements = [ deindent`
const oldState = state;
state = Object.assign( {}, oldState, newState );
` ];
if ( templateProperties.computed ) {
const dependencies = new Map();
templateProperties.computed.properties.forEach( prop => {
const key = prop.key.name;
const value = prop.value;
const deps = value.params.map( param => param.name );
dependencies.set( key, deps );
});
const visited = new Set();
function visit ( key ) {
if ( !dependencies.has( key ) ) return; // not a computation
if ( visited.has( key ) ) return;
visited.add( key );
const deps = dependencies.get( key );
deps.forEach( visit );
setStatements.push( deindent`
if ( ${deps.map( dep => `( '${dep}' in newState && typeof state.${dep} === 'object' || state.${dep} !== oldState.${dep} )` ).join( ' || ' )} ) {
state.${key} = newState.${key} = template.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} );
}
` );
}
templateProperties.computed.properties.forEach( prop => visit( prop.key.name ) );
}
setStatements.push( deindent`
dispatchObservers( observers.immediate, newState, oldState );
mainFragment.update( state );
dispatchObservers( observers.deferred, newState, oldState );
` );
const result = deindent` const result = deindent`
${parsed.js ? `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` : ``} ${parsed.js ? `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` : ``}
@ -367,9 +410,11 @@ export default function generate ( parsed, template ) {
deferred: Object.create( null ) deferred: Object.create( null )
}; };
function dispatchObservers ( group, state, oldState ) { function dispatchObservers ( group, newState, oldState ) {
for ( const key in group ) { for ( const key in group ) {
const newValue = state[ key ]; if ( !( key in newState ) ) continue;
const newValue = newState[ key ];
const oldValue = oldState[ key ]; const oldValue = oldState[ key ];
if ( newValue === oldValue && typeof newValue !== 'object' ) continue; if ( newValue === oldValue && typeof newValue !== 'object' ) continue;
@ -388,8 +433,7 @@ export default function generate ( parsed, template ) {
}; };
component.set = function set ( newState ) { component.set = function set ( newState ) {
Object.assign( state, newState ); ${setStatements.join( '\n\n' )}
mainFragment.update( state );
}; };
component.observe = function ( key, callback, options = {} ) { component.observe = function ( key, callback, options = {} ) {

@ -1,11 +1,11 @@
import * as assert from 'assert'; import * as assert from 'assert';
export default { export default {
html: '<p>1 + 2 = 3</p><p>3 * 3 = 9</p>', html: '<p>1 + 2 = 3</p>\n<p>3 * 3 = 9</p>',
test ( component, target ) { test ( component, target ) {
component.set({ a: 3 }); component.set({ a: 3 });
assert.equal( component.get( 'c' ), 5 ); assert.equal( component.get( 'c' ), 5 );
assert.equal( component.get( 'cSquared' ), 25 ); assert.equal( component.get( 'cSquared' ), 25 );
assert.equal( target.innerHTML, '<p>3 + 2 = 5</p><p>5 * 5 = 25</p>' ); assert.equal( target.innerHTML, '<p>3 + 2 = 5</p>\n<p>5 * 5 = 25</p>' );
} }
}; };

Loading…
Cancel
Save