pull/1367/head
Rich Harris 8 years ago
parent f8db2eee61
commit 662363cca2

@ -6,6 +6,7 @@ import addToSet from '../../utils/addToSet';
import { DomGenerator } from '../dom/index'; import { DomGenerator } from '../dom/index';
import Node from './shared/Node'; import Node from './shared/Node';
import Element from './Element'; import Element from './Element';
import Text from './Text';
import Block from '../dom/Block'; import Block from '../dom/Block';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
@ -22,37 +23,51 @@ export default class Attribute extends Node {
compiler: DomGenerator; compiler: DomGenerator;
parent: Element; parent: Element;
name: string; name: string;
isSpread: boolean;
isTrue: boolean; isTrue: boolean;
isDynamic: boolean; isDynamic: boolean;
chunks: Node[]; expression?: Expression;
chunks: (Text | Expression)[];
dependencies: Set<string>; dependencies: Set<string>;
expression: Node;
constructor(compiler, parent, scope, info) { constructor(compiler, parent, scope, info) {
super(compiler, parent, scope, info); super(compiler, parent, scope, info);
this.name = info.name; if (info.type === 'Spread') {
this.isTrue = info.value === true; this.name = null;
this.isSpread = true;
this.isTrue = false;
this.dependencies = new Set(); this.expression = new Expression(compiler, this, scope, info.expression);
this.dependencies = this.expression.dependencies;
this.chunks = null;
this.chunks = this.isTrue this.isDynamic = true; // TODO not necessarily
? [] }
: info.value.map(node => {
if (node.type === 'Text') return node; else {
this.name = info.name;
this.isTrue = info.value === true;
const expression = new Expression(compiler, this, scope, node.expression); this.dependencies = new Set();
addToSet(this.dependencies, expression.dependencies); this.chunks = this.isTrue
return expression; ? []
}); : info.value.map(node => {
if (node.type === 'Text') return node;
this.isDynamic = this.chunks.length === 1 const expression = new Expression(compiler, this, scope, node.expression);
? this.chunks[0].type !== 'Text'
: this.chunks.length > 1;
// TODO this would be better, but it breaks some stuff addToSet(this.dependencies, expression.dependencies);
// this.isDynamic = this.dependencies.size > 0; return expression;
});
// TODO this would be better, but it breaks some stuff
// this.isDynamic = this.dependencies.size > 0;
this.isDynamic = this.chunks.length === 1
? this.chunks[0].type !== 'Text'
: this.chunks.length > 1;
}
} }
getValue() { getValue() {

@ -57,6 +57,7 @@ export default class Element extends Node {
break; break;
case 'Attribute': case 'Attribute':
case 'Spread':
// special case // special case
if (node.name === 'xmlns') this.namespace = node.value[0].data; if (node.name === 'xmlns') this.namespace = node.value[0].data;
@ -151,18 +152,6 @@ export default class Element extends Node {
block.outros += 1; block.outros += 1;
} }
this.attributes.forEach(attribute => {
if (attribute.type === 'Attribute' && attribute.value !== true) {
// removed
} else {
if (this.parent) this.parent.cannotUseInnerHTML();
if (attribute.type === 'Spread') {
block.addDependencies(attribute.metadata.dependencies);
}
}
});
const valueAttribute = this.attributes.find((attribute: Attribute) => attribute.name === 'value'); const valueAttribute = this.attributes.find((attribute: Attribute) => attribute.name === 'value');
if (this.name === 'textarea') { if (this.name === 'textarea') {
@ -526,23 +515,20 @@ export default class Element extends Node {
this.attributes this.attributes
.filter(attr => attr.type === 'Attribute' || attr.type === 'Spread') .filter(attr => attr.type === 'Attribute' || attr.type === 'Spread')
.forEach(attr => { .forEach(attr => {
if (attr.type === 'Attribute') { const condition = attr.dependencies.size > 0
const { dynamic, value, dependencies } = mungeAttribute(attr, block); ? [...attr.dependencies].map(d => `changed.${d}`).join(' || ')
: null;
if (attr.isSpread) {
const { snippet, dependencies } = attr.expression;
const snippet = `{ ${quoteIfNecessary(attr.name)}: ${value} }`;
initialProps.push(snippet); initialProps.push(snippet);
const condition = dependencies && dependencies.map(d => `changed.${d}`).join(' || ');
updates.push(condition ? `${condition} && ${snippet}` : snippet); updates.push(condition ? `${condition} && ${snippet}` : snippet);
} } else {
const snippet = `{ ${quoteIfNecessary(attr.name)}: ${attr.getValue()} }`;
else {
block.contextualise(attr.expression); // TODO gah
const { snippet, dependencies } = attr.metadata;
initialProps.push(snippet); initialProps.push(snippet);
const condition = dependencies && dependencies.map(d => `changed.${d}`).join(' || ');
updates.push(condition ? `${condition} && ${snippet}` : snippet); updates.push(condition ? `${condition} && ${snippet}` : snippet);
} }
}); });

@ -14,8 +14,7 @@ type MungedAttribute = {
export default function mungeAttribute(attribute: Node, block: Block): MungedAttribute { export default function mungeAttribute(attribute: Node, block: Block): MungedAttribute {
if (attribute.type === 'Spread') { if (attribute.type === 'Spread') {
block.contextualise(attribute.expression); // TODO remove const { dependencies, snippet } = attribute.expression;
const { dependencies, snippet } = attribute.metadata;
return { return {
spread: true, spread: true,

@ -35,13 +35,12 @@ export default function visitElement(
appendTarget.slots[slotName] = ''; appendTarget.slots[slotName] = '';
} }
if (node.attributes.find(attr => attr.type === 'Spread')) { if (node.attributes.find(attr => attr.isSpread)) {
// TODO dry this out // TODO dry this out
const args = []; const args = [];
node.attributes.forEach((attribute: Node) => { node.attributes.forEach((attribute: Node) => {
if (attribute.type === 'Spread') { if (attribute.type === 'Spread') {
block.contextualise(attribute.expression); args.push(attribute.expression.snippet);
args.push(attribute.metadata.snippet);
} else if (attribute.type === 'Attribute') { } else if (attribute.type === 'Attribute') {
if (attribute.name === 'value' && node.name === 'textarea') { if (attribute.name === 'value' && node.name === 'textarea') {
textareaContents = stringifyAttributeValue(block, attribute.value); textareaContents = stringifyAttributeValue(block, attribute.value);
@ -53,8 +52,7 @@ export default function visitElement(
attribute.value[0].type !== 'Text' attribute.value[0].type !== 'Text'
) { ) {
// a boolean attribute with one non-Text chunk // a boolean attribute with one non-Text chunk
block.contextualise(attribute.value[0].expression); args.push(`{ ${quoteIfNecessary(attribute.name)}: ${attribute.value[0].expression.snippet} }`);
args.push(`{ ${quoteIfNecessary(attribute.name)}: ${attribute.value[0].metadata.snippet} }`);
} else { } else {
args.push(`{ ${quoteIfNecessary(attribute.name)}: \`${stringifyAttributeValue(block, attribute.value)}\` }`); args.push(`{ ${quoteIfNecessary(attribute.name)}: \`${stringifyAttributeValue(block, attribute.value)}\` }`);
} }

Loading…
Cancel
Save