Merge pull request #709 from sveltejs/gh-708

[WIP] Fix #708
pull/723/head
Rich Harris 8 years ago committed by GitHub
commit 1474556dc1

@ -125,9 +125,6 @@ export default function dom(
@dispatchObservers( this, this._observers.pre, newState, oldState );
${block.hasUpdateMethod && `this._fragment.update( newState, this._state );`}
@dispatchObservers( this, this._observers.post, newState, oldState );
${generator.hasComponents && `@callAll(this._oncreate);`}
${generator.hasComplexBindings && `@callAll(this._bindings);`}
${generator.hasIntroTransitions && `@callAll(this._postcreate);`}
`;
if (hasJs) {
@ -207,9 +204,20 @@ export default function dom(
${generator.stylesheet.hasStyles &&
options.css !== false &&
`if ( !document.getElementById( '${generator.stylesheet.id}-style' ) ) @add_css();`}
${generator.hasComponents && `this._oncreate = [];`}
${generator.hasComplexBindings && `this._bindings = [];`}
${generator.hasIntroTransitions && `this._postcreate = [];`}
${templateProperties.oncreate && `var oncreate = @template.oncreate.bind( this );`}
${(templateProperties.oncreate || generator.hasComponents || generator.hasComplexBindings || generator.hasIntroTransitions) && deindent`
if ( !options._root ) {
this._oncreate = [${templateProperties.oncreate && `oncreate`}];
${(generator.hasComponents || generator.hasComplexBindings) && `this._beforecreate = [];`}
${(generator.hasComponents || generator.hasIntroTransitions) && `this._aftercreate = [];`}
} ${templateProperties.oncreate && deindent`
else {
this._root._oncreate.push(oncreate);
}
`}
`}
this._fragment = @create_main_fragment( this._state, this );
@ -226,18 +234,16 @@ export default function dom(
`}
this._fragment.${block.hasIntroMethod ? 'intro' : 'mount'}( options.target, null );
}
${generator.hasComponents && `@callAll(this._oncreate);`}
${generator.hasComplexBindings && `@callAll(this._bindings);`}
${templateProperties.oncreate && deindent`
if ( options._root ) {
options._root._oncreate.push( @template.oncreate.bind( this ) );
} else {
@template.oncreate.call( this );
}`}
${generator.hasIntroTransitions && `@callAll(this._postcreate);`}
${(generator.hasComponents || generator.hasComplexBindings || templateProperties.oncreate || generator.hasIntroTransitions) && deindent`
if ( !options._root ) {
${generator.hasComponents && `this._lock = true;`}
${(generator.hasComponents || generator.hasComplexBindings) && `@callAll(this._beforecreate);`}
${(generator.hasComponents || templateProperties.oncreate) && `@callAll(this._oncreate);`}
${(generator.hasComponents || generator.hasIntroTransitions) && `@callAll(this._aftercreate);`}
${generator.hasComponents && `this._lock = false;`}
}
`}
}
@assign( ${prototypeBase}, ${proto});

@ -66,15 +66,24 @@ export default function visitBinding(
const updating = block.getUniqueName(`${local.name}_updating`);
block.addVariable(updating, 'false');
const observer = block.getUniqueName('observer');
const value = block.getUniqueName('value');
local.create.addBlock(deindent`
#component._bindings.push( function () {
if ( ${local.name}._torndown ) return;
${local.name}.observe( '${attribute.name}', function ( value ) {
if ( ${updating} ) return;
${updating} = true;
${setter}
${updating} = false;
}, { init: @differs( ${local.name}.get( '${attribute.name}' ), ${snippet} ) });
function ${observer} ( value ) {
if ( ${updating} ) return;
${updating} = true;
${setter}
${updating} = false;
}
${local.name}.observe( '${attribute.name}', ${observer}, { init: false });
#component._root._beforecreate.push( function () {
var value = ${local.name}.get( '${attribute.name}' );
if ( @differs( value, ${snippet} ) ) {
${observer}.call( ${local.name}, value );
}
});
`);

@ -94,7 +94,7 @@ export default function visitBinding(
generator.hasComplexBindings = true;
block.builders.hydrate.addBlock(
`if ( !('${name}' in state) ) #component._bindings.push( ${handler} );`
`if ( !('${name}' in state) ) #component._root._beforecreate.push( ${handler} );`
);
} else if (attribute.name === 'group') {
// <input type='checkbox|radio' bind:group='selected'> special case
@ -120,7 +120,7 @@ export default function visitBinding(
updateElement = `${state.parentNode}.checked = ${condition};`;
} else if (node.name === 'audio' || node.name === 'video') {
generator.hasComplexBindings = true;
block.builders.hydrate.addBlock(`#component._bindings.push( ${handler} );`);
block.builders.hydrate.addBlock(`#component._root._beforecreate.push( ${handler} );`);
if (attribute.name === 'currentTime') {
const frame = block.getUniqueName(`${state.parentNode}_animationframe`);

@ -23,7 +23,7 @@ export default function addTransitions(
const fn = `@template.transitions.${intro.name}`;
block.builders.intro.addBlock(deindent`
#component._postcreate.push( function () {
#component._root._aftercreate.push( function () {
if ( !${name} ) ${name} = @wrapTransition( #component, ${state.name}, ${fn}, ${snippet}, true, null );
${name}.run( true, function () {
#component.fire( 'intro.end', { node: ${state.name} });
@ -58,7 +58,7 @@ export default function addTransitions(
}
block.builders.intro.addBlock(deindent`
#component._postcreate.push( function () {
#component._root._aftercreate.push( function () {
${introName} = @wrapTransition( #component, ${state.name}, ${fn}, ${snippet}, true, null );
${introName}.run( true, function () {
#component.fire( 'intro.end', { node: ${state.name} });

@ -27,10 +27,10 @@ export default function getSetter({
list[index]${tail} = ${value};
${computed
? `#component._set({ ${dependencies
? `#component.set({ ${dependencies
.map((prop: string) => `${prop}: state.${prop}`)
.join(', ')} });`
: `#component._set({ ${dependencies
: `#component.set({ ${dependencies
.map((prop: string) => `${prop}: #component.get( '${prop}' )`)
.join(', ')} });`}
`;
@ -40,13 +40,13 @@ export default function getSetter({
return deindent`
var state = #component.get();
${snippet} = ${value};
#component._set({ ${dependencies
#component.set({ ${dependencies
.map((prop: string) => `${prop}: state.${prop}`)
.join(', ')} });
`;
}
return `#component._set({ ${name}: ${value} });`;
return `#component.set({ ${name}: ${value} });`;
}
function isComputed(node: Node) {

@ -106,7 +106,12 @@ export function onDev(eventName, handler) {
export function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
export function callAll(fns) {

@ -115,7 +115,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -91,7 +91,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -124,7 +124,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -109,7 +109,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -115,7 +115,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -115,7 +115,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -103,7 +103,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {
@ -178,7 +183,12 @@ function SvelteComponent ( options ) {
this._yield = options._yield;
this._torndown = false;
this._oncreate = [];
if ( !options._root ) {
this._oncreate = [];
this._beforecreate = [];
this._aftercreate = [];
}
this._fragment = create_main_fragment( this._state, this );
@ -187,7 +197,13 @@ function SvelteComponent ( options ) {
this._fragment.mount( options.target, null );
}
callAll(this._oncreate);
if ( !options._root ) {
this._lock = true;
callAll(this._beforecreate);
callAll(this._oncreate);
callAll(this._aftercreate);
this._lock = false;
}
}
assign( SvelteComponent.prototype, proto );
@ -197,7 +213,6 @@ SvelteComponent.prototype._set = function _set ( newState ) {
this._state = assign( {}, oldState, newState );
dispatchObservers( this, this._observers.pre, newState, oldState );
dispatchObservers( this, this._observers.post, newState, oldState );
callAll(this._oncreate);
};
SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) {

@ -62,7 +62,12 @@ function SvelteComponent ( options ) {
this._yield = options._yield;
this._torndown = false;
this._oncreate = [];
if ( !options._root ) {
this._oncreate = [];
this._beforecreate = [];
this._aftercreate = [];
}
this._fragment = create_main_fragment( this._state, this );
@ -71,7 +76,13 @@ function SvelteComponent ( options ) {
this._fragment.mount( options.target, null );
}
callAll(this._oncreate);
if ( !options._root ) {
this._lock = true;
callAll(this._beforecreate);
callAll(this._oncreate);
callAll(this._aftercreate);
this._lock = false;
}
}
assign( SvelteComponent.prototype, proto );
@ -81,7 +92,6 @@ SvelteComponent.prototype._set = function _set ( newState ) {
this._state = assign( {}, oldState, newState );
dispatchObservers( this, this._observers.pre, newState, oldState );
dispatchObservers( this, this._observers.post, newState, oldState );
callAll(this._oncreate);
};
SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) {

@ -91,7 +91,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {
@ -143,6 +148,14 @@ function SvelteComponent ( options ) {
this._torndown = false;
var oncreate = template.oncreate.bind( this );
if ( !options._root ) {
this._oncreate = [oncreate];
} else {
this._root._oncreate.push(oncreate);
}
this._fragment = create_main_fragment( this._state, this );
if ( options.target ) {
@ -150,10 +163,8 @@ function SvelteComponent ( options ) {
this._fragment.mount( options.target, null );
}
if ( options._root ) {
options._root._oncreate.push( template.oncreate.bind( this ) );
} else {
template.oncreate.call( this );
if ( !options._root ) {
callAll(this._oncreate);
}
}

@ -1,4 +1,4 @@
import { assign, dispatchObservers, noop, proto } from "svelte/shared.js";
import { assign, callAll, dispatchObservers, noop, proto } from "svelte/shared.js";
var template = (function () {
return {
@ -37,6 +37,14 @@ function SvelteComponent ( options ) {
this._torndown = false;
var oncreate = template.oncreate.bind( this );
if ( !options._root ) {
this._oncreate = [oncreate];
} else {
this._root._oncreate.push(oncreate);
}
this._fragment = create_main_fragment( this._state, this );
if ( options.target ) {
@ -44,10 +52,8 @@ function SvelteComponent ( options ) {
this._fragment.mount( options.target, null );
}
if ( options._root ) {
options._root._oncreate.push( template.oncreate.bind( this ) );
} else {
template.oncreate.call( this );
if ( !options._root ) {
callAll(this._oncreate);
}
}

@ -115,7 +115,12 @@ function on(eventName, handler) {
function set(newState) {
this._set(assign({}, newState));
if (this._root._lock) return;
this._root._lock = true;
callAll(this._root._beforecreate);
callAll(this._root._oncreate);
callAll(this._root._aftercreate);
this._root._lock = false;
}
function callAll(fns) {

@ -137,10 +137,9 @@ describe("runtime", () => {
throw err;
}
let usedObjectAssign = false;
Object.assign = () => {
throw new Error(
"cannot use Object.assign in generated code, as it is not supported everywhere"
);
usedObjectAssign = true;
};
global.window = window;
@ -182,14 +181,18 @@ describe("runtime", () => {
assert.htmlEqual(target.innerHTML, config.html);
}
Object.assign = Object_assign;
if (config.test) {
config.test(assert, component, target, window, raf);
} else {
component.destroy();
assert.equal(target.innerHTML, "");
}
if (usedObjectAssign) {
throw new Error(
"cannot use Object.assign in generated code, as it is not supported everywhere"
);
}
})
.catch(err => {
Object.assign = Object_assign;

@ -0,0 +1,18 @@
<li>
{{yield}}
</li>
<script>
const initialValues = {
'id-0': 'zero',
'id-1': 'one',
'id-2': 'two',
'id-3': 'three'
};
export default {
oncreate() {
this.set({ value: initialValues[this.get('id')] });
}
};
</script>

@ -0,0 +1,33 @@
export default {
'skip-ssr': true,
data: {
count: 3
},
html: `
<input type='number'>
<ol>
<li>id-0: value is zero</li>
<li>id-1: value is one</li>
<li>id-2: value is two</li>
</ol>
`,
test (assert, component, target, window) {
const input = target.querySelector('input');
input.value = 4;
input.dispatchEvent(new window.Event('input'));
assert.htmlEqual(target.innerHTML, `
<input type='number'>
<ol>
<li>id-0: value is zero</li>
<li>id-1: value is one</li>
<li>id-2: value is two</li>
<li>id-3: value is three</li>
</ol>
`);
}
};

@ -0,0 +1,33 @@
<input type='number' bind:value='count'>
<ol>
{{#each ids as id}}
<Nested :id bind:value="idToValue[id]">
{{id}}: value is {{idToValue[id]}}
</Nested>
{{/each}}
</ol>
<script>
import Nested from './Nested.html';
export default {
data() {
return {
idToValue: Object.create(null)
};
},
computed: {
ids(count) {
return new Array(count)
.fill(null)
.map((_, i) => 'id-' + i);
}
},
components: {
Nested
}
};
</script>
Loading…
Cancel
Save