Skip to content

feat: allow runes in POJO properties #15593

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

Ocean-OS
Copy link
Contributor

@Ocean-OS Ocean-OS commented Mar 22, 2025

This is currently an experiment to see how well runes could work as properties in POJOs. This is similar to #11210, but much more seamless. This would enable explicit fine-grained reactivity in objects, without proxying them. Here's an example:

let counter = {
    count: $state(0);
}

This would get compiled to an IIFE, returning something like this:

let counter = (() => {
    let $$1 = $.state(0);
    return {
        get count() {
            return $.get($$1);
        },
        set count($$value) {
            $.set($$1, $$value, true);
        }
    }
})();

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

@svelte-docs-bot
Copy link

Copy link
Contributor

Playground

pnpm add https://pkg.pr.new/svelte@15593

Copy link

changeset-bot bot commented Mar 22, 2025

🦋 Changeset detected

Latest commit: 1b0918c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Ocean-OS
Copy link
Contributor Author

I think this references should be working, try to break them to see if there's any issues.

@Ocean-OS
Copy link
Contributor Author

I apparently forgot how this works in POJOs, so unfortunately this doesn't work anymore, you would have to do something like this instead. It was a nice shortcut, but we probably wouldn't want to confuse people by not following JavaScript's rules.

@notramo
Copy link

notramo commented Apr 15, 2025

If wrapping is needed, then there's a simpler solution using closures, using the currently available Svelte features.

@Tyler-Petrov
Copy link

I have two examples that I would use this in the real world, and would love to see this happen! Thanks for your work on it @Ocean-OS!

Sveltekit-Superforms Scenario

I has creating a wrapper function around the superForm() function, so I could return a separate open state along side my form (for forms in collapse and modal components).

function newSuperForm(form, formOptions) {
    const newForm = superForm(form, formOptions)
    return {
        ...newForm,
        open: $state(false),
    }
}

As this syntax isn't avaliable atm, I'm making due with this.

function newSuperForm(form, formOptions) {
    const newForm = superForm(form, formOptions)
    return {
        ...newForm,
        get open() {
            return open
        },
        set open(newOpen) {
            open = newOpen
        }
    }
}

Passing values as $derived to functions

When passing values to functions its helpful to declare them explicitly as $derived or there was reactivity issues (could definitely be a skill issue though).

const addressForm = formBuilder(
    () => $derived({ ...reactiveAddressObject, _id: databaseId });,
    addressFormSchema,
);

I'm currently using a temp variable for the $derived call atm:

let addressFormInitialData = $derived({ ...reactiveAddressObject, _id: databaseId });
const addressForm = formBuilder(
    () => addressFormInitialData,
    addressFormSchema,
);

Edit: After some digging this example actually doesn't change anything, but the point still stands (even if the code doesn't).

Conclusion

I hope this comment adds constructively to the conversation, and not destructively to the chaos.

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants