more simplification

pull/1934/head
Richard Harris 7 years ago
parent 49db9e7524
commit e0eaf24522

@ -28,6 +28,7 @@ export default class BindingWrapper {
}; };
snippet: string; snippet: string;
initialUpdate: string; initialUpdate: string;
isReadOnly: boolean;
needsLock: boolean; needsLock: boolean;
constructor(block: Block, node: Binding, parent: ElementWrapper) { constructor(block: Block, node: Binding, parent: ElementWrapper) {
@ -66,14 +67,17 @@ export default class BindingWrapper {
this.snippet = this.node.expression.render(); this.snippet = this.node.expression.render();
const isReadOnly = ( const type = parent.node.getStaticAttributeValue('type');
this.isReadOnly = (
dimensions.test(this.node.name) ||
(parent.node.isMediaNode() && readOnlyMediaAttributes.has(this.node.name)) || (parent.node.isMediaNode() && readOnlyMediaAttributes.has(this.node.name)) ||
dimensions.test(this.node.name) (parent.node.name === 'input' && type === 'file') // TODO others?
); );
this.needsLock = !isReadOnly && ( this.needsLock = !this.isReadOnly && (
parent.node.name !== 'input' || // TODO others?
!/radio|checkbox|range|color/.test(parent.node.getStaticAttributeValue('type')) parent.node.name !== 'input'
); );
} }
@ -97,45 +101,47 @@ export default class BindingWrapper {
} }
render(block: Block, lock: string) { render(block: Block, lock: string) {
// bind:offsetWidth and bind:offsetHeight — readonly if (this.isReadOnly) return;
if (dimensions.test(this.node.name)) return;
const { parent } = this; const { parent } = this;
const { renderer } = parent;
let updateConditions: string[] = this.needsLock ? [`!${lock}`] : []; let updateConditions: string[] = this.needsLock ? [`!${lock}`] : [];
// model to view // model to view
let updateDom = getDomUpdater(parent, this); let updateDom = getDomUpdater(parent, this);
let initialUpdate = updateDom;
// special cases // special cases
if (this.node.name === 'group') { switch (this.node.name) {
const bindingGroup = getBindingGroup(renderer, this.node.expression.node); case 'group':
const bindingGroup = getBindingGroup(parent.renderer, this.node.expression.node);
block.builders.hydrate.addLine(
`(#component.$$.binding_groups[${bindingGroup}] || (#component.$$.binding_groups[${bindingGroup}] = [])).push(${parent.var});` block.builders.hydrate.addLine(
); `(#component.$$.binding_groups[${bindingGroup}] || (#component.$$.binding_groups[${bindingGroup}] = [])).push(${parent.var});`
);
block.builders.destroy.addLine(
`#component.$$.binding_groups[${bindingGroup}].splice(#component.$$.binding_groups[${bindingGroup}].indexOf(${parent.var}), 1);` block.builders.destroy.addLine(
); `#component.$$.binding_groups[${bindingGroup}].splice(#component.$$.binding_groups[${bindingGroup}].indexOf(${parent.var}), 1);`
} );
break;
if (this.node.name === 'currentTime' || this.node.name === 'volume') {
updateConditions.push(`!isNaN(${this.snippet})`); case 'currentTime':
case 'volume':
if (this.node.name === 'currentTime') initialUpdate = null; updateConditions.push(`!isNaN(${this.snippet})`);
} break;
if (this.node.name === 'paused') { case 'paused':
// this is necessary to prevent audio restarting by itself // this is necessary to prevent audio restarting by itself
const last = block.getUniqueName(`${parent.var}_is_paused`); const last = block.getUniqueName(`${parent.var}_is_paused`);
block.addVariable(last, 'true'); block.addVariable(last, 'true');
updateConditions.push(`${last} !== (${last} = ${this.snippet})`); updateConditions.push(`${last} !== (${last} = ${this.snippet})`);
updateDom = `${parent.var}[${last} ? "pause" : "play"]();`; updateDom = `${parent.var}[${last} ? "pause" : "play"]();`;
initialUpdate = null; break;
case 'value':
if (parent.getStaticAttributeValue('type') === 'file') {
updateDom = null;
}
} }
const dependencyArray = [...this.node.expression.dynamic_dependencies] const dependencyArray = [...this.node.expression.dynamic_dependencies]
@ -154,8 +160,8 @@ export default class BindingWrapper {
); );
} }
if (initialUpdate) { if (!/(currentTime|paused)/.test(this.node.name)) {
block.builders.mount.addBlock(initialUpdate); block.builders.mount.addBlock(updateDom);
} }
} }
} }

@ -370,13 +370,7 @@ export default class ElementWrapper extends Wrapper {
renderer.component.has_reactive_assignments = true; renderer.component.has_reactive_assignments = true;
const needsLock = this.node.name !== 'input' || !/radio|checkbox|range|color/.test(this.getStaticAttributeValue('type')); const lock = this.bindings.some(binding => binding.needsLock) ?
// TODO munge in constructor
// const mungedBindings = this.bindings.map(binding => binding.munge(block));
const mungedBindings = this.bindings;
const lock = mungedBindings.some(binding => binding.needsLock) ?
block.getUniqueName(`${this.var}_updating`) : block.getUniqueName(`${this.var}_updating`) :
null; null;
@ -385,7 +379,7 @@ export default class ElementWrapper extends Wrapper {
const groups = events const groups = events
.map(event => ({ .map(event => ({
events: event.eventNames, events: event.eventNames,
bindings: mungedBindings bindings: this.bindings
.filter(binding => binding.node.name !== 'this') .filter(binding => binding.node.name !== 'this')
.filter(binding => event.filter(this.node, binding.node.name)) .filter(binding => event.filter(this.node, binding.node.name))
})) }))
@ -411,8 +405,6 @@ export default class ElementWrapper extends Wrapper {
binding.render(block, lock); binding.render(block, lock);
}); });
const mutations = group.bindings.map(binding => binding.handler.mutation).filter(Boolean).join('\n');
// media bindings — awkward special case. The native timeupdate events // media bindings — awkward special case. The native timeupdate events
// fire too infrequently, so we need to take matters into our // fire too infrequently, so we need to take matters into our
// own hands // own hands
@ -422,47 +414,35 @@ export default class ElementWrapper extends Wrapper {
block.addVariable(animation_frame); block.addVariable(animation_frame);
} }
const has_local_function = contextual_dependencies.size > 0 || needsLock || animation_frame;
let callee; let callee;
// TODO dry this out — similar code for event handlers and component bindings // TODO dry this out — similar code for event handlers and component bindings
if (contextual_dependencies.size > 0) { if (has_local_function) {
const deps = Array.from(contextual_dependencies); // need to create a block-local function that calls an instance-level function
block.builders.init.addBlock(deindent` block.builders.init.addBlock(deindent`
function ${handler}() { function ${handler}() {
ctx.${handler}.call(this, ctx); ${animation_frame && deindent`
} cancelAnimationFrame(${animation_frame});
`); if (!${this.var}.paused) ${animation_frame} = requestAnimationFrame(${handler});`}
${needsLock && `${lock} = true;`}
this.renderer.component.partly_hoisted.push(deindent` ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', ctx' : ''});
function ${handler}({ ${deps.join(', ')} }) {
${
animation_frame && deindent`
cancelAnimationFrame(${animation_frame});
if (!${this.var}.paused) ${animation_frame} = requestAnimationFrame(${handler});`
}
${mutations.length > 0 && mutations}
${Array.from(dependencies).map(dep => `$$invalidate('${dep}', ${dep});`)}
} }
`); `);
callee = handler; callee = handler;
} else { } else {
this.renderer.component.partly_hoisted.push(deindent`
function ${handler}() {
${
animation_frame && deindent`
cancelAnimationFrame(${animation_frame});
if (!${this.var}.paused) ${animation_frame} = requestAnimationFrame(${handler});`
}
${mutations.length > 0 && mutations}
${Array.from(dependencies).map(dep => `$$invalidate('${dep}', ${dep});`)}
}
`);
callee = `ctx.${handler}`; callee = `ctx.${handler}`;
} }
this.renderer.component.partly_hoisted.push(deindent`
function ${handler}(${contextual_dependencies.size > 0 ? `{ ${[...contextual_dependencies].join(', ')} }` : ``}) {
${group.bindings.map(b => b.handler.mutation)}
${Array.from(dependencies).map(dep => `$$invalidate('${dep}', ${dep});`)}
}
`);
group.events.forEach(name => { group.events.forEach(name => {
if (name === 'resize') { if (name === 'resize') {
// special case // special case
@ -488,8 +468,9 @@ export default class ElementWrapper extends Wrapper {
.join(' || '); .join(' || ');
if (this.node.name === 'select' || group.bindings.find(binding => binding.node.name === 'indeterminate' || binding.isReadOnlyMediaAttribute())) { if (this.node.name === 'select' || group.bindings.find(binding => binding.node.name === 'indeterminate' || binding.isReadOnlyMediaAttribute())) {
const callback = has_local_function ? handler : `() => ${callee}.call(${this.var})`;
block.builders.hydrate.addLine( block.builders.hydrate.addLine(
`if (${someInitialStateIsUndefined}) @add_render_callback(() => ${callee}.call(${this.var}));` `if (${someInitialStateIsUndefined}) @add_render_callback(${callback});`
); );
} }
@ -500,6 +481,10 @@ export default class ElementWrapper extends Wrapper {
} }
}); });
if (lock) {
block.builders.update.addLine(`${lock} = false;`);
}
const this_binding = this.bindings.find(b => b.node.name === 'this'); const this_binding = this.bindings.find(b => b.node.name === 'this');
if (this_binding) { if (this_binding) {
const name = renderer.component.getUniqueName(`${this.var}_binding`); const name = renderer.component.getUniqueName(`${this.var}_binding`);

@ -1,8 +1,8 @@
/* generated by Svelte vX.Y.Z */ /* generated by Svelte vX.Y.Z */
import { SvelteComponent as SvelteComponent_1, addListener, createElement, detachNode, flush, init, insert, run, safe_not_equal, setAttribute } from "svelte/internal"; import { SvelteComponent as SvelteComponent_1, addListener, createElement, detachNode, flush, init, insert, noop, run, safe_not_equal, setAttribute } from "svelte/internal";
function create_fragment(component, ctx) { function create_fragment(component, ctx) {
var input, input_updating = false, current, dispose; var input, current, dispose;
return { return {
c() { c() {
@ -14,15 +14,10 @@ function create_fragment(component, ctx) {
m(target, anchor) { m(target, anchor) {
insert(target, input, anchor); insert(target, input, anchor);
input.files = ctx.files;
current = true; current = true;
}, },
p(changed, ctx) { p: noop,
if (!input_updating && changed.files) input.files = ctx.files;
},
i(target, anchor) { i(target, anchor) {
if (current) return; if (current) return;

@ -2,55 +2,40 @@
import { SvelteComponent as SvelteComponent_1, addListener, add_render_callback, createElement, detachNode, flush, init, insert, run, run_all, safe_not_equal, timeRangesToArray } from "svelte/internal"; import { SvelteComponent as SvelteComponent_1, addListener, add_render_callback, createElement, detachNode, flush, init, insert, run, run_all, safe_not_equal, timeRangesToArray } from "svelte/internal";
function create_fragment(component, ctx) { function create_fragment(component, ctx) {
var audio, audio_is_paused = true, audio_updating = false, audio_animationframe, current, dispose; var audio, audio_updating = false, audio_animationframe, audio_is_paused = true, current, dispose;
function audio_timeupdate_handler() { function audio_timeupdate_handler() {
cancelAnimationFrame(audio_animationframe); cancelAnimationFrame(audio_animationframe);
if (!audio.paused) audio_animationframe = requestAnimationFrame(audio_timeupdate_handler); if (!audio.paused) audio_animationframe = requestAnimationFrame(audio_timeupdate_handler);
audio_updating = true; audio_updating = true;
ctx.audio_timeupdate_handler(audio); ctx.audio_timeupdate_handler.call(audio);
}
function audio_durationchange_handler() {
audio_updating = true;
ctx.audio_durationchange_handler(audio);
} }
function audio_play_pause_handler() { function audio_play_pause_handler() {
audio_updating = true; audio_updating = true;
ctx.audio_durationchange_handler(audio); ctx.audio_play_pause_handler.call(audio);
}
function audio_progress_handler() {
audio_updating = true;
ctx.audio_progress_handler(audio);
}
function audio_loadedmetadata_handler() {
audio_updating = true;
ctx.audio_loadedmetadata_handler(audio);
} }
function audio_volumechange_handler() { function audio_volumechange_handler() {
audio_updating = true; audio_updating = true;
ctx.audio_volumechange_handler(audio); ctx.audio_volumechange_handler.call(audio);
} }
return { return {
c() { c() {
audio = createElement("audio"); audio = createElement("audio");
if (ctx.played === void 0 || ctx.currentTime === void 0) add_render_callback(audio_timeupdate_handler); if (ctx.played === void 0 || ctx.currentTime === void 0) add_render_callback(audio_timeupdate_handler);
if (ctx.duration === void 0) add_render_callback(audio_durationchange_handler); if (ctx.duration === void 0) add_render_callback(() => ctx.audio_durationchange_handler.call(audio));
if (ctx.buffered === void 0) add_render_callback(audio_progress_handler); if (ctx.buffered === void 0) add_render_callback(() => ctx.audio_progress_handler.call(audio));
if (ctx.buffered === void 0 || ctx.seekable === void 0) add_render_callback(audio_loadedmetadata_handler); if (ctx.buffered === void 0 || ctx.seekable === void 0) add_render_callback(() => ctx.audio_loadedmetadata_handler.call(audio));
dispose = [ dispose = [
addListener(audio, "timeupdate", audio_timeupdate_handler), addListener(audio, "timeupdate", audio_timeupdate_handler),
addListener(audio, "durationchange", audio_durationchange_handler), addListener(audio, "durationchange", ctx.audio_durationchange_handler),
addListener(audio, "play", audio_play_pause_handler), addListener(audio, "play", audio_play_pause_handler),
addListener(audio, "pause", audio_play_pause_handler), addListener(audio, "pause", audio_play_pause_handler),
addListener(audio, "progress", audio_progress_handler), addListener(audio, "progress", ctx.audio_progress_handler),
addListener(audio, "loadedmetadata", audio_loadedmetadata_handler), addListener(audio, "loadedmetadata", ctx.audio_loadedmetadata_handler),
addListener(audio, "volumechange", audio_volumechange_handler) addListener(audio, "volumechange", audio_volumechange_handler)
]; ];
}, },
@ -67,7 +52,6 @@ function create_fragment(component, ctx) {
if (!audio_updating && !isNaN(ctx.currentTime) && changed.currentTime) audio.currentTime = ctx.currentTime; if (!audio_updating && !isNaN(ctx.currentTime) && changed.currentTime) audio.currentTime = ctx.currentTime;
if (!audio_updating && audio_is_paused !== (audio_is_paused = ctx.paused) && changed.paused) audio[audio_is_paused ? "pause" : "play"](); if (!audio_updating && audio_is_paused !== (audio_is_paused = ctx.paused) && changed.paused) audio[audio_is_paused ? "pause" : "play"]();
if (!audio_updating && !isNaN(ctx.volume) && changed.volume) audio.volume = ctx.volume; if (!audio_updating && !isNaN(ctx.volume) && changed.volume) audio.volume = ctx.volume;
audio_updating = false; audio_updating = false;
}, },
@ -91,30 +75,38 @@ function create_fragment(component, ctx) {
function instance($$self, $$props, $$invalidate) { function instance($$self, $$props, $$invalidate) {
let { buffered, seekable, played, currentTime, duration, paused, volume } = $$props; let { buffered, seekable, played, currentTime, duration, paused, volume } = $$props;
function audio_timeupdate_handler(audio) { function audio_timeupdate_handler() {
$$invalidate('played', played = timeRangesToArray(audio.played)); played = timeRangesToArray(this.played);
$$invalidate('currentTime', currentTime = audio.currentTime); currentTime = this.currentTime;
$$invalidate('played', played);
$$invalidate('currentTime', currentTime);
} }
function audio_durationchange_handler(audio) { function audio_durationchange_handler() {
$$invalidate('duration', duration = audio.duration); duration = this.duration;
$$invalidate('duration', duration);
} }
function audio_play_pause_handler(audio) { function audio_play_pause_handler() {
$$invalidate('paused', paused = audio.paused); paused = this.paused;
$$invalidate('paused', paused);
} }
function audio_progress_handler(audio) { function audio_progress_handler() {
$$invalidate('buffered', buffered = timeRangesToArray(audio.buffered)); buffered = timeRangesToArray(this.buffered);
$$invalidate('buffered', buffered);
} }
function audio_loadedmetadata_handler(audio) { function audio_loadedmetadata_handler() {
$$invalidate('buffered', buffered = timeRangesToArray(audio.buffered)); buffered = timeRangesToArray(this.buffered);
$$invalidate('seekable', seekable = timeRangesToArray(audio.seekable)); seekable = timeRangesToArray(this.seekable);
$$invalidate('buffered', buffered);
$$invalidate('seekable', seekable);
} }
function audio_volumechange_handler(audio) { function audio_volumechange_handler() {
$$invalidate('volume', volume = audio.volume); volume = this.volume;
$$invalidate('volume', volume);
} }
$$self.$set = $$props => { $$self.$set = $$props => {

Loading…
Cancel
Save