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