This repository was archived by the owner on Dec 27, 2025. It is now read-only.
forked from luau-lang/lute
-
Notifications
You must be signed in to change notification settings - Fork 0
sync #2
Open
cheesycod
wants to merge
282
commits into
mluau:primary
Choose a base branch
from
luau-lang:primary
base: primary
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
sync #2
Conversation
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
…et_version.cmake` output (#419) Our release workflow depends on the output of `get_version.cmake` being the raw version. We added some extra text in #396 that is currently causing errors during the release tag generation step, so this PR reverts that change. Someone reached out about recent changes not being "released" yet, which was surprising because we're on a nightly release schedule—this was the root cause.
This PR comes with a small change to tools/luthier.luau to pick a different delimiter string.
tin makes net.request work with https on windows. should also work on linux according to the [docs](https://curl.se/libcurl/c/CURLOPT_SSL_OPTIONS.html)
### Problem
The issue can be replicated with a simple script that calls
`process.run` twice, like this:
```luau
local process = require("@lute/process")
process.run({"echo", "hello!"})
process.run({"echo", "goodbye!"})
```
Very rarely, some runs throw unexpected errors, crash, or corrupt Lute
output with random bytes. The problem is a subtle UAF bug in
`process.cpp`. Despite the small PR diff, this was a very tricky bug to
nail down. Had to go digging pretty deep into the libuv source to
understand what was going on.
Essentially, it's not correct to check if the `stdout` and `stderr`
pipes are active before closing them. Since these pipes are used as
read-only data streams, they're automatically made inactive by libuv
upon reaching EOF. In this situation, we don't need to call
`uv_read_stop` on these streams because they're already stopped
(although it is fine to do it; `uv_read_stop` is
[idempotent](https://docs.libuv.org/en/v1.x/stream.html#c.uv_read_stop)),
but we do still need to close the underlying pipe handle.
We're currently in a situation where calling `process.run` might
immediately close either the `stdout` or `stderr` streams (at EOF),
causing the `uv_is_active` check to fail, preventing us from calling
`uv_close` on the handle and from incrementing `pendingCloses`.
Failing to close these handles means that libuv retains data internally
associated with them, and by not incrementing `pendingCloses`
(essentially a refcount), we end up destroying the owning
`ProcessHandle` of these handles before libuv has been able to clean
them up internally.
Then, when we go to initialize new handles for the next `process.run`
call, we have a UAF manifest deep inside of libuv's circular doubly
linked queue code: adding a new handle to the data structure requires
adjusting pointers on the last-added handle, which happens to be a
handle created from the previous `process.run` call. At this point, it
is freed memory that was supposed to be removed from libuv's internals
before being freed (using `uv_close`).
### Solution
Check instead if the handles still need closing with `!uv_is_closing`
since `uv_is_active` is not relevant to whether `uv_close` needs to be
called in this case.
### Problem There was no std lib for `system` related functionalities. ### Solution We introduce a `std` library analogue for `system`, where we can now check the environment with boolean flags. Closes #167 To test (with huge help from @vrn-sn), we wanted to write a C++ file that compares the "os" captured by the C++ executable and compares to the `@std/system` OS. To write that (and other similar output comparison test cases), we exposed the `CliRuntimeFixture` and a `runCode()` function that was used by `require.test.cpp` before but we added a `capture()` function based on the `Luau/ReplFixture` class. Then, we changed some function signatures to ensure the program args (`argc` and `argv`) are not statically passed to avoid some tests failing. ### Example: ```lua local system = require("@std/system") if system.linux then print("Running on Linux") end ``` See `examples/system_environment_check.luau` for example use case
continuation of #416 (comment) to avoid duplicating a `static` function each time the header is included --------- Co-authored-by: Varun Saini <61795485+vrn-sn@users.noreply.github.com>
Some filesystem operations didn't clean up and free all their data. This PR attempts to fix this. Some general observations: - `uv_fs_req_cleanup` has to be called on all requests (sync/async). The documentation doesn't really mention this in much detail. For some operations, this might be a noop, but that's not part of the API and libuv is free to change this afaik. - When handling errors, the request wasn't always free'd. - The data associated with requests wasn't always free'd. - Some code was unreachable due to a Lua error thrown before. These errors seem hard to detect statically. Maybe there could be some RAII type for typed requests?
This should now provide exit as an option when invoking process. + provide better in editor typechecking.
Static casting `void*` to `T*` is always allowed, so it's better to use the narrower cast when possible.
Refactoring to make lute's API formatting more consistent
When running a script with `LUA_MINSTACK - 1` (19) or more arguments, Luau fails with `L->top < L->ci->top`, because `getRefForThread` tries to push the current thread onto a full stack [in `runBytecode`](https://github.com/luau-lang/lute/blob/a70354de11446cc95b65f00d853b0c3d0b0faf84/lute/cli/src/climain.cpp#L115). The stack only had `argc` slots, because it was resized in `setupArguments`. With this PR, `setupArguments` reserves one more slot (an alternative would be to reserve space in `getRefForThread`). `setupArguments` should probably be declared `static` as well, since it's not declared in any header.
This PR takes a different approach to #434 by saying "yes, the data will be visible, and we'll communicate intent for it to generally be undisturbed with an underscore prefix." This is generally accepted as the idiom for information hiding in Luau today, and I don't feel like this is worth making a point of difference.
…+ testing assertions (#411) This PR comes with some changes to the testing api to reduce the amount of global state we depend on - when making subcases, we now pass in the suite object on which the user can operate. Additionally, assertions are passed in with the test case itself, making them more accessible and reducing an additional line of code needed to start writing tests. - [x] {before,after}x{all,each} lifecycle methods - [x] Table assertions For example: <img width="463" height="79" alt="image" src="https://github.com/user-attachments/assets/31003849-ae2c-469d-a23b-415c4135865b" />
#449) This is a pre-req for a future PR for Multi-File bytecode compilation. Doing this lets me use the module path interface more flexibly.
I was trying to get the code generation to run through CMake (which would run lute in the build). When integrating this into luthier, I needed a way to identify the current lute executable to pass to CMake. This adds `execpath` to `@lute/process`, which mirrors Node.js' [process.execPath](https://nodejs.org/docs/latest/api/process.html#processexecpath) to get the lute executable path - this is immune to `exec -a foo lute` having `foo` as `argv[0]`. [`uv_setup_args`](https://docs.libuv.org/en/v1.x/misc.html#c.uv_setup_args) can allocate on some platforms. That memory should be free'd with [`uv_library_shutdown`](https://docs.libuv.org/en/v1.x/misc.html#c.uv_library_shutdown). I'm not sure where it's appropriate to call this. Passing around the `argv0` also seems a bit wrong. Maybe this path shouldn't be stored in `Runtime`?
Small change, but "CI" makes more sense than "Gated Commits" for the README icon: <img width="253" height="52" alt="image" src="https://github.com/user-attachments/assets/82b052c7-c445-47a0-993e-ac9943d2881b" />
[Rendered](https://github.com/luau-lang/lute/blob/vrn-sn/contributing-md/CONTRIBUTING.md). Feel free to commit to this branch directly. --------- Co-authored-by: ariel <arielweiss@roblox.com>
### Problem
Lute did not support user input yet.
### Solution
We introduce user input support to the Lute and the Lute standard
library!
Users can use the `input()` function found in`@std/io` to process and
store user input from command line, piped input, or file redirection.
See examples below and in `examples/user_input.luau`.
Functionality was implemented using `libuv`'s library and can be found
in `lute/io`
### Examples
#### Scripts
Get user input
```lua
local io = require("@std/io")
local input = io.input()
print(input)
```
Get user input with prompt
```lua
local io = require("@std/io")
local name = io.input("Please enter your name: ")
print(name)
```
#### Ways to execute the script
Command line
```bash
$ lute user_input.luau
> [will wait for user input in command line]
```
Piped input
```bash
$ echo hello | lute user_input.luau
```
Input redirected from file
```bash
$ lute user_input.luau < input_text.txt
```
### Future Work
- Tests
- `stdout` and `stderr` functionality and other I/O utilities.
- Currently, providing a prompt to the user with `.input()` will produce
a new line between said prompt and the user input, this will most likely
be resolved once `stdout` is implemented
Thank you @vrn-sn for massive help (esp with `libuv`) 🙏
Resolves #360
Not visible in a monospaced font, but the mighty en dash strikes again. 😉
Printing line numbers in `prettydiff` provides a lot of utility/clarity in properly visualizing differences b/w files. It also helps distinguish the diff output from other arbitrary text in the command line. Here is an example on a 100 line diff, to showcase the alignment of printed side-headers: <img width="351" height="1313" alt="Screenshot 2025-12-08 at 3 22 31 PM" src="https://github.com/user-attachments/assets/79780be7-0298-4f61-9483-f2bf233ba152" />
**Luau**: Updated from `0.702` to `0.703` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.703 --- *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: Varun Saini <61795485+vrn-sn@users.noreply.github.com>
We use the new `to_alias_override` Luau.Require callback to ensure that the `@std` and `@lute` aliases always point at the embedded libraries, not ones on disk that the user may have set up using `.luaurc` or `.config.luau` files. @Vighnesh-V, this means that `@std/test` will always point at the embedded module now.
When invoking lute, it will attempt to discover a script named with the provided argument, or within a `.lute` directory. This change supports the same discovery mechanism, but additionally supports discovering scripts in hierarchical `.lute` directories. As a practical example, I provided a luthier shorthand to demonstrate how this mechanism can be used. Instead of `lute tools/luthier.luau ...args` we can now invoke `lute luthier ...args`, and this can now be invoked from within any nested directory of lute.
**Lute**: Updated from `0.1.0-nightly.20251205` to `0.1.0-nightly.20251220` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/0.1.0-nightly.20251220 --- *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>
Thanks to recent changes to how require works, namely that `@std` requires will always resolve to the single builtin instance in the runtime (ignoring aliases), `lute test` can now handle transitive and batteries requires correctly without needing to intercept requires at all. This was the last blocker remaining before `lute test` could be used in CI. This PR: a) updates CI to call `lute test` b) removes the require interception that `lute test` did b) removes the explicit call to test.run() within the test files in our repo, since test discovery handles this I've left `test.run()` in for now, in case there is some desire to use the testing library without `lute test` (and the standard library tests in `std.test.luau` exercise this behaviour). I'm open to opinions about what to do with it, and can address those in a followup. Resolves issue #634
The lute runtime currently schedules coroutines in a std::vector, and we always pop off the first thread in the vector to run. For small numbers of coroutines, this is okay, but when you get to 10k+ this becomes very inefficient as we have to move all the other elements one over `O(n)`. This PR just replaces the `std::vector` with a `Luau::VecDeque`, making the pop operation `O(1)`. I've also included a profiling script that I used to profile lute since I keep forgetting the `xctrace` incantation - it can be invoked by: ``` ./tools/profile.sh /path/to/.luau(defaults to profile.luau) ```
Addresses #710 Updates `lute check` to use the new solver by default. Fails the test as expected without the change ``` Failed Tests (1): ❌ lute check.uses new solver /Users/rng/dev/lute/tests/cli/check.test.luau:32 eq: 1 ~= 0 ```
**Luau**: Updated from `0.703` to `0.704` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.704 --- *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>
**Lute**: Updated from `0.1.0-nightly.20251220` to `0.1.0-nightly.20260109` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/0.1.0-nightly.20260109 --- *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>
`AstExprTableItem` nodes are not serialized with location right now. I encountered a bug due to this behavior while using `lute lint` CLI: ``` Error linting file '/Users/wmccarthy/git/roblox/luau-ui-ecosystem-lints/repro_nil_location.luau': @std/syntax/init.luau:14: attempt to index nil with 'beginline' ``` If you follow the trace from std/syntax/init.luau:14, you'll see the error stems from calls to syntax.span.subsumes in lint's init file ([see here](https://github.com/luau-lang/lute/blob/primary/lute/cli/commands/lint/init.luau?rgh-link-date=2026-01-07T21%3A07%3A33Z#L150-L160)). Here, `nodeIsSuppressed` is used as the default visitor function, in other words, it is called at every visited node as the visitor walks the tree. It relies on the assumption that every node has location field, which is not true. `ExprTableItem` nodes, specifically, do not have a `location` field. Adding `location` to table item nodes will fix this issue and help avoid any similar future issues.
The bulk of the changes are refactoring some of the linting logic to extract the common logic between linting a file and a string. Also, paths in reported lint violations are now optional since they're not relevant to linting string input. The broader context for this PR is that it allows linting to be consumed by VSCode (and maybe other) extensions, since the source of truth for file contents is whatever the editor/LSP server has in memory, rather than what's on disk in the file.
I had a need for `any` when working on something else, and added `all` along the way
This lays the groundwork for the autofix work, and means that normal `lute lint` invocations can function as dry runs.
New lint rule! It's also useful for a test case I want to add for the autofix stuff
Adds support for autofixing reported lint violations (if the lint rules provide suggested fixes). The core logic for applying the fixes is pretty simple: split the content by line and do the replacements to the relevant lines. For now, we don't handle the cases where suggested fixes overlap (although my approach would probably be to just ignore fixes that overlap with previously applied fixes). We rerun the lints after applying fixes and report any violations that are still left. It's possible that those reported violations have suggested fixes, but we ignore them to prevent the chance of looping between suggested fixes infinitely.
Co-authored-by: ariel <arielweiss@roblox.com>
Port of [this Selene rule](https://kampfkarren.github.io/selene/lints/constant_table_comparison.html) to lute lint
#734) This PR just updates the `run`, `test` and `compile` cli command reference.
This PR just pulls in the Luau CLI's Profiler and Code Coverage modules into `lute`. We're doing this instead of exposing them from Luau because these features are not really products, so much as best effort attempts, so we don't necessarily want to expose them from Luau yet. This is just copied from Luau/CLI - no changes have been made.
Adds some more description to the docs for `lute lint` and `lute transform`
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.