start work on refs and lifecycle

pull/1864/head
Rich Harris 7 years ago
parent 6a752a5675
commit 9f586a9aed

@ -0,0 +1,3 @@
import { onprops, onmount, onupdate, ondestroy } from './internal.js';
export { onprops, onmount, onupdate, ondestroy };

30
package-lock.json generated

@ -553,7 +553,7 @@
}, },
"camelcase-keys": { "camelcase-keys": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -918,7 +918,7 @@
"dependencies": { "dependencies": {
"domelementtype": { "domelementtype": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
"dev": true "dev": true
} }
@ -926,7 +926,7 @@
}, },
"domelementtype": { "domelementtype": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
"integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
"dev": true "dev": true
}, },
@ -1423,7 +1423,7 @@
}, },
"fast-deep-equal": { "fast-deep-equal": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
"dev": true "dev": true
}, },
@ -2422,7 +2422,7 @@
}, },
"is-builtin-module": { "is-builtin-module": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -2795,7 +2795,7 @@
}, },
"load-json-file": { "load-json-file": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -2895,7 +2895,7 @@
}, },
"meow": { "meow": {
"version": "3.7.0", "version": "3.7.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -2913,7 +2913,7 @@
"dependencies": { "dependencies": {
"load-json-file": { "load-json-file": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -3092,7 +3092,7 @@
}, },
"multiline": { "multiline": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/multiline/-/multiline-1.0.2.tgz", "resolved": "http://registry.npmjs.org/multiline/-/multiline-1.0.2.tgz",
"integrity": "sha1-abHyX/B00oKJBPJE3dBrfZbvbJM=", "integrity": "sha1-abHyX/B00oKJBPJE3dBrfZbvbJM=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -5473,7 +5473,7 @@
}, },
"pify": { "pify": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true "dev": true
}, },
@ -5962,7 +5962,7 @@
}, },
"rollup-plugin-typescript": { "rollup-plugin-typescript": {
"version": "0.8.1", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-0.8.1.tgz", "resolved": "http://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-0.8.1.tgz",
"integrity": "sha1-L/fuzCHPa7K0P8J+W2iJUs5xkko=", "integrity": "sha1-L/fuzCHPa7K0P8J+W2iJUs5xkko=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -5981,7 +5981,7 @@
}, },
"rollup-pluginutils": { "rollup-pluginutils": {
"version": "1.5.2", "version": "1.5.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", "resolved": "http://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz",
"integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -6156,7 +6156,7 @@
}, },
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -6462,7 +6462,7 @@
}, },
"through": { "through": {
"version": "2.3.8", "version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true "dev": true
}, },
@ -6484,7 +6484,7 @@
}, },
"readable-stream": { "readable-stream": {
"version": "1.1.14", "version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dev": true, "dev": true,
"requires": { "requires": {

@ -2,7 +2,7 @@
"name": "svelte", "name": "svelte",
"version": "2.15.1", "version": "2.15.1",
"description": "The magical disappearing UI framework", "description": "The magical disappearing UI framework",
"main": "compiler/svelte.js", "main": "index.js",
"bin": { "bin": {
"svelte": "svelte" "svelte": "svelte"
}, },
@ -10,10 +10,8 @@
"cli", "cli",
"compiler/*.js", "compiler/*.js",
"ssr/*.js", "ssr/*.js",
"shared.js", "index.js",
"store.js", "internal.js",
"store.umd.js",
"store.d.ts",
"svelte", "svelte",
"README.md" "README.md"
], ],

@ -107,19 +107,26 @@ export default function dom(
customElements.define("${component.tag}", ${name}); customElements.define("${component.tag}", ${name});
`); `);
} else { } else {
const refs = Array.from(component.refs);
builder.addBlock(deindent` builder.addBlock(deindent`
class ${name} extends @SvelteComponent { class ${name} extends @SvelteComponent {
$$init($$set_inject_props, $$set_inject_refs, $$make_dirty) { $$init($$make_dirty) {
${component.javascript || component.exports.map(x => `let ${x.name};`)} ${component.javascript || component.exports.map(x => `let ${x.name};`)}
$$set_inject_props(props => { return [
// TODO only do this for export let|var () => ({ ${(component.declarations).join(', ')} }),
${(component.exports.map(name => props => {
`if ('${name.as}' in props) ${name.as} = props.${name.as};` // TODO only do this for export let|var
))} ${(component.exports.map(name =>
}); `if ('${name.as}' in props) ${name.as} = props.${name.as};`
))}
return () => ({ ${(component.declarations).join(', ')} }); },
refs => {
// TODO only if we have some refs
${refs.map(name => `${name} = refs.${name};`)}
}
];
} }
$$create_fragment(${component.alias('component')}, ctx) { $$create_fragment(${component.alias('component')}, ctx) {
@ -128,7 +135,7 @@ export default function dom(
${component.exports.map(x => deindent` ${component.exports.map(x => deindent`
get ${x.as}() { get ${x.as}() {
return this.$$get_state().${x.name}; return this.$$.get_state().${x.name};
} }
set ${x.as}(value) { set ${x.as}(value) {

@ -688,7 +688,7 @@ export default class ElementWrapper extends Wrapper {
} }
addRef(block: Block) { addRef(block: Block) {
const ref = `#component.refs.${this.node.ref.name}`; const ref = `#component.$$refs.${this.node.ref.name}`;
block.builders.mount.addLine( block.builders.mount.addLine(
`${ref} = ${this.var};` `${ref} = ${this.var};`

@ -347,7 +347,7 @@ export default class InlineComponentWrapper extends Wrapper {
block.builders.mount.addBlock(deindent` block.builders.mount.addBlock(deindent`
if (${name}) { if (${name}) {
${name}.$$mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'}); ${name}.$$mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});
${this.node.ref && `#component.refs.${this.node.ref.name} = ${name};`} ${this.node.ref && `#component.$$refs.${this.node.ref.name} = ${name};`}
} }
`); `);
@ -392,12 +392,12 @@ export default class InlineComponentWrapper extends Wrapper {
${name}.on("${handler.name}", ${handler.var}); ${name}.on("${handler.name}", ${handler.var});
`)} `)}
${this.node.ref && `#component.refs.${this.node.ref.name} = ${name};`} ${this.node.ref && `#component.$$refs.${this.node.ref.name} = ${name};`}
} else { } else {
${name} = null; ${name} = null;
${this.node.ref && deindent` ${this.node.ref && deindent`
if (#component.refs.${this.node.ref.name} === ${name}) { if (#component.$$refs.${this.node.ref.name} === ${name}) {
#component.refs.${this.node.ref.name} = null; #component.$$refs.${this.node.ref.name} = null;
}`} }`}
} }
} }
@ -434,7 +434,7 @@ export default class InlineComponentWrapper extends Wrapper {
}); });
`)} `)}
${this.node.ref && `#component.refs.${this.node.ref.name} = ${name};`} ${this.node.ref && `#component.$$refs.${this.node.ref.name} = ${name};`}
`); `);
block.builders.create.addLine(`${name}.$$fragment.c();`); block.builders.create.addLine(`${name}.$$fragment.c();`);
@ -459,7 +459,7 @@ export default class InlineComponentWrapper extends Wrapper {
block.builders.destroy.addLine(deindent` block.builders.destroy.addLine(deindent`
${name}.$destroy(${parentNode ? '' : 'detach'}); ${name}.$destroy(${parentNode ? '' : 'detach'});
${this.node.ref && `if (#component.refs.${this.node.ref.name} === ${name}) #component.refs.${this.node.ref.name} = null;`} ${this.node.ref && `if (#component.$$refs.${this.node.ref.name} === ${name}) #component.$$refs.${this.node.ref.name} = null;`}
`); `);
} }

@ -1,21 +1,31 @@
import { schedule_update, flush } from './scheduler'; import { schedule_update, flush } from './scheduler.js';
import { set_current_component } from './lifecycle.js'
import { run_all } from '../shared/utils.js';
export class SvelteComponent { export class SvelteComponent {
constructor(options) { constructor(options) {
this.$$get_state = this.$$init( this.$$onprops = [];
fn => this.$$inject_props = fn, this.$$onmount = [];
fn => this.$$inject_refs = fn, this.$$onupdate = [];
this.$$ondestroy = [];
set_current_component(this);
const [get_state, inject_props, inject_refs] = this.$$init(
key => this.$$make_dirty(key) key => this.$$make_dirty(key)
); );
this.$$ = { get_state, inject_props, inject_refs };
this.$$refs = {};
this.$$dirty = null; this.$$dirty = null;
this.$$bindingGroups = []; // TODO find a way to not have this here? this.$$bindingGroups = []; // TODO find a way to not have this here?
if (options.props) { if (options.props) {
this.$$inject_props(options.props); this.$$.inject_props(options.props);
} }
this.$$fragment = this.$$create_fragment(this, this.$$get_state()); this.$$fragment = this.$$create_fragment(this, this.$$.get_state());
if (options.target) { if (options.target) {
this.$$mount(options.target); this.$$mount(options.target);
@ -42,19 +52,31 @@ export class SvelteComponent {
$$mount(target, anchor) { $$mount(target, anchor) {
this.$$fragment.c(); this.$$fragment.c();
this.$$fragment.m(target, anchor); this.$$fragment.m(target, anchor);
this.$$.inject_refs(this.$$refs);
const ondestroy = this.$$onmount.map(fn => fn()).filter(Boolean);
this.$$ondestroy.push(...ondestroy);
this.$$onmount = null;
} }
$$set(key, value) { $$set(key, value) {
this.$$inject_props({ [key]: value }); this.$$.inject_props({ [key]: value });
run_all(this.$$onprops);
this.$$make_dirty(key); this.$$make_dirty(key);
} }
$$update() { $$update() {
this.$$fragment.p(this.$$dirty, this.$$get_state()); this.$$fragment.p(this.$$dirty, this.$$.get_state());
this.$$.inject_refs(this.$$refs);
run_all(this.$$onupdate);
this.$$dirty = null; this.$$dirty = null;
} }
$$destroy(detach) { $$destroy(detach) {
this.$$fragment.d(detach); this.$$fragment.d(detach);
run_all(this.$$ondestroy);
// TODO null out other refs
this.$$ondestroy = null;
} }
} }

@ -1,5 +1,6 @@
import { assign, isPromise } from './utils.js'; import { assign, isPromise } from './utils.js';
import { groupOutros } from './transitions.js'; import { groupOutros } from './transitions.js';
import { flush } from '../internal/scheduler.js';
export function handlePromise(promise, info) { export function handlePromise(promise, info) {
var token = info.token = {}; var token = info.token = {};
@ -30,7 +31,10 @@ export function handlePromise(promise, info) {
block.c(); block.c();
block[block.i ? 'i' : 'm'](info.mount(), info.anchor); block[block.i ? 'i' : 'm'](info.mount(), info.anchor);
info.component.root.set({}); // flush any handlers that were created // TODO is some of this redundant?
info.component.$$.inject_refs(info.component.$$refs);
run_all(info.component.$$onupdate);
flush();
} }
info.block = block; info.block = block;

@ -2,6 +2,7 @@ export * from './animations.js';
export * from './await-block.js'; export * from './await-block.js';
export * from './dom.js'; export * from './dom.js';
export * from './keyed-each.js'; export * from './keyed-each.js';
export * from './lifecycle.js';
export * from './scheduler.js'; export * from './scheduler.js';
export * from './spread.js'; export * from './spread.js';
export * from './ssr.js'; export * from './ssr.js';

@ -0,0 +1,21 @@
let current_component;
export function set_current_component(component) {
current_component = component;
}
export function onprops(fn) {
current_component.$$onprops.push(fn);
}
export function onmount(fn) {
current_component.$$onmount.push(fn);
}
export function onupdate(fn) {
current_component.$$onupdate.push(fn);
}
export function ondestroy(fn) {
current_component.$$ondestroy.push(fn);
}

@ -36,3 +36,8 @@ export function exclude(src, prop) {
export function run(fn) { export function run(fn) {
fn(); fn();
} }
export function run_all(fns) {
let i = fns.length;
while (i--) fns[i]();
}
Loading…
Cancel
Save