Chuks v0.2.0-rc.1 Is Out, We Need You to Try to Break It
DEV Community

Chuks v0.2.0-rc.1 Is Out, We Need You to Try to Break It

Chuks v0.2.0-rc.1 is live, and unlike our last few release posts, this one isn't "here's what shipped." It's an ask. What we need Chuks compiles two ways: a bytecode VM you develop against, and a native binary you ship. Every release lives or dies on those two modes computing the same thing. We have a serious internal gate for that, golden tests on both backends, a differential fuzzer, 24 differential suites, cross-compilation to five targets. What that gate can't do is run a program it's never seen. So here's the ask: build something with rc.1, or point an existing program at it, and run it both ways. chuks run main.chuks # the bytecode VM chuks build main.chuks # the native binary If they don't agree, byte for byte, on everything the program prints, that's a bug we want. File it here with chuks --version and the smallest file that shows it. # already have Chuks chuks upgrade --prerelease # first install curl -fsSL https://chuks.org/install.sh | bash && chuks upgrade --prerelease A plain chuks upgrade stays on v0.1.2 until v0.2.0 actually ships, this is opt-in. Why this matters more than usual this time Most of what's fixed in rc.1 wasn't found by a test. It was found by building real programs. Two examples, because they show why "someone else's program" is the thing our gate structurally can't replace. A precedence bug that produced two different wrong answers. await and spawn used to bind to the wrong side of an expression: "[" + await f() + "]" This used to parse as await (f() + "]") awaiting the string concatenation instead of the call. The VM printed "Task(pending)" . The native binary printed "0" . Same source, two backends, two different wrong answers, because the bug was in the grammar itself, not in either backend's implementation of a correctly-parsed program. Our differential fuzzer generates programs; it doesn't yet think like someone writing an async pipeline by hand, which is exactly how this surfaced. A closure bug that both backends agreed on, and were both wrong about. This is the more interesting failure mode: var fns = [] for (var i = 0; i < 3; i++) { fns.push(function(): int { return i }) } // every fn used to return 3, on BOTH the VM and the native binary Every closure made in a loop was reading one shared binding instead of its own per-iteration value, on both backends, identically. Our differential testing checks that the VM and native binary agree. It does not check that what they agree on is correct. They agreed here, and they were both wrong, in exactly the way var in a pre-let JavaScript loop was wrong. Fixed now: each pass gets its own binding. That second one is why we're asking for outside testing specifically. Agreement between two backends is necessary but not sufficient, it can't catch a bug baked into both from the start. Only someone hitting the actual behavior, expecting something else, catches that. Also in this RC - String indexing now counts bytes consistently on both backends, with accessors like at/slice snapping to whole Unicode characters, this used to differ between the VM (characters) and native (bytes) for some methods. - A dropped spawn 'd task's failure used to disappear silently. It's reported now, at exit for a CLI program, immediately for an embedding host. - Reserved words are usable as field/key names now ( dataType Rec { from: string, class: string } ), a payload's fields aren't the language's to rename. - Generic base classes now work correctly across module boundaries, with this reflection ( json.stringify(this) ) seeing the whole object, subclass fields included, identically on both backends. Full changelog, including all the breaking changes and exact migration notes: chuks.org/blog/chuks-v020-rc1-the-release-candidate If you try it and it breaks, that's the best possible outcome for this post. File it. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.