more refactoring

pull/380/head
Rich Harris 9 years ago
parent 574503d101
commit 17db22ac63

@ -1,77 +1,41 @@
import deindent from '../../../../utils/deindent.js';
import isReference from '../../../../utils/isReference.js';
import flattenReference from '../../../../utils/flattenReference.js';
import getSetter from './binding/getSetter.js';
export default function createBinding ( generator, node, attribute, current, local ) {
const { name, parts, keypath } = flattenReference( attribute.value );
const { name } = flattenReference( attribute.value );
const { snippet, contexts, dependencies } = generator.contextualise( attribute.value );
const contextual = name in current.contexts;
if ( dependencies.length > 1 ) throw new Error( 'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!' );
if ( contextual && !~local.allUsedContexts.indexOf( name ) ) {
local.allUsedContexts.push( name );
}
contexts.forEach( context => {
if ( !~local.allUsedContexts.indexOf( context ) ) local.allUsedContexts.push( context );
});
const contextual = name in current.contexts;
let obj;
let prop;
let value;
if ( contextual ) {
obj = current.listNames[ name ];
prop = current.indexNames[ name ];
value = keypath;
} else if ( attribute.value.type === 'MemberExpression' ) {
prop = `'[✂${attribute.value.property.start}-${attribute.value.property.end}✂]}'`;
obj = `root.[✂${attribute.value.object.start}-${attribute.value.object.end}✂]}`;
} else {
prop = `'${parts.slice( -1 )}'`;
obj = parts.length > 1 ? `root.${parts.slice( 0, -1 ).join( '.' )}` : `root`;
value = `root.${keypath}`;
obj = 'root';
prop = `'${name}'`;
}
local.bindings.push({ name: attribute.name, value, obj, prop });
let setter;
if ( contextual ) {
// find the top-level property that this is a child of
let fragment = current;
let prop = name;
do {
if ( fragment.expression && fragment.context === prop ) {
if ( !isReference( fragment.expression ) ) {
// TODO this should happen in prior validation step
throw new Error( `${prop} is read-only, it cannot be bound` );
}
prop = flattenReference( fragment.expression ).name;
}
} while ( fragment = fragment.parent );
local.bindings.push({
name: attribute.name,
value: snippet,
obj,
prop
});
generator.expectedProperties[ prop ] = true;
const listName = current.listNames[ name ];
const indexName = current.indexNames[ name ];
const context = local.isComponent ? `_context` : `__svelte`;
setter = deindent`
var list = this.${context}.${listName};
var index = this.${context}.${indexName};
list[index]${parts.slice( 1 ).map( part => `.${part}` ).join( '' )} = value;
component._set({ ${prop}: component.get( '${prop}' ) });
`;
} else {
if ( parts.length > 1 ) {
setter = deindent`
var ${name} = component.get( '${name}' );
${name}.${parts.slice( 1 ).join( '.' )} = value;
component._set({ ${name}: ${name} });
`;
} else {
setter = `component._set({ ${keypath}: value });`;
}
generator.expectedProperties[ name ] = true;
}
const setter = getSetter({ current, name, context: '_context', attribute, dependencies, snippet, value: 'value' });
generator.hasComplexBindings = true;
@ -88,11 +52,9 @@ export default function createBinding ( generator, node, attribute, current, loc
});
` );
const dependencies = name in current.contexts ? current.contextDependencies[ name ] : [ name ];
local.update.addBlock( deindent`
if ( !${local.name}_updating && ${dependencies.map( dependency => `'${dependency}' in changed` ).join( '||' )} ) {
${local.name}._set({ ${attribute.name}: ${contextual ? keypath : `root.${keypath}`} });
${local.name}._set({ ${attribute.name}: ${snippet} });
}
` );
}

@ -1,5 +1,6 @@
import deindent from '../../../../utils/deindent.js';
import flattenReference from '../../../../utils/flattenReference.js';
import getSetter from './binding/getSetter.js';
export default function createBinding ( generator, node, attribute, current, local ) {
const { name } = flattenReference( attribute.value );
@ -17,30 +18,7 @@ export default function createBinding ( generator, node, attribute, current, loc
const value = getBindingValue( local, node, attribute, isMultipleSelect );
const eventName = getBindingEventName( node );
let setter;
if ( name in current.contexts ) {
const prop = dependencies[0];
const tail = attribute.value.type === 'MemberExpression' ? getTailSnippet( attribute.value ) : '';
setter = deindent`
var list = this.__svelte.${current.listNames[ name ]};
var index = this.__svelte.${current.indexNames[ name ]};
list[index]${tail} = ${value};
component._set({ ${prop}: component.get( '${prop}' ) });
`;
} else {
if ( attribute.value.type === 'MemberExpression' ) {
setter = deindent`
var ${name} = component.get( '${name}' );
${snippet} = ${value};
component._set({ ${name}: ${name} });
`;
} else {
setter = `component._set({ ${name}: ${value} });`;
}
}
let setter = getSetter({ current, name, context: '__svelte', attribute, dependencies, snippet, value });
// special case
if ( node.name === 'select' && !isMultipleSelect ) {

@ -0,0 +1,34 @@
import deindent from '../../../../../utils/deindent.js';
export default function getSetter ({ current, name, context, attribute, dependencies, snippet, value }) {
if ( name in current.contexts ) {
const prop = dependencies[0];
const tail = attribute.value.type === 'MemberExpression' ? getTailSnippet( attribute.value ) : '';
return deindent`
var list = this.${context}.${current.listNames[ name ]};
var index = this.${context}.${current.indexNames[ name ]};
list[index]${tail} = ${value};
component._set({ ${prop}: component.get( '${prop}' ) });
`;
}
if ( attribute.value.type === 'MemberExpression' ) {
return deindent`
var ${name} = component.get( '${name}' );
${snippet} = ${value};
component._set({ ${name}: ${name} });
`;
}
return `component._set({ ${name}: ${value} });`;
}
function getTailSnippet ( node ) {
const end = node.end;
while ( node.type === 'MemberExpression' ) node = node.object;
const start = node.end;
return `[✂${start}-${end}✂]`;
}
Loading…
Cancel
Save