Merge pull request #1941 from sveltejs/gh-1889

allow reactive store references anywhere in script
pull/1942/head
Rich Harris 7 years ago committed by GitHub
commit 45d375e15d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

18
package-lock.json generated

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "3.0.0-alpha12", "version": "3.0.0-alpha13",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -2806,20 +2806,12 @@
"dev": true "dev": true
}, },
"is-reference": { "is-reference": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.0.tgz", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.1.tgz",
"integrity": "sha512-h37O/IX4efe56o9k41II1ECMqKwtqHa7/12dLDEzJIFux2x15an4WCDb0/eKdmUgRpLJ3bR0DrzDc7vOrVgRDw==", "integrity": "sha512-URlByVARcyP2E2GC7d3Ur702g3vqW391VKCHuF5Goo/M8IT97k4RU/+56OYImwDdX1J/V/VRxECE/wJqB0I2tg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/estree": "0.0.38" "@types/estree": "0.0.39"
},
"dependencies": {
"@types/estree": {
"version": "0.0.38",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.38.tgz",
"integrity": "sha512-F/v7t1LwS4vnXuPooJQGBRKRGIoxWUTmA4VHfqjOccFsNDThD5bfUNpITive6s352O7o384wcpEaDV8rHCehDA==",
"dev": true
}
} }
}, },
"is-typedarray": { "is-typedarray": {

@ -63,7 +63,7 @@
"eslint-plugin-html": "^4.0.3", "eslint-plugin-html": "^4.0.3",
"eslint-plugin-import": "^2.11.0", "eslint-plugin-import": "^2.11.0",
"estree-walker": "^0.6.0", "estree-walker": "^0.6.0",
"is-reference": "^1.1.0", "is-reference": "^1.1.1",
"jsdom": "^11.8.0", "jsdom": "^11.8.0",
"kleur": "^3.0.0", "kleur": "^3.0.0",
"locate-character": "^2.0.5", "locate-character": "^2.0.5",

@ -539,9 +539,43 @@ export default class Component {
this.extract_imports_and_exports(script.content, this.imports, this.props); this.extract_imports_and_exports(script.content, this.imports, this.props);
this.hoist_instance_declarations(); this.hoist_instance_declarations();
this.extract_reactive_declarations(); this.extract_reactive_declarations();
this.extract_reactive_store_references();
this.javascript = this.extract_javascript(script); this.javascript = this.extract_javascript(script);
} }
extract_reactive_store_references() {
// TODO this pattern happens a lot... can we abstract it
// (or better still, do fewer AST walks)?
const component = this;
let { instance_scope: scope, instance_scope_map: map } = this;
walk(this.instance_script.content, {
enter(node, parent) {
if (map.has(node)) {
scope = map.get(node);
}
if (isReference(node, parent)) {
const object = getObject(node);
const { name } = object;
if (name[0] === '$' && !scope.has(name)) {
component.warn_if_undefined(object, null);
// cheeky hack
component.template_references.add(name);
}
}
},
leave(node) {
if (map.has(node)) {
scope = scope.parent;
}
}
});
}
rewrite_props() { rewrite_props() {
const component = this; const component = this;
const { code, instance_scope, instance_scope_map: map, meta } = this; const { code, instance_scope, instance_scope_map: map, meta } = this;
@ -735,7 +769,11 @@ export default class Component {
const { name } = flattenReference(node); const { name } = flattenReference(node);
const owner = scope.findOwner(name); const owner = scope.findOwner(name);
if (owner === instance_scope) { if (name[0] === '$' && !owner) {
hoistable = false;
}
else if (owner === instance_scope) {
if (name === fn_declaration.id.name) return; if (name === fn_declaration.id.name) return;
if (hoistable_names.has(name)) return; if (hoistable_names.has(name)) return;
if (imported_declarations.has(name)) return; if (imported_declarations.has(name)) return;
@ -818,13 +856,7 @@ export default class Component {
const object = getObject(node); const object = getObject(node);
const { name } = object; const { name } = object;
if (component.declarations.indexOf(name) !== -1) { if (name[0] === '$' || component.declarations.indexOf(name) !== -1) {
dependencies.add(name);
} else if (name[0] === '$') {
component.warn_if_undefined(object, null);
// cheeky hack
component.template_references.add(name);
dependencies.add(name); dependencies.add(name);
} }

@ -0,0 +1,26 @@
import { writable } from '../../../../store.js';
const count = writable(0);
export default {
props: {
count
},
html: `
<button>+1</button>
`,
async test({ assert, component, target, window }) {
assert.equal(component.get_count(), 0);
const button = target.querySelector('button');
const click = new window.MouseEvent('click');
await button.dispatchEvent(click);
assert.equal(component.get_count(), 1);
await count.set(42);
assert.equal(component.get_count(), 42);
}
};

@ -0,0 +1,9 @@
<script>
export let count;
export function get_count() {
return $count;
}
</script>
<button on:click="{() => count.update(n => n + 1)}">+1</button>
Loading…
Cancel
Save