├── .gitignore ├── .gitmodules ├── .github └── ISSUE_TEMPLATE │ └── specific-version-commit-build-request.md ├── CMakeLists.txt ├── LICENSE.txt ├── main.cpp ├── snippets ├── Vector3Table.txt └── ExtraCodeSnippet.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | build_wasm 3 | 4 | .vscode -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "luau"] 2 | path = luau 3 | url = https://github.com/Roblox/luau.git 4 | [submodule "emsdk"] 5 | path = emsdk 6 | url = https://github.com/emscripten-core/emsdk.git 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/specific-version-commit-build-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Specific version/commit build request 3 | about: Request a specific version/commit of Luau 4 | title: "[Version Request] 0.xxx" 5 | labels: version request 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Requesting version 11 | 0.5xx or 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | project(LuauInLuau LANGUAGES CXX) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | option(LUAU_BUILD_CLI "Build CLI" OFF) 6 | option(LUAU_BUILD_TESTS "Build tests" OFF) 7 | option(LUAU_BUILD_WEB "Build Web module" OFF) 8 | option(LUAU_WERROR "Warnings as errors" OFF) 9 | option(LUAU_STATIC_CRT "Link with the static CRT (/MT)" OFF) 10 | add_subdirectory(luau) 11 | 12 | add_executable(LuauInLuau main.cpp) 13 | target_link_libraries(LuauInLuau Luau.Compiler) 14 | target_link_libraries(LuauInLuau Luau.VM) -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 RadiatedExodus (RealEthanPlayzDev) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lualib.h" 3 | #include "luacode.h" 4 | #include "Luau/Common.h" 5 | #include "Luau/ExperimentalFlags.h" 6 | #include 7 | 8 | LUAU_NOINLINE int LuauRunUsingCustomState(lua_State* L, const char* bytecode) 9 | { 10 | std::string BytecodeStdString = bytecode; 11 | int LoadResult = luau_load(L, "LuauInLuau_Chunk", bytecode, BytecodeStdString.size(), 0); 12 | if (LoadResult == 1) { return 1; } 13 | return lua_pcall(L, 0, 0, 0); 14 | } 15 | 16 | LUAU_NOINLINE bool SetLuauFlag(std::string name, bool state) 17 | { 18 | for (Luau::FValue* flag = Luau::FValue::list; flag; flag = flag->next) 19 | { 20 | if (name == flag->name) 21 | { 22 | flag->value = state; 23 | return true; 24 | } 25 | } 26 | return false; 27 | } 28 | 29 | LUAU_NOINLINE void SetLuauFlags(bool state) 30 | { 31 | for (Luau::FValue* flag = Luau::FValue::list; flag; flag = flag->next) 32 | if (strncmp(flag->name, "Luau", 4) == 0) 33 | flag->value = state; 34 | } 35 | 36 | LUAU_NOINLINE void SetLuauFlagsDefault() 37 | { 38 | for (Luau::FValue* flag = Luau::FValue::list; flag; flag = flag->next) 39 | if (strncmp(flag->name, "Luau", 4) == 0 && !Luau::isFlagExperimental(flag->name)) 40 | flag->value = true; 41 | } 42 | 43 | int main() 44 | { 45 | return 0; 46 | } -------------------------------------------------------------------------------- /snippets/Vector3Table.txt: -------------------------------------------------------------------------------- 1 | --// Vanilla Luau Vector3 implementation 2 | --// Only does this if it does not find a Vector3 global 3 | local type = type 4 | local typeof = typeof 5 | local Vector3 = Vector3 6 | if not Vector3 then 7 | local Vector3Internal = {} 8 | Vector3Internal.__index = Vector3 9 | Vector3Internal.__type = "Vector3" 10 | Vector3Internal.__metatable = "This metatable is locked" 11 | 12 | Vector3 = {} 13 | Vector3.new = function(x, y, z) 14 | return setmetatable({X = x or 0, Y = y or 0, Z = z or 0}, Vector3Internal) 15 | end 16 | table.freeze(Vector3) 17 | 18 | Vector3Internal.__concat = function() 19 | assert(false, "attempt to concatenate Vector3 with Vector3") 20 | return 21 | end 22 | Vector3Internal.__unm = function(self) 23 | return Vector3.new(-self.X, -self.Y, -self.Z) 24 | end 25 | Vector3Internal.__add = function(self, v3_2) 26 | v3_2 = if (typeof(v3_2) == "number") then Vector3.new(v3_2, v3_2, v3_2) else v3_2 27 | return Vector3.new(self.X + v3_2.X, self.Y + v3_2.Y, self.Z + v3_2.Z) 28 | end 29 | Vector3Internal.__sub = function(self, v3_2) 30 | v3_2 = if (typeof(v3_2) == "number") then Vector3.new(v3_2, v3_2, v3_2) else v3_2 31 | return Vector3.new(self.X - v3_2.X, self.Y - v3_2.Y, self.Z - v3_2.Z) 32 | end 33 | Vector3Internal.__mul = function(self, v3_2) 34 | v3_2 = if (typeof(v3_2) == "number") then Vector3.new(v3_2, v3_2, v3_2) else v3_2 35 | return Vector3.new(self.X * v3_2.X, self.Y * v3_2.Y, self.Z * v3_2.Z) 36 | end 37 | Vector3Internal.__div = function(self, v3_2) 38 | v3_2 = if (typeof(v3_2) == "number") then Vector3.new(v3_2, v3_2, v3_2) else v3_2 39 | return Vector3.new(self.X / v3_2.X, self.Y / v3_2.Y, self.Z / v3_2.Z) 40 | end 41 | Vector3Internal.__div = function(_, t) 42 | if (typeof(t) == "table") and (t["__type"] == "Vector3") then 43 | assert(false, "attempt to perform arithmetic (mod) on Vector3") 44 | else 45 | assert(false, "attempt to perform arithmetic (mod) on Vector3 and "..typeof(t)) 46 | end 47 | return 48 | end 49 | Vector3Internal.__pow = function(_, t) 50 | if (typeof(t) == "table") and (t["__type"] == "Vector3") then 51 | assert(false, "attempt to perform arithmetic (pow) on Vector3") 52 | else 53 | assert(false, "attempt to perform arithmetic (pow) on Vector3 and "..typeof(t)) 54 | end 55 | return 56 | end 57 | Vector3Internal.__tostring = function(self) 58 | return self.X..", "..self.Y..", "..self.Z 59 | end 60 | Vector3Internal.__eq = function(self, v3_2) 61 | if (typeof(v3_2) ~= "table") or (v3_2["__type"] == "Vector3") then return false end 62 | return (self.X == v3_2.X) and (self.Y == v3_2.Y) and (self.Z == v3_2.Z) 63 | end 64 | Vector3Internal.__lt = function(self, v3_2) 65 | if (typeof(v3_2) ~= "table") or (v3_2["__type"] == "Vector3") then return false end 66 | return (self.X < v3_2.X) and (self.Y < v3_2.Y) and (self.Z < v3_2.Z) 67 | end 68 | Vector3Internal.__le = function(self, v3_2) 69 | if (typeof(v3_2) ~= "table") or (v3_2["__type"] == "Vector3") then return false end 70 | return (self.X <= v3_2.X) and (self.Y <= v3_2.Y) and (self.Z <= v3_2.Z) 71 | end 72 | Vector3Internal.__len = function() 73 | assert(false, "attempt to get length of a Vector3 value") 74 | return 75 | end 76 | 77 | local oldtype = type 78 | type = function(v) 79 | return if (oldtype(v) == "table") and v["__type"] then v["__type"] else oldtype(v) 80 | end 81 | 82 | local oldtypeof = typeof 83 | typeof = function(v) 84 | return if (oldtypeof(v) == "table") and v["__type"] then v["__type"] else oldtypeof(v) 85 | end 86 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | https://github.com/RealEthanPlayzDev/LuauCeption 3 | 4 | # LuauInLuau 5 | Inspired by @Rerumu's [LuauInLuau](https://gist.github.com/Rerumu/ecaf1de2f2b31d0fa91b9bac8e1e15d8), I've created this repository to translate Luau to Luau. 6 | 7 | ## Features 8 | - Running Luau code (with or without safe env) 9 | - Compiling Luau code into bytecode (with support for setting optimization and debug levels) 10 | 11 | ## Fix list 12 | - [ ] Fix issue where if a error occurs during runtime, it crashes the thread calling the function and does not provide any useful information 13 | 14 | ## Getting LuauInLuau 15 | You can get it from releases or compile using the following instruction: (they were tested in Linux, WSL2 to be specific, using bash) 16 | 1. Clone this repository 17 | 2. Initialize all submodules 18 | 3. Install emsdk (``cd emsdk && ./emsdk install latest && ./emsdk activate latest && cd ..``) 19 | 4. Compile this project into WebAssembly (``sh build.sh``, make sure cmake, clang/gcc, and llvm is installed) 20 | 5. Use Wasynth to translate the WebAssembly to Luau (``wasm2luau LuauInLuau.wasm > LuauInLuau.luau``) 21 | 6. Copy over the contents of ``ExtraCodeSnippet.txt`` (at the ``snippets`` folder) and comment out the old returned function generated by Wasynth, _you might need to change some things if theres a breaking change update_. 22 | 7. (ONLY NEEDED IF RUNNING VANILLA LUAU) Copy the contents of ``Vector3Table.txt`` (at the ``snippets`` folder) to the top of the script, no changes should be required, you need this to have the script work at vanilla Luau (like the luau repl for example) as Wasynth uses Roblox's Vector3 datatype (the snippet checks for the existence of the V3 global and if it doesn't exist then it recreates it + overriding type and typeof for getting the V3 datatype). Alternatively compile Wasynth with ``default-features = false``, since it will include the Vector3 table implementation directly without any need of user interference. (Thanks [@Rerumu](https://github.com/Rerumu) for the Wasynth compile tip) 23 | 24 | ## How it works and a bit of a motivation background 25 | I've started working on this around December 2022, where I found @Rerumu's LuauInLuau gist which caught my interest since I've been looking for a Luau compiler and interpreter written in Luau, the way it works was pretty simple, you compile C++ code into WebAssembly and use [@Rerumu](https://github.com/Rerumu)'s [Wasynth](https://github.com/Rerumu/Wasynth) to translate WebAssembly to Luau, [@Rerumu](https://github.com/Rerumu) and a few others in their server had helped me with this process. I was then able to produce a working LuauInLuau for version 0.556. 26 | 27 | Now skipping to January 14 2023, I've come back to this little project under one goal, to be able to compile Luau code and have the bytecode string in Luau, I could have just directly used ``luau_compile`` but when I first started trying things, I was too stupid to understand how Wasynth even handles loading and storing string and integers. 28 | 29 | My solution? Make a C++ program to wrap around those functions! Yes, that is why there is C++ code in this repository, albeit the functions weren't exported independently and I still had to learn how to load and store things myself, thanks to the cleaner generated code however, I was able to understand the basic principle of how it works. In the end I was able to export functions to run and compile Luau code respectively. 30 | 31 | ## Credits 32 | - [Luau](https://github.com/Roblox/luau) - The Roblox Luau repository 33 | - [emsdk](https://github.com/emscripten-core/emsdk) - Emscripten SDK for compiling C++ -> WebAssembly 34 | - [Wasynth](https://github.com/Rerumu/Wasynth) - WebAssembly -> Luau translation tool 35 | - [The original LuauInLuau](https://gist.github.com/Rerumu/ecaf1de2f2b31d0fa91b9bac8e1e15d8) - What started this project, and used some code from it. 36 | - [Fiu](https://github.com/TheGreatSageEqualToHeaven/Fiu) - Used their Luau bytecode version verification code 37 | - [NougatBitz/Luau](https://github.com/NougatBitz/Luau) - Used code from here (with permission) to patch things further 38 | 39 | ## Acknowledgements 40 | - [@Roblox](https://github.com/Roblox) and Luau contributors 41 | - Emscripten contributors and creators 42 | - [@Rerumu](https://github.com/Rerumu) 43 | - [@TheGreatSageEqualToHeaven](https://github.com/TheGreatSageEqualToHeaven) 44 | - [@NougatBitz](https://github.com/NougatBitz) 45 | -------------------------------------------------------------------------------- /snippets/ExtraCodeSnippet.txt: -------------------------------------------------------------------------------- 1 | --// Named function dictionary 2 | local NamedFunctionList = { 3 | --// Luau 4 | ["luau_compile"] = FUNC_LIST[762]; 5 | ["luaL_newstate"] = FUNC_LIST[1091]; 6 | ["luaL_openlibs"] = FUNC_LIST[1088]; 7 | ["lua_close"] = FUNC_LIST[1158]; 8 | ["luaL_sandbox"] = FUNC_LIST[1090]; 9 | ["lua_tolstring"] = FUNC_LIST[793]; 10 | ["luaL_pushresult"] = FUNC_LIST[897]; 11 | 12 | --// Standard Library 13 | ["dlmalloc"] = FUNC_LIST[3453]; 14 | ["dlfree"] = FUNC_LIST[3454]; 15 | ["strlen"] = FUNC_LIST[3199]; 16 | 17 | --// WebAssembly 18 | ["__wasm_call_ctors"] = FUNC_LIST[350]; 19 | 20 | --// LuauInLuau 21 | ["LuauRunUsingCustomState"] = FUNC_LIST[351]; 22 | ["SetLuauFlags"] = FUNC_LIST[355]; 23 | ["SetLuauFlagsDefault"] = FUNC_LIST[356]; 24 | ["SetLuauFlag"] = FUNC_LIST[353]; 25 | 26 | --// Macros 27 | ["lua_tostring"] = function(L, i) return FUNC_LIST[793](L, i, 0) end; --// lua_tolstring 28 | } 29 | 30 | --// Pre-init environment function setup 31 | local NOW_TIME = os.time() * 1000 32 | local FILE_MAP = { {}, {} } 33 | local load_string = rt.load.string 34 | local table_insert = table.insert 35 | 36 | local function CreateStub(ret) 37 | return function() 38 | return ret 39 | end 40 | end 41 | 42 | local function fd_flush(file) 43 | local final = table.concat(file) 44 | local last = 1 45 | for index, data in string.gmatch(final, '()([^\n]*)\n') do 46 | last = index + #data 47 | print(data) 48 | end 49 | table.clear(file) 50 | file[1] = string.sub(final, last + 1) 51 | end 52 | 53 | --// Stubbed functions 54 | FUNC_LIST[311] = CreateStub(0) --// _emscripten_get_progname 55 | FUNC_LIST[344] = CreateStub(0) --// fd_seek 56 | FUNC_LIST[347] = CreateStub(0) --// fd_pread 57 | FUNC_LIST[348] = CreateStub(0) --// fd_pwrite 58 | FUNC_LIST[349] = CreateStub(0) --// __syscall_truncate64 59 | FUNC_LIST[346] = CreateStub(0) --// __syscall_fallocate 60 | FUNC_LIST[298] = CreateStub(0) --// fd_sync 61 | FUNC_LIST[302] = CreateStub(0) --// fd_fdstat_get 62 | FUNC_LIST[260] = CreateStub(0) --// environ_sizes_get 63 | FUNC_LIST[261] = CreateStub(0) --// environ_get 64 | FUNC_LIST[266] = CreateStub(0) --// fd_close 65 | FUNC_LIST[267] = CreateStub(0) --// fd_read 66 | 67 | --// __cxa_throw 68 | FUNC_LIST[0] = function(except, _info, _dtor) 69 | local what = NamedFunctionList.luaL_pushresult(except) 70 | local len = NamedFunctionList.strlen(what) 71 | error("An exception was thrown\n" .. load_string(memory_at_0, what, len)) 72 | end 73 | 74 | --// emscripten_memcpy_big 75 | FUNC_LIST[281] = function(destination, source, size) 76 | rt.store.copy(memory_at_0, destination, memory_at_0, source, size) 77 | end 78 | 79 | --// emscripten_date_now 80 | FUNC_LIST[285] = function() 81 | return NOW_TIME + os.clock() * 1000 82 | end 83 | 84 | --// fd_write 85 | FUNC_LIST[268] = function(fd, list, count, ret_pointer) 86 | local file = FILE_MAP[fd] 87 | if not file then return 8 end 88 | local total = 0 89 | for pointer = list, list + (count - 1) * 8, 8 do 90 | local start = load_i32(memory_at_0, pointer) 91 | local len = load_i32(memory_at_0, pointer + 4) 92 | local read = load_string(memory_at_0, start, len) 93 | table_insert(file, read) 94 | total = total + #read 95 | end 96 | store_i32(memory_at_0, ret_pointer, total) 97 | fd_flush(file) 98 | return 0 99 | end 100 | 101 | --// abort 102 | FUNC_LIST[312] = function(reason) 103 | assert(false, "Aborted("..reason..")") 104 | end 105 | 106 | --// proc_exit 107 | FUNC_LIST[259] = function() 108 | return FUNC_LIST[312]("process exited") 109 | end 110 | 111 | --// Initialize 112 | run_init_code() 113 | memory_at_0 = MEMORY_LIST[0] 114 | NamedFunctionList.__wasm_call_ctors() 115 | 116 | --// Patching existing required functions in env 117 | local function lua_try_catch(index, ...) 118 | return TABLE_LIST[0].data[index](...) 119 | end 120 | 121 | local DoNotPatchTargets = { 0, 259, 260, 261, 266, 267, 268, 281, 285, 298, 302, 311, 312, 344, 346, 347, 348, 349 } 122 | local PatchTargets = {} 123 | for i = 0, 349 do 124 | if table.find(DoNotPatchTargets, i) then continue end 125 | table.insert(PatchTargets, i) 126 | end 127 | 128 | for _, v in ipairs(PatchTargets) do 129 | FUNC_LIST[v] = lua_try_catch 130 | end 131 | 132 | --// Functions that will be exported 133 | local function ValidLuauBytecode(bytecode: string) 134 | --// This isn't really checking the contents of the string and just checking the version identifier (first byte) 135 | --// Thanks to @TheGreatSageEqualToHeaven since I took this from Fiu (read_byte at luau_deserialize and the version identifier check) 136 | return string.unpack(">B", bytecode, 1) == 3 137 | end 138 | 139 | local function ResultCodeToBoolean(code) 140 | return code == 0 141 | end 142 | 143 | local function LuauCompile(src: string, optimizationlevel: number?, debuglevel: number?) 144 | --// Create source string (char*) and bytecode size thing (size_t) 145 | local SrcLength = #src 146 | local SrcBuffer = NamedFunctionList.dlmalloc(SrcLength + 1) 147 | rt.store.string(memory_at_0, SrcBuffer, src) 148 | rt.store.i32_n8(memory_at_0, SrcBuffer + SrcLength, 0) 149 | local BytecodeSizePtr = NamedFunctionList.dlmalloc(8) --// size_t = 8 bytes, thanks @Rerumu 150 | 151 | --// Create a CompileOptions (luau/Compiler/include/Luau/Compiler.h#L17) 152 | --// Struct object 153 | --// We're only using the optimizationLevel and debugLevel properties on the struct, 154 | --// both are int, a int is 4 bytes, so we allocate 8 bytes to store those 2 properties: 155 | --[[ 156 | // 0 - no optimization 157 | // 1 - baseline optimization level that doesn't prevent debuggability 158 | // 2 - includes optimizations that harm debuggability such as inlining 159 | int optimizationLevel = 1; 160 | 161 | // 0 - no debugging support 162 | // 1 - line info & function names only; sufficient for backtraces 163 | // 2 - full debug info with local & upvalue names; necessary for debugger 164 | int debugLevel = 1; 165 | --]] 166 | local CompileOptionsPtr = NamedFunctionList.dlmalloc(8) 167 | rt.store.i64(memory_at_0, CompileOptionsPtr, rt.i64.from_u32(optimizationlevel or 1, debuglevel or 1)) 168 | 169 | --// Compile bytecode and get the size 170 | local BytecodePtr = NamedFunctionList.luau_compile(SrcBuffer, SrcLength, CompileOptionsPtr, BytecodeSizePtr) 171 | local BytecodeSize = load_i32(memory_at_0, BytecodeSizePtr) 172 | local Bytecode = load_string(memory_at_0, BytecodePtr, BytecodeSize) 173 | local ValidLuauBytecode = ValidLuauBytecode(Bytecode) 174 | 175 | --// Cleanup 176 | NamedFunctionList.dlfree(SrcBuffer) 177 | NamedFunctionList.dlfree(BytecodeSizePtr) 178 | NamedFunctionList.dlfree(BytecodePtr) 179 | NamedFunctionList.dlfree(CompileOptionsPtr) 180 | 181 | --// Return 182 | --// If the compiler failed, then Bytecode will be the error that occured while compiling (BytecodeSize will be the length of the error) 183 | return ValidLuauBytecode, Bytecode, BytecodeSize 184 | end 185 | 186 | local function LuauRun(src: string, safeenv: boolean?, optimizationlevel: number?, debuglevel: number?) 187 | --// Compile bytecode 188 | local CompileSuccess, Result, ResultSize = LuauCompile(src, optimizationlevel, debuglevel) 189 | assert(CompileSuccess, Result) 190 | 191 | --// Load bytecode string into memory 192 | local BytecodePtr = NamedFunctionList.dlmalloc(ResultSize) 193 | rt.store.string(memory_at_0, BytecodePtr, Result) 194 | 195 | --// lua_State setup 196 | local L = NamedFunctionList.luaL_newstate() 197 | NamedFunctionList.luaL_openlibs(L) 198 | if safeenv then 199 | NamedFunctionList.luaL_sandbox(L) 200 | end 201 | 202 | --// Load and run bytecode 203 | local Result = NamedFunctionList.LuauRunUsingCustomState(L, BytecodePtr) 204 | 205 | --// Cleanup and return 206 | NamedFunctionList.lua_close(L) 207 | NamedFunctionList.dlfree(BytecodePtr) 208 | return ResultCodeToBoolean(Result) 209 | end 210 | 211 | local function LuauRunWithSafeEnv(src: string) 212 | return LuauRun(src, true) 213 | end 214 | 215 | local function LuauRunWithoutSafeEnv(src: string) 216 | return LuauRun(src, false) 217 | end 218 | 219 | local function LuauRunBytecode(bytecode: string, safeenv: boolean?) 220 | --// Load bytecode string into memory 221 | local BytecodePtr = NamedFunctionList.dlmalloc(#bytecode) 222 | rt.store.string(memory_at_0, BytecodePtr, bytecode) 223 | 224 | --// lua_State setup 225 | local L = NamedFunctionList.luaL_newstate() 226 | NamedFunctionList.luaL_openlibs(L) 227 | if safeenv then 228 | NamedFunctionList.luaL_sandbox(L) 229 | end 230 | 231 | --// Load bytecode into lua_State and run bytecode 232 | local Result = NamedFunctionList.LuauRunUsingCustomState(L, BytecodePtr) 233 | 234 | --// Cleanup and return 235 | NamedFunctionList.lua_close(L) 236 | NamedFunctionList.dlfree(BytecodePtr) 237 | return ResultCodeToBoolean(Result) 238 | end 239 | 240 | local function CreateClosureFromSource(src: string, safeenv: boolean?, optimizationlevel: number?, debuglevel: number?) 241 | return function() 242 | LuauRun(src, safeenv, optimizationlevel, debuglevel) 243 | return 244 | end 245 | end 246 | 247 | local function SetLuauFlag(name: string, value: boolean) 248 | --// Load name string into memory 249 | local NamePtr = NamedFunctionList.dlmalloc(#name) 250 | rt.store.string(memory_at_0, NamePtr, name) 251 | 252 | --// Set the flag 253 | NamedFunctionList.SetLuauFlag(NamePtr, if value then 0 else 1) 254 | 255 | --// Cleanup and return 256 | NamedFunctionList.dlfree(NamePtr) 257 | return 258 | end 259 | 260 | local function SetLuauFlags(value: boolean) 261 | --// Set all flags and return 262 | NamedFunctionList.SetLuauFlags(if value then 0 else 1) 263 | return 264 | end 265 | 266 | --// Return 267 | return { 268 | --// Run functions 269 | Run = LuauRun; 270 | RunWithoutSafeEnv = LuauRunWithoutSafeEnv; 271 | RunWithSafeEnv = LuauRunWithSafeEnv; 272 | RunBytecode = LuauRunBytecode; 273 | 274 | --// Compile related functions 275 | Compile = LuauCompile; 276 | CreateClosureFromSource = CreateClosureFromSource; 277 | 278 | --// Luau flag utilities 279 | ResetFlags = NamedFunctionList.SetLuauFlagsDefault; 280 | SetLuauFlag = SetLuauFlag; 281 | SetLuauFlags = SetLuauFlags; 282 | 283 | --// Misc utilities 284 | ValidLuauBytecode = ValidLuauBytecode; 285 | ResultCodeToBoolean = ResultCodeToBoolean; 286 | 287 | --// Wasynth related utilities 288 | NamedFunctionList = NamedFunctionList; 289 | rt = rt; 290 | FUNC_LIST = FUNC_LIST; 291 | } --------------------------------------------------------------------------------