Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .seal/typedefs/interop/extern.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

--[=[
Load external libraries at runtime.

External libraries (also called plugins), can be used to expand *seal*'s functionality,
add bindings to C and Rust libraries, and allow performance-critical code execution without mluau or Luau VM overhead.
]=]
export type extern = {
--[=[
Loads the native dynamic library at `path`, calling the symbol `seal_open_extern` in that library with a pointer to the Luau state.

It is expected that calling `seal_open_extern` pushes 1 value directly onto the Luau stack. This function returns that value unchanged.

This function does not handle platform-specific behavior; it is expected the caller loads the correct dynamic library for
supported platforms/architectures.

# ⚠️ Safety

This function is extremely unsafe.

External libraries can easily bypass Rust's and mluau's safety guarantees, including but not limited to:
- causing memory safety vulnerabilities,
- incorrectly using the Luau stack (causing hard crashes or UB),
- modifying the Luau state in cursed ways,
- execute arbitrary code.

The caller is responsible for ensuring the library:

- is compatible with the caller's operating system, platform, and architecture,
- is a *seal* extern library, not any other shared/dynamic library,
- contains a *not mangled* function symbol `seal_open_extern` that:
- is in the C ABI (use `"C-unwind"` in Rust),
- takes in a Luau `lua_State` pointer as its first argument,
- returns `1` as an `i32 (c_int)`.

Library/plugin maintainers are responsible for ensuring the library:

- uses the Luau stack correctly,
- does NOT share the passed `lua_State` between multiple OS threads,
- does NOT free memory owned by Luau,
- correctly links to Luau (not Lua) for using the Luau stack,
- should not throw an uncaught foreign exception or Rust panic.

# Errors

Throws an error if:

- The dynamic library cannot be found (usually with a message like "dlopen failed"),
- The dynamic library is missing the symbol `seal_open_extern`,
- The dynamic library could not be loaded for a different reason,
- `seal_open_extern` does not return 1 (c_int),
- `seal_open_extern` returns 1 but does not push exactly 1 value to the Luau stack.
]=]
load: (path: string) -> unknown,
}

return {} :: extern
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ A library is a good candidate for `@std` if:
5. please don't run a formatter over the whole codebase.
1. I don't mind if `wrap_err!`s go off the RHS of the page if that means vertical space is better used for code.
2. On the other hand, let's try to keep non-wrap_err! code and comments to 85-110 colwidth?
6. Documentation goes in `./.seal/typedefs/std/*`.
6. Inline documentation goes in `./.seal/typedefs/std/*`.
1. For documentation, try to stick with the newer docs headers like seen in the `@std/process` API docs.
2. No Moonwave `@attributes`, they make code less readable and we don't use Moonwave.
7. Register the library in `./src/require/mod.rs` and `./.seal/typedefs/init.luau` in 3 places:
7. After you finish writing inline documentation, regenerate markdown documentation by running `seal ./docs/docscripts/reference.luau`. Generated docs aren't going to be perfect, we'll fix them later.
8. Register the library in `./src/require/mod.rs` and `./.seal/typedefs/init.luau` in 3 places:
1. The Big Beautiful Table (BBT) in `./src/require/mod.rs`, which handles when the library is required directly (`@std/mylib`)
2. the Small Beautiful Table in `./src/require/mod.rs`, which handles when the entire `@std` is required at once.
3. in `./.seal/typedefs/init.luau` to provide `require` support when the entire `@std` is required at once.
8. Add tests in `./tests/luau/std/libname/*` or `./tests/luau/std/libname.luau`.
9. Add tests in `./tests/luau/std/libname/*` or `./tests/luau/std/libname.luau`.
Loading