Skip to content

Commit 9a0af96

Browse files
committed
Support invalid JS attributes when passing data to components and on binding attributes, too
1 parent c641ce4 commit 9a0af96

File tree

7 files changed

+98
-19
lines changed

7 files changed

+98
-19
lines changed

src/compile/nodes/Component.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import stringifyProps from '../../utils/stringifyProps';
55
import CodeBuilder from '../../utils/CodeBuilder';
66
import getTailSnippet from '../../utils/getTailSnippet';
77
import getObject from '../../utils/getObject';
8-
import { quoteNameIfNecessary } from '../../utils/quoteIfNecessary';
8+
import { quoteNameIfNecessary, quotePropIfNecessary } from '../../utils/quoteIfNecessary';
99
import { escape, escapeTemplate, stringify } from '../../utils/stringify';
1010
import Node from './shared/Node';
1111
import Block from '../dom/Block';
@@ -219,7 +219,7 @@ export default class Component extends Node {
219219
updates.push(deindent`
220220
if (${[...attribute.dependencies]
221221
.map(dependency => `changed.${dependency}`)
222-
.join(' || ')}) ${name_changes}.${attribute.name} = ${attribute.getValue()};
222+
.join(' || ')}) ${name_changes}${quotePropIfNecessary(attribute.name)} = ${attribute.getValue()};
223223
`);
224224
}
225225
});
@@ -250,10 +250,10 @@ export default class Component extends Node {
250250

251251
const lhs = binding.value.node.type === 'MemberExpression'
252252
? binding.value.snippet
253-
: `${head}${tail} = childState.${binding.name}`;
253+
: `${head}${tail} = childState${quotePropIfNecessary(binding.name)}`;
254254

255255
setFromChild = deindent`
256-
${lhs} = childState.${binding.name};
256+
${lhs} = childState${quotePropIfNecessary(binding.name)};
257257
258258
${[...binding.value.dependencies]
259259
.map((name: string) => {
@@ -264,7 +264,7 @@ export default class Component extends Node {
264264
if (isStoreProp) hasStoreBindings = true;
265265
else hasLocalBindings = true;
266266
267-
return `${newState}.${prop} = ctx.${name};`;
267+
return `${newState}${quotePropIfNecessary(prop)} = ctx${quotePropIfNecessary(name)};`;
268268
})}
269269
`;
270270
}
@@ -279,32 +279,32 @@ export default class Component extends Node {
279279

280280
if (binding.value.node.type === 'MemberExpression') {
281281
setFromChild = deindent`
282-
${binding.value.snippet} = childState.${binding.name};
283-
${newState}.${prop} = ctx.${key};
282+
${binding.value.snippet} = childState${quotePropIfNecessary(binding.name)};
283+
${newState}${quotePropIfNecessary(prop)} = ctx${quotePropIfNecessary(key)};
284284
`;
285285
}
286286

287287
else {
288-
setFromChild = `${newState}.${prop} = childState.${binding.name};`;
288+
setFromChild = `${newState}${quotePropIfNecessary(prop)} = childState${quotePropIfNecessary(binding.name)};`;
289289
}
290290
}
291291

292292
statements.push(deindent`
293293
if (${binding.value.snippet} !== void 0) {
294-
${name_initial_data}.${binding.name} = ${binding.value.snippet};
295-
${name_updating}.${binding.name} = true;
294+
${name_initial_data}${quotePropIfNecessary(binding.name)} = ${binding.value.snippet};
295+
${name_updating}${quotePropIfNecessary(binding.name)} = true;
296296
}`
297297
);
298298

299299
builder.addConditional(
300-
`!${name_updating}.${binding.name} && changed.${binding.name}`,
300+
`!${name_updating}${quotePropIfNecessary(binding.name)} && changed${quotePropIfNecessary(binding.name)}`,
301301
setFromChild
302302
);
303303

304304
updates.push(deindent`
305-
if (!${name_updating}.${binding.name} && ${[...binding.value.dependencies].map((dependency: string) => `changed.${dependency}`).join(' || ')}) {
306-
${name_changes}.${binding.name} = ${binding.value.snippet};
307-
${name_updating}.${binding.name} = ${binding.value.snippet} !== void 0;
305+
if (!${name_updating}${quotePropIfNecessary(binding.name)} && ${[...binding.value.dependencies].map((dependency: string) => `changed.${dependency}`).join(' || ')}) {
306+
${name_changes}${quotePropIfNecessary(binding.name)} = ${binding.value.snippet};
307+
${name_updating}${quotePropIfNecessary(binding.name)} = ${binding.value.snippet} !== void 0;
308308
}
309309
`);
310310
});
@@ -329,7 +329,7 @@ export default class Component extends Node {
329329

330330
beforecreate = deindent`
331331
#component.root._beforecreate.push(() => {
332-
${name}._bind({ ${this.bindings.map(b => `${b.name}: 1`).join(', ')} }, ${name}.get());
332+
${name}._bind({ ${this.bindings.map(b => `${quoteNameIfNecessary(b.name)}: 1`).join(', ')} }, ${name}.get());
333333
});
334334
`;
335335
}
@@ -519,7 +519,7 @@ export default class Component extends Node {
519519
? getTailSnippet(binding.value.node)
520520
: '';
521521

522-
return `${binding.name}: ctx.${name}${tail}`;
522+
return `${quoteNameIfNecessary(binding.name)}: ctx${quotePropIfNecessary(name)}${tail}`;
523523
});
524524

525525
function getAttributeValue(attribute) {
@@ -547,14 +547,14 @@ export default class Component extends Node {
547547
if (attribute.isSpread) {
548548
return attribute.expression.snippet;
549549
} else {
550-
return `{ ${attribute.name}: ${getAttributeValue(attribute)} }`;
550+
return `{ ${quoteNameIfNecessary(attribute.name)}: ${getAttributeValue(attribute)} }`;
551551
}
552552
})
553553
.concat(bindingProps.map(p => `{ ${p} }`))
554554
.join(', ')
555555
})`
556556
: `{ ${this.attributes
557-
.map(attribute => `${attribute.name}: ${getAttributeValue(attribute)}`)
557+
.map(attribute => `${quoteNameIfNecessary(attribute.name)}: ${getAttributeValue(attribute)}`)
558558
.concat(bindingProps)
559559
.join(', ')} }`;
560560

@@ -585,7 +585,7 @@ export default class Component extends Node {
585585
if (${conditions.reverse().join('&&')}) {
586586
tmp = ${expression}.data();
587587
if ('${name}' in tmp) {
588-
ctx.${binding.name} = tmp.${name};
588+
ctx${quotePropIfNecessary(binding.name)} = tmp.${name};
589589
settled = false;
590590
}
591591
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<button on:click='set({ "x-count": state["x-count"] + 1 })'>+1</button>
2+
3+
<script>
4+
export default {
5+
data: () => ({
6+
"x-count": 0
7+
}),
8+
computed: {
9+
state(arg) {
10+
return arg;
11+
}
12+
}
13+
};
14+
</script>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export default {
2+
'skip-ssr': true, // TODO delete this line, once binding works
3+
4+
html: `
5+
<button>+1</button>
6+
<p>count: 0</p>
7+
`,
8+
9+
test ( assert, component, target, window ) {
10+
const click = new window.MouseEvent( 'click' );
11+
const button = target.querySelector( 'button' );
12+
13+
button.dispatchEvent( click );
14+
15+
assert.equal( component.get().x, 1 );
16+
assert.htmlEqual( target.innerHTML, `
17+
<button>+1</button>
18+
<p>count: 1</p>
19+
` );
20+
21+
button.dispatchEvent( click );
22+
23+
assert.equal( component.get().x, 2 );
24+
assert.htmlEqual( target.innerHTML, `
25+
<button>+1</button>
26+
<p>count: 2</p>
27+
` );
28+
}
29+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Counter bind:x-count='x'/>
2+
<p>count: {x}</p>
3+
4+
<script>
5+
import Counter from './Counter.html';
6+
7+
export default {
8+
components: {
9+
Counter
10+
}
11+
};
12+
</script>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<p>{state["b-c"]}</p>
2+
<script>
3+
export default {
4+
computed: {
5+
state(states) {
6+
return states;
7+
}
8+
}
9+
};
10+
</script>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
html: '<div><p>i am a widget</p></div>'
3+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<div>
2+
<Widget b-c="i am a widget"/>
3+
</div>
4+
5+
<script>
6+
import Widget from './Widget.html';
7+
8+
export default {
9+
components: { Widget }
10+
};
11+
</script>

0 commit comments

Comments
 (0)