LÖVE to Web: love.js Compatibility Kit
A downloadable tool
A drop-in Lua folder that fixes the PUC Lua 5.1 and WebGL1 differences that most often break a LÖVE 11.x game under love.js.
Desktop LÖVE runs LuaJIT on OpenGL. love.js runs plain Lua 5.1 on WebGL1, and some code that works on desktop crashes or silently misbehaves in the browser. This kit came out of porting a real LÖVE 11.5 game to the browser. Add two lines to the top of main.lua:
local compat = require('lovejs_compat')
compat.install()
On desktop it changes nothing by default. Each Lua shim checks first whether it is needed, and the graphics/input/window shims only turn on when love.system.getOS() returns 'Web' (one exception: mipmap stripping also turns on if the GPU reports no full NPOT support).
The 9 shims
| Shim | Problem in love.js | Where it was seen |
|---|---|---|
require('bit') | Lua 5.1 has no bit library. A pure-Lua bit with LuaJIT semantics is added | real browser |
xpcall(f, h, ...) | Lua 5.1 drops the extra args, so f gets nil | real browser |
load(string, name, mode, env) | Lua 5.1 load only takes a function | Lua 5.1 |
math.log(x, base) | base is ignored without an error | Lua 5.1 |
string.rep(s, n, sep) | sep is ignored without an error | Lua 5.1 |
| mipmaps on NPOT textures | WebGL1 GL_INVALID_VALUE, so the image fails to load | real browser |
newCanvas format | a format the GPU doesn't support falls back to 'normal' | web build |
| mouse events | some events arrive with non-number x/y. They are dropped | real browser |
updateMode / setMode | love.resize isn't called. The shim calls it | real browser |
What's inside (zip, about 95 KB)
lovejs_compat/: the drop-in folder (6 Lua files, about 450 lines, pure Lua 5.1, no C)tools/scan.lua: a pattern-based scanner that lists lines needing attention: FFI,jit,goto,\xescapes,table.unpack, threads,math.randomseedand more. It is heuristic, so expect some false positivesexample/: a small LÖVE project that uses every shimtests/: tests you can run with Lua 5.1, LuaJIT orlove tests. They include 9,570 expected results generated from LuaJIT's realbitlibraryREADME.txt: documentation for each shim and a porting checklist (no JIT, threads, saves, pixel cost, caching, yield-across-pcall, RNG differences)
What was tested, and what wasn't
- Tests pass under PUC Lua 5.1 (39 checks) and under LÖVE 11.5's LuaJIT on macOS (34 checks).
example/ran on desktop LÖVE 11.5 (macOS), both normally and with the web shims forced on.- The fixes marked "real browser" came from the original game port, using the 2dengine love.js build of LÖVE 11.5.
- Not tested: this packaged kit running as its own project in a browser, Windows/Linux, other love.js builds, and LÖVE 12. Pure-Lua
bitis much slower than native bit operations.
The free sample contains the scanner and the full porting checklist. Try it on your code before you buy.
How it was made
The code, tests, README and these page images were written by an AI (Claude, by Anthropic). It worked from fixes and notes made while porting a real LÖVE game to the browser, then generalized and tested them as described above. No human-drawn art is included. The product is code and text.
License
You can use it in commercial and non-commercial games and apps, modify it, and ship the lovejs_compat code inside your games. No credit is required. You can't resell or redistribute the kit's files on their own or as part of another code or asset pack. See LICENSE.txt.
Purchase
In order to download this tool you must purchase it at or above the minimum price of $4 USD. You will get access to the following files:




Leave a comment
Log in with itch.io to leave a comment.