Skip to content

Commit 4acfee4

Browse files
mschmickingclaude
andcommitted
docs: split the reference out of the README into docs/
The README was 353 lines, 219 of them a single API code block. That block was also the worst part of it: one continuous listing of JSDoc comments, which cannot be linked to, scanned, or read on a phone. Splits it into docs/ and rewrites the reference as real prose with per-method sections, grouped by what you are trying to do rather than by declaration order. Adds the type-conversion tables and the stack-index rules, which were previously only discoverable by reading the tests. docs/api.md full reference, with its own table of contents docs/migrating-to-2.0.md the breaking-changes table and what to check docs/troubleshooting.md build failures, including the Windows node-gyp and npm-12-blocks-scripts cases users will actually hit docs/development.md layout, CI, and the release process README keeps what someone needs to decide whether to use this and get it running: what it is, install, quick start, links, caveats. Now 100 lines with a table of contents. Documentation links are absolute GitHub URLs so they also work when the README is rendered on npmjs.com, where relative links break. docs/ is not in the files allowlist, so the tarball does not grow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 1545968 commit 4acfee4

5 files changed

Lines changed: 559 additions & 293 deletions

File tree

README.md

Lines changed: 39 additions & 293 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ Lua and [LuaFileSystem](https://github.com/lunarmodules/luafilesystem) are compi
66
the addon, so there is no system Lua to install and nothing to configure — `npm install` builds
77
everything from source on Linux, macOS and Windows, on both x64 and ARM64.
88

9+
- [Installation](#installation)
10+
- [Quick start](#quick-start)
11+
- [Documentation](#documentation)
12+
- [Examples](#examples)
13+
- [How it works](#how-it-works)
14+
- [Caveats](#caveats)
15+
- [License](#license)
16+
917
## Installation
1018

1119
```
@@ -18,19 +26,11 @@ The addon is compiled at install time, so you need a working C/C++ toolchain:
1826
- **macOS** — the Xcode Command Line Tools (`xcode-select --install`)
1927
- **Windows** — the "Desktop development with C++" workload from Visual Studio Build Tools
2028

21-
Nothing else. Earlier versions needed you to build and install LuaJIT yourself on Linux; that is
22-
no longer the case.
29+
Nothing else. Node.js 18 or newer.
2330

24-
> **Windows with Visual Studio 2026:** `node-gyp` 11.x cannot detect that version and fails with
25-
> `find VS unknown version "undefined"`. It is what npm bundles on Node.js 20 and 22. Install
26-
> node-gyp 12 and point npm at it — note the explicit `@12`, since `@latest` still resolves to
27-
> 11.x on those Node versions:
28-
>
29-
> ```
30-
> npm install -g node-gyp@12
31-
> set npm_config_node_gyp=%APPDATA%\npm\node_modules\node-gyp\bin\node-gyp.js
32-
> npm install node-lua-runner
33-
> ```
31+
If the install fails, see
32+
[troubleshooting](https://github.com/mschmicking/node-lua-runner/blob/master/docs/troubleshooting.md)
33+
— the common ones are Visual Studio 2026 on Windows and npm 12 blocking build scripts.
3434

3535
## Quick start
3636

@@ -55,300 +55,46 @@ lua.DoString('print("2 + 3 = " .. add(2, 3))');
5555
lua.Close();
5656
```
5757

58-
## Breaking changes in 2.0.0
59-
60-
2.0.0 is a maintenance release that makes the package build and run on current Node.js. It fixes
61-
several long-standing bugs, and those fixes change behaviour:
62-
63-
| Change | Before | Now |
64-
|---|---|---|
65-
| `SetField(index, key, value)` | Wrote the *key* into the field, ignoring the value | Writes the value, and resolves a relative `index` before pushing |
66-
| `LoadFile` / `LoadString` | Executed the chunk, identical to `DoFile` / `DoString` | Compile and push the chunk without running it; call `Call(0, 0)` to run it |
67-
| Lua booleans read into JS | Arrived as the numbers `1` and `0` | Arrive as `true` and `false` |
68-
| `Push(3.5)` | Truncated to `3` | Keeps the fractional value |
69-
| `AddPackagePath` | Appended without a separator, corrupting `package.path`, so `require` usually failed | Appends correctly, and no longer breaks on paths containing quotes |
70-
| `ToValue` on a table | Only converted correctly when the table was at the top of the stack | Works at any stack index, including nested tables |
71-
| Calling a method after `Close()` | Use-after-free | Throws |
72-
| `Resume(args)` | Returned `undefined` | Returns the Lua status code |
73-
74-
Other things worth knowing if you are upgrading:
75-
76-
- **LuaJIT has been replaced by stock Lua 5.1.5.** Windows builds used to link LuaJIT 2.0.3, so
77-
Windows users lose JIT compilation. In exchange, macOS on Apple Silicon and Linux on ARM64 work
78-
at all, which they previously did not. The Lua C API and language are unchanged.
79-
- **`require('lfs')` now works on every platform.** It used to be a Windows-only prebuilt DLL
80-
loaded through an `LUA_CPATH` hack; LuaFileSystem is now compiled into the addon.
81-
- Node.js 18 or newer is required.
58+
## Documentation
8259

83-
## About
84-
85-
Built on the [Lua 5.1 C API](https://www.lua.org/manual/5.1/manual.html). The binding uses
86-
[Node-API](https://nodejs.org/api/n-api.html), which is ABI-stable — a compiled build keeps
87-
working across future Node.js releases instead of breaking on each major version.
88-
89-
**Based on:**
90-
- nodelua ( https://github.com/brettlangdon/NodeLua )
91-
- node-luajit ( https://github.com/whtiehack/node-luajit )
92-
- LuaFileSystem ( https://github.com/lunarmodules/luafilesystem )
93-
94-
**Features:**
95-
- Low-level API mapping closely onto the Lua C API
96-
- Synchronous only
60+
- [**API reference**](https://github.com/mschmicking/node-lua-runner/blob/master/docs/api.md)
61+
every method, type conversion, and how stack indices behave
62+
- [**Migrating to 2.0**](https://github.com/mschmicking/node-lua-runner/blob/master/docs/migrating-to-2.0.md)
63+
— what changed and what to check in existing code
64+
- [**Troubleshooting**](https://github.com/mschmicking/node-lua-runner/blob/master/docs/troubleshooting.md)
65+
— build and install problems
66+
- [**Development**](https://github.com/mschmicking/node-lua-runner/blob/master/docs/development.md)
67+
— layout, CI, and how releases are cut
68+
- [**Changelog**](https://github.com/mschmicking/node-lua-runner/blob/master/CHANGELOG.md)
9769

9870
## Examples
9971

100-
- [Simple](https://github.com/mschmicking/node-lua-runner/blob/master/examples/simple/index.js)
101-
- [Using the lua require function](https://github.com/mschmicking/node-lua-runner/blob/master/examples/lua_require/index.js)
72+
- [Simple](https://github.com/mschmicking/node-lua-runner/blob/master/examples/simple/index.js)
73+
running code, registering a JavaScript function, reading globals
74+
- [Using `require`](https://github.com/mschmicking/node-lua-runner/blob/master/examples/lua_require/index.js)
75+
— loading Lua modules from disk
10276
- [Using LuaFileSystem](https://github.com/mschmicking/node-lua-runner/tree/master/examples/lua_lfs)
10377

104-
## API
105-
106-
```javascript
107-
108-
const nodelua = require('node-lua-runner');
109-
110-
var lua = new nodelua.LuaState();
111-
112-
113-
/**
114-
* [Add a path to the lua package.path variable. Set a root path for lua require (see example)]
115-
* @param {String} path
116-
*/
117-
lua.AddPackagePath(__dirname);
118-
119-
120-
/**
121-
* [Loads and runs the given file]
122-
* @type {String} file
123-
* @throws {Exception}
124-
*/
125-
lua.DoFile(__dirname + "/test.lua");
126-
127-
128-
/**
129-
* [Loads and runs the given string]
130-
* @type {String} str
131-
* @throws {Exception}
132-
*/
133-
lua.DoString("print('Hello world!')");
134-
135-
136-
/**
137-
* [Compiles the given file and pushes it onto the stack WITHOUT running it.
138-
* Use Call to run it.]
139-
* @type {String} file
140-
* @throws {Exception}
141-
*/
142-
lua.LoadFile(__dirname + "/test.lua");
143-
144-
145-
/**
146-
* [Compiles the given string and pushes it onto the stack WITHOUT running it.
147-
* Use Call to run it.]
148-
* @type {String} str
149-
* @throws {Exception}
150-
*/
151-
lua.LoadString("print('Hello world!')");
152-
153-
154-
/**
155-
* [Sets the function f as the new value of global name.
156-
* Arguments are read off the Lua stack with ToValue; the return value is the
157-
* number of results the function pushed.]
158-
* @param {String} name [name of the global in lua]
159-
* @param {Function} f [function to set]
160-
*/
161-
lua.RegisterFunction('add', function() {
162-
var a = lua.ToValue(1);
163-
var b = lua.ToValue(2);
164-
lua.Pop(2);
165-
lua.Push(a + b);
166-
return 1;
167-
});
168-
169-
170-
/**
171-
* [Pops a value from the stack and sets it as the new value of global name]
172-
* @type {String} name
173-
*/
174-
lua.SetGlobal("myVar");
175-
176-
177-
/**
178-
* [Pushes onto the stack the value of the global name]
179-
* @type {String} name
180-
*/
181-
lua.GetGlobal('myVar');
182-
183-
184-
/**
185-
* [Does the equivalent to t[k] = v, where t is the value at the given valid index.
186-
* Unlike the raw C API, v is passed as an argument rather than taken from the
187-
* top of the stack.]
188-
* @type {Number} index
189-
* @type {String} key
190-
* @type {*} value
191-
* @throws {Exception} [if the value at index is not a table]
192-
*/
193-
lua.SetField(index, "key", value);
194-
195-
196-
/**
197-
* [Pushes onto the stack the value t[key], where t is the value at the given valid index.]
198-
* @type {Number} index
199-
* @type {String} key
200-
* @throws {Exception} [if the value at index is not a table]
201-
*/
202-
lua.GetField(index, "key");
203-
78+
## How it works
20479

205-
/**
206-
* [Get value at the given acceptable index]
207-
* @type {Number} index
208-
* @return value
209-
*/
210-
var value = lua.ToValue(-1);
80+
Built on the [Lua 5.1 C API](https://www.lua.org/manual/5.1/manual.html) through
81+
[Node-API](https://nodejs.org/api/n-api.html), which is ABI-stable — a compiled build keeps working
82+
across future Node.js releases instead of breaking on each major version.
21183

84+
The API is low-level and maps closely onto the C API, and it is synchronous throughout.
21285

213-
/**
214-
* [Calls a function. Gets the function and arguments from the stack. Pushes the results onto the stack. See https://www.lua.org/manual/5.1/manual.html#pdf-pcall for more information]
215-
* @type {Number} args
216-
* @type {Number} results
217-
* @throws {Exception}
218-
*/
219-
lua.Call(args, results);
220-
221-
222-
/**
223-
* [Yields a coroutine.]
224-
* @type {Number} args
225-
*/
226-
lua.Yield(args);
227-
228-
229-
/**
230-
* [Starts and resumes a coroutine in a given thread.]
231-
* @type {Number} args
232-
* @return {Number} [status code]
233-
*/
234-
lua.Resume(args);
235-
236-
237-
/**
238-
* [Pushes a value n onto the stack]
239-
* @type n
240-
*/
241-
lua.Push(5);
242-
243-
244-
/**
245-
* [Pops n elements from the stack. Default value is 1]
246-
* @type {Number} n
247-
*/
248-
lua.Pop();
249-
lua.Pop(n);
250-
251-
252-
/**
253-
* [Returns the index of the top element in the stack. Because indices start at 1, this result is equal to the number of elements in the stack (and so 0 means an empty stack)]
254-
* @return {Number}
255-
*/
256-
var size = lua.GetTop();
257-
258-
259-
/**
260-
* [Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed]
261-
* @type {Number} index
262-
*/
263-
lua.SetTop(index);
264-
265-
266-
/**
267-
* [Moves the top element into the given position (and pops it), without shifting any element (therefore replacing the value at the given position)]
268-
* @type {Number} index
269-
*/
270-
lua.Replace(index);
271-
272-
273-
/**
274-
* [Returns the status of the state]
275-
* @return {Number} [compare against nodelua.STATUS.*]
276-
*/
277-
lua.Status();
278-
279-
280-
/**
281-
* [Controls the Lua garbage collector]
282-
* @type {Number} what [one of nodelua.GC.*]
283-
* @return {Number}
284-
*/
285-
lua.CollectGarbage(nodelua.GC.COLLECT);
286-
287-
288-
/**
289-
* [Destroys the Lua state and frees its memory. Safe to call more than once.
290-
* Any further use of the state throws.]
291-
*/
292-
lua.Close();
293-
294-
```
295-
296-
### Constants
297-
298-
```javascript
299-
nodelua.INFO.VERSION // "Lua 5.1"
300-
nodelua.INFO.VERSION_NUM // 501
301-
nodelua.INFO.COPYRIGHT
302-
nodelua.INFO.AUTHORS
303-
304-
nodelua.LUA.GLOBALSINDEX // pseudo-index of the globals table
305-
nodelua.LUA.REGISTRYINDEX // pseudo-index of the registry
306-
307-
nodelua.STATUS.YIELD
308-
nodelua.STATUS.ERRRUN
309-
nodelua.STATUS.ERRSYNTAX
310-
nodelua.STATUS.ERRMEM
311-
nodelua.STATUS.ERRERR
312-
313-
nodelua.GC.STOP
314-
nodelua.GC.RESTART
315-
nodelua.GC.COLLECT
316-
nodelua.GC.COUNT
317-
nodelua.GC.COUNTB
318-
nodelua.GC.STEP
319-
nodelua.GC.SETPAUSE
320-
nodelua.GC.SETSTEPMUL
321-
```
86+
Descended from [NodeLua](https://github.com/brettlangdon/NodeLua) and
87+
[node-luajit](https://github.com/whtiehack/node-luajit).
32288

32389
## Caveats
32490

32591
This is a thin wrapper over the Lua C API, and it does not shield you from every way of misusing
326-
that API. Some stack operations on values of an unexpected type raise an *unprotected* Lua error,
327-
which aborts the process rather than throwing a JavaScript exception. `SetField` and `GetField`
328-
guard against this explicitly; other methods do not. Keep track of what is on the stack.
329-
330-
## Development
331-
332-
```
333-
npm install
334-
npm test
335-
```
336-
337-
### Releasing
338-
339-
Commits follow [Conventional Commits](https://www.conventionalcommits.org/); the pull request
340-
title is what matters, since it becomes the squashed commit message.
341-
342-
release-please keeps an open `chore(master): release x.y.z` pull request that accumulates merged
343-
changes, works out the next version and rewrites `CHANGELOG.md`. Merging that pull request tags the
344-
commit and publishes a GitHub Release, which is what triggers the npm publish. So merging the
345-
release pull request is the single deliberate act that ships a version — nothing publishes on an
346-
ordinary merge to `master`.
347-
348-
Publishing uses [npm trusted publishing](https://docs.npmjs.com/trusted-publishers) over OIDC, so
349-
there is no npm token stored in this repository.
92+
it. Some stack operations on a value of an unexpected type raise an *unprotected* Lua error, which
93+
aborts the process rather than throwing a JavaScript exception. `SetField` and `GetField` guard
94+
against this; other methods do not. Keep track of what is on the stack — see
95+
[stack indices](https://github.com/mschmicking/node-lua-runner/blob/master/docs/api.md#stack-indices).
35096

35197
## License
35298

353-
ISC — see [LICENSE](LICENSE). The vendored Lua and LuaFileSystem sources are MIT; their
354-
notices are in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
99+
ISC — see [LICENSE](LICENSE). The vendored Lua and LuaFileSystem sources are MIT; their notices are
100+
in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).

0 commit comments

Comments
 (0)