Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Consider replacing export const and export function with a rune #12778

Closed
mon-jai opened this issue Aug 9, 2024 · 7 comments
Closed

Consider replacing export const and export function with a rune #12778

mon-jai opened this issue Aug 9, 2024 · 7 comments

Comments

@mon-jai
Copy link

mon-jai commented Aug 9, 2024

Describe the problem

I just finished reading the documentation on Svelte 5. The syntax has become more JavaScript-fy, closely mirroring vanilla semantics with some magic for reactivity, except for one key difference: export.

export const and export function are the last pieces of Svelte that look like JavaScript but have entirely different functionality (which is a drawback for some). If we drop these (and perhaps move their functionality to a new rune), Svelte’s syntax would work "the same" as JavaScript, making it more approachable for newcomers from other frameworks.

It would also make <script context="module"> obsolete, as we could then export named variables just like how we do in JavaScript."

Describe the proposed solution

Introduce a new rune to replace export const and export function. Maybe $this()?

Importance

would make my life easier

@trueadm
Copy link
Contributor

trueadm commented Aug 9, 2024

export const expose the values on the instance of the component instance, not the module. So you'd still very much need context module scripts, otherwise you get scoping issues.

@Conduitry
Copy link
Member

Conduitry commented Aug 9, 2024

Right, but the suggestion is to introduce a rune for exposing things on the component instance, and then to make exports instead be module-level.

I still really don't think this is a good idea, though, for a few reasons. Everything else in <script> is instance-scoped already, so I don't know how we'd selectively make some of it be module-scoped. It'd be mixing two very different types of code in one script block.

@trueadm
Copy link
Contributor

trueadm commented Aug 9, 2024

That's what I was trying to get at. If you mix them up then the scoping becomes a mess as things created in the instance can't be referenced as an export too.

@Conduitry Conduitry closed this as not planned Won't fix, can't repro, duplicate, stale Aug 9, 2024
@mon-jai
Copy link
Author

mon-jai commented Aug 12, 2024

@Conduitry @trueadm You are right about the scoping issue, but in my opinion, the argument that "the last pieces of Svelte that look like JavaScript but have entirely different functionality" still holds. It doesn't make sense to export something at the instance level.

If we think of a component as a class, exporting something might look like this (in a programmer's mental model):

export default class Counter {
  count = $state(0)

  export function increment() {
    count++
  }
}

If we think of a component as a function (as is the behavior in Svelte 5):

export default function Counter {
  count = $state(0)

  export function increment() {
    count++
  }
  
  return <div />
}

Neither of these examples makes sense in the context of vanilla JavaScript. The syntax is different with vanilla semantics and confusing.

@mon-jai
Copy link
Author

mon-jai commented Aug 15, 2024

@Rich-Harris Any comment on this?

@mon-jai mon-jai changed the title Consider dropping export const and export function, in favor of allowing native ESM exports in Svelte 5 Consider replacing export const and export function with a rune Aug 15, 2024
@Rich-Harris
Copy link
Member

It's true that we're using export differently here than in vanilla JS. But runes are also not vanilla JS, so we haven't really made things 'more vanilla' by replacing export with a rune.

So it becomes a question of what makes things easier to work with. And it's not clear to me that a rune would really help here. The export keyword has a bunch of nice properties:

  • putting it in front of a declaration doesn't prevent the declaration from being locally accessible
  • it has to be at the top level already — no need to add new compiler logic to restrict where it can go
  • it exposes live bindings from a module (albeit normally read-only, from the outside) whereas an object literal, such as you'd use with a $this or $return or whatever rune, contains the value at the moment of evaluation. sure, we can change the rules — an object literal inside $return is live — but then you've introduced a syntactical anomaly, and created a situation where you can't separate the declaration from the export (i.e you have to do $return({...}), you can't do $return(stuff))

In other words it's all downside as far as I can tell.

@mon-jai
Copy link
Author

mon-jai commented Sep 23, 2024

@Rich-Harris Sorry for the delayed response. I gave some thought to your comments.


it has to be at the top level already — no need to add new compiler logic to restrict where it can go

The same logic is also applied to other runes like $props. Couldn't this logic be shared with $return/$this as well?

it exposes live bindings from a module (albeit normally read-only, from the outside) whereas an object literal, such as you'd use with a $this or $return or whatever rune, contains the value at the moment of evaluation. sure, we can change the rules — an object literal inside $return is live — but then you've introduced a syntactical anomaly, and created a situation where you can't separate the declaration from the export (i.e you have to do $return({...}), you can't do $return(stuff))

Considering we only have export const and export function in Svelte 5, does this issue still exist?

function $returned(args) {
  return args;
}

const anArray = [0, 1, 2];
function push(value) {
  anArray.push(value)
}

const stuff = { anArray, push };
const returnedValues = $returned(stuff);

returnedValues.push(3);

console.log(stuff.anArray); // [0, 1, 2, 3]
console.log(anArray); // [0, 1, 2, 3]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants