further improvements

loosen-state-rune
Dominic Gannaway 5 months ago
parent 0da2215cf2
commit 37154706d3

@ -721,7 +721,7 @@ function validate_call_expression(node, scope, path) {
if (
node.arguments.length === 1 &&
node.arguments[0].type !== 'SpreadElement' &&
should_proxy_or_freeze(node.arguments[0])
should_proxy_or_freeze(node.arguments[0], scope)
) {
return;
}

@ -293,7 +293,7 @@ export function serialize_set_binding(node, context, fallback, options) {
if (
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
) {
const assignment = fallback();
if (assignment.type === 'AssignmentExpression') {
@ -310,7 +310,7 @@ export function serialize_set_binding(node, context, fallback, options) {
left,
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
? private_state.kind === 'frozen_state'
? b.call('$.freeze', value)
: b.call('$.proxy', value)
@ -330,7 +330,7 @@ export function serialize_set_binding(node, context, fallback, options) {
context.state.analysis.runes &&
public_state !== undefined &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
) {
const assignment = fallback();
if (assignment.type === 'AssignmentExpression') {
@ -398,7 +398,7 @@ export function serialize_set_binding(node, context, fallback, options) {
b.id(left_name),
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
? b.call('$.proxy', value)
: value
);
@ -408,7 +408,7 @@ export function serialize_set_binding(node, context, fallback, options) {
b.id(left_name),
context.state.analysis.runes &&
!options?.skip_proxy_and_freeze &&
should_proxy_or_freeze(value)
should_proxy_or_freeze(value, context.state.scope)
? b.call('$.freeze', value)
: value
);
@ -623,8 +623,11 @@ export function get_prop_source(binding, state, name, initial) {
return b.call('$.prop', ...args);
}
/** @param {import('estree').Expression} node */
export function should_proxy_or_freeze(node) {
/**
* @param {import('estree').Expression} node
* @param {import("../../scope.js").Scope | null} scope
*/
export function should_proxy_or_freeze(node, scope) {
if (
!node ||
node.type === 'Literal' ||
@ -637,5 +640,20 @@ export function should_proxy_or_freeze(node) {
) {
return false;
}
if (node.type === 'Identifier' && scope !== null) {
const binding = scope.get(node.name);
// Let's see if the reference is something that can be proxied or frozen
if (
binding !== null &&
!binding.reassigned &&
binding.initial !== null &&
binding.initial.type !== 'FunctionDeclaration' &&
binding.initial.type !== 'ClassDeclaration' &&
binding.initial.type !== 'ImportDeclaration' &&
binding.initial.type !== 'EachBlock'
) {
return should_proxy_or_freeze(binding.initial, null);
}
}
return true;
}

@ -85,11 +85,14 @@ export const javascript_visitors_runes = {
value =
field.kind === 'state'
? b.call('$.source', should_proxy_or_freeze(init) ? b.call('$.proxy', init) : init)
? b.call(
'$.source',
should_proxy_or_freeze(init, state.scope) ? b.call('$.proxy', init) : init
)
: field.kind === 'frozen_state'
? b.call(
'$.source',
should_proxy_or_freeze(init) ? b.call('$.freeze', init) : init
should_proxy_or_freeze(init, state.scope) ? b.call('$.freeze', init) : init
)
: b.call('$.derived', b.thunk(init));
} else {
@ -238,7 +241,7 @@ export const javascript_visitors_runes = {
*/
const create_state_declarator = (id, value) => {
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(id.name));
if (should_proxy_or_freeze(value)) {
if (should_proxy_or_freeze(value, state.scope)) {
value = b.call(rune === '$state' ? '$.proxy' : '$.freeze', value);
}
if (is_state_source(binding, state)) {

@ -0,0 +1,10 @@
import { test } from '../../test';
export default test({
error: {
code: 'invalid-state-location',
message:
'$state() can only be used as a variable declaration initializer, a class field or if passed an object or array, can be used as an expression',
position: [113, 124]
}
});

@ -0,0 +1,11 @@
<script>
function a() {
let ref = { a: 1 };
return $state(ref);
}
function b() {
let ref = 1;
return $state(ref);
}
</script>
Loading…
Cancel
Save