Awesome
JS library for Fengari
Fengari is a lua VM written in Javascript. Its implementation makes use of the JS garbage collector, which means it is fully capable of cross language interop.
Features
- Call any JS function from Lua
- Give Lua tables/functions/userdata to Javascript
js
library
js = require "js"
null
A userdata representing JavaScript null
global
A reference to the JavaScript global context. In the browser, this is usually equivalent to the window
object. In node.js it's equal to global
.
new(constructor, ...)
Invokes the JavaScript new
operator on constructor
passing the arguments specified.
Returns the created object.
of(iterable)
Returns a iterating function and an iterator state that behave like a JavaScript for...of loop. Suitable for use as a lua iterator. e.g.
for f in js.of(js.global:Array(10,20,30)) do
print(f)
end
Note: this function only exists if the JavaScript runtime supports Symbols
createproxy(x[, type])
Note: Only available if your JS environment has the Proxy
constructor
Creates a JavaScript Proxy object. The proxy supports configuring traps by setting them as metamethods on your object.
type
may be "function"
(the default) "arrow_function"
or "object"
:
"function"
:typeof p === "function"
- Can be used as a constructor
"arrow_function"
:typeof p === "function"
- Can not be used as a constructor
"object"
:typeof p === "object"
- Can not be used as a constructor
Note that JavaScript coerces all types except Symbols to strings before using them as a key in an indexing operation.
tonumber(x)
Coerces the value x
to a number using JavaScript coercion rules.
tostring(x)
Coerces the value x
to a string using JavaScript coercion rules.
instanceof(x, y)
Returns if the value x
is an instance of the class y
via use of the JavaScript instanceof
operator
typeof(x)
Returns what JavaScript sees as the type of x
. Uses the JavaScript typeof
operator
JavaScript API
push(L, value)
Pushes an arbitrary JavaScript object value
as the most suitable lua type onto the lua stack L
.
Performs deduplication so that the same JavaScript objects are pushed as the same lua objects.
pushjs(L, value)
Pushes an arbitrary JavaScript object value
as a userdata onto the lua stack L
.
Rarely used; see push(L, value)
instead.
checkjs(L, idx)
If the value on the lua stack L
at index idx
is a JavaScript userdata object (as pushed by push
or pushjs
) then return it.
Otherwise throw an error.
testjs(L, idx)
If the value on the lua stack L
at index idx
is a JavaScript userdata object (as pushed by push
or pushjs
) then return it.
Otherwise returns undefined
.
tojs(L, idx)
Returns the object on the lua stack L
at index idx
as the most suitable javascript type.
nil
is returned asundefined
- booleans are returned as booleans
- numbers are returned as numbers
- strings are returned as JavaScript strings (Note: this can throw an error if the lua string is not represenable as a JavaScript string)
- JavaScript userdata object (as pushed by
push
orpushjs
) returns the pushed JavaScript object - Other objects are returned wrapped in a JavaScript function object with methods:
apply(this, [args...])
: calls the lua object. Returns only the first return valueinvoke(this, [args...])
: calls the lua object. Returns results as an arrayget(key)
: indexes the lua objecthas(key)
: checks if indexing the lua object results innil
set(key, value)
delete(key)
: sets the key tonil
toString()
JavaScript arguments to these methods are passed in viapush()
and results are returned viatojs()
. Calling the function is equivalent to calling the lua function wrapped.
luaopen_js
The entrypoint for loading the js library into a fengari lua_State
.
Usually passed to luaL_requiref
.
Symbols
If the JavaScript environment supports Symbols, then some runtime-wide symbols can be used to customise behaviour:
__pairs
The __pairs
Symbol can be used to describe how to iterate over a JavaScript object. Use Symbol.for("__pairs")
to get the symbol. It should be used as a key on your objects, where the value is a function returning an object with three properties: "iter"
, "state"
and "first"
.
"iter"
should be a function that follows the standard Lua generic for protocol, that is, it gets called with your state (as this
) and the previous value produced; it should return an array of values or undefined
if done.
e.g. to make pairs
on a Map return entries in the map via the iterator symbol:
Map.prototype[Symbol.for("__pairs")] = function() {
return {
iter: function(last) {
var v = this.next();
if (v.done) return;
return v.value;
},
state: this[Symbol.iterator]()
};
};
If there is no __pairs
Symbol attached to an object, an iterator over Object.keys
is returned.
__len
The __len
Symbol can be used to describe how to get the length (used by the lua #
operator) of a JavaScript object.
Use Symbol.for("__len")
to get the symbol. It should be used as a key on your objects, where the value is a function returning the length of your objects (passed as this
).
e.g. to have the lua #
operator applied to a Map return the size
field:
Map.prototype[Symbol.for("__len")] = function() {
return this.size;
};
If there is no __len
Symbol attached to an object, the value of the .length
property is returned.