Repository: sveltejs/svelte (JavaScript) — Bug Fix

Issue:
Internal state can be exposed
[REPL](https://v3.svelte.technology/repl?version=3.0.0-alpha12&gist=454e39c0b3c8b0e93d8bdbcd83d1017d)


Discussion:

Resolving patch:
diff --git a/src/compile/render-dom/index.ts b/src/compile/render-dom/index.ts
--- a/src/compile/render-dom/index.ts
+++ b/src/compile/render-dom/index.ts
@@ -80,7 +80,7 @@ export default function dom(
 				$$invalidate('${component.meta.props_object}', ${component.meta.props_object});
 				`}
 				${props.map(prop =>
-				`if ('${prop.as}' in $$props) ${prop.name} = $$props.${prop.as};`)}
+				`if ('${prop.as}' in $$props) $$invalidate('${prop.name}', ${prop.name} = $$props.${prop.as});`)}
 			}
 		`
 		: null;
@@ -231,8 +231,7 @@ export default function dom(
 	}
 
 	const args = ['$$self'];
-	if (component.props.length > 0 || component.has_reactive_assignments) args.push('$$props');
-	if (component.has_reactive_assignments) args.push('$$invalidate');
+	if (component.props.length > 0 || component.has_reactive_assignments) args.push('$$props', '$$invalidate');
 
 	builder.addBlock(deindent`
 		function create_fragment(${component.alias('component')}, ctx) {
@@ -301,7 +300,7 @@ export default function dom(
 
 				${reactive_store_subscriptions}
 
-				${set && `$$self.$$.set = ${set};`}
+				${set && `$$self.$set = ${set};`}
 
 				${component.reactive_declarations.length > 0 && deindent`
 				$$self.$$.update = ($$dirty = { ${Array.from(all_reactive_dependencies).map(n => `${n}: 1`).join(', ')} }) => {
diff --git a/src/internal/Component.js b/src/internal/Component.js
--- a/src/internal/Component.js
+++ b/src/internal/Component.js
@@ -151,17 +151,8 @@ if (typeof HTMLElement !== 'undefined') {
 			};
 		}
 
-		$set(values) {
-			if (this.$$) {
-				const { ctx, set, not_equal } = this.$$;
-				set(values);
-				for (const key in values) {
-					if (not_equal(ctx[key], values[key])) {
-						ctx[key] = values[key];
-						make_dirty(this, key);
-					}
-				}
-			}
+		$set() {
+			// overridden by instance, if it has props
 		}
 	}
 }
@@ -182,18 +173,8 @@ export class SvelteComponent {
 		};
 	}
 
-	$set(values) {
-		if (this.$$) {
-			const { ctx, set, not_equal } = this.$$;
-			set(values);
-
-			for (const key in values) {
-				if (not_equal(ctx[key], values[key])) {
-					ctx[key] = values[key];
-					make_dirty(this, key);
-				}
-			}
-		}
+	$set() {
+		// overridden by instance, if it has props
 	}
 }
 


Test patch:
diff --git a/test/js/samples/action-custom-event-handler/expected.js b/test/js/samples/action-custom-event-handler/expected.js
--- a/test/js/samples/action-custom-event-handler/expected.js
+++ b/test/js/samples/action-custom-event-handler/expected.js
@@ -43,15 +43,15 @@ function foo(node, callback) {
 	// code goes here
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { bar } = $$props;
 
 	function foo_function() {
 		return handleFoo(bar);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('bar' in $$props) bar = $$props.bar;
+	$$self.$set = $$props => {
+		if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar);
 	};
 
 	return { bar, foo_function };
diff --git a/test/js/samples/bind-width-height/expected.js b/test/js/samples/bind-width-height/expected.js
--- a/test/js/samples/bind-width-height/expected.js
+++ b/test/js/samples/bind-width-height/expected.js
@@ -46,9 +46,9 @@ function instance($$self, $$props, $$invalidate) {
 		$$invalidate('h', h);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('w' in $$props) w = $$props.w;
-		if ('h' in $$props) h = $$props.h;
+	$$self.$set = $$props => {
+		if ('w' in $$props) $$invalidate('w', w = $$props.w);
+		if ('h' in $$props) $$invalidate('h', h = $$props.h);
 	};
 
 	return { w, h, div_resize_handler };
diff --git a/test/js/samples/collapses-text-around-comments/expected.js b/test/js/samples/collapses-text-around-comments/expected.js
--- a/test/js/samples/collapses-text-around-comments/expected.js
+++ b/test/js/samples/collapses-text-around-comments/expected.js
@@ -45,11 +45,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { foo = 42 } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { foo };
diff --git a/test/js/samples/computed-collapsed-if/expected.js b/test/js/samples/computed-collapsed-if/expected.js
--- a/test/js/samples/computed-collapsed-if/expected.js
+++ b/test/js/samples/computed-collapsed-if/expected.js
@@ -14,7 +14,7 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { x } = $$props;
 
 	function a() {
@@ -25,8 +25,8 @@ function instance($$self, $$props) {
 		return x * 3;
 	}
 
-	$$self.$$.set = $$props => {
-		if ('x' in $$props) x = $$props.x;
+	$$self.$set = $$props => {
+		if ('x' in $$props) $$invalidate('x', x = $$props.x);
 	};
 
 	return { x, a, b };
diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js
--- a/test/js/samples/debug-empty/expected.js
+++ b/test/js/samples/debug-empty/expected.js
@@ -54,11 +54,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { name } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('name' in $$props) name = $$props.name;
+	$$self.$set = $$props => {
+		if ('name' in $$props) $$invalidate('name', name = $$props.name);
 	};
 
 	return { name };
diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js
--- a/test/js/samples/debug-foo-bar-baz-things/expected.js
+++ b/test/js/samples/debug-foo-bar-baz-things/expected.js
@@ -139,14 +139,14 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { things, foo, bar, baz } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('things' in $$props) things = $$props.things;
-		if ('foo' in $$props) foo = $$props.foo;
-		if ('bar' in $$props) bar = $$props.bar;
-		if ('baz' in $$props) baz = $$props.baz;
+	$$self.$set = $$props => {
+		if ('things' in $$props) $$invalidate('things', things = $$props.things);
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
+		if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar);
+		if ('baz' in $$props) $$invalidate('baz', baz = $$props.baz);
 	};
 
 	return { things, foo, bar, baz };
diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js
--- a/test/js/samples/debug-foo/expected.js
+++ b/test/js/samples/debug-foo/expected.js
@@ -139,12 +139,12 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { things, foo } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('things' in $$props) things = $$props.things;
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('things' in $$props) $$invalidate('things', things = $$props.things);
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { things, foo };
diff --git a/test/js/samples/deconflict-builtins/expected.js b/test/js/samples/deconflict-builtins/expected.js
--- a/test/js/samples/deconflict-builtins/expected.js
+++ b/test/js/samples/deconflict-builtins/expected.js
@@ -105,11 +105,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { createElement } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('createElement' in $$props) createElement = $$props.createElement;
+	$$self.$set = $$props => {
+		if ('createElement' in $$props) $$invalidate('createElement', createElement = $$props.createElement);
 	};
 
 	return { createElement };
diff --git a/test/js/samples/deconflict-globals/expected.js b/test/js/samples/deconflict-globals/expected.js
--- a/test/js/samples/deconflict-globals/expected.js
+++ b/test/js/samples/deconflict-globals/expected.js
@@ -15,15 +15,15 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { foo = 'bar' } = $$props;
 
 	onMount(() => {
 		alert(JSON.stringify(data()));
 	});
 
-	$$self.$$.set = $$props => {
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { foo };
diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js
--- a/test/js/samples/dev-warning-missing-data-computed/expected.js
+++ b/test/js/samples/dev-warning-missing-data-computed/expected.js
@@ -57,8 +57,8 @@ function instance($$self, $$props, $$invalidate) {
 
 	let bar;
 
-	$$self.$$.set = $$props => {
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	$$self.$$.update = ($$dirty = { foo: 1 }) => {
diff --git a/test/js/samples/do-use-dataset/expected.js b/test/js/samples/do-use-dataset/expected.js
--- a/test/js/samples/do-use-dataset/expected.js
+++ b/test/js/samples/do-use-dataset/expected.js
@@ -43,11 +43,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { bar } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('bar' in $$props) bar = $$props.bar;
+	$$self.$set = $$props => {
+		if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar);
 	};
 
 	return { bar };
diff --git a/test/js/samples/dont-use-dataset-in-legacy/expected.js b/test/js/samples/dont-use-dataset-in-legacy/expected.js
--- a/test/js/samples/dont-use-dataset-in-legacy/expected.js
+++ b/test/js/samples/dont-use-dataset-in-legacy/expected.js
@@ -43,11 +43,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { bar } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('bar' in $$props) bar = $$props.bar;
+	$$self.$set = $$props => {
+		if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar);
 	};
 
 	return { bar };
diff --git a/test/js/samples/dont-use-dataset-in-svg/expected.js b/test/js/samples/dont-use-dataset-in-svg/expected.js
--- a/test/js/samples/dont-use-dataset-in-svg/expected.js
+++ b/test/js/samples/dont-use-dataset-in-svg/expected.js
@@ -41,11 +41,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { bar } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('bar' in $$props) bar = $$props.bar;
+	$$self.$set = $$props => {
+		if ('bar' in $$props) $$invalidate('bar', bar = $$props.bar);
 	};
 
 	return { bar };
diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js
--- a/test/js/samples/each-block-changed-check/expected.js
+++ b/test/js/samples/each-block-changed-check/expected.js
@@ -145,14 +145,14 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { comments, elapsed, time, foo } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('comments' in $$props) comments = $$props.comments;
-		if ('elapsed' in $$props) elapsed = $$props.elapsed;
-		if ('time' in $$props) time = $$props.time;
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('comments' in $$props) $$invalidate('comments', comments = $$props.comments);
+		if ('elapsed' in $$props) $$invalidate('elapsed', elapsed = $$props.elapsed);
+		if ('time' in $$props) $$invalidate('time', time = $$props.time);
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { comments, elapsed, time, foo };
diff --git a/test/js/samples/each-block-keyed-animated/expected.js b/test/js/samples/each-block-keyed-animated/expected.js
--- a/test/js/samples/each-block-keyed-animated/expected.js
+++ b/test/js/samples/each-block-keyed-animated/expected.js
@@ -120,11 +120,11 @@ function foo(node, animation, params) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { things } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('things' in $$props) things = $$props.things;
+	$$self.$set = $$props => {
+		if ('things' in $$props) $$invalidate('things', things = $$props.things);
 	};
 
 	return { things };
diff --git a/test/js/samples/each-block-keyed/expected.js b/test/js/samples/each-block-keyed/expected.js
--- a/test/js/samples/each-block-keyed/expected.js
+++ b/test/js/samples/each-block-keyed/expected.js
@@ -90,11 +90,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { things } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('things' in $$props) things = $$props.things;
+	$$self.$set = $$props => {
+		if ('things' in $$props) $$invalidate('things', things = $$props.things);
 	};
 
 	return { things };
diff --git a/test/js/samples/if-block-no-update/expected.js b/test/js/samples/if-block-no-update/expected.js
--- a/test/js/samples/if-block-no-update/expected.js
+++ b/test/js/samples/if-block-no-update/expected.js
@@ -93,11 +93,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { foo } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { foo };
diff --git a/test/js/samples/if-block-simple/expected.js b/test/js/samples/if-block-simple/expected.js
--- a/test/js/samples/if-block-simple/expected.js
+++ b/test/js/samples/if-block-simple/expected.js
@@ -69,11 +69,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { foo } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { foo };
diff --git a/test/js/samples/inline-style-optimized-multiple/expected.js b/test/js/samples/inline-style-optimized-multiple/expected.js
--- a/test/js/samples/inline-style-optimized-multiple/expected.js
+++ b/test/js/samples/inline-style-optimized-multiple/expected.js
@@ -41,13 +41,13 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { color, x, y } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('color' in $$props) color = $$props.color;
-		if ('x' in $$props) x = $$props.x;
-		if ('y' in $$props) y = $$props.y;
+	$$self.$set = $$props => {
+		if ('color' in $$props) $$invalidate('color', color = $$props.color);
+		if ('x' in $$props) $$invalidate('x', x = $$props.x);
+		if ('y' in $$props) $$invalidate('y', y = $$props.y);
 	};
 
 	return { color, x, y };
diff --git a/test/js/samples/inline-style-optimized-url/expected.js b/test/js/samples/inline-style-optimized-url/expected.js
--- a/test/js/samples/inline-style-optimized-url/expected.js
+++ b/test/js/samples/inline-style-optimized-url/expected.js
@@ -36,11 +36,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { data } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('data' in $$props) data = $$props.data;
+	$$self.$set = $$props => {
+		if ('data' in $$props) $$invalidate('data', data = $$props.data);
 	};
 
 	return { data };
diff --git a/test/js/samples/inline-style-optimized/expected.js b/test/js/samples/inline-style-optimized/expected.js
--- a/test/js/samples/inline-style-optimized/expected.js
+++ b/test/js/samples/inline-style-optimized/expected.js
@@ -36,11 +36,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { color } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('color' in $$props) color = $$props.color;
+	$$self.$set = $$props => {
+		if ('color' in $$props) $$invalidate('color', color = $$props.color);
 	};
 
 	return { color };
diff --git a/test/js/samples/inline-style-unoptimized/expected.js b/test/js/samples/inline-style-unoptimized/expected.js
--- a/test/js/samples/inline-style-unoptimized/expected.js
+++ b/test/js/samples/inline-style-unoptimized/expected.js
@@ -47,13 +47,13 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { style, key, value } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('style' in $$props) style = $$props.style;
-		if ('key' in $$props) key = $$props.key;
-		if ('value' in $$props) value = $$props.value;
+	$$self.$set = $$props => {
+		if ('style' in $$props) $$invalidate('style', style = $$props.style);
+		if ('key' in $$props) $$invalidate('key', key = $$props.key);
+		if ('value' in $$props) $$invalidate('value', value = $$props.value);
 	};
 
 	return { style, key, value };
diff --git a/test/js/samples/input-files/expected.js b/test/js/samples/input-files/expected.js
--- a/test/js/samples/input-files/expected.js
+++ b/test/js/samples/input-files/expected.js
@@ -49,8 +49,8 @@ function instance($$self, $$props, $$invalidate) {
 		$$invalidate('files', files);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('files' in $$props) files = $$props.files;
+	$$self.$set = $$props => {
+		if ('files' in $$props) $$invalidate('files', files = $$props.files);
 	};
 
 	return { files, input_input_handler };
diff --git a/test/js/samples/input-range/expected.js b/test/js/samples/input-range/expected.js
--- a/test/js/samples/input-range/expected.js
+++ b/test/js/samples/input-range/expected.js
@@ -52,8 +52,8 @@ function instance($$self, $$props, $$invalidate) {
 		$$invalidate('value', value);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('value' in $$props) value = $$props.value;
+	$$self.$set = $$props => {
+		if ('value' in $$props) $$invalidate('value', value = $$props.value);
 	};
 
 	return { value, input_change_input_handler };
diff --git a/test/js/samples/input-without-blowback-guard/expected.js b/test/js/samples/input-without-blowback-guard/expected.js
--- a/test/js/samples/input-without-blowback-guard/expected.js
+++ b/test/js/samples/input-without-blowback-guard/expected.js
@@ -48,8 +48,8 @@ function instance($$self, $$props, $$invalidate) {
 		$$invalidate('foo', foo);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('foo' in $$props) foo = $$props.foo;
+	$$self.$set = $$props => {
+		if ('foo' in $$props) $$invalidate('foo', foo = $$props.foo);
 	};
 
 	return { foo, input_change_handler };
diff --git a/test/js/samples/media-bindings/expected.js b/test/js/samples/media-bindings/expected.js
--- a/test/js/samples/media-bindings/expected.js
+++ b/test/js/samples/media-bindings/expected.js
@@ -93,14 +93,14 @@ function instance($$self, $$props, $$invalidate) {
 		$$invalidate('volume', volume);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('buffered' in $$props) buffered = $$props.buffered;
-		if ('seekable' in $$props) seekable = $$props.seekable;
-		if ('played' in $$props) played = $$props.played;
-		if ('currentTime' in $$props) currentTime = $$props.currentTime;
-		if ('duration' in $$props) duration = $$props.duration;
-		if ('paused' in $$props) paused = $$props.paused;
-		if ('volume' in $$props) volume = $$props.volume;
+	$$self.$set = $$props => {
+		if ('buffered' in $$props) $$invalidate('buffered', buffered = $$props.buffered);
+		if ('seekable' in $$props) $$invalidate('seekable', seekable = $$props.seekable);
+		if ('played' in $$props) $$invalidate('played', played = $$props.played);
+		if ('currentTime' in $$props) $$invalidate('currentTime', currentTime = $$props.currentTime);
+		if ('duration' in $$props) $$invalidate('duration', duration = $$props.duration);
+		if ('paused' in $$props) $$invalidate('paused', paused = $$props.paused);
+		if ('volume' in $$props) $$invalidate('volume', volume = $$props.volume);
 	};
 
 	return {
diff --git a/test/js/samples/select-dynamic-value/expected.js b/test/js/samples/select-dynamic-value/expected.js
--- a/test/js/samples/select-dynamic-value/expected.js
+++ b/test/js/samples/select-dynamic-value/expected.js
@@ -63,11 +63,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { current } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('current' in $$props) current = $$props.current;
+	$$self.$set = $$props => {
+		if ('current' in $$props) $$invalidate('current', current = $$props.current);
 	};
 
 	return { current };
diff --git a/test/js/samples/title/expected.js b/test/js/samples/title/expected.js
--- a/test/js/samples/title/expected.js
+++ b/test/js/samples/title/expected.js
@@ -22,11 +22,11 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { custom } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('custom' in $$props) custom = $$props.custom;
+	$$self.$set = $$props => {
+		if ('custom' in $$props) $$invalidate('custom', custom = $$props.custom);
 	};
 
 	return { custom };
diff --git a/test/js/samples/use-elements-as-anchors/expected.js b/test/js/samples/use-elements-as-anchors/expected.js
--- a/test/js/samples/use-elements-as-anchors/expected.js
+++ b/test/js/samples/use-elements-as-anchors/expected.js
@@ -249,15 +249,15 @@ function create_fragment(component, ctx) {
 	};
 }
 
-function instance($$self, $$props) {
+function instance($$self, $$props, $$invalidate) {
 	let { a, b, c, d, e } = $$props;
 
-	$$self.$$.set = $$props => {
-		if ('a' in $$props) a = $$props.a;
-		if ('b' in $$props) b = $$props.b;
-		if ('c' in $$props) c = $$props.c;
-		if ('d' in $$props) d = $$props.d;
-		if ('e' in $$props) e = $$props.e;
+	$$self.$set = $$props => {
+		if ('a' in $$props) $$invalidate('a', a = $$props.a);
+		if ('b' in $$props) $$invalidate('b', b = $$props.b);
+		if ('c' in $$props) $$invalidate('c', c = $$props.c);
+		if ('d' in $$props) $$invalidate('d', d = $$props.d);
+		if ('e' in $$props) $$invalidate('e', e = $$props.e);
 	};
 
 	return { a, b, c, d, e };
diff --git a/test/js/samples/window-binding-scroll/expected.js b/test/js/samples/window-binding-scroll/expected.js
--- a/test/js/samples/window-binding-scroll/expected.js
+++ b/test/js/samples/window-binding-scroll/expected.js
@@ -63,8 +63,8 @@ function instance($$self, $$props, $$invalidate) {
 		y = window.pageYOffset; $$invalidate('y', y);
 	}
 
-	$$self.$$.set = $$props => {
-		if ('y' in $$props) y = $$props.y;
+	$$self.$set = $$props => {
+		if ('y' in $$props) $$invalidate('y', y = $$props.y);
 	};
 
 	return { y, onwindowscroll };
diff --git a/test/runtime/samples/internal-state/Foo.html b/test/runtime/samples/internal-state/Foo.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/internal-state/Foo.html
@@ -0,0 +1,5 @@
+<script>
+	let internal = 1;
+</script>
+
+<p>internal: {internal}</p>
\ No newline at end of file
diff --git a/test/runtime/samples/internal-state/_config.js b/test/runtime/samples/internal-state/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/internal-state/_config.js
@@ -0,0 +1,18 @@
+export default {
+    html: `
+        <p>internal: 1</p>
+        <button>click me</button>
+    `,
+
+    async test({ assert, target, window }) {
+        const button = target.querySelector('button');
+        const click = new window.MouseEvent('click');
+
+        await button.dispatchEvent(click);
+
+        assert.htmlEqual(target.innerHTML, `
+            <p>internal: 1</p>
+            <button>click me</button>
+        `);
+    }
+};
\ No newline at end of file
diff --git a/test/runtime/samples/internal-state/main.html b/test/runtime/samples/internal-state/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/internal-state/main.html
@@ -0,0 +1,9 @@
+<script>
+	import Foo from './Foo.html';
+	
+	let x = 2;
+</script>
+
+<Foo internal={x}/>
+
+<button on:click="{() => x += 1}">click me</button>
\ No newline at end of file