A fast, small, safe, gradually typed embeddable scripting language derived from Lua
Find a file
LoganDark 4373f65fbd
Add back thread identity section as thread userdata instead
Thread userdata shouldn't be overlooked - even though security contexts are
Roblox-specific, the thread userdata can still be used to implement a
permissions model for sandboxing, whether this is based on security contexts
(like Roblox, or like Ring 0/3), on capabilities, or maybe even something else.
I think it is worth it to document this in the sandboxing page.

For everyone's future reference:

* Every lua_State has an associated userdata pointer at the end. It's just a
  pointer at the end called userdata:

    void* userdata;

  This pointer is never accessed or set by Luau itself, except for when
  first initializing the state, where it is set to NULL.

  This userdata can be set by the host after creating the thread, and is 100%
  invisible to Luau code. C functions exposed by the host can access the
  userdata by L->userdata, and, safe in the knowledge that it cannot be tampered
  with, use it to validate the thread.

* The global_State (the VM, as opposed to just the main thread) contains a field
  called cb:

    lua_Callbacks cb;

  The struct is currently defined as:

    /* Callbacks that can be used to reconfigure behavior of the VM dynamically.
     * These are shared between all coroutines.
     *
     * Note: interrupt is safe to set from an arbitrary thread but all other
     * callbacks can only be changed when the VM is not running any code */
    struct lua_Callbacks
    {
        /* gets called at safepoints (loop back edges, call/ret, gc) if set */
        void (*interrupt)(lua_State* L, int gc);

        /* gets called when an unprotected error is raised (if longjmp is
         * used) */
        void (*panic)(lua_State* L, int errcode);


        /* gets called when L is created (LP == parent) or destroyed (LP ==
         * NULL) */
        void (*userthread)(lua_State* LP, lua_State* L);

        /* gets called when a string is created; returned atom can be retrieved
         * via tostringatom */
        int16_t (*useratom)(const char* s, size_t l);


        /* gets called when BREAK instruction is encountered */
        void (*debugbreak)(lua_State* L, lua_Debug* ar);

        /* gets called after each instruction in single step mode */
        void (*debugstep)(lua_State* L, lua_Debug* ar);

        /* gets called when thread execution is interrupted by break in another
         * thread */
        void (*debuginterrupt)(lua_State* L, lua_Debug* ar);

        /* gets called when protected call results in an error */
        void (*debugprotectederror)(lua_State* L);
    };

  Assuming you cache the global_State when creating the main thread (which you
  should - it's just L->global), you can set g->cb->userthread to a C function
  to define what should happen when a new thread is created or destroyed.

  This can be used to:
  * Inherit userdata from parent threads; great for permission models.
  * Run destructors on userdata when threads are collected; great for resources.

That is a lot of information to digest, but if a Luau dev reads this, they'll
probably have said "yep, exactly" at least once. Documenting this small aspect
of the VM will be another step towards making it a bit friendlier for people to
start using Luau.

Obviously, the more technical documentation will remain here (in this commit &
pull request), but even the public facing documentation (which developers, like
me, will reference) should contain information just like the thread identity
section that was removed.

Hopefully, this is a suitable replacement, as thread userdata IS available in
the open-source version of Luau - and is used by Roblox for its "extra space" to
store things like thread identity.
2021-11-07 07:20:42 -08:00
.github Update CI scripts to ignore .md changes (#100) 2021-11-03 12:30:30 -07:00
Analysis Sync to upstream/release/503 (#135) 2021-11-05 08:47:21 -07:00
Ast Fix unused variable treatment (#139) 2021-11-05 12:39:27 -07:00
bench Sync to upstream/release/503 (#135) 2021-11-05 08:47:21 -07:00
CLI Fix CLI analysis reporting wrong file names (#146) 2021-11-05 19:11:56 -07:00
Compiler Fix small assert ordering (#143) 2021-11-05 14:38:08 -07:00
docs Add back thread identity section as thread userdata instead 2021-11-07 07:20:42 -08:00
extern Sync to upstream/release/501 (#20) 2021-11-01 14:52:34 -07:00
fuzz Sync to upstream/release/501 (#20) 2021-11-01 14:52:34 -07:00
papers Fix HATRA '21 README.md formatting (#118) 2021-11-04 09:00:41 -05:00
rfcs Spelling (#119) 2021-11-04 09:50:46 -05:00
tests Fold length operations when argument is a constant string (#141) 2021-11-05 13:24:30 -07:00
tools Sync to upstream/release/503 (#135) 2021-11-05 08:47:21 -07:00
VM Sync to upstream/release/503 (#135) 2021-11-05 08:47:21 -07:00
.clang-format Sync to upstream/release/501 (#20) 2021-11-01 14:52:34 -07:00
.gitignore Update .gitignore to match upstream 2021-11-01 14:52:34 -07:00
CMakeLists.txt Sync to upstream/release/501 (#20) 2021-11-01 14:52:34 -07:00
CONTRIBUTING.md Update CONTRIBUTING.md 2021-11-03 22:08:23 -07:00
LICENSE.txt Update LICENSE.txt 2021-11-03 09:41:30 -07:00
lua_LICENSE.txt Sync to upstream/release/501 (#20) 2021-11-01 14:52:34 -07:00
Makefile Fix unused variable treatment (#139) 2021-11-05 12:39:27 -07:00
README.md Update README.md 2021-11-05 10:16:28 -07:00
Sources.cmake Sync to upstream/release/503 (#135) 2021-11-05 08:47:21 -07:00

Luau CI Coverage

Luau (lowercase u, /ˈlu.aʊ/) is a fast, small, safe, gradually typed embeddable scripting language derived from Lua.

It is designed to be backwards compatible with Lua 5.1, as well as incorporating some features from future Lua releases, but also expands the feature set (most notably with type annotations). Luau is largely implemented from scratch, with the language runtime being a very heavily modified version of Lua 5.1 runtime, with completely rewritten interpreter and other performance innovations. The runtime mostly preserves Lua 5.1 API, so existing bindings should be more or less compatible with a few caveats.

Luau is used by Roblox game developers to write game code, as well as by Roblox engineers to implement large parts of the user-facing application code as well as portions of the editor (Roblox Studio) as plugins. Roblox chose to open-source Luau to foster collaboration within the Roblox community as well as to allow other companies and communities to benefit from the ongoing language and runtime innovation.

This repository hosts source code for the language implementation and associated tooling, documentation for the language as well as RFCs and other materials. The documentation portion of this repository can be viewed at https://luau-lang.org/

Usage

Luau is an embeddable language, but it also comes with two command-line tools by default, luau and luau-analyze.

luau is a command-line REPL and can also run input files. Note that REPL runs in a sandboxed environment and as such doesn't have access to the underlying file system except for ability to require modules.

luau-analyze is a command-line type checker and linter; given a set of input files, it produces errors/warnings according to the file configuration, which can be customized by using --! comments in the files or .luaurc files. For details please refer to type checking and linting documentation.

You can download the binaries from a recent release.

Building

To build Luau tools or tests yourself, you can use CMake on all platforms:

mkdir cmake && cd cmake
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build . --target Luau.Repl.CLI --config RelWithDebInfo
cmake --build . --target Luau.Analyze.CLI --config RelWithDebInfo

Alternatively, on Linus/macOS you can use make:

make config=release luau luau-analyze

To integrate Luau into your CMake application projects, at the minimum you'll need to depend on Luau.Compiler and Luau.VM projects. From there you need to create a new Luau state (using Lua 5.x API such as lua_newstate), compile source to bytecode and load it into the VM like this:

std::string bytecode = Luau::compile(source); // needs Luau/Compiler.h include
if (luau_load(L, chunkname, bytecode.data(), bytecode.size()) == 0)
    return 1; /* return chunk main function */

For more details about the use of host API you currently need to consult Lua 5.x API. Luau closely tracks that API but has a few deviations, such as the need to compile source separately (which is important to be able to deploy VM without a compiler), or lack of __gc support (use lua_newuserdatadtor instead).

To gain advantage of many performance improvements it's highly recommended to use safeenv feature, which sandboxes individual scripts' global tables from each other as well as protects builtin libraries from monkey-patching. For this to work you need to call luaL_sandbox for the global state and luaL_sandboxthread for each new script's execution thread.

Testing

Luau has an internal test suite; in CMake builds it is split into two targets, Luau.UnitTest (for bytecode compiler and type checker/linter tests) and Luau.Conformance (for VM tests). The unit tests are written in C++, whereas the conformance tests are largely written in Luau (see tests/conformance).

Makefile builds combine both into a single target and can be ran via make test.

Dependencies

Luau uses C++ as its implementation language. The runtime requires C++11, whereas the compiler and analysis components require C++17. It should build without issues using Microsoft Visual Studio 2017 or later, or gcc-7 or clang-7 or later.

Other than the STL/CRT, Luau library components don't have external dependencies. The test suite depends on doctest testing framework, and the REPL command-line depends on cpp-linenoise.

License

Luau implementation is distributed under the terms of MIT License. It is based on Lua 5.x implementation that is MIT licensed as well.

When Luau is integrated into external projects, we ask to honor the license agreement and include Luau attribution into the user-facing product documentation. The attribution using Luau logo is also encouraged.