This repository was archived by the owner on Dec 27, 2025. It is now read-only.
sync - #2
Open
cheesycod wants to merge 690 commits into
Open
Conversation
Refactor for #919
All instances of `execpath` have become `execPath`.
This PR renames all the test lifecycle methods (beforeEach/afterEach/beforeAll/afterAll) etc + updates the documentation.
I've also fixed the remaining type checker errors in the examples, either by re-writing them or adding casts or annotations where appropriate.
We should still support writing tests without using `lute test`, but now the method for doing this is explicitly moved into @std/test/runner.
This PR makes `lute check` a blocking check, instead of a 'don't add new type errors to lute' job. For the remaining type check errors in the lint rules, I've explicitly silenced them and cut this ticket :#932 to track un-silencing them when we bump our luau dependency to version 716.
I discovered an issue in CI where `lute test` would fail to require the `difftext` test file. Instead of causing CI to fail, this would silently skip that test suite. Moreover, there is a divergence in how tests run in the presence of the .ci.luaurc file vs the .luaurc file. Today, we don't define a batteries alias in the .ci.luaurc because we have tests that rely on asserting that user code cannot require batteries. This also causes a divergence in how C++ and luau tests are run - luau tests pass with the regular .luaurc because some tests rely on the .luaurc to figure out where batteries are located. - luau tests fail with the .luaurc.ci because that doesn't have a batteries alias. - C++ tests pass with the .luaurc.i because that doesn't have a batteries alias - C++ tests fail with the regular .luaurc because the batteries alias is defined in the root of the repo The cause of the luau tests failing is that `loadModule` loads a test case as user code, which has no access to @Batteries. It uses a .luaurc to find the local `@batteries`. The `difftext` battery itself requires the `deque` module in batteries, which causes us to look for a @Batteries alias somewhere (which doesn't exist in CI). To fix this, I've added a .luaurc with the `@batteries` alias defined to the batteries/ directories. I've also: - gotten rid of the step that changes the luaurc we run with in CI - added .luaurc's to files that rely on local access to batteries, either for execution (examples/ tools/) or for editor support (std/libs). - added a ps.exit(1), so that test running failures will cause CI to fail.
**Luau**: Updated from `0.714` to `0.715` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.715 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* --------- Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com>
This also fixes a bug where files containing ".." (such as: https://github.com/luau-lang/lute/blob/primary/tests/std/JSONParsingTestSuite/n_structure_angle_bracket_..json) would prevent the repo from being used as a package dependency.
This PR adds support for a variadic argument to the CLI parsing battery. Any arguments not consumed by an option or positional argument which come before a `--` is seen will now be consumed by the variadic argument if present. If a variadic argument isn't specified, then arguments before a `--` that aren't otherwise consumed will still be considered forwarded. I also added a test suite for the CLI battery. --------- Co-authored-by: ariel <arielweiss@roblox.com>
**Lute**: Updated from `0.1.0-nightly.20260327` to `0.1.0-nightly.20260403` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/0.1.0-nightly.20260403 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: Nick Winans <nick@winans.io> Co-authored-by: ariel <arielweiss@roblox.com>
This results in a slight API change for the CLI. Previously, options forwarded on to the code transformation scripts could be passed anywhere, not just after a `--`, but now we only forward them if they come after a `--`. This is because we now use the CLI battery's shiny new variadic argument feature to parse file paths to be transformed.
… a killed task (#943) Cancelling a task should error at call time if closing a coroutine is not possible, but should not create errors in the runtime. Currently, running code like: ``` local task = require("@std/task") local t = task.spawn(function() task.wait(2) end) task.cancel(t)/coroutine.close(t) ``` will cause the runtime to print "cannot resume dead coroutine". The reason that this happens is because of how scheduling resumes works. When the user calls `coroutine.close()` on the task, we reset the thread state to 'dead'. If the function passed to `spawn` schedules a continuation in the runtime, then when this continuation is called, we **may** end up mutating the state of a cancelled thread. For example, the `WaitData` uses the resumeToken to schedule a callback that pushes one value onto the stack associated with the callback. Because this thread is dead by the time the wait elapses, we end up pushing a number onto the stack, which makes it so that callback's top and base are not the same. When this happens, the runtime check for this thread's state using `lua_costatus` will return CO_SUS instead of CO_FIN, which causes the subsequent resume in the runtime to fail. This uncovered another bug with the FS Watch handle, whereby the combination of task.wait and fs.watch caused a pending token to be registered with the runtime that never got cleared, which caused the runtime to loop forever. I refactored the watch handle code a bit to make it's initialization and tear down clearer, and removed the pending token, as the existence of a `uv_fs_event_t` handle is already tracked by the event loop to prevent premature shutdown.
As part of internal explorations, we built a library that reimplements
the Linux `glob` functionality in Lute. Since we anticipate this being
widely useful for ecosystem tooling (particularly for defining
configuration formats for common tools like package managers, unit test
dispatchers, etc.), we want to propose moving our implementation into
batteries so that it can be shared and improved communally, rather than
fragmenting this functionality across the ecosystem.
The new library has two APIs: `glob.matches()`, which returns a boolean
if a path matches a glob pattern, and `glob.discover()`, which
efficiently walks the filesystem with pruning to discover all paths that
match a glob pattern.
---
**Note:** at lute/lute/cli/commands/lib/ignore.luau there are some
similar globbing facilities, but they're pretty divergent in
implementation and in API surface. It's nothing we can't expand this new
glob surface to standardise; I got Claude to summarise:
> **What they share** — both implement the core glob metacharacters (*,
?, **) with the same semantic meaning (don't cross /, match any char,
recurse into subdirectories).
>
> **Where they diverge:**
>
> - **Purpose:** batteries/glob is a filesystem glob that walks the tree
and returns matching paths. parseIgnores is gitignore matching that
tests whether a path matches an ignore rule.
> - **Matching strategy:** batteries/glob does recursive backtracking,
char-by-char, per segment. parseIgnores compiles globs into Lua patterns
and uses string.match on full relative paths.
> - **Filesystem:** batteries/glob walks directories via
fs.listDirectory. parseIgnores has no filesystem interaction — it just
tests a string.
Returns: batteries/glob returns { string } (list of matching paths).
parseIgnores returns boolean.
> - **Character classes:** batteries/glob has full [...], [!...], [a-z]
range support. parseIgnores doesn't support them — [ passes through as a
literal.
> - **Gitignore semantics:** batteries/glob has none. parseIgnores
supports ! negation/whitelists, trailing / for directory-only matching,
anchoring rules (patterns with / anchor to the .gitignore location,
without / they match anywhere), and hierarchical .gitignore chain
resolution.
> - **Separator handling:** batteries/glob handles this implicitly — it
matches one segment name at a time, so separators never appear in the
match input. parseIgnores does it explicitly, baking the platform
separator into compiled patterns ([^\]* vs [^/]*).
I imagine we can introduce an `options` table for enabling/disabling
features like character classes and gitignore patterns, and the choice
between full-string vs per-segment processing, and the idea of whether
to compile to regex or just directly ingest the string, is basically
just a performance tradeoff.
…`@batteries/cli` a bit in support of that) (#951) I got annoyed by luthier being kinda jank when you do incorrect invocations, so I put in some work to make the UX of the tool better. It has colorized help output now, and now will list subcommands and usage formats for the commands to the user, along side showing the full help output whenever you invoke it. Longer-term, it would probably be better if the cli library actually had a proper concept of subcommands because it could streamline _a lot_ of this logic, but this is an improvement for now.
…rectly without requiring `@lute/time` (#958) A strange bug got reported on Discord (and unfortunately they never made a ticket here) where durations that the user got from `@lute/fs` would ultimately behave incorrectly when `@lute/time` was not imported into that script. The underlying cause is that the metatable was not initialized when `@lute/time` was not imported, and therefore the code that constructs the durations in `@lute/fs` would look for a duration metatable that did not exist and just set the metatable to `nil`. We fix this by making initialization of the duration library idempotent and then invoking that initialization for `@lute/fs` as well.
Adds support for the compile command to support bundling .config.luau for require alias resolution.
The job that will be used for automating releases and the job that will
be used for nightlies share a lot of common actions. This PR separates
the common chunk out into a re-usable workflow, called shared-build
which is parameterized on the branch name.
1) Nightlies can be manually kicked off, but will continue to run with
the current cadence. These will automatically run of the 'primary'
branch.
2) Releases will be kicked off on release/v{Major}.{Minor}.x branches.
In both cases the job will check out the branch and derive the tag name
directly from the get_version.cmake command. If the branch is primary,
we'll get 'nightly.YYYMMDD' appended.
#959) There's a lot of inconsistency between the different runtime library definitions, and it's bothered me for a while. To try to make things more structured, this PR introduces a shared interface `LuteLibrary` and refactors each library namespace to instead be a `struct` that implements that `LuteLibrary` interface. The goal here is to make it more difficult to author a library that isn't structured how we would expect, and to bring all of the existing libraries into that uniform structure.
previously had some test files here in `docs/` that we wanted to ignore, but those have been moved and excluding `/test/` caused our `std/test` doc files and the CLI docs for `test` to not get generated `@std/test` is now being generated <img width="224" height="228" alt="image" src="https://github.com/user-attachments/assets/4bf18b89-3d36-4ed3-bede-9f61a8ab63d0" /> same with CLI test docs <img width="124" height="103" alt="image" src="https://github.com/user-attachments/assets/a2bf5fcf-99c7-4191-a756-5ee48f6b5c4f" /> ty @Vighnesh-V for the catch!
Create initial bindings for `lute/debug` to Luau, which primarily focuses on breakpoint behavior. - Add some basic Luau tests - A definitions file for the library for type checking - Renames `debugger.cpp` to `debuginternals.cpp` to more clearly separate out the bindings from internal implementation
**Luau**: Updated from `0.730` to `0.731` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.731 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
**Lute**: Updated from `1.0.1-nightly.20260717` to `1.0.1-nightly.20260723` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260723 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: Sora Kanosue <kanosuesora@gmail.com>
Add support for multiple sources in the debugger * Intercept calls to loading new modules by modifying the `RequireCtx` * also add `getLoadedSources` to debugger Target + bindings
to support partial reads into buffers and more, this PR introduces a new fs API ```lua --- Reads up to `count` bytes from `handle` at `fileOffset` into `buf` starting at `bufferOffset`. --- Returns the number of bytes actually read (may be less than `count` if EOF is reached). --- - `bufferOffset` defaults to 0. fs.readIntoBuffer(handle: FileHandle, buf: buffer, fileOffset: number, count: number, bufferOffset: number?): number ```
`tableext.deepClone` failed to correctly clone tables with `__iter` metamethods that didn't perform conventional key, value iteration. I discovered this while cloning the CST returned by lute's `parser` APIs, and found that `CstPunctuated` nodes were missing the `separators` field due to their `__iter` method. This PR updates `deepClone`'s iteration over a table to use `pairs`, such that all key, value pairs of cloned tables are handled.
A basic implementation of a DAP adapter that can handle breakpoints, continuing, and pausing * Also changes `onBreakpointInstall` to signal when installation fails as well <img width="1203" height="960" alt="Screenshot 2026-07-24 at 3 22 39 PM" src="https://github.com/user-attachments/assets/4db8b3e1-b760-4a2b-b3e8-434e465ff537" /> (Note: line highlighting is provided by stack frames, which is why it's stuck at line 1 above. really the important thing to look at is the breakpoints bar in the bottom left, where we can see that we've hit a bp)
**Lute**: Updated from `1.0.1-nightly.20260723` to `1.0.1-nightly.20260730` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260730 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
**Luau**: Updated from `0.731` to `0.732` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.732 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
We've got some interest in trying out a merge queue for lute, which means that we need to modify our CI to actually _run_ in the event that we have a merge queue going. Otherwise, everything will just fail immediately.
Fix `Target` destructor in infinite loop case as part of splitting #1233 up. - If the debugger is running an infinite loop, that coroutine would never break and so the destructor will stall infinitely. - This PR fixes this by making sure that always coroutines break out of execution in our destructor by setting the `interrupt` callback. This interrupt callback is called on back edges of loops or function calls/returns (which realistically will always occur when the thread is running an infinite loop)
Adds thread/coroutine inspection for multiple co-routines (part 1/3 of PRs dealing with inspecting into state) * Creates data structures to keep track of threads getting created and destroyed while working with bps * Make sure `onPause` and `onBreakpointHit` take in threadId, keeping in align with DAP protocol * Add `getStoppedThread`, `getThreads` and `getMainThread` for inspection * (maybe?) replace `task.spawn()` behavior with `task.defer()` in debug mode to allow for correct pausing * switch everything to use 1-indexing to match Luau btw: i use threads and coroutines interchangeably even though they are semantically different since we have `Thread` objects tracking coroutines <img width="1503" height="927" alt="Screenshot 2026-07-31 at 11 36 06 AM" src="https://github.com/user-attachments/assets/0be8b04b-79aa-4217-8028-5de6386fc54c" />
We got some feedback from folks about the existing README being misleading because it doesn't clearly delineate between things that are complete and things that are aspirational, and that it doesn't do enough to contextualize what our version status indicates. This PR updates the leading bits of the README to try to address some of this: removing mention of sockets as a supported feature since we have not implemented them yet, de-ambitioning claims of unifying runtimes with the standard library (really, limiting the scope of the claims to what we're actually able to do work towards ourselves), and contextualizing more of both "where the software is today, what 1.0.0 means" and "where we would like the software to go." Everything beyond the Lute Libraries section is purely formatting changes with no text. I used mdformat to wrap the whole file to 120 characters so that diffs on it will be hopefully less gross in the future.
`stoppedThreads` and `scriptThreads` could get garbage collected when they shouldn't have, which this PR fixes * this happens for example when stoppedThreads is no longer running and has been dequeued from the `Runtime` so there's no longer an active `Ref` to it
Adds output redirection for `lute/debug` when calling `print()` * When `onPrint` is specified that function is called instead of normal `print()` to stdout * Modfied DAP + bindings to incorporate this feature <img width="1082" height="938" alt="Screenshot 2026-07-31 at 10 18 34 AM" src="https://github.com/user-attachments/assets/5eb079c9-d0fb-4828-8e8f-1a2a3087a582" />
instead of returning `true/false`, surface compile errors on launch to the user this is what it looks like: <img width="1120" height="839" alt="Screenshot 2026-08-03 at 9 46 46 AM" src="https://github.com/user-attachments/assets/3ca0db3c-0dd3-44e4-894e-97690c06f7ca" />
- Related #1272 - Adds `lute pkg run` to `lute pkg --help` - <details><summary>Improved `lute pkg install --help`: </summary> Before: ``` @batteries/cli.luau:103: Unknown argument: help stacktrace: [C] function assert @batteries/cli.luau:103 function parse @cli/pkg/loom-core/src/commands/install.luau:43 function install @cli/pkg/init.luau:33 function main @cli/pkg/init.luau:43 ``` After: ``` @batteries/cli.luau:103: Unknown argument: help Usage: --exclude-dev - Skip dev dependencies --locked - Error if lockfile doesn't match manifest (CI mode) stacktrace: [C] function error @cli/pkg/loom-core/src/commands/install.luau:48 function install @cli/pkg/init.luau:34 function main @cli/pkg/init.luau:44 ``` </details> - <details><summary>Improved `lute pkg auth --help`: </summary> Before: ``` @batteries/cli.luau:103: Unknown argument: help stacktrace: [C] function assert @batteries/cli.luau:103 function parse @cli/pkg/loom-core/src/commands/authenticate.luau:8 function authenticate @cli/pkg/init.luau:35 function main @cli/pkg/init.luau:43 ``` After: ``` @batteries/cli.luau:103: Unknown argument: help Usage: --token - (required) Authentication token --domain - Domain to authenticate with stacktrace: [C] function error @cli/pkg/loom-core/src/commands/authenticate.luau:13 function authenticate @cli/pkg/init.luau:36 function main @cli/pkg/init.luau:44 ``` </details>
Incorporate stepping to `lute/debug` * Add capabilities for `stepIn`, `stepOver`, and `stepOut` * Also add `getLine()` to streamline testing https://github.com/user-attachments/assets/2916d967-50b7-43ea-b7de-d9703d780e6b
**Luau**: Updated from `0.732` to `0.733` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.733 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* --------- Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: Hunter Goldstein <hgoldstein@roblox.com>
**Lute**: Updated from `1.0.1-nightly.20260730` to `1.0.1-nightly.20260807` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260807 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
Adds stack frames/stack traces (part 2/3 of PRs dealing with inspecting into state) * Adds `getStackDepth`, `getStackFrame`, and `getStackTrace` to debugger * Modify `getLine` to `getStoppedLocation` to include source path * Allows for delayed stack loading in DAP * In DAP by supporting stack frames we allow for line highlighting https://github.com/user-attachments/assets/ea426af3-2952-4141-803f-0797ce2f2f37
- `cli.usage` now prepends the "Usage:" label - `cli.help` now returns the constructed string (instead of printing it) - `cli.help` now formats positional and variadic arguments - The existing lute subcommands have been migrate to a consistent pattern for rendering usage/help fields
…biguity (#1289) fixes #1279 When a file like `foo.luau` has a sibling directory named `foo/`, we previously reported an ambiguity error unconditionally. But if the directory had no `init.luau` or `init.lua` file, we shouldn't be reporting an ambiguity error because we know that we aren't requiring the `foo/` directory directly. This fix defers the ambiguity check until after we scan the directory for init files, so now if we `require(foo)` with: * `foo.luau` + `foo/` with no init = require resolves to `foo.luau` (and we can still require any files inside the directory) * `foo.luau` + `foo/` with `init.luau` results in an ambiguous error
Enable variable + scope inspection for `lute/debug`. Part 3/3 of a series of PRs on inspection. * Generally, you take a stack frame and first drill into a `VariableScope` (a scope represents something like a group of local variables or upvalue variables) * Each scope has its own `variableReference` and you can get a set of `Variable` objects per scope. * For tables, the `Variable` objects themselves may have a `variableReference`, allowing for additional lazy inspection of deeper levels of the table https://github.com/user-attachments/assets/f0346606-3961-429d-92c5-111a4f4fc8aa
this one line fix to stack frames corrects the stack frame display during multi-threading * `stoppedLine` correction only should apply on the thread that was actually dequeued from the Lute runtime queue * other threads are still stopped but can really on `lua_getinfo` for accurate information * significantly buff multi-threaded testing https://github.com/user-attachments/assets/5d688875-f4ad-40e4-adb6-b6b41e4f5c83 [ignore what happens when you need to press the resume button again at the end of the video to actually get the program to exit, this issue is caused by the one documented here #1250]
@Vighnesh-V mentioned the #1289 logic might've not been fully correct, so this reworks the logic and adds another test case logic and the cases we could have are now: * `if (hasInit && resolvedType)` -> init + sibling (file w same name as dir) -> ambiguous * `if hasInit` -> init + no sibling -> file * `else if !resolvedType` -> no init + no sibling -> directory * no init -> sibling -> file (already set earlier in the code)
…1250) Fixes scheduled continuations and callbacks blocking on `uv_run(getEventLoop(), UV_RUN_ONCE)` in `runOnce`. * When testing the DAP adapter, I was seeing behavior where callbacks such as `onExit` would not fire until after receiving I/O from the VSCode debugging client. * This uses `uv_async` to attempt to fix that. * Empirically it fixes the DAP problem above.
**Lute**: Updated from `1.0.1-nightly.20260807` to `1.0.1-nightly.20260814` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260814 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.