diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 764388b..f4c8659 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup emsdk - uses: mymindstorm/setup-emsdk@v7 + uses: mymindstorm/setup-emsdk@v11 + with: + version: 3.1.9 - name: Use Node.js 12.13.1 uses: actions/setup-node@v1 with: @@ -21,3 +23,4 @@ jobs: registry-url: "https://registry.npmjs.org" - run: npm ci - run: npm run complete-build + - run: npm run test diff --git a/.gitignore b/.gitignore index fa8f2ae..10b8ab3 100644 --- a/.gitignore +++ b/.gitignore @@ -178,3 +178,4 @@ dist # End of https://www.toptal.com/developers/gitignore/api/node,c .DS_Store +.vscode/settings.json diff --git a/README.md b/README.md index 7d65109..652cabb 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ ## Lua WASM Bindings -WASM bindings and binaries for Lua 5.1 to 5.4. +WASM bindings and binaries for Lua 5.0 to 5.4. -Make sure to run `./scripts/setup.ts` (requires emscripten sdk) first before using `npm run build`. +Make sure to run `./scripts/setup.sh` (requires emscripten sdk) first before using `npm run build`. ### Important: This currently only includes the bindings used to test TypescriptToLua diff --git a/package-lock.json b/package-lock.json index 9cd37d1..7f51247 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,10 @@ "name": "lua-wasm-bindings", "version": "0.2.2", "license": "MIT", + "dependencies": { + "@types/semver": "^7.3.9", + "semver": "^7.3.7" + }, "devDependencies": { "@types/emscripten": "^1.39.4", "@types/node": "^14.14.31", @@ -15,6 +19,7 @@ "eslint": "^7.21.0", "eslint-plugin-import": "^2.22.1", "prettier": "^2.2.1", + "ts-node": "^10.7.0", "typescript": "^4.2.2" } }, @@ -58,6 +63,27 @@ "node": ">=4" } }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", @@ -78,6 +104,30 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, "node_modules/@types/emscripten": { "version": "1.39.4", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.4.tgz", @@ -96,6 +146,11 @@ "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", + "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==" + }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -114,6 +169,15 @@ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -156,6 +220,12 @@ "node": ">=4" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -369,6 +439,12 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -413,6 +489,15 @@ "node": ">= 0.4" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1280,7 +1365,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -1288,6 +1372,12 @@ "node": ">=10" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1710,10 +1800,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1982,6 +2071,61 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/ts-node": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -2070,6 +2214,12 @@ "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", "dev": true }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -2194,8 +2344,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "16.2.0", @@ -2223,6 +2372,15 @@ "engines": { "node": ">=10" } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } } }, "dependencies": { @@ -2265,6 +2423,21 @@ } } }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, "@eslint/eslintrc": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", @@ -2282,6 +2455,30 @@ "strip-json-comments": "^3.1.1" } }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, "@types/emscripten": { "version": "1.39.4", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.4.tgz", @@ -2300,6 +2497,11 @@ "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", "dev": true }, + "@types/semver": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", + "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==" + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -2312,6 +2514,12 @@ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2345,6 +2553,12 @@ "color-convert": "^1.9.0" } }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2526,6 +2740,12 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2561,6 +2781,12 @@ "object-keys": "^1.0.12" } }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -3279,11 +3505,16 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -3617,10 +3848,9 @@ "dev": true }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "requires": { "lru-cache": "^6.0.0" } @@ -3856,6 +4086,35 @@ } } }, + "ts-node": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + } + } + }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -3928,6 +4187,12 @@ "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -4024,8 +4289,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "16.2.0", @@ -4047,6 +4311,12 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz", "integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==", "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/package.json b/package.json index 3190ef1..ff977c8 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "lint:prettier": "prettier --check . || (echo 'Run `npm run fix:prettier` to fix it.' && exit 1)", "lint:eslint": "eslint . --ext .js,.ts", "fix:prettier": "prettier --write .", + "test": "npx ts-node simple-test.ts", "preversion": "npm run complete-build", "postversion": "git push && git push --tags" }, @@ -29,6 +30,11 @@ "eslint": "^7.21.0", "eslint-plugin-import": "^2.22.1", "prettier": "^2.2.1", + "ts-node": "^10.7.0", "typescript": "^4.2.2" + }, + "dependencies": { + "@types/semver": "^7.3.9", + "semver": "^7.3.7" } } diff --git a/scripts/build.sh b/scripts/build.sh index e70a70a..b98acc6 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -6,14 +6,56 @@ mkdir -p `dirname "$0"`/../dist/glue cd `dirname "$0"`/../thirdparty/$1 make clean -make generic MYLIBS= MYCFLAGS= CC='emcc -O3 -s WASM=1' AR='emar rcu' RANLIB='emranlib' + +if [[ "$1" == "lua-5.0.3" ]]; then + make all MYLIBS= MYCFLAGS= CC='emcc -O3' AR='emar rcu' RANLIB='emranlib' +else + make generic MYLIBS= MYCFLAGS= CC='emcc -O3' AR='emar rcu' RANLIB='emranlib' +fi cd ../.. -if [[ "$1" == "lua-5.1.5" ]]; then +# TODO write a proper script and clean up this mess + +if [[ "$1" == "lua-5.0.3" ]]; then + emcc -Ithirdparty/$1 thirdparty/$1/lib/liblua.a thirdparty/$1/lib/liblualib.a \ + -s WASM=1 -O3 -o dist/glue/glue-$1.js \ + -s EXPORTED_RUNTIME_METHODS="['cwrap']" \ + -s MODULARIZE=1 \ + -s ALLOW_TABLE_GROWTH \ + -s EXPORT_NAME="glue" \ + -s ALLOW_MEMORY_GROWTH=1 \ + -s STRICT=1 \ + -s MALLOC=emmalloc \ + -s WASM_ASYNC_COMPILATION=0 \ + -s EXPORTED_FUNCTIONS="[ + '_luaL_loadbuffer', \ + '_lua_close', \ + '_lua_gettable', \ + '_lua_insert', \ + '_lua_isstring', \ + '_lua_open', \ + '_lua_pcall', \ + '_lua_pushstring', \ + '_lua_pushvalue', \ + '_lua_remove', \ + '_lua_replace', \ + '_lua_settable', \ + '_lua_settop', \ + '_lua_tostring', \ + '_lua_type', \ + '_lua_typename', \ + '_luaopen_math', \ + '_luaopen_string', \ + '_luaopen_io', \ + '_luaopen_table', \ + '_luaopen_debug', \ + '_luaopen_base' \ + ]" +elif [[ "$1" == "lua-5.1.5" ]]; then emcc -Ithirdparty/$1 thirdparty/$1/src/liblua.a \ -s WASM=1 -O3 -o dist/glue/glue-$1.js \ - -s EXTRA_EXPORTED_RUNTIME_METHODS="['cwrap']" \ + -s EXPORTED_RUNTIME_METHODS="['cwrap']" \ -s MODULARIZE=1 \ -s ALLOW_TABLE_GROWTH \ -s EXPORT_NAME="glue" \ @@ -23,21 +65,36 @@ if [[ "$1" == "lua-5.1.5" ]]; then -s WASM_ASYNC_COMPILATION=0 \ -s EXPORTED_FUNCTIONS="[ '_luaL_newstate', \ - '_lua_close', \ '_luaL_openlibs', \ + '_luaL_loadbuffer', \ '_luaL_loadstring', \ + '_lua_close', \ '_lua_getfield', \ + '_lua_gettable', \ + '_lua_insert', \ '_lua_isstring', \ '_lua_pcall', \ + '_lua_pushstring', \ + '_lua_pushvalue', \ + '_lua_remove', \ + '_lua_replace', \ '_lua_setfield', \ + '_lua_settable', \ + '_lua_settop', \ '_lua_tolstring', \ '_lua_type', \ - '_lua_typename' \ + '_lua_typename', \ + '_luaopen_math', \ + '_luaopen_string', \ + '_luaopen_io', \ + '_luaopen_table', \ + '_luaopen_debug', \ + '_luaopen_base' \ ]" -else +elif [[ "$1" == "lua-5.2.4" ]]; then emcc -Ithirdparty/$1 thirdparty/$1/src/liblua.a \ -s WASM=1 -O3 -o dist/glue/glue-$1.js \ - -s EXTRA_EXPORTED_RUNTIME_METHODS="['cwrap']" \ + -s EXPORTED_RUNTIME_METHODS="['cwrap']" \ -s MODULARIZE=1 \ -s ALLOW_TABLE_GROWTH \ -s EXPORT_NAME="glue" \ @@ -47,16 +104,68 @@ else -s WASM_ASYNC_COMPILATION=0 \ -s EXPORTED_FUNCTIONS="[ '_luaL_newstate', \ + '_luaL_openlibs', \ + '_luaL_loadstring', \ '_lua_close', \ + '_lua_getfield', \ + '_lua_getglobal', \ + '_lua_gettable', \ + '_lua_insert', \ + '_lua_isstring', \ + '_lua_pcallk', \ + '_lua_pushstring', \ + '_lua_pushvalue', \ + '_lua_remove', \ + '_lua_replace', \ + '_lua_setfield', \ + '_lua_settable', \ + '_lua_settop', \ + '_lua_tolstring', \ + '_lua_type', \ + '_lua_typename', \ + '_luaopen_math', \ + '_luaopen_string', \ + '_luaopen_io', \ + '_luaopen_table', \ + '_luaopen_debug', \ + '_luaopen_base' \ + ]" +else + emcc -Ithirdparty/$1 thirdparty/$1/src/liblua.a \ + -s WASM=1 -O3 -o dist/glue/glue-$1.js \ + -s EXPORTED_RUNTIME_METHODS="['cwrap']" \ + -s MODULARIZE=1 \ + -s ALLOW_TABLE_GROWTH \ + -s EXPORT_NAME="glue" \ + -s ALLOW_MEMORY_GROWTH=1 \ + -s STRICT=1 \ + -s MALLOC=emmalloc \ + -s WASM_ASYNC_COMPILATION=0 \ + -s EXPORTED_FUNCTIONS="[ + '_luaL_newstate', \ '_luaL_openlibs', \ '_luaL_loadstring', \ + '_lua_close', \ + '_lua_copy', \ '_lua_getfield', \ '_lua_getglobal', \ + '_lua_gettable', \ '_lua_isstring', \ '_lua_pcallk', \ + '_lua_pushstring', \ + '_lua_pushvalue', \ + '_lua_rotate', \ '_lua_setfield', \ + '_lua_settable', \ + '_lua_settop', \ '_lua_tolstring', \ '_lua_type', \ - '_lua_typename' \ + '_lua_typename', \ + '_luaopen_math', \ + '_luaopen_string', \ + '_luaopen_io', \ + '_luaopen_table', \ + '_luaopen_debug', \ + '_luaopen_base' \ ]" fi diff --git a/scripts/download.sh b/scripts/download.sh index 59ffc55..10d5c94 100755 --- a/scripts/download.sh +++ b/scripts/download.sh @@ -1,6 +1,8 @@ mkdir -p `dirname "$0"`/../thirdparty +curl https://www.lua.org/ftp/lua-5.0.3.tar.gz | tar xvz -C `dirname "$0"`/../thirdparty curl https://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xvz -C `dirname "$0"`/../thirdparty curl https://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xvz -C `dirname "$0"`/../thirdparty curl https://www.lua.org/ftp/lua-5.3.6.tar.gz | tar xvz -C `dirname "$0"`/../thirdparty -curl https://www.lua.org/ftp/lua-5.4.2.tar.gz | tar xvz -C `dirname "$0"`/../thirdparty \ No newline at end of file +curl https://www.lua.org/ftp/lua-5.4.2.tar.gz | tar xvz -C `dirname "$0"`/../thirdparty + diff --git a/scripts/setup.sh b/scripts/setup.sh index a46bc05..044e1c2 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -1,5 +1,6 @@ `dirname "$0"`/download.sh +`dirname "$0"`/build.sh lua-5.0.3 `dirname "$0"`/build.sh lua-5.1.5 `dirname "$0"`/build.sh lua-5.2.4 `dirname "$0"`/build.sh lua-5.3.6 diff --git a/simple-test.ts b/simple-test.ts new file mode 100644 index 0000000..81cd743 --- /dev/null +++ b/simple-test.ts @@ -0,0 +1,18 @@ +import { LauxLib, Lua, LuaLib } from "./dist/lua"; + +import * as Lua50 from "./dist/lua.50"; +import * as Lua51 from "./dist/lua.51"; +import * as Lua52 from "./dist/lua.52"; +import * as Lua53 from "./dist/lua.53"; +import * as Lua54 from "./dist/lua.54"; + +function simpleTest(luaBundle: {lua: Lua, lauxlib: LauxLib, lualib: LuaLib}) { + const state = luaBundle.lauxlib.luaL_newstate(); + luaBundle.lualib.luaL_openlibs(state); +} + +simpleTest(Lua50); +simpleTest(Lua51); +simpleTest(Lua52); +simpleTest(Lua53); +simpleTest(Lua54); \ No newline at end of file diff --git a/src/binding-factory.ts b/src/binding-factory.ts index 9305817..19bd55d 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -1,73 +1,252 @@ +import { satisfies } from "semver"; import { LuaEmscriptenModule } from "./glue/glue"; -import { LauxLib, Lua, LuaLib, LuaState, LUA_MULTRET } from "./lua"; +import { LauxLib, Lua, LuaLib, LuaState, LUA_GLOBALSINDEX, LUA_MULTRET } from "./lua"; -function safeCwrap( - glue: LuaEmscriptenModule, - ident: string, - returnType: Emscripten.JSType | null, - argTypes: Emscripten.JSType[], - opts?: Emscripten.CCallOpts -): (...args: any[]) => any { - if ((glue as any)["_" + ident]) { - return glue.cwrap(ident, returnType, argTypes, opts); - } else { - return _args => { - throw `${ident} not supported in this Lua version!`; +type luaBindingFactoryFunc = (luaGlue: LuaEmscriptenModule) => Partial; +const luaBindings: Record = { + "*": function(luaGlue: LuaEmscriptenModule) { + return { + lua_close: luaGlue.cwrap("lua_close", null, ["number"]), + lua_gettable: luaGlue.cwrap("lua_gettable", "number", ["number", "number"]), + lua_isstring: luaGlue.cwrap("lua_isstring", "number", ["number", "number"]), + // #define in all versions + lua_pop: function(L: LuaState, n: number) { + (this as Lua).lua_settop(L, -(n)-1); + }, + lua_pushstring: luaGlue.cwrap("lua_pushstring", "string", ["number", "string"]), + lua_pushvalue: luaGlue.cwrap("lua_pushvalue", null, ["number", "number"]), + lua_settable: luaGlue.cwrap("lua_settable", null, ["number", "number"]), + lua_settop: luaGlue.cwrap("lua_settop", null, ["number", "number"]), + lua_type: luaGlue.cwrap("lua_type", "number", ["number", "number"]), + lua_typename: luaGlue.cwrap("lua_typename", "string", ["number", "number"]), + }; + }, + "5.0.x": function(luaGlue: LuaEmscriptenModule){ + return { + lua_getfield: function(L: LuaState, index: number, k: string) { + (this as Lua).lua_pushstring(L, k); + return (this as Lua).lua_gettable(L, index); + }, + lua_setfield: function(L: LuaState, index: number, k: string) { + // The value to set is expected to be on the top of the stack + + // Push Key + (this as Lua).lua_pushstring(L, k); + + // Swap key and value because settable expects stack in that order + + // Copy value to top of stack + (this as Lua).lua_pushvalue(L, -2); + + // Remove original value from stack + (this as Lua).lua_remove(L, -3); + + const result = (this as Lua).lua_settable(L, index); + + return result; + }, + lua_tolstring: function(_L: LuaState, _index: number, _size: number) { + throw "lua_tolstring is currently not supported in 5.0"; + }, + lua_tostring: luaGlue.cwrap("lua_tostring", "number", ["number", "number"]) + }; + }, + "<=5.1.0": function(luaGlue: LuaEmscriptenModule){ + return { + // #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s) + lua_getglobal: function (L: LuaState, name: string) { + return (this as Lua).lua_getfield(L, LUA_GLOBALSINDEX, name); + }, + // Need to overwrite because in lua 5.1 this is a function and not a #define (5.2 and higher) + lua_pcall: luaGlue.cwrap("lua_pcall", "number", ["number", "number", "number", "number"]), + // TODO there might be some way to mimic pcallk behaviour with 5.1 somehow + lua_pcallk: function (_L: LuaState, _nargs: number, _nresults: number, _errfunc: number, _ctx: number, _k: number) { + throw "pcallk not supported with Lua 5.1 and lower"; + } + }; + }, + ">=5.1.0": function(luaGlue: LuaEmscriptenModule){ + return { + lua_getfield: luaGlue.cwrap("lua_getfield", "number", ["number", "number", "string"]), + lua_setfield: luaGlue.cwrap("lua_setfield", null, ["number", "number", "string"]), + // TODO 3rd param is a output param (currently ignored) + lua_tolstring: luaGlue.cwrap("lua_tolstring", "string", ["number", "number", "number"]), + // #define + lua_tostring: function (L: LuaState, index: number) { + return (this as Lua).lua_tolstring(L, index, 0); + }, + }; + }, + ">=5.2.0": function(luaGlue: LuaEmscriptenModule){ + return { + lua_getglobal: luaGlue.cwrap("lua_getglobal", "number", ["number", "string"]), + lua_pcall: function (L: LuaState, nargs: number, nresults: number, msgh: number) { + return (this as Lua).lua_pcallk(L, nargs, nresults, msgh, 0, 0); + }, + lua_pcallk: luaGlue.cwrap("lua_pcallk", "number", [ + "number", + "number", + "number", + "number", + "number", + "number", + ]) + }; + }, + "<=5.2.0": function(luaGlue: LuaEmscriptenModule){ + return { + lua_copy: function (_L: LuaState, _fromIndex: number, _toIndex: number) { + throw "lua_copy not supported with Lua 5.2 and lower"; + }, + lua_insert: luaGlue.cwrap("lua_insert", null, ["number", "number"]), + lua_remove: luaGlue.cwrap("lua_remove", null, ["number", "number"]), + lua_replace: luaGlue.cwrap("lua_replace", null, ["number", "number"]), + lua_rotate: function (_L: LuaState, _index: number, _n: number) { + throw "lua_rotate not supported with Lua 5.2 and lower"; + } + }; + }, + ">=5.3.0": function(luaGlue: LuaEmscriptenModule){ + return { + lua_copy: luaGlue.cwrap("lua_copy", null, ["number", "number", "number"]), + // #define + lua_insert: function (L: LuaState, index: number) { + (this as Lua).lua_rotate(L, index, 1); + }, + // #define + lua_remove: function (L: LuaState, index: number) { + (this as Lua).lua_rotate(L, index, -1); + (this as Lua).lua_pop(L, 1); + }, + // #define + lua_replace: function (L: LuaState, index: number) { + (this as Lua).lua_copy(L, -1, index); + (this as Lua).lua_pop(L, 1); + }, + lua_rotate: luaGlue.cwrap("lua_replace", null, ["number", "number", "number"]), }; } } /** @internal */ -export function createLua(glue: LuaEmscriptenModule, overrides: Partial): Lua { - const defaultLua: Lua = { - lua_close: glue.cwrap("lua_close", null, ["number"]), - lua_getfield: glue.cwrap("lua_getfield", "number", ["number", "number", "string"]), - lua_getglobal: glue.cwrap("lua_getglobal", null, ["number", "string"]), - lua_isstring: glue.cwrap("lua_isstring", "number", ["number", "number"]), - // In C this is just a #define so we have to recreate it ourself - lua_pcall: function (L: LuaState, nargs: number, nresults: number, msgh: number) { - return this.lua_pcallk(L, nargs, nresults, msgh, 0, 0); - }, - lua_pcallk: safeCwrap(glue, "lua_pcallk", "number", [ - "number", - "number", - "number", - "number", - "number", - "number", - ]), - lua_setfield: glue.cwrap("lua_setfield", null, ["number", "number", "string"]), - lua_tolstring: glue.cwrap("lua_tolstring", "string", ["number", "number", "number"]), - // In C this is just a #define so we have to recreate it ourself - lua_tostring: function (L: LuaState, index: number) { - return this.lua_tolstring(L, index, 0); - }, - lua_type: glue.cwrap("lua_type", "number", ["number", "number"]), - lua_typename: glue.cwrap("lua_typename", "string", ["number", "number"]), - }; +export function createLua(luaGlue: LuaEmscriptenModule, version: string): Lua { + const result: Partial = {}; + for (const [supportedVersion, factoryFunc] of Object.entries(luaBindings)) { + if (satisfies(version, supportedVersion)) { + const addedFunctions = factoryFunc(luaGlue); + + // Validate + if (Object.keys(addedFunctions).some(k => k in result)) { + throw "Error multiple possible bindings for one function, please ensure that only a single possible function exists for a specific version!"; + } + + Object.assign(result, addedFunctions); + } + } + + return result as Lua; +} - return Object.assign(defaultLua, overrides); +type lauxBindingFactoryFunc = (luaGlue: LuaEmscriptenModule, lua: Lua) => Partial; +const lauxBindings: Record = { + "5.0.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { + return { + luaL_dostring: luaGlue.cwrap("luaL_dostring", "number", ["number", "string"]), + luaL_loadstring: function(L: LuaState, s: string) { + return (this as LauxLib).luaL_loadbuffer(L, s, s.length, s); + }, + luaL_newstate: luaGlue.cwrap("lua_open", "number", []), + } + }, + "<=5.1.0": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { + return { + luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]), + } + }, + ">=5.1.0": function(luaGlue: LuaEmscriptenModule, lua: Lua) { + return { + // #define + luaL_dostring: function (L: LuaState, s: string) { + return (this as LauxLib).luaL_loadstring(L, s) || lua.lua_pcall(L, 0, LUA_MULTRET, 0); + }, + luaL_loadstring: luaGlue.cwrap("luaL_loadstring", "number", ["number", "string"]), + luaL_newstate: luaGlue.cwrap("luaL_newstate", "number", []), + } + }, + ">=5.2.0": function(_luaGlue: LuaEmscriptenModule, _lua: Lua) { + return { + luaL_loadbuffer: function(_L: LuaState, _s: string, _slen: number, _name: string) { + throw "luaL_loadbuffer not supported in 5.2 and higher use luaL_loadstring instead."; + } + } + }, } /** @internal */ -export function createLauxLib(glue: LuaEmscriptenModule, lua: Lua, overrides: Partial): LauxLib { - const defaultLauxLib: LauxLib = { - // In C this is just a #define so we have to recreate it ourself - luaL_dostring: function (L: LuaState, s: string) { - return this.luaL_loadstring(L, s) || lua.lua_pcall(L, 0, LUA_MULTRET, 0); - }, - luaL_loadstring: glue.cwrap("luaL_loadstring", "number", ["number", "string"]), - luaL_newstate: glue.cwrap("luaL_newstate", "number", []), - }; +export function createLauxLib(luaGlue: LuaEmscriptenModule, lua: Lua, version: string): LauxLib { + const result: Partial = {}; + for (const [supportedVersion, factoryFunc] of Object.entries(lauxBindings)) { + if (satisfies(version, supportedVersion)) { + const addedFunctions = factoryFunc(luaGlue, lua); + + // Validate + if (Object.keys(addedFunctions).some(k => k in result)) { + throw "Error multiple possible bindings for one function, please ensure that only a single possible function exists for a specific version!"; + } - return Object.assign(defaultLauxLib, overrides); + Object.assign(result, addedFunctions); + } + } + + return result as LauxLib; +} + +type luaLibBindingFactoryFunc = (luaGlue: LuaEmscriptenModule) => Partial; +const luaLibBindings: Record = { + "*": function(luaGlue: LuaEmscriptenModule) { + return { + luaopen_base: luaGlue.cwrap("luaopen_base", null, ["number"]), + luaopen_math: luaGlue.cwrap("luaopen_math", null, ["number"]), + luaopen_string: luaGlue.cwrap("luaopen_string", null, ["number"]), + luaopen_io: luaGlue.cwrap("luaopen_io", null, ["number"]), + luaopen_table: luaGlue.cwrap("luaopen_table", null, ["number"]), + luaopen_debug: luaGlue.cwrap("luaopen_debug", null, ["number"]), + } + }, + "5.0.x": function(_luaGlue: LuaEmscriptenModule) { + return { + luaL_openlibs: function(L: LuaState) { + (this as LuaLib).luaopen_base(L); + (this as LuaLib).luaopen_math(L); + (this as LuaLib).luaopen_string(L); + (this as LuaLib).luaopen_io(L); + (this as LuaLib).luaopen_table(L); + (this as LuaLib).luaopen_debug(L); + } + } + }, + ">=5.1.0": function(luaGlue: LuaEmscriptenModule) { + return { + luaL_openlibs: luaGlue.cwrap("luaL_openlibs", null, ["number"]), + } + }, } /** @internal */ -export function createLuaLib(glue: LuaEmscriptenModule, overrides: Partial): LuaLib { - const defaultLuaLib: LuaLib = { - luaL_openlibs: glue.cwrap("luaL_openlibs", null, ["number"]), - }; +export function createLuaLib(luaGlue: LuaEmscriptenModule, version: string): LuaLib { + const result: Partial = {}; + for (const [supportedVersion, factoryFunc] of Object.entries(luaLibBindings)) { + if (satisfies(version, supportedVersion)) { + const addedFunctions = factoryFunc(luaGlue); + + // Validate + if (Object.keys(addedFunctions).some(k => k in result)) { + throw "Error multiple possible bindings for one function, please ensure that only a single possible function exists for a specific version!"; + } - return Object.assign(defaultLuaLib, overrides); -} + Object.assign(result, addedFunctions); + } + } + + return result as LuaLib; +} \ No newline at end of file diff --git a/src/glue/glue-lua-5.0.3.d.ts b/src/glue/glue-lua-5.0.3.d.ts new file mode 100644 index 0000000..90cf317 --- /dev/null +++ b/src/glue/glue-lua-5.0.3.d.ts @@ -0,0 +1,5 @@ +import type { EmscriptenModuleFactorySync, LuaEmscriptenModule } from "./glue"; + +declare const glue: EmscriptenModuleFactorySync; + +export default glue; diff --git a/src/lua.50.ts b/src/lua.50.ts new file mode 100644 index 0000000..309574d --- /dev/null +++ b/src/lua.50.ts @@ -0,0 +1,10 @@ +import { createLauxLib, createLua, createLuaLib } from "./binding-factory"; +import glue from "./glue/glue-lua-5.0.3"; + +let luaGlue = glue({ + print: console.log, + printErr: console.error, +}); +export const lua = createLua(luaGlue, "5.0.3"); +export const lauxlib = createLauxLib(luaGlue, lua, "5.0.3"); +export const lualib = createLuaLib(luaGlue, "5.0.3"); diff --git a/src/lua.51.ts b/src/lua.51.ts index 9438283..7a9664d 100644 --- a/src/lua.51.ts +++ b/src/lua.51.ts @@ -1,25 +1,11 @@ import { createLauxLib, createLua, createLuaLib } from "./binding-factory"; import glue from "./glue/glue-lua-5.1.5"; -import { Lua, LuaState } from "./lua"; let luaGlue = glue({ print: console.log, printErr: console.error, }); -// For 5.1 we need to plyfill getglobal and pcallk -export const lua = createLua(luaGlue, { - // #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s) - lua_getglobal: function (L: LuaState, name: string) { - // TODO avoid cast - return (this as Lua).lua_getfield(L, -10002, name); - }, - // Need to overwrite because in lua 5.1 this is a function and not a #define (5.2 and higher) - lua_pcall: luaGlue.cwrap("lua_pcall", "number", ["number", "number", "number", "number"]), - // TODO there might be some way to mimic pcallk behaviour with 5.1 somehow - lua_pcallk: function (_L: LuaState, _nargs: number, _nresults: number, _errfunc: number, _ctx: number, _k: number) { - throw "pcallk not supported with Lua 5.1"; - }, -}); -export const lauxlib = createLauxLib(luaGlue, lua, {}); -export const lualib = createLuaLib(luaGlue, {}); +export const lua = createLua(luaGlue, "5.1.5"); +export const lauxlib = createLauxLib(luaGlue, lua, "5.1.5"); +export const lualib = createLuaLib(luaGlue, "5.1.5"); diff --git a/src/lua.52.ts b/src/lua.52.ts index 9eeb865..6b1e7f0 100644 --- a/src/lua.52.ts +++ b/src/lua.52.ts @@ -6,6 +6,6 @@ let luaGlue = glue({ printErr: console.error, }); -export const lua = createLua(luaGlue, {}); -export const lauxlib = createLauxLib(luaGlue, lua, {}); -export const lualib = createLuaLib(luaGlue, {}); +export const lua = createLua(luaGlue, "5.2.4"); +export const lauxlib = createLauxLib(luaGlue, lua, "5.2.4"); +export const lualib = createLuaLib(luaGlue, "5.2.4"); diff --git a/src/lua.53.ts b/src/lua.53.ts index 51988ae..db8c57f 100644 --- a/src/lua.53.ts +++ b/src/lua.53.ts @@ -6,6 +6,6 @@ let luaGlue = glue({ printErr: console.error, }); -export const lua = createLua(luaGlue, {}); -export const lauxlib = createLauxLib(luaGlue, lua, {}); -export const lualib = createLuaLib(luaGlue, {}); +export const lua = createLua(luaGlue, "5.3.6"); +export const lauxlib = createLauxLib(luaGlue, lua, "5.3.6"); +export const lualib = createLuaLib(luaGlue, "5.3.6"); diff --git a/src/lua.54.ts b/src/lua.54.ts index 49248e4..5facd81 100644 --- a/src/lua.54.ts +++ b/src/lua.54.ts @@ -6,6 +6,6 @@ let luaGlue = glue({ printErr: console.error, }); -export const lua = createLua(luaGlue, {}); -export const lauxlib = createLauxLib(luaGlue, lua, {}); -export const lualib = createLuaLib(luaGlue, {}); +export const lua = createLua(luaGlue, "5.4.2"); +export const lauxlib = createLauxLib(luaGlue, lua, "5.4.2"); +export const lualib = createLuaLib(luaGlue, "5.4.2"); diff --git a/src/lua.ts b/src/lua.ts index 18b6ecc..51562bc 100644 --- a/src/lua.ts +++ b/src/lua.ts @@ -6,6 +6,12 @@ export type LuaState = number & LuaStateUnique; // For usage in call and pcall export const LUA_MULTRET = -1; +// 5.0 & 5.1 +export const LUA_GLOBALSINDEX = -1002; + +// 5.2^ +export const LUA_RIDX_GLOBALS = 2; + // Thread Status Codes export const LUA_OK = 0; export const LUA_YIELD = 1; @@ -16,12 +22,26 @@ export const LUA_ERRERR = 5; export interface Lua { lua_close(L: LuaState): void; + lua_copy(L: LuaState, fromIndex: number, toIndex: number): void; + // TODO returns int in some lua versions void in others lua_getfield(L: LuaState, index: number, k: string): number; lua_getglobal(L: LuaState, name: string): number; + // TODO returns int in some lua versions void in others + lua_gettable(L: LuaState, index: number): number; + lua_insert(L: LuaState, index: number): void; lua_isstring(L: LuaState, index: number): number; lua_pcall(L: LuaState, nargs: number, nresults: number, msgh: number): number; lua_pcallk(L: LuaState, nargs: number, nresults: number, errfunc: number, ctx: number, k: number): number; + lua_pop(L: LuaState, n: number): void; + // TODO returns string in some lua versions void in others + lua_pushstring(L: LuaState, s: string): string; + lua_pushvalue(L: LuaState, index: number): void; + lua_remove(L: LuaState, index: number): void; + lua_replace(L: LuaState, index: number): void; + lua_rotate(L: LuaState, index: number, n: number): void; lua_setfield(L: LuaState, index: number, k: string): void; + lua_settable(L: LuaState, index: number): void; + lua_settop(L: LuaState, index: number): void; lua_tolstring(L: LuaState, index: number, size: number): string; lua_tostring(L: LuaState, index: number): string; lua_type(L: LuaState, index: number): number; @@ -30,10 +50,17 @@ export interface Lua { export interface LuaLib { luaL_openlibs(L: LuaState): void; + luaopen_base(L: LuaState): void, + luaopen_math(L: LuaState): void, + luaopen_string(L: LuaState): void, + luaopen_io(L: LuaState): void, + luaopen_table(L: LuaState): void, + luaopen_debug(L: LuaState): void, } export interface LauxLib { luaL_dostring(L: LuaState, s: string): number; + luaL_loadbuffer(L: LuaState, s: string, slen: number, name: string): typeof LUA_OK | typeof LUA_ERRSYNTAX | typeof LUA_ERRMEM luaL_loadstring(L: LuaState, s: string): typeof LUA_OK | typeof LUA_ERRSYNTAX | typeof LUA_ERRMEM; luaL_newstate(): LuaState; } diff --git a/tsconfig.json b/tsconfig.json index 454aa5d..7ea4bd2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,5 +24,6 @@ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, "skipLibCheck": true /* Skip type checking of declaration files. */, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - } + }, + "exclude": ["simple-test.ts", "dist"], }