8000
Skip to content

Implement sass --embedded in pure JS mode - #2413

Draft
ntkme wants to merge 1 commit into
sass:mainfrom
ntkme:embedded-compiler
Draft

Implement sass --embedded in pure JS mode#2413
ntkme wants to merge 1 commit into
sass:mainfrom
ntkme:embedded-compiler

Conversation

@ntkme
@ntkme ntkme commented Oct 26, 2024
Copy link
Copy Markdown
Contributor

Closes #2325.

Implementation

The actual isolate dispatcher and compilation dispatcher are nearly unchanged. However, I had to replace isolate with worker communication, and mock tons of small things that do not work on node.

Testing

  • All Dart embedded tests are passing. - GitHub CI has been updated to run these in this PR.
  • All JS API tests are passing. - GitHub CI has been updated to run these in this PR.
  • All Ruby API tests are passing.

Current Status

Functionally it's ready to merge. Cosmetically it's waiting on dart-sass (depends on node_interop) to migrate off the legacy js interop to avoid the confusion of mixing legacy and new js interop, which is currently blocked by dart-lang/sdk#63403

Because FreeBSD support has been requested a lot for ruby's sass-embedded gem, this patch has been bundled within sass-embedded gem.

@ntkme
ntkme force-pushed the embedded-compiler branch from 8d7d4de to 7084da7 Compare October 26, 2024 02:31
@ntkme
ntkme marked this pull request as ready for review October 26, 2024 02:50
@ntkme
ntkme marked this pull request as draft October 26, 2024 03:40
@ntkme
ntkme force-pushed the embedded-compiler branch 2 times, most recently from e66df5b to d53fcc5 Compare October 26, 2024 17:27
@ntkme
ntkme force-pushed the embedded-compiler branch 9 times, most recently from d7e6206 to b3794eb Compare October 28, 2024 06:35
@ntkme
ntkme marked this pull request as ready for review October 28, 2024 06:49
@ntkme
ntkme force-pushed the embedded-compiler branch 3 times, most recently from 9112b44 to 54fabf3 Compare October 28, 2024 07:42
@ntkme
ntkme force-pushed the embedded-compiler branch from d0c8c1f to 5fa8f0d Compare December 10, 2024 18:08
@Goodwine
Goodwine requested a review from nex3 December 10, 2024 21:05
@ntkme
ntkme force-pushed the embedded-compiler branch from 5fa8f0d to 7c9069e Compare December 11, 2024 22:11
@ntkme
ntkme commented Feb 15, 2025
Copy link
Copy Markdown
Contributor Author

@nex3 I can see that the team is focusing most of the time on the postcss sass parser and this pull request has low priority.

However, I would like to get this done in next few month before dart 3.8 become stable so that we can offer this as a replacement for dart ia32. Please take a look when you get a chance and let me know if you have any questions.

@verm
verm commented Feb 24, 2025
Copy link
Copy Markdown

Would really be great to see this merged to have embedded support on FreeBSD even if in pure JS mode. Thank you!

@nex3 nex3 left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally managed to carve out some time for this. I haven't done a complete review yet, but this should be enough to get you started.

Comment thread .github/workflows/test.yml Outdated
Comment thread .github/workflows/test.yml Outdated
Comment thread .github/workflows/test.yml
Comment thread lib/src/embedded/compilation_dispatcher.dart Outdated
Comment thread lib/src/embedded/concurrency.dart Outdated
Comment thread lib/src/embedded/worker_dispatcher.dart Outdated
Comment thread lib/src/embedded/worker_dispatcher.dart Outdated
Comment thread lib/src/embedded/js/reusable_isolate.dart Outdated
Comment thread lib/src/embedded/js/executable.dart Outdated
Comment thread lib/src/embedded/isolate_dispatcher.dart
@nex3 nex3 left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another partial review, but I think we're making good progress!

Comment thread lib/src/embedded/README.md Outdated
Comment thread lib/src/embedded/js/reusable_isolate.dart Outdated
Comment thread lib/src/embedded/compilation_dispatcher.dart Outdated
Comment thread lib/src/embedded/compilation_dispatcher.dart Outdated
Comment thread lib/src/embedded/sync_receive_port.dart
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can also just go in the existing io catch-all.

Comment thread lib/src/embedded/js/executable.dart Outdated
Comment thread lib/src/embedded/worker_dispatcher.dart Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be part of the existing IO library (which already has definitions for exitCode).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I was trying to implement this with new js interop from dart 3.3 without relying on the node_interop package which heavily depends on deprecated dart:js_util, which will start to break at some point.

For exitCode I can use the existing one we have.

What about Stdin, Stdout, Stderr? These are effectively wrapper classes on node stdio to create an interface that's same as the dart built-in classes while it only partially implement necessarily methods we need on those interface. @nex3 What's your preference here? Create another interface that wraps the original dart interface?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any work to expose existing JS APIs should go in lib/src/js.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this is a saparate file because it's new js interop from dart 3.3, which I found a bit awkward to put it together with the classic interop code in the same place. Any recommendation on how to deal with it?

@ntkme
ntkme commented Apr 8, 2025
Copy link
Copy Markdown
Contributor Author

Applied most of the feedbacks. However, I have a awkward feeling about mixing classic js interop and new js interop in the same file, which is why I have lots of js specific things with new interop are only in embedded folder instead of in the generic folder.

@nex3 I haven't changed these yet, as I want to hear what's your thought on this.

@ntkme
ntkme commented Apr 8, 2025
Copy link
Copy Markdown
Contributor Author

Another note: The reason I tried to avoid classic interop and node_introp is that I couldn't get channel.port2 passed to Worker() constructor correctly with node_interop. Neither allowInterop() nor explicit casting worked, and it was a nightmare trying to debug what went wrong. I looked at node_interop repo trying to see if there is any example for it and there is no actual usage of transferList anywhere.

The new dart 3.3 js interop on the other hands was way more straight forward to use and debug. I got Worker() working on my first attempt.

@ntkme
ntkme commented May 31, 2025
Copy link
Copy Markdown
Contributor Author

@nex3 Any feedbacks on my last two comments above?

@ntkme
ntkme commented Jul 16, 2025
Copy link
Copy Markdown
Contributor Author

@nex3 Pinging again regarding how to deal with legacy js package vs new js_introp:

  • The legacy js package has been officially marked discontinued.
  • Both the legacy js package and new js_introp provides @JS annotations. This issue is addressed in 0.7.0 of legacy js:

    Breaking Change: Moved annotations to single location in dart:_js_annotations. This makes it easier to avoid collisions with dart:js_interop's @JS, as you will now see a static error instead of it resolving in favor of the package definition. However, since this may result in breakages in previously working code, this is treated as a breaking change.

  • Ideally node_interop should be rewritten with new js_interop but nothing is happening. On the other hand, node_interop cannot be easily upgraded to js 0.7.x due to js 0.7.x requires dart >=3.1.x, while node_interop's dev dependencies build_node_compilers do not support dart 3.x at all. This means node_interop is effectively stuck at js 0.6.x as of now, which means we have @JS conflict that we cannot mix old js and new js_interop code in the same file.

So honestly I think the way js interop is handled in this PR is already at best effort. - That new code only uses js_interop and it's currently isolated from the legacy js code.

Any more thoughts? Would you mind take another look at this?

@nex3
nex3 commented Jul 16, 2025
Copy link
Copy Markdown
Contributor

Sorry that this has taken me so long to finish reviewing, there have been a lot of things to juggle this year.

I'm working on a major change (https://github.com/sass/dart-sass/tree/js-interop) to move Dart Sass to the new JS interop system. This includes creating a new package for defining typings and wrappers for the JS core library (as well as possibly pushing some changes upstream to dart:js_interop) as well as updating node_interop which will probably include dropping its compiler dependency. You can see the work in progress on each of these at https://github.com/sass/dart_js_core and https://github.com/pulyaevskiy/node-interop/tree/js_interop.

At this point it may make sense to wait on landing this PR until that work is finished. We're already closing in on that, so it shouldn't be too much more time.

@karolyi
karolyi commented Aug 23, 2025
Copy link
Copy Markdown

Rooting for this, as I can't use embedded sass on FreeBSD.

@verm
verm commented Aug 23, 2025
Copy link
Copy Markdown

Rooting for this, as I can't use embedded sass on FreeBSD.

Me too as I use it on FreeBSD and it works great.

@nex3
nex3 commented Aug 25, 2025
Copy link
Copy Markdown
Contributor

The JS interop work is close to being done, at which point this will be unblocked.

@verm
verm commented Oct 14, 2025
Copy link
Copy Markdown

Would just like to add on top of using this to get Discourse on FreeBSD I just got Vikunja working. Both work flawlessly thank you for this change it's been a huge help.

@ntkme
ntkme commented Oct 14, 2025
Copy link
Copy Markdown
Contributor Author

@nex3 Any updates on the js_interop migration? I saw that you opened quite a lot issues in dart-sdk in this area - is there any blocker?

@nex3
nex3 commented Oct 15, 2025
Copy link
Copy Markdown
Contributor

The only real blocker is merging a bunch of my JS type definitions which are currently living in a private package into Dart team owned sources. I'm in discussion with @srujzs about the best way to do that, and I may pitch in to help land it. If you'd like to help as well, we could probably loop you in.

@chalin
chalin commented Nov 22, 2025
Copy link
Copy Markdown

Hi @nex. Do you have an ETA for this PR?

@verm
verm commented May 28, 2026
Copy link
Copy Markdown

Is this still planned to be merged? I use this frequently on FreeBSD and it's always worked perfectly it would be fantastic to see it merged as part of the base. Thank you as well @ntkme for maintaining this as well as you do it's greatly appreciated.

Comment thread .github/workflows/test.yml Fixed
@nex3
nex3 commented Aug 18, 2026
Copy link
Copy Markdown
Contributor

@verm Yes, but it's blocked on getting Dart Sass working with the new Dart JS interop system, which is itself a long process.

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

Successfully merging this pull request may close these issues.

Implement sass --embedded in pure JS mode

6 participants

0