only create source for state that is reassigned

proxied-state-set
Rich Harris 12 months ago
parent 4b6e0eb4c8
commit 2bc7c03241

@ -240,11 +240,12 @@ export function client_component(source, analysis, options) {
const properties = analysis.exports.map(({ name, alias }) => { const properties = analysis.exports.map(({ name, alias }) => {
const binding = analysis.instance.scope.get(name); const binding = analysis.instance.scope.get(name);
const is_source =
binding?.kind === 'state' && (!state.analysis.immutable || binding.reassigned);
// TODO This is always a getter because the `renamed-instance-exports` test wants it that way. // TODO This is always a getter because the `renamed-instance-exports` test wants it that way.
// Should we for code size reasons make it an init in runes mode and/or non-dev mode? // Should we for code size reasons make it an init in runes mode and/or non-dev mode?
return b.get(alias ?? name, [ return b.get(alias ?? name, [b.return(is_source ? b.call('$.get', b.id(name)) : b.id(name))]);
b.return(binding?.kind === 'state' ? b.call('$.get', b.id(name)) : b.id(name))
]);
}); });
if (analysis.accessors) { if (analysis.accessors) {

@ -79,7 +79,8 @@ export function serialize_get_binding(node, state) {
} }
if ( if (
binding.kind === 'state' || (binding.kind === 'state' &&
(!state.analysis.immutable || state.analysis.accessors || binding.reassigned)) ||
binding.kind === 'derived' || binding.kind === 'derived' ||
binding.kind === 'prop' || binding.kind === 'prop' ||
binding.kind === 'rest_prop' || binding.kind === 'rest_prop' ||

@ -211,21 +211,28 @@ export const javascript_visitors_runes = {
} }
const args = /** @type {import('estree').CallExpression} */ (init).arguments; const args = /** @type {import('estree').CallExpression} */ (init).arguments;
const value = let value =
args.length === 0 args.length === 0
? b.id('undefined') ? b.id('undefined')
: /** @type {import('estree').Expression} */ (visit(args[0])); : /** @type {import('estree').Expression} */ (visit(args[0]));
const opts = args[1] && /** @type {import('estree').Expression} */ (visit(args[1]));
if (declarator.id.type === 'Identifier') { if (declarator.id.type === 'Identifier') {
const callee = rune === '$state' ? '$.source' : '$.derived'; if (rune === '$state') {
const arg = const binding = /** @type {import('#compiler').Binding} */ (
rune === '$state' state.scope.get(declarator.id.name)
? should_proxy(value) );
? b.call('$.proxy', value) if (should_proxy(value)) {
: value value = b.call('$.proxy', value);
: b.thunk(value); }
declarations.push(b.declarator(declarator.id, b.call(callee, arg, opts)));
if (!state.analysis.immutable || state.analysis.accessors || binding.reassigned) {
value = b.call('$.source', value);
}
} else {
value = b.call('$.derived', b.thunk(value));
}
declarations.push(b.declarator(declarator.id, value));
continue; continue;
} }

@ -9,8 +9,8 @@ export default function Main($$anchor, $$props) {
$.push($$props, true); $.push($$props, true);
// needs to be a snapshot test because jsdom does auto-correct the attribute casing // needs to be a snapshot test because jsdom does auto-correct the attribute casing
let x = $.source('test'); let x = 'test';
let y = $.source(() => 'test'); let y = () => 'test';
/* Init */ /* Init */
var fragment = $.open_frag($$anchor, false, frag); var fragment = $.open_frag($$anchor, false, frag);
var node = $.child_frag(fragment); var node = $.child_frag(fragment);
@ -21,24 +21,24 @@ export default function Main($$anchor, $$props) {
var custom_element_1 = $.sibling($.sibling(svg_1)); var custom_element_1 = $.sibling($.sibling(svg_1));
/* Update */ /* Update */
$.attr_effect(div, "foobar", () => $.get(y)()); $.attr_effect(div, "foobar", () => y());
$.attr_effect(svg_1, "viewBox", () => $.get(y)()); $.attr_effect(svg_1, "viewBox", () => y());
$.set_custom_element_data_effect(custom_element_1, "fooBar", () => $.get(y)()); $.set_custom_element_data_effect(custom_element_1, "fooBar", () => y());
var node_foobar; var node_foobar;
var svg_viewBox; var svg_viewBox;
var custom_element_fooBar; var custom_element_fooBar;
$.render_effect(() => { $.render_effect(() => {
if (node_foobar !== (node_foobar = $.get(x))) { if (node_foobar !== (node_foobar = x)) {
$.attr(node, "foobar", node_foobar); $.attr(node, "foobar", node_foobar);
} }
if (svg_viewBox !== (svg_viewBox = $.get(x))) { if (svg_viewBox !== (svg_viewBox = x)) {
$.attr(svg, "viewBox", svg_viewBox); $.attr(svg, "viewBox", svg_viewBox);
} }
if (custom_element_fooBar !== (custom_element_fooBar = $.get(x))) { if (custom_element_fooBar !== (custom_element_fooBar = x)) {
$.set_custom_element_data(custom_element, "fooBar", custom_element_fooBar); $.set_custom_element_data(custom_element, "fooBar", custom_element_fooBar);
} }
}); });

@ -0,0 +1,4 @@
/* index.svelte.js generated by Svelte VERSION */
import * as $ from "svelte/internal";
export const object = $.proxy({ ok: true });

@ -0,0 +1,5 @@
/* index.svelte.js generated by Svelte VERSION */
import * as $ from "svelte/internal/server";
export const object = { ok: true };

@ -0,0 +1,3 @@
export const object = $state({
ok: true
});
Loading…
Cancel
Save