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
68 changes: 50 additions & 18 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,21 +220,53 @@ jobs:
# files: ./coverage.info
# token: ${{ secrets.CODECOV_TOKEN }}

# web:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v1
# - uses: actions/checkout@v2
# with:
# repository: emscripten-core/emsdk
# path: emsdk
# - name: emsdk install
# run: |
# cd emsdk
# ./emsdk install latest
# ./emsdk activate latest
# - name: make
# run: |
# source emsdk/emsdk_env.sh
# emcmake cmake . -DLUAU_BUILD_WEB=ON -DCMAKE_BUILD_TYPE=Release
# make -j2 Luau.Web
verify-builtins:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/checkout@v4
with:
repository: secondlife/lsl-definitions
path: lsl-definitions

- name: Install dependencies
run: pip install pyyaml llsd

- name: Generate builtins.txt
run: |
cd lsl-definitions
python gen_definitions.py lsl_definitions.yaml gen_builtins_txt builtins.txt

- name: Verify builtins.txt matches
run: |
if ! diff -q builtins.txt lsl-definitions/builtins.txt; then
echo "ERROR: builtins.txt is out of sync with secondlife/lsl-definitions"
diff builtins.txt lsl-definitions/builtins.txt || true
echo ""
echo "To fix: clone secondlife/lsl-definitions and run:"
echo " python gen_definitions.py lsl_definitions.yaml gen_builtins_txt /path/to/slua/builtins.txt"
exit 1
fi
echo "builtins.txt is up to date"

web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
with:
repository: emscripten-core/emsdk
path: emsdk
- name: emsdk install
run: |
cd emsdk
./emsdk install latest
./emsdk activate latest
- name: make
run: |
source emsdk/emsdk_env.sh
emcmake cmake . -DLUAU_BUILD_WEB=ON -DCMAKE_BUILD_TYPE=Release
make -j2 Luau.Web
- name: smoke test
run: node CLI/test/Web.test.js ./Luau.Web.js
28 changes: 28 additions & 0 deletions .github/workflows/build_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,31 @@ jobs:
runs-on: "ubuntu-22.04"
steps:
- uses: secondlife/action-autobuild-release@v3

web:
needs: ["release"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
with:
repository: emscripten-core/emsdk
path: emsdk
- name: emsdk install
run: |
cd emsdk
./emsdk install latest
./emsdk activate latest
- name: make
run: |
source emsdk/emsdk_env.sh
emcmake cmake . -DLUAU_BUILD_WEB=ON -DCMAKE_BUILD_TYPE=Release
make -j2 Luau.Web
- uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: Luau.Web.js
asset_name: Luau.Web.js
asset_content_type: application/octet-stream
8 changes: 4 additions & 4 deletions CLI/src/LSLBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,16 @@ void luauSL_init_global_builtins(const char* builtins_file)
sSLConstantStrings.clear();

LUAU_ASSERT(builtins_file != nullptr);
std::ifstream fp(builtins_file, std::ios::binary);

if (!fp.good())
std::ifstream file_stream(builtins_file);
if (!file_stream)
{
fprintf(stderr, "couldn't open %s", builtins_file);
fprintf(stderr, "couldn't open %s\n", builtins_file);
exit(EXIT_FAILURE);
}

std::string line;
while (std::getline(fp, line))
while (std::getline(file_stream, line))
{
// ignore comment and blank lines
if (!line.rfind("//", 0) || !line.rfind('\r', 0) || !line.rfind('\n', 0) || line.empty())
Expand Down
55 changes: 54 additions & 1 deletion CLI/src/Web.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
#include "lua.h"
#include "lualib.h"
#include "luacode.h"
#include "llsl.h"

#include "Luau/Common.h"
#include "Luau/Frontend.h"
#include "Luau/BuiltinDefinitions.h"
#include "Luau/LSLBuiltins.h"

#include <string>
#include <memory>
Expand Down Expand Up @@ -62,17 +64,48 @@ struct DemoConfigResolver : Luau::ConfigResolver
Luau::Config defaultConfig;
};

// SL mode state
static lua_SLRuntimeState sl_state;

static void userthread_callback(lua_State* LP, lua_State* L)
{
if (LP == nullptr)
return;
lua_setthreaddata(L, lua_getthreaddata(LP));
}

static void setupState(lua_State* L)
{
luaL_openlibs(L);

// SL mode setup
lua_setthreaddata(L, &sl_state);
sl_state.slIdentifier = LUA_SL_IDENTIFIER;
lua_callbacks(L)->userthread = userthread_callback;

// SL libraries
luaopen_sl(L, true);
luaopen_ll(L, true);
lua_pop(L, 1);

// JSON and Base64
luaopen_cjson(L);
lua_pop(L, 1);
luaopen_llbase64(L);
lua_pop(L, 1);

// Set SL constants on _G
luaSL_set_constant_globals(L);

luaL_sandbox(L);
lua_fixallcollectable(L);
}

static std::string runCode(lua_State* L, const std::string& source)
{
size_t bytecodeSize = 0;
char* bytecode = luau_compile(source.data(), source.length(), nullptr, &bytecodeSize);
lua_setmemcat(L, 0);
int result = luau_load(L, "=stdin", bytecode, bytecodeSize, 0);
free(bytecode);

Expand All @@ -87,7 +120,9 @@ static std::string runCode(lua_State* L, const std::string& source)
return error;
}

lua_setmemcat(L, 2);
lua_State* T = lua_newthread(L);
lua_setmemcat(L, 0);

lua_pushvalue(L, -2);
lua_remove(L, -3);
Expand Down Expand Up @@ -189,16 +224,34 @@ extern "C" const char* executeScript(const char* source)
if (strncmp(flag->name, "Luau", 4) == 0)
flag->value = true;

// Initialize SL builtins once from embedded file
static bool builtins_initialized = false;
if (!builtins_initialized)
{
luauSL_init_global_builtins("/builtins.txt");
builtins_initialized = true;
}

// create new state
std::unique_ptr<lua_State, void (*)(lua_State*)> globalState(luaL_newstate(), lua_close);
lua_State* L = globalState.get();

// setup state
setupState(L);

// sandbox thread
// sandbox thread first (like REPL does)
luaL_sandboxthread(L);

// Event and timer managers (after sandbox)
luaSL_createeventmanager(L);
lua_ref(L, -1);
lua_pushvalue(L, -1); // Duplicate for timer manager (it expects LLEvents on stack)
lua_setglobal(L, "LLEvents");

luaSL_createtimermanager(L);
lua_ref(L, -1);
lua_setglobal(L, "LLTimers");

// static string for caching result (prevents dangling ptr on function exit)
static std::string result;

Expand Down
10 changes: 10 additions & 0 deletions CLI/test/Web.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Smoke test for Luau.Web
// Usage: node Web.test.js ./Luau.Web.js

const Module = require(require('path').resolve(process.cwd(), process.argv[2]));

Module.onRuntimeInitialized = () => {
const exec = Module.cwrap('executeScript', 'string', ['string']);
const err = exec('print(ZERO_VECTOR)');
process.exit(err ? 1 : 0);
};
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ endif()

if(LUAU_BUILD_WEB)
target_compile_options(Luau.Web PRIVATE ${LUAU_OPTIONS})
target_link_libraries(Luau.Web PRIVATE Luau.Compiler Luau.VM Luau.Analysis)
target_link_libraries(Luau.Web PRIVATE Luau.Compiler Luau.VM Luau.Analysis Luau.CLI.lib)

# declare exported functions to emscripten
target_link_options(Luau.Web PRIVATE -sEXPORTED_FUNCTIONS=["_executeScript","_checkScript"] -sEXPORTED_RUNTIME_METHODS=["ccall","cwrap"])
Expand All @@ -312,6 +312,9 @@ if(LUAU_BUILD_WEB)

# the output is a single .js file with an embedded wasm blob
target_link_options(Luau.Web PRIVATE -sSINGLE_FILE=1)

# Embed builtins.txt into the wasm virtual filesystem for SL constants
target_link_options(Luau.Web PRIVATE --embed-file ${CMAKE_SOURCE_DIR}/builtins.txt@/builtins.txt)
endif()

# validate dependencies for internal libraries
Expand Down
Loading