set immutable option correctly - fixes #1968

pull/1982/head
Richard Harris 7 years ago
parent a8f905f933
commit 3359b5fb3a

@ -1030,20 +1030,29 @@ export default class Component {
} }
function process_meta(component, nodes) { function process_meta(component, nodes) {
const meta: Meta = {}; const meta: Meta = {
immutable: component.options.immutable || false
};
const node = nodes.find(node => node.name === 'svelte:meta'); const node = nodes.find(node => node.name === 'svelte:meta');
function get_value(attribute, message) { function get_value(attribute, code, message) {
const { name, value } = attribute; const { value } = attribute;
const chunk = value[0];
if (value.length > 1 || (value[0] && value[0].type !== 'Text')) { if (!chunk) return true;
component.error(attribute, {
code: `invalid-${name}-attribute`, if (value.length > 1) {
message component.error(attribute, { code, message });
}); }
if (chunk.type === 'Text') return chunk.data;
if (chunk.expression.type !== 'Literal') {
component.error(attribute, { code, message });
} }
return value[0] ? value[0].data : true; return chunk.expression.value;
} }
if (node) { if (node) {
@ -1052,8 +1061,12 @@ function process_meta(component, nodes) {
const { name } = attribute; const { name } = attribute;
switch (name) { switch (name) {
case 'tag': case 'tag': {
const tag = get_value(attribute, `'tag' must be a string literal`); const code = 'invalid-tag-attribute';
const message = `'tag' must be a string literal`;
const tag = get_value(attribute, code, message);
if (typeof tag !== 'string') component.error({ code, message });
if (!/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) { if (!/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
component.error(attribute, { component.error(attribute, {
@ -1064,9 +1077,14 @@ function process_meta(component, nodes) {
meta.tag = tag; meta.tag = tag;
break; break;
}
case 'namespace': {
const code = 'invalid-namespace-attribute';
const message = `The 'namespace' attribute must be a string literal representing a valid namespace`;
const ns = get_value(attribute, code, message);
case 'namespace': if (typeof ns !== 'string') component.error({ code, message });
const ns = get_value(attribute, `The 'namespace' attribute must be a string literal representing a valid namespace`);
if (validNamespaces.indexOf(ns) === -1) { if (validNamespaces.indexOf(ns) === -1) {
const match = fuzzymatch(ns, validNamespaces); const match = fuzzymatch(ns, validNamespaces);
@ -1085,9 +1103,16 @@ function process_meta(component, nodes) {
meta.namespace = ns; meta.namespace = ns;
break; break;
}
case 'immutable': case 'immutable':
meta.immutable = get_value(attribute, `immutable attribute must be true or false`) !== 'false'; const code = `invalid-immutable-value`;
const message = `immutable attribute must be true or false`
const value = get_value(attribute, code, message);
if (typeof value !== 'boolean') component.error({ code, message });
meta.immutable = value;
break; break;
default: default:

@ -87,7 +87,7 @@ export default function dom(
const body = []; const body = [];
const not_equal = component.options.immutable ? `@not_equal` : `@safe_not_equal`; const not_equal = component.meta.immutable ? `@not_equal` : `@safe_not_equal`;
let dev_props_check; let dev_props_check;
component.props.forEach(x => { component.props.forEach(x => {

@ -0,0 +1,10 @@
export default {
immutable: true,
html: `<div><h3>Called 1 times.</h3></div>`,
test({ assert, component, target }) {
component.foo = component.foo;
assert.htmlEqual(target.innerHTML, `<div><h3>Called 1 times.</h3></div>`);
}
};

@ -1,6 +1,8 @@
<script> <script>
export let count = 0; export let count = 0;
export let foo = { bar: 'baz' }; export let foo = { bar: 'baz' };
$: if (foo) count += 1;
</script> </script>
<div> <div>

@ -1,17 +0,0 @@
export default {
immutable: true,
html: `<div><h3>Called 0 times.</h3></div>`,
test({ assert, component, target, window }) {
component.$on('state', ({ changed }) => {
if (changed.foo) {
component.count = component.count + 1;
}
});
assert.htmlEqual(target.innerHTML, `<div><h3>Called 0 times.</h3></div>`);
component.foo = component.foo;
assert.htmlEqual(target.innerHTML, `<div><h3>Called 0 times.</h3></div>`);
}
};

@ -0,0 +1,10 @@
export default {
immutable: true,
html: `<div><h3>Called 1 times.</h3></div>`,
test({ assert, component, target }) {
component.foo = component.foo;
assert.htmlEqual(target.innerHTML, `<div><h3>Called 2 times.</h3></div>`);
}
};

@ -0,0 +1,12 @@
<svelte:meta immutable={false}/>
<script>
export let count = 0;
export let foo = { bar: 'baz' };
$: if (foo) count += 1;
</script>
<div>
<h3>Called {count} times.</h3>
</div>

@ -0,0 +1,8 @@
export default {
html: `<div><h3>Called 1 times.</h3></div>`,
test({ assert, component, target }) {
component.foo = component.foo;
assert.htmlEqual(target.innerHTML, `<div><h3>Called 1 times.</h3></div>`);
}
};

@ -0,0 +1,12 @@
<svelte:meta immutable/>
<script>
export let count = 0;
export let foo = { bar: 'baz' };
$: if (foo) count += 1;
</script>
<div>
<h3>Called {count} times.</h3>
</div>
Loading…
Cancel
Save