From 25e806f2e37155a8dd23b1ccbb7670e229626bb2 Mon Sep 17 00:00:00 2001 From: tanhauhau Date: Mon, 12 Sep 2022 15:59:04 +0800 Subject: [PATCH] supports bind naturalWidth and naturalHeight with load event --- src/compiler/compile/nodes/Binding.ts | 4 +- src/compiler/compile/nodes/Element.ts | 7 ++ .../render_dom/wrappers/Element/index.ts | 5 + .../natural-dimension-binding/expected.js | 95 +++++++++++++++++++ .../natural-dimension-binding/input.svelte | 8 ++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 test/js/samples/natural-dimension-binding/expected.js create mode 100644 test/js/samples/natural-dimension-binding/input.svelte diff --git a/src/compiler/compile/nodes/Binding.ts b/src/compiler/compile/nodes/Binding.ts index 594490a5fb..4f7b566145 100644 --- a/src/compiler/compile/nodes/Binding.ts +++ b/src/compiler/compile/nodes/Binding.ts @@ -22,7 +22,9 @@ const read_only_media_attributes = new Set([ 'seeking', 'ended', 'videoHeight', - 'videoWidth' + 'videoWidth', + 'naturalWidth', + 'naturalHeight' ]); export default class Binding extends Node { diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index df0e649122..81927fa07b 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -830,6 +830,13 @@ export default class Element extends Node { } else if (is_void(this.name)) { return component.error(binding, compiler_errors.invalid_binding_on(binding.name, `void elements like <${this.name}>. Use a wrapper element instead`)); } + } else if ( + name === 'naturalWidth' || + name === 'naturalHeight' + ) { + if (this.name !== 'img') { + return component.error(binding, compiler_errors.invalid_binding_element_with('', name)); + } } else if ( name === 'textContent' || name === 'innerHTML' diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 531208c476..2bd7a52b4d 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -132,6 +132,11 @@ const events = [ event_names: ['toggle'], filter: (node: Element, _name: string) => node.name === 'details' + }, + + { + event_names: ['load'], + filter: (_: Element, name: string) => name === 'naturalHeight' || name === 'naturalWidth' } ]; diff --git a/test/js/samples/natural-dimension-binding/expected.js b/test/js/samples/natural-dimension-binding/expected.js new file mode 100644 index 0000000000..3920c61009 --- /dev/null +++ b/test/js/samples/natural-dimension-binding/expected.js @@ -0,0 +1,95 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + add_render_callback, + attr, + detach, + element, + init, + insert, + listen, + noop, + safe_not_equal, + set_data, + space, + src_url_equal, + text +} from "svelte/internal"; + +function create_fragment(ctx) { + let img; + let img_src_value; + let t0; + let t1; + let t2; + let t3; + let mounted; + let dispose; + + return { + c() { + img = element("img"); + t0 = space(); + t1 = text(/*naturalWidth*/ ctx[0]); + t2 = text(" x "); + t3 = text(/*naturalHeight*/ ctx[1]); + if (!src_url_equal(img.src, img_src_value = "something.jpg")) attr(img, "src", img_src_value); + if (/*naturalWidth*/ ctx[0] === void 0 || /*naturalHeight*/ ctx[1] === void 0) add_render_callback(() => /*img_load_handler*/ ctx[2].call(img)); + }, + m(target, anchor) { + insert(target, img, anchor); + insert(target, t0, anchor); + insert(target, t1, anchor); + insert(target, t2, anchor); + insert(target, t3, anchor); + + if (!mounted) { + dispose = listen(img, "load", /*img_load_handler*/ ctx[2]); + mounted = true; + } + }, + p(ctx, [dirty]) { + if (dirty & /*naturalWidth*/ 1) set_data(t1, /*naturalWidth*/ ctx[0]); + if (dirty & /*naturalHeight*/ 2) set_data(t3, /*naturalHeight*/ ctx[1]); + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(img); + if (detaching) detach(t0); + if (detaching) detach(t1); + if (detaching) detach(t2); + if (detaching) detach(t3); + mounted = false; + dispose(); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let { naturalWidth = 0 } = $$props; + let { naturalHeight = 0 } = $$props; + + function img_load_handler() { + naturalWidth = this.naturalWidth; + naturalHeight = this.naturalHeight; + $$invalidate(0, naturalWidth); + $$invalidate(1, naturalHeight); + } + + $$self.$$set = $$props => { + if ('naturalWidth' in $$props) $$invalidate(0, naturalWidth = $$props.naturalWidth); + if ('naturalHeight' in $$props) $$invalidate(1, naturalHeight = $$props.naturalHeight); + }; + + return [naturalWidth, naturalHeight, img_load_handler]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, { naturalWidth: 0, naturalHeight: 1 }); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/natural-dimension-binding/input.svelte b/test/js/samples/natural-dimension-binding/input.svelte new file mode 100644 index 0000000000..b06b8f0ee9 --- /dev/null +++ b/test/js/samples/natural-dimension-binding/input.svelte @@ -0,0 +1,8 @@ + + + + +{naturalWidth} x {naturalHeight} \ No newline at end of file