First of all, congrats.
The website doesn't explain how it works in a lot of detail. I am the author of tsonic [1], a TS compiler that produces binaries via Clr NativeAOT (on Linux/Mac). The hardest parts were numbers (TS has no ints or shorts), Generics, and TS Utility Types. I've been on it for the last 6 months (almost every day); getting to near complete TS compatibility is a very long journey because of its expressiveness.
Add: A request is to explain how it works on the website. I did take a look at https://www.perryts.com/en/internals/ but are those techniques described really sufficient to express TS? Based on my experience, I must say I'm surprised. But the proof is in the pudding, and if it's compiling those examples it must be working somehow!
[1]: https://tsonic.org
Fascinating. I've written cross platform (WASM, iOS, Android) libraries with Rust before and had a good time but Rust can be a pain too. Cross-platform Typescript is a really interesting proposition.
That said, the more I think about it the more dubious I am. The site boasts no runtime dependencies but clearly it’s going to need things like a garbage collector, you can’t just magic that requirement away. At a certain point is it just doing what a JS engine’s JIT compilation does… except ahead of time?
Also doesn't inspire confidence that the text on the site is very clearly AI generated and the GitHub log shows an endless stream of AI powered commits. About 15 per hour, every hour? Doesn’t scream stability.
Why is this on the front page of Hacker News? Isn't it just more vibe-coded garbage where nobody takes responsibility for the resulting code?
Calling a couple million lines of ai written Rust "stable software" is a bold statement
It would be super cool, if we can get this to compile the typescript compiler and see how fast it is against the go version.
P.S: does it have PGO for collapsing numbers to ints when possible etc
Perry uses NaN-boxing to preserve TypeScript's dynamic type system at runtime, the same approach as JavaScriptCore. The PERF_ROADMAP is honest about the cost: 1.86x behind Zig on image convolution, with 1.24 billion wasted instructions traced specifically to NaN-box unboxing. You cannot get C-level performance without dropping TypeScript semantics, and dropping them means you are no longer compiling TypeScript.
I'm not against AI usage but the website, documentation, and even the comments the creator (proggeramlug) makes in response to questions are all very clearly AI-generated. Also, as someone else noticed, the pacing of the commits is eerily fast. That combined with the level of functionality makes me dubious how much accountability the creators have over the implementation.
Like you really built a backend that lowers to LLVM, integrated it with a generational gc, wrote a cross-platform reactive runtime, and built support for eleven different targets within like a year? Are you just prompting the model to tack on the next coolest thing or do you understand how these features work?
I worry how many of these kinds of projects will show up now. How do you guarantee stability? If there's a memory corruption error in the GC implementation, who's going to debug it?
Browsing through the repo, I noticed this, and wondered if that isn't a recipe for disaster (code is condensed to showcase my concern)?
app.get('/api/auth/callback', async (request: any, reply: any) => {
const params: any = request.query || {};
const code = params.code || '';
const state = params.state || '';
// Exchange code for token via curl
const tokenResult = curlExec(
'curl -s -X POST "https://github.com/login/oauth/access_token" -H "Accept: application/json" -d "client_id=' + GITHUB_CLIENT_ID + '&client_secret=' + GITHUB_CLIENT_SECRET + '&code=' + code + '"'
);
Shell injection?the claim of "no runtime" is a bit dubious... you're telling me that you're statically linking a full, modern UI library into every app?
A very interesting project because I always thought TypeScript or at least some subset of it should be natively compiled.
It looks like others had a similar idea too, adding a "sound mode" to TypeScript, such as this project which is converting tsgo to Rust, also with LLMs.
> Traditional OOP runtimes use vtables for method resolution, adding a layer of indirection on every call. Perry resolves all method calls statically during compilation, turning interface method calls into direct jumps.
What? How is this possible, even with something as simple as:
interface Animal {
speak(): string;
}
class Cat implements Animal {}
class Dog implements Animal {}
function makeSound(animal: Animal) {
return animal.speak();
}Curious where on spectrum compiling to wasm falls between art project & optimization potential. Should be able to make some nice interfaces between TS-wasm & TS-web
> 0 ms Startup time
Is that true? It just goes right into the code with no initialization of any other libraries needed?
Why go through LLVM at all?
There are a bunch of tools that JIT somewhat optimized assembly.
Perry definitely looks interesting, was just looking at getting one of these to include into my framework.
Would love to see more about it, or see more about the actual compiler docs.
While the UI framework part is neat, I prefer not to force everything into TS. Combining it means UI definitions and semantics get mixed into AST, making the unbundling of them a humongous task in itself.
Exactly the reason I built my own with pretty similar native UI semantics which supports Rust, Go, Kotlin and more (https://hypen.space) - would love to integrate Perry with it to compile TS apps directly into the runtime - but while the idea itself is great, looking at the documentation makes it hard to implement, and a lot of parts seem confusing.
Can I just use the compiler without the rest of the framework? What is the architecture? What are the limits?
After digging through the documentation, I'm unfortunately just more confused honestly. There are dozens of packages and slop markdown files such as `BUG_STRING_COMPARISON.md` and or `PERRY_UI_IMPLEMENTATION.md` which is an instruction file left for the LLM that just makes me trust the project less.
So while the idea is cool and the performance seems cool, the AI slop presentation would definitely need improvement. Adding a human touch would make it much, much better, as one could actually understand what they are dealing with.
I'm confused by the (frankly bad) documentation. It says that for pure js dependencies we need to use the v8 flag to bring in the runtime (which is undesirable), but what is the practical difference between a js file and the same file with .ts extension and explicit *any* type in every signature? Does this mean that we have to be very careful how we write our typescript to avoid v8 (and if yes, how? I couldn't find that on the site) or does it mean that we can get away with transpiling everything to ts with loose typing? I suspect it's the first, in which case it's literally the most important information that anyone using Perry needs to know, and it should be one of the first things mentioned in their AI-vibed page.
[flagged]
I understand that implementing the TypeScript compiler is not the same thing as implementing all Node.js APIs, but still, advertising "no runtime" and then requiring JS runtime (and a full local Rust setup to compile it) for something as basic as an Express web server makes the "no runtime" claim look like a slight exaggeration. I'm not saying that it's bad, it's just that the website is too optimistic.
Edit: as discussed in the thread below, the most likely reason for that is that Express is pure JS with types from @types/express, so the TypeScript compiler bails on it. Reasonable, but still frustrating.
Overall, it seems like every time I decide to try a vibe coded compiler I get this feeling like when you see a plate with fruits on a table but, coming closer, see that they are fake plastic fruits. No, I cannot use it to build a native binary of my project without V8 as easy as shown on the front page. Maybe some other project, yes, but not a real one.
Unrelated: if a project is called Perry, should the icon be a platypus in a hat, you know?