only create source for state that is reassigned

proxied-state-set
Rich Harris 10 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 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.
// Should we for code size reasons make it an init in runes mode and/or non-dev mode?
return b.get(alias ?? name, [
b.return(binding?.kind === 'state' ? b.call('$.get', b.id(name)) : b.id(name))
]);
return b.get(alias ?? name, [b.return(is_source ? b.call('$.get', b.id(name)) : b.id(name))]);
});
if (analysis.accessors) {

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

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

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

@ -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