Replies
What about the performance of Bridge-ast way? Does this RFC show how to implement babel AST compatibility? |
I can accept last idea if I just need to update my Cargo.toml and compile/publish it. |
Have other serialization formats than json been considered? For example msgpack should be somewhat faster but is it enough to make a meaningful difference? |
Who are the target of this plugin system? Why the plugin cannot be implemented directly in Rust? |
Do you need mutation? Could the plugin API be like Another wild idea: say you decide supporting all this ABI stable plugin system stuff is too much work, too slow, or causes too much perf regression in core. Have you thought of inverting the model? Rather than core loading a config, finding plugins, and calling them, the config could just be a small Rust program with a normal crate dependency on both SWC core's defaults and whatever plugins it wanted. You basically already have this, but with a much simpler API for the defaults and a standard API for plugins it might be simple enough for most people to understand even if they don't know Rust. And this avoids the ABI stability and plugin loading problems entirely. If you wanted, you could even have a config format in another language like JSON that you compile to a Rust program to make it even simpler. |
Insert Link
Loading
Translated from {{ originalLanguageInEnglish }}
Beta Was this translation helpful? Give Feedback
Beta 이 번역이 도움이 되셨나요? 피드백 제공
Beta Esta tradução foi útil? Dê sua opinião
Beta ¿Fue útil esta traducción? Envía tus comentarios
Terms
normal ast
: AST used by core transforms.plugin ast
: AST representation which can be passed to the dynamic library directly.Requirements
These are what we want to achieve
Triage: serde
This is a good old technique for implementing plugin systems.
Previously
serde_json
is used to serialize/deserialize AST. This approach is easy to implement, but serialization and deserialization are costly enough to take more time than the plugin itself.But adding fields or variants to AST nodes is breaking change. If a new plugin ignores fields, it will be simply removed from the output of the plugin.
Triage: Bridge-ast
This is the current design. This is conceptually very similar to serde-based one. Instead of representing AST in serialized form, we convert
normal ast
toplugin ast
, which can be passed to dynamic libraries directly. Then dynamic library converts it back tonormal ast
.But the ast compatibility issue is not solved. We can detect ast compatibility issue on load time, but we can't automatically fix it. All plugins will be broken when a field or variant is added.
Triage: Plugin-only ast (X)
This is based on
prefix type
ofabi_stable
. It didn't work, but idea is that we can make every type an opaque pointer. Accessing fields is done by calling methods on the pointer and it does not depend on the exact layout of ast types.Problem is that
abi_stable
currently does not support mutating fields in prefix types.Also, this requires lots of more work. We need to reimplement the visitor generator and we can't use exising utilities for
swc_ecma_ast
.Finally, this makes all plugins slower.
rustc
optimize it well because there will be a lot of indirection. I expect it to be at least 2x slower. It's based on https://nullderef.com/blog/plugin-abi-stable/ and I expect much more slowdown like 5x to 20x, because we have lots of opaque types.Ideas
Some ideas about this issue.
Idea: Add
Unknown
variant to enums andextra
to structsIn this way, plugin will ignore extra fields and variants if they don't know the way to handle it.
The problems of this approach are that it will make the core slower, and target syntax in newly-added AST nodes cannot be handled.
e.g. If you use some feature in static blocks and if plugin is too old so it does not know static blocks, all ast nodes in static blocks will be simply ignored.
Idea: Just bump major version on breaking changes
This is too bad solution IMO, but may work.
Version history: https://crates.io/crates/swc_ecma_ast/versions