diff --git a/.changeset/stupid-dodos-hide.md b/.changeset/stupid-dodos-hide.md new file mode 100644 index 0000000000..1fb49adbf1 --- /dev/null +++ b/.changeset/stupid-dodos-hide.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +feat: unwrap function expressions where possible, and optimise bindings diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js index b7819b874c..860154e3ed 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/BindDirective.js @@ -36,13 +36,20 @@ export function BindDirective(node, context) { ); } - const getter = b.thunk(/** @type {Expression} */ (context.visit(expression))); - - const setter = b.arrow( - [b.id('$$value')], - /** @type {Expression} */ (context.visit(b.assignment('=', expression, b.id('$$value')))) + const get = b.thunk(/** @type {Expression} */ (context.visit(expression))); + + /** @type {Expression | undefined} */ + let set = b.unthunk( + b.arrow( + [b.id('$$value')], + /** @type {Expression} */ (context.visit(b.assignment('=', expression, b.id('$$value')))) + ) ); + if (get === set) { + set = undefined; + } + /** @type {CallExpression} */ let call; @@ -52,15 +59,15 @@ export function BindDirective(node, context) { b.literal(node.name), b.literal(property.event), context.state.node, - setter, - property.bidirectional && getter + set ?? get, + property.bidirectional && get ); } else { // special cases switch (node.name) { // window case 'online': - call = b.call(`$.bind_online`, setter); + call = b.call(`$.bind_online`, set ?? get); break; case 'scrollX': @@ -68,8 +75,8 @@ export function BindDirective(node, context) { call = b.call( '$.bind_window_scroll', b.literal(node.name === 'scrollX' ? 'x' : 'y'), - getter, - setter + get, + set ); break; @@ -77,47 +84,47 @@ export function BindDirective(node, context) { case 'innerHeight': case 'outerWidth': case 'outerHeight': - call = b.call('$.bind_window_size', b.literal(node.name), setter); + call = b.call('$.bind_window_size', b.literal(node.name), set ?? get); break; // document case 'activeElement': - call = b.call('$.bind_active_element', setter); + call = b.call('$.bind_active_element', set ?? get); break; // media case 'muted': - call = b.call(`$.bind_muted`, context.state.node, getter, setter); + call = b.call(`$.bind_muted`, context.state.node, get, set); break; case 'paused': - call = b.call(`$.bind_paused`, context.state.node, getter, setter); + call = b.call(`$.bind_paused`, context.state.node, get, set); break; case 'volume': - call = b.call(`$.bind_volume`, context.state.node, getter, setter); + call = b.call(`$.bind_volume`, context.state.node, get, set); break; case 'playbackRate': - call = b.call(`$.bind_playback_rate`, context.state.node, getter, setter); + call = b.call(`$.bind_playback_rate`, context.state.node, get, set); break; case 'currentTime': - call = b.call(`$.bind_current_time`, context.state.node, getter, setter); + call = b.call(`$.bind_current_time`, context.state.node, get, set); break; case 'buffered': - call = b.call(`$.bind_buffered`, context.state.node, setter); + call = b.call(`$.bind_buffered`, context.state.node, set ?? get); break; case 'played': - call = b.call(`$.bind_played`, context.state.node, setter); + call = b.call(`$.bind_played`, context.state.node, set ?? get); break; case 'seekable': - call = b.call(`$.bind_seekable`, context.state.node, setter); + call = b.call(`$.bind_seekable`, context.state.node, set ?? get); break; case 'seeking': - call = b.call(`$.bind_seeking`, context.state.node, setter); + call = b.call(`$.bind_seeking`, context.state.node, set ?? get); break; case 'ended': - call = b.call(`$.bind_ended`, context.state.node, setter); + call = b.call(`$.bind_ended`, context.state.node, set ?? get); break; case 'readyState': - call = b.call(`$.bind_ready_state`, context.state.node, setter); + call = b.call(`$.bind_ready_state`, context.state.node, set ?? get); break; // dimensions @@ -125,28 +132,33 @@ export function BindDirective(node, context) { case 'contentBoxSize': case 'borderBoxSize': case 'devicePixelContentBoxSize': - call = b.call('$.bind_resize_observer', context.state.node, b.literal(node.name), setter); + call = b.call( + '$.bind_resize_observer', + context.state.node, + b.literal(node.name), + set ?? get + ); break; case 'clientWidth': case 'clientHeight': case 'offsetWidth': case 'offsetHeight': - call = b.call('$.bind_element_size', context.state.node, b.literal(node.name), setter); + call = b.call('$.bind_element_size', context.state.node, b.literal(node.name), set ?? get); break; // various case 'value': { if (parent?.type === 'RegularElement' && parent.name === 'select') { - call = b.call(`$.bind_select_value`, context.state.node, getter, setter); + call = b.call(`$.bind_select_value`, context.state.node, get, set); } else { - call = b.call(`$.bind_value`, context.state.node, getter, setter); + call = b.call(`$.bind_value`, context.state.node, get, set); } break; } case 'files': - call = b.call(`$.bind_files`, context.state.node, getter, setter); + call = b.call(`$.bind_files`, context.state.node, get, set); break; case 'this': @@ -160,18 +172,18 @@ export function BindDirective(node, context) { '$.bind_content_editable', b.literal(node.name), context.state.node, - getter, - setter + get, + set ); break; // checkbox/radio case 'checked': - call = b.call(`$.bind_checked`, context.state.node, getter, setter); + call = b.call(`$.bind_checked`, context.state.node, get, set); break; case 'focused': - call = b.call(`$.bind_focused`, context.state.node, setter); + call = b.call(`$.bind_focused`, context.state.node, set ?? get); break; case 'group': { @@ -184,7 +196,7 @@ export function BindDirective(node, context) { // We need to additionally invoke the value attribute signal to register it as a dependency, // so that when the value is updated, the group binding is updated - let group_getter = getter; + let group_getter = get; if (parent?.type === 'RegularElement') { const value = /** @type {any[]} */ ( @@ -215,7 +227,7 @@ export function BindDirective(node, context) { b.array(indexes), context.state.node, group_getter, - setter + set ?? get ); break; } diff --git a/packages/svelte/src/compiler/utils/builders.js b/packages/svelte/src/compiler/utils/builders.js index 060a8c2990..fc1cdf4adb 100644 --- a/packages/svelte/src/compiler/utils/builders.js +++ b/packages/svelte/src/compiler/utils/builders.js @@ -419,19 +419,31 @@ export function template(elements, expressions) { * @returns {ESTree.Expression} */ export function thunk(expression, async = false) { + const fn = arrow([], expression); + if (async) fn.async = true; + return unthunk(fn); +} + +/** + * Replace "(arg) => func(arg)" to "func" + * @param {ESTree.Expression} expression + * @returns {ESTree.Expression} + */ +export function unthunk(expression) { if ( - expression.type === 'CallExpression' && - expression.callee.type !== 'Super' && - expression.callee.type !== 'MemberExpression' && - expression.callee.type !== 'CallExpression' && - expression.arguments.length === 0 + expression.type === 'ArrowFunctionExpression' && + expression.async === false && + expression.body.type === 'CallExpression' && + expression.body.callee.type === 'Identifier' && + expression.params.length === expression.body.arguments.length && + expression.params.every((param, index) => { + const arg = /** @type {ESTree.SimpleCallExpression} */ (expression.body).arguments[index]; + return param.type === 'Identifier' && arg.type === 'Identifier' && param.name === arg.name; + }) ) { - return expression.callee; + return expression.body.callee; } - - const fn = arrow([], expression); - if (async) fn.async = true; - return fn; + return expression; } /** diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/input.js b/packages/svelte/src/internal/client/dom/elements/bindings/input.js index 35dd229d39..a1406925f5 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/input.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/input.js @@ -8,18 +8,18 @@ import { hydrating } from '../../hydration.js'; /** * @param {HTMLInputElement} input - * @param {() => unknown} get_value - * @param {(value: unknown) => void} update + * @param {() => unknown} get + * @param {(value: unknown) => void} set * @returns {void} */ -export function bind_value(input, get_value, update) { +export function bind_value(input, get, set = get) { listen_to_event_and_reset_event(input, 'input', () => { if (DEV && input.type === 'checkbox') { // TODO should this happen in prod too? e.bind_invalid_checkbox_value(); } - update(is_numberlike_input(input) ? to_number(input.value) : input.value); + set(is_numberlike_input(input) ? to_number(input.value) : input.value); }); render_effect(() => { @@ -28,12 +28,12 @@ export function bind_value(input, get_value, update) { e.bind_invalid_checkbox_value(); } - var value = get_value(); + var value = get(); // If we are hydrating and the value has since changed, then use the update value // from the input instead. if (hydrating && input.defaultValue !== input.value) { - update(input.value); + set(input.value); return; } @@ -60,11 +60,11 @@ const pending = new Set(); * @param {HTMLInputElement[]} inputs * @param {null | [number]} group_index * @param {HTMLInputElement} input - * @param {() => unknown} get_value - * @param {(value: unknown) => void} update + * @param {() => unknown} get + * @param {(value: unknown) => void} set * @returns {void} */ -export function bind_group(inputs, group_index, input, get_value, update) { +export function bind_group(inputs, group_index, input, get, set = get) { var is_checkbox = input.getAttribute('type') === 'checkbox'; var binding_group = inputs; @@ -91,14 +91,14 @@ export function bind_group(inputs, group_index, input, get_value, update) { value = get_binding_group_value(binding_group, value, input.checked); } - update(value); + set(value); }, // TODO better default value handling - () => update(is_checkbox ? [] : null) + () => set(is_checkbox ? [] : null) ); render_effect(() => { - var value = get_value(); + var value = get(); // If we are hydrating and the value has since changed, then use the update value // from the input instead. @@ -147,29 +147,29 @@ export function bind_group(inputs, group_index, input, get_value, update) { value = hydration_input?.__value; } - update(value); + set(value); } }); } /** * @param {HTMLInputElement} input - * @param {() => unknown} get_value - * @param {(value: unknown) => void} update + * @param {() => unknown} get + * @param {(value: unknown) => void} set * @returns {void} */ -export function bind_checked(input, get_value, update) { +export function bind_checked(input, get, set = get) { listen_to_event_and_reset_event(input, 'change', () => { var value = input.checked; - update(value); + set(value); }); - if (get_value() == undefined) { - update(false); + if (get() == undefined) { + set(false); } render_effect(() => { - var value = get_value(); + var value = get(); input.checked = Boolean(value); }); } @@ -215,15 +215,15 @@ function to_number(value) { /** * @param {HTMLInputElement} input - * @param {() => FileList | null} get_value - * @param {(value: FileList | null) => void} update + * @param {() => FileList | null} get + * @param {(value: FileList | null) => void} set */ -export function bind_files(input, get_value, update) { +export function bind_files(input, get, set = get) { listen_to_event_and_reset_event(input, 'change', () => { - update(input.files); + set(input.files); }); render_effect(() => { - input.files = get_value(); + input.files = get(); }); } diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/media.js b/packages/svelte/src/internal/client/dom/elements/bindings/media.js index 320e3856f2..ad955c89dc 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/media.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/media.js @@ -15,11 +15,11 @@ function time_ranges_to_array(ranges) { /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {() => number | undefined} get_value - * @param {(value: number) => void} update + * @param {() => number | undefined} get + * @param {(value: number) => void} set * @returns {void} */ -export function bind_current_time(media, get_value, update) { +export function bind_current_time(media, get, set = get) { /** @type {number} */ var raf_id; /** @type {number} */ @@ -37,7 +37,7 @@ export function bind_current_time(media, get_value, update) { var next_value = media.currentTime; if (value !== next_value) { - update((value = next_value)); + set((value = next_value)); } }; @@ -45,7 +45,7 @@ export function bind_current_time(media, get_value, update) { media.addEventListener('timeupdate', callback); render_effect(() => { - var next_value = Number(get_value()); + var next_value = Number(get()); if (value !== next_value && !isNaN(/** @type {any} */ (next_value))) { media.currentTime = value = next_value; @@ -57,66 +57,66 @@ export function bind_current_time(media, get_value, update) { /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {(array: Array<{ start: number; end: number }>) => void} update + * @param {(array: Array<{ start: number; end: number }>) => void} set */ -export function bind_buffered(media, update) { - listen(media, ['loadedmetadata', 'progress'], () => update(time_ranges_to_array(media.buffered))); +export function bind_buffered(media, set) { + listen(media, ['loadedmetadata', 'progress'], () => set(time_ranges_to_array(media.buffered))); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {(array: Array<{ start: number; end: number }>) => void} update + * @param {(array: Array<{ start: number; end: number }>) => void} set */ -export function bind_seekable(media, update) { - listen(media, ['loadedmetadata'], () => update(time_ranges_to_array(media.seekable))); +export function bind_seekable(media, set) { + listen(media, ['loadedmetadata'], () => set(time_ranges_to_array(media.seekable))); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {(array: Array<{ start: number; end: number }>) => void} update + * @param {(array: Array<{ start: number; end: number }>) => void} set */ -export function bind_played(media, update) { - listen(media, ['timeupdate'], () => update(time_ranges_to_array(media.played))); +export function bind_played(media, set) { + listen(media, ['timeupdate'], () => set(time_ranges_to_array(media.played))); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {(seeking: boolean) => void} update + * @param {(seeking: boolean) => void} set */ -export function bind_seeking(media, update) { - listen(media, ['seeking', 'seeked'], () => update(media.seeking)); +export function bind_seeking(media, set) { + listen(media, ['seeking', 'seeked'], () => set(media.seeking)); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {(seeking: boolean) => void} update + * @param {(seeking: boolean) => void} set */ -export function bind_ended(media, update) { - listen(media, ['timeupdate', 'ended'], () => update(media.ended)); +export function bind_ended(media, set) { + listen(media, ['timeupdate', 'ended'], () => set(media.ended)); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {(ready_state: number) => void} update + * @param {(ready_state: number) => void} set */ -export function bind_ready_state(media, update) { +export function bind_ready_state(media, set) { listen( media, ['loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'emptied'], - () => update(media.readyState) + () => set(media.readyState) ); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {() => number | undefined} get_value - * @param {(playback_rate: number) => void} update + * @param {() => number | undefined} get + * @param {(playback_rate: number) => void} set */ -export function bind_playback_rate(media, get_value, update) { +export function bind_playback_rate(media, get, set = get) { // Needs to happen after element is inserted into the dom (which is guaranteed by using effect), // else playback will be set back to 1 by the browser effect(() => { - var value = Number(get_value()); + var value = Number(get()); if (value !== media.playbackRate && !isNaN(value)) { media.playbackRate = value; @@ -127,24 +127,24 @@ export function bind_playback_rate(media, get_value, update) { // else playback will be set to 1 by the browser effect(() => { listen(media, ['ratechange'], () => { - update(media.playbackRate); + set(media.playbackRate); }); }); } /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {() => boolean | undefined} get_value - * @param {(paused: boolean) => void} update + * @param {() => boolean | undefined} get + * @param {(paused: boolean) => void} set */ -export function bind_paused(media, get_value, update) { +export function bind_paused(media, get, set = get) { var mounted = hydrating; - var paused = get_value(); + var paused = get(); var callback = () => { if (paused !== media.paused) { paused = media.paused; - update((paused = media.paused)); + set((paused = media.paused)); } }; @@ -160,7 +160,7 @@ export function bind_paused(media, get_value, update) { } render_effect(() => { - paused = !!get_value(); + paused = !!get(); if (paused !== media.paused) { var toggle = () => { @@ -169,7 +169,7 @@ export function bind_paused(media, get_value, update) { media.pause(); } else { media.play().catch(() => { - update((paused = true)); + set((paused = true)); }); } }; @@ -195,22 +195,22 @@ export function bind_paused(media, get_value, update) { /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {() => number | undefined} get_value - * @param {(volume: number) => void} update + * @param {() => number | undefined} get + * @param {(volume: number) => void} set */ -export function bind_volume(media, get_value, update) { +export function bind_volume(media, get, set = get) { var callback = () => { - update(media.volume); + set(media.volume); }; - if (get_value() == null) { + if (get() == null) { callback(); } listen(media, ['volumechange'], callback, false); render_effect(() => { - var value = Number(get_value()); + var value = Number(get()); if (value !== media.volume && !isNaN(value)) { media.volume = value; @@ -220,22 +220,22 @@ export function bind_volume(media, get_value, update) { /** * @param {HTMLVideoElement | HTMLAudioElement} media - * @param {() => boolean | undefined} get_value - * @param {(muted: boolean) => void} update + * @param {() => boolean | undefined} get + * @param {(muted: boolean) => void} set */ -export function bind_muted(media, get_value, update) { +export function bind_muted(media, get, set = get) { var callback = () => { - update(media.muted); + set(media.muted); }; - if (get_value() == null) { + if (get() == null) { callback(); } listen(media, ['volumechange'], callback, false); render_effect(() => { - var value = !!get_value(); + var value = !!get(); if (media.muted !== value) media.muted = value; }); diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/select.js b/packages/svelte/src/internal/client/dom/elements/bindings/select.js index 5cd08a598e..4d3dbff812 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/select.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/select.js @@ -73,11 +73,11 @@ export function init_select(select, get_value) { /** * @param {HTMLSelectElement} select - * @param {() => unknown} get_value - * @param {(value: unknown) => void} update + * @param {() => unknown} get + * @param {(value: unknown) => void} set * @returns {void} */ -export function bind_select_value(select, get_value, update) { +export function bind_select_value(select, get, set = get) { var mounting = true; listen_to_event_and_reset_event(select, 'change', () => { @@ -92,12 +92,12 @@ export function bind_select_value(select, get_value, update) { value = selected_option && get_option_value(selected_option); } - update(value); + set(value); }); // Needs to be an effect, not a render_effect, so that in case of each loops the logic runs after the each block has updated effect(() => { - var value = get_value(); + var value = get(); select_option(select, value, mounting); // Mounting and value undefined -> take selection from dom @@ -106,7 +106,7 @@ export function bind_select_value(select, get_value, update) { var selected_option = select.querySelector(':checked'); if (selected_option !== null) { value = get_option_value(selected_option); - update(value); + set(value); } } diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/size.js b/packages/svelte/src/internal/client/dom/elements/bindings/size.js index c817787497..a76c70aab1 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/size.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/size.js @@ -78,9 +78,9 @@ var resize_observer_device_pixel_content_box = /* @__PURE__ */ new ResizeObserve /** * @param {Element} element * @param {'contentRect' | 'contentBoxSize' | 'borderBoxSize' | 'devicePixelContentBoxSize'} type - * @param {(entry: keyof ResizeObserverEntry) => void} update + * @param {(entry: keyof ResizeObserverEntry) => void} set */ -export function bind_resize_observer(element, type, update) { +export function bind_resize_observer(element, type, set) { var observer = type === 'contentRect' || type === 'contentBoxSize' ? resize_observer_content_box @@ -88,21 +88,21 @@ export function bind_resize_observer(element, type, update) { ? resize_observer_border_box : resize_observer_device_pixel_content_box; - var unsub = observer.observe(element, /** @param {any} entry */ (entry) => update(entry[type])); + var unsub = observer.observe(element, /** @param {any} entry */ (entry) => set(entry[type])); teardown(unsub); } /** * @param {HTMLElement} element * @param {'clientWidth' | 'clientHeight' | 'offsetWidth' | 'offsetHeight'} type - * @param {(size: number) => void} update + * @param {(size: number) => void} set */ -export function bind_element_size(element, type, update) { - var unsub = resize_observer_border_box.observe(element, () => update(element[type])); +export function bind_element_size(element, type, set) { + var unsub = resize_observer_border_box.observe(element, () => set(element[type])); effect(() => { // The update could contain reads which should be ignored - untrack(() => update(element[type])); + untrack(() => set(element[type])); return unsub; }); } diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/universal.js b/packages/svelte/src/internal/client/dom/elements/bindings/universal.js index bb00e09da6..5b10abdc4c 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/universal.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/universal.js @@ -4,24 +4,24 @@ import { listen } from './shared.js'; /** * @param {'innerHTML' | 'textContent' | 'innerText'} property * @param {HTMLElement} element - * @param {() => unknown} get_value - * @param {(value: unknown) => void} update + * @param {() => unknown} get + * @param {(value: unknown) => void} set * @returns {void} */ -export function bind_content_editable(property, element, get_value, update) { +export function bind_content_editable(property, element, get, set = get) { element.addEventListener('input', () => { // @ts-ignore - update(element[property]); + set(element[property]); }); render_effect(() => { - var value = get_value(); + var value = get(); if (element[property] !== value) { if (value == null) { // @ts-ignore var non_null_value = element[property]; - update(non_null_value); + set(non_null_value); } else { // @ts-ignore element[property] = value + ''; @@ -65,11 +65,11 @@ export function bind_property(property, event_name, element, set, get) { /** * @param {HTMLElement} element - * @param {(value: unknown) => void} update + * @param {(value: unknown) => void} set * @returns {void} */ -export function bind_focused(element, update) { +export function bind_focused(element, set) { listen(element, ['focus', 'blur'], () => { - update(element === document.activeElement); + set(element === document.activeElement); }); } diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/window.js b/packages/svelte/src/internal/client/dom/elements/bindings/window.js index 23f594a0fe..61775b9d4b 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/window.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/window.js @@ -3,11 +3,11 @@ import { listen } from './shared.js'; /** * @param {'x' | 'y'} type - * @param {() => number} get_value - * @param {(value: number) => void} update + * @param {() => number} get + * @param {(value: number) => void} set * @returns {void} */ -export function bind_window_scroll(type, get_value, update) { +export function bind_window_scroll(type, get, set = get) { var is_scrolling_x = type === 'x'; var target_handler = () => { @@ -15,7 +15,7 @@ export function bind_window_scroll(type, get_value, update) { clearTimeout(timeout); timeout = setTimeout(clear, 100); // TODO use scrollend event if supported (or when supported everywhere?) - update(window[is_scrolling_x ? 'scrollX' : 'scrollY']); + set(window[is_scrolling_x ? 'scrollX' : 'scrollY']); }; addEventListener('scroll', target_handler, { @@ -32,7 +32,7 @@ export function bind_window_scroll(type, get_value, update) { var first = true; render_effect(() => { - var latest_value = get_value(); + var latest_value = get(); // Don't scroll to the initial value for accessibility reasons if (first) { first = false; @@ -58,8 +58,8 @@ export function bind_window_scroll(type, get_value, update) { /** * @param {'innerWidth' | 'innerHeight' | 'outerWidth' | 'outerHeight'} type - * @param {(size: number) => void} update + * @param {(size: number) => void} set */ -export function bind_window_size(type, update) { - listen(window, ['resize'], () => update(window[type])); +export function bind_window_size(type, set) { + listen(window, ['resize'], () => set(window[type])); }