diff --git a/src/compile/Component.ts b/src/compile/Component.ts index 1b843e9ca2..c4695abcec 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -839,6 +839,13 @@ export default class Component { current_group.declarators.push(declarator); } + + if (next) { + const next_variable = component.var_lookup.get(next.id.name) + if (next_variable && !next_variable.export_name) { + code.overwrite(declarator.end, next.start, ` ${node.kind} `); + } + } } else { current_group = null; @@ -1042,15 +1049,17 @@ export default class Component { } if (node.type === 'AssignmentExpression') { - assignees.add(getObject(node.left).name); + const { name } = getObject(node.left) + assignees.add(name); + dependencies.delete(name); } else if (node.type === 'UpdateExpression') { - assignees.add(getObject(node.argument).name); + const { name } = getObject(node.argument); + assignees.add(name); + dependencies.delete(name); } else if (isReference(node, parent)) { - const object = getObject(node); - const { name } = object; - + const { name } = getObject(node); const owner = scope.findOwner(name); - if ((!owner || owner === component.instance_scope) && (name[0] === '$' || component.var_lookup.has(name))) { + if ((!owner || owner === component.instance_scope) && (name[0] === '$' || component.var_lookup.has(name)) && !assignees.has(name)) { dependencies.add(name); } diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts index 24378b180c..33d84b2009 100644 --- a/src/compile/nodes/Element.ts +++ b/src/compile/nodes/Element.ts @@ -18,7 +18,7 @@ import TemplateScope from './shared/TemplateScope'; const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; -const ariaAttributes = 'activedescendant atomic autocomplete busy checked controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); +const ariaAttributes = 'activedescendant atomic autocomplete busy checked colindex controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowindex selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const ariaAttributeSet = new Set(ariaAttributes); const ariaRoles = 'alert alertdialog application article banner button cell checkbox columnheader combobox command complementary composite contentinfo definition dialog directory document feed figure form grid gridcell group heading img input landmark link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option presentation progressbar radio radiogroup range region roletype row rowgroup rowheader scrollbar search searchbox section sectionhead select separator slider spinbutton status structure switch tab table tablist tabpanel term textbox timer toolbar tooltip tree treegrid treeitem widget window'.split(' '); diff --git a/src/parse/state/mustache.ts b/src/parse/state/mustache.ts index 980ec8555a..bdeb8bdede 100644 --- a/src/parse/state/mustache.ts +++ b/src/parse/state/mustache.ts @@ -316,6 +316,8 @@ export default function mustache(parser: Parser) { } } else if (parser.eat('@html')) { // {@html content} tag + parser.requireWhitespace(); + const expression = readExpression(parser); parser.allowWhitespace(); diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js index e3dff9649d..dcd1078a6d 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -56,8 +56,8 @@ function instance($$self, $$props, $$invalidate) { if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo); }; - $$self.$$.update = ($$dirty = { bar: 1, foo: 1 }) => { - if ($$dirty.bar || $$dirty.foo) { + $$self.$$.update = ($$dirty = { foo: 1 }) => { + if ($$dirty.foo) { bar = foo * 2; $$invalidate('bar', bar); } }; diff --git a/test/js/samples/reactive-values-non-topologically-ordered/expected.js b/test/js/samples/reactive-values-non-topologically-ordered/expected.js index de1a4cdc8c..edf98e9613 100644 --- a/test/js/samples/reactive-values-non-topologically-ordered/expected.js +++ b/test/js/samples/reactive-values-non-topologically-ordered/expected.js @@ -22,11 +22,11 @@ function instance($$self, $$props, $$invalidate) { if ('x' in $$props) $$invalidate('x', x = $$props.x); }; - $$self.$$.update = ($$dirty = { b: 1, x: 1, a: 1 }) => { - if ($$dirty.b || $$dirty.x) { + $$self.$$.update = ($$dirty = { x: 1, b: 1 }) => { + if ($$dirty.x) { b = x; $$invalidate('b', b); } - if ($$dirty.a || $$dirty.b) { + if ($$dirty.b) { a = b; $$invalidate('a', a); } }; diff --git a/test/js/samples/reactive-values-non-writable-dependencies/expected.js b/test/js/samples/reactive-values-non-writable-dependencies/expected.js index fc2ca37d31..42f57a0037 100644 --- a/test/js/samples/reactive-values-non-writable-dependencies/expected.js +++ b/test/js/samples/reactive-values-non-writable-dependencies/expected.js @@ -17,12 +17,12 @@ let a = 1; let b = 2; function instance($$self, $$props, $$invalidate) { - + let max; - $$self.$$.update = ($$dirty = { max: 1, Math: 1, a: 1, b: 1 }) => { - if ($$dirty.max || $$dirty.a || $$dirty.b) { + $$self.$$.update = ($$dirty = { Math: 1, a: 1, b: 1 }) => { + if ($$dirty.a || $$dirty.b) { max = Math.max(a, b); $$invalidate('max', max); } }; diff --git a/test/parser/samples/raw-mustaches-whitespace-error/error.json b/test/parser/samples/raw-mustaches-whitespace-error/error.json new file mode 100644 index 0000000000..abb9f8ed0f --- /dev/null +++ b/test/parser/samples/raw-mustaches-whitespace-error/error.json @@ -0,0 +1,10 @@ +{ + "code": "missing-whitespace", + "message": "Expected whitespace", + "start": { + "line": 1, + "column": 6, + "character": 6 + }, + "pos": 6 +} diff --git a/test/parser/samples/raw-mustaches-whitespace-error/input.svelte b/test/parser/samples/raw-mustaches-whitespace-error/input.svelte new file mode 100644 index 0000000000..94e75fda09 --- /dev/null +++ b/test/parser/samples/raw-mustaches-whitespace-error/input.svelte @@ -0,0 +1 @@ +{@htmlfoo} diff --git a/test/runtime/samples/mixed-let-export/_config.js b/test/runtime/samples/mixed-let-export/_config.js new file mode 100644 index 0000000000..5ac8585742 --- /dev/null +++ b/test/runtime/samples/mixed-let-export/_config.js @@ -0,0 +1,9 @@ +export default { + props: { + a: 42 + }, + + html: ` + 42 + ` +} diff --git a/test/runtime/samples/mixed-let-export/main.svelte b/test/runtime/samples/mixed-let-export/main.svelte new file mode 100644 index 0000000000..659c73a860 --- /dev/null +++ b/test/runtime/samples/mixed-let-export/main.svelte @@ -0,0 +1,7 @@ + + +{a} diff --git a/test/runtime/samples/reactive-values-readonly/_config.js b/test/runtime/samples/reactive-values-overwrite/_config.js similarity index 76% rename from test/runtime/samples/reactive-values-readonly/_config.js rename to test/runtime/samples/reactive-values-overwrite/_config.js index bf5c9dbb67..644a49ec0d 100644 --- a/test/runtime/samples/reactive-values-readonly/_config.js +++ b/test/runtime/samples/reactive-values-overwrite/_config.js @@ -11,11 +11,11 @@ export default {
doubled: 4
`); - component.doubled = 6; + component.doubled = 3; - assert.equal(component.doubled, 4); + assert.equal(component.doubled, 3); assert.htmlEqual(target.innerHTML, ` -doubled: 4
+doubled: 3
`); } }; diff --git a/test/runtime/samples/reactive-values-readonly/main.svelte b/test/runtime/samples/reactive-values-overwrite/main.svelte similarity index 100% rename from test/runtime/samples/reactive-values-readonly/main.svelte rename to test/runtime/samples/reactive-values-overwrite/main.svelte diff --git a/test/runtime/samples/reactive-values-subscript-assignment/_config.js b/test/runtime/samples/reactive-values-subscript-assignment/_config.js new file mode 100644 index 0000000000..e29fe2c676 --- /dev/null +++ b/test/runtime/samples/reactive-values-subscript-assignment/_config.js @@ -0,0 +1,11 @@ +export default { + test({ assert, component }) { + assert.deepEqual(component.foo, {}); + component.bar = 'hello'; + assert.deepEqual(component.foo, { hello: true }); + component.bar = 'world'; + assert.deepEqual(component.foo, { hello: true, world: true }); + component.bar = false; + assert.deepEqual(component.foo, { hello: true, world: true }); + } +}; diff --git a/test/runtime/samples/reactive-values-subscript-assignment/main.svelte b/test/runtime/samples/reactive-values-subscript-assignment/main.svelte new file mode 100644 index 0000000000..9753032618 --- /dev/null +++ b/test/runtime/samples/reactive-values-subscript-assignment/main.svelte @@ -0,0 +1,7 @@ +