Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fengari-lua/fengari-interop
Fengari <=> JS Interop
https://github.com/fengari-lua/fengari-interop
fengari javascript js lua
Last synced: 1 day ago
JSON representation
Fengari <=> JS Interop
- Host: GitHub
- URL: https://github.com/fengari-lua/fengari-interop
- Owner: fengari-lua
- License: mit
- Created: 2017-05-12T01:50:52.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2024-03-02T13:21:50.000Z (11 months ago)
- Last Synced: 2025-01-19T20:08:14.833Z (8 days ago)
- Topics: fengari, javascript, js, lua
- Language: JavaScript
- Size: 609 KB
- Stars: 99
- Watchers: 9
- Forks: 13
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![Build Status](https://github.com/fengari-lua/fengari-interop/actions/workflows/ci.yaml/badge.svg)](https://github.com/fengari-lua/fengari-interop/actions/workflows/ci.yaml?query=event%3Apush)
[![npm](https://img.shields.io/npm/v/fengari-interop.svg)](https://npmjs.com/package/fengari-interop)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![#fengari on libera.chat](https://img.shields.io/badge/chat-%23fengari-brightgreen)](https://web.libera.chat/?channels=#fengari)# JS library for Fengari
[Fengari](https://github.com/fengari-lua/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
```lua
js = require "js"
```### `null`
A userdata representing JavaScript [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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`](https://nodejs.org/api/globals.html#globals_global).
### `new(constructor, ...)`
Invokes the JavaScript [`new` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new) 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop.
Suitable for use as a lua iterator. e.g.```lua
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)*
### `createproxy(x[, type])`
*Note: Only available if your JS environment has the `Proxy` constructor*
Creates a JavaScript [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 constructorNote 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof)
### `typeof(x)`
Returns what JavaScript sees as the type of `x`. Uses the JavaScript [`typeof` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof)
## 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 as `undefined`
- 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` or `pushjs`) 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 value
- `invoke(this, [args...])`: calls the lua object. Returns results as an array
- `get(key)`: indexes the lua object
- `has(key)`: checks if indexing the lua object results in `nil`
- `set(key, value)`
- `delete(key)`: sets the key to `nil`
- `toString()`
JavaScript arguments to these methods are passed in via `push()` and results are returned via `tojs()`.
Calling the function is equivalent to calling the lua function wrapped.### `luaopen_js`
The entrypoint for loading the [js library](#js-library) into a fengari `lua_State`.
Usually passed to `luaL_requiref`.## Symbols
If the JavaScript environment supports [Symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), 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](http://www.lua.org/manual/5.3/manual.html#3.3.5), 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) return entries in the map via the [iterator symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@iterator):
```js
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`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) return the [`size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) field:
```js
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.