aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lapi.js2
-rw-r--r--src/lauxlib.js4
-rw-r--r--src/ljstype.js10
-rw-r--r--src/lstrlib.js6
-rw-r--r--tests/lstrlib.js189
5 files changed, 201 insertions, 10 deletions
diff --git a/src/lapi.js b/src/lapi.js
index 6840ef9..5872545 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -542,7 +542,7 @@ const lua_toboolean = function(L, idx) {
const lua_tolstring = function(L, idx) {
let o = index2addr(L, idx);
- if (!o.ttisstring() && !o.ttisnumber())
+ if ((!o.ttisstring() && !o.ttisnumber()))
return null;
return o.ttisstring() ? o.jsstring() : `${o.value}`;
diff --git a/src/lauxlib.js b/src/lauxlib.js
index 879d081..ac7ab00 100644
--- a/src/lauxlib.js
+++ b/src/lauxlib.js
@@ -299,10 +299,12 @@ const luaL_tolstring = function(L, idx) {
} else {
switch(lapi.lua_type(L, idx)) {
case CT.LUA_TNUMBER:
- case CT.LUA_TSTRING:
case CT.LUA_TBOOLEAN:
lapi.lua_pushstring(L, `${lapi.index2addr(L, idx).value}`);
break;
+ case CT.LUA_TSTRING:
+ lapi.lua_pushstring(L, lapi.index2addr(L, idx).jsstring());
+ break;
case CT.LUA_TNIL:
lapi.lua_pushstring(L, `nil`);
break;
diff --git a/src/ljstype.js b/src/ljstype.js
index ef4be1d..7de9d9a 100644
--- a/src/ljstype.js
+++ b/src/ljstype.js
@@ -3,23 +3,23 @@
const assert = require('assert');
const lisdigit = function(c) {
- return /^\d$/.test(c.charAt(0));
+ return typeof c === 'string' && /^\d$/.test(c.charAt(0));
};
const lisxdigit = function(c) {
- return /^[0-9a-fA-F]$/.test(c.charAt(0));
+ return typeof c === 'string' && /^[0-9a-fA-F]$/.test(c.charAt(0));
};
const lisspace = function(c) {
- return /^\s$/.test(c.charAt(0));
+ return typeof c === 'string' && /^\s$/.test(c.charAt(0));
};
const lislalpha = function(c) {
- return /^[_a-zA-Z]$/.test(c.charAt(0));
+ return typeof c === 'string' && /^[_a-zA-Z]$/.test(c.charAt(0));
};
const lislalnum = function(c) {
- return /^[_a-zA-Z0-9]$/.test(c.charAt(0));
+ return typeof c === 'string' && /^[_a-zA-Z0-9]$/.test(c.charAt(0));
};
module.exports.lisdigit = lisdigit;
diff --git a/src/lstrlib.js b/src/lstrlib.js
index dc3845b..3872cb2 100644
--- a/src/lstrlib.js
+++ b/src/lstrlib.js
@@ -176,7 +176,7 @@ const MAX_FORMAT = 32;
const isalpha = e => /^[a-zA-Z]$/.test(e.charAt(0));
const isdigit = e => "0".charCodeAt(0) <= e && e <= "9".charCodeAt(0);
const iscntrl = e => (0x00 <= e && e <= 0x1f) || e === 0x7f;
-const isgraph = e => e.charCodeAt(0) > 32 && e.charCodeAt < 127; // TODO: Will only work for ASCII
+const isgraph = e => e.charCodeAt(0) > 32 && e.charCodeAt(0) < 127; // TODO: Will only work for ASCII
const islower = e => /^(?![A-Z]).*$/.test(e.charAt(0));
const isupper = e => /^(?![a-z]).*$/.test(e.charAt(0));
const isalnum = e => /^[a-zA-Z0-9]$/.test(e.charAt(0));
@@ -1269,7 +1269,7 @@ const add_s = function(ms, b, s, e) {
lauxlib.luaL_addchar(b, news.charAt(i));
else {
i++; /* skip ESC */
- if (!isdigit(news.charAt(i))) {
+ if (!isdigit(news.charCodeAt(i))) {
if (news.charAt(i) !== sL_ESC)
lauxlib.luaL_error(L, `invalid use of '${sL_ESC}' in replacement string`);
lauxlib.luaL_addchar(b, news.charAt(i));
@@ -1277,7 +1277,7 @@ const add_s = function(ms, b, s, e) {
lauxlib.luaL_addlstring(b, ms.src.slice(s), e - s);
else {
push_onecapture(ms, news.charCodeAt(i) - '1'.charCodeAt(0), s, e);
- lauxlib.luaL_tostring(L, -1);
+ lauxlib.luaL_tolstring(L, -1);
lapi.lua_remove(L, -2); /* remove original value */
lauxlib.luaL_addvalue(b); /* add capture to accumulated result */
}
diff --git a/tests/lstrlib.js b/tests/lstrlib.js
index ce77bdc..12df173 100644
--- a/tests/lstrlib.js
+++ b/tests/lstrlib.js
@@ -677,4 +677,193 @@ test('string.gmatch', function (t) {
"Lua",
"Correct element(s) on the stack"
);
+});
+
+
+test('string.gsub', function (t) {
+ let luaCode = `
+ return string.gsub("hello world", "(%w+)", "%1 %1")
+ `, L;
+
+ t.plan(4);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -2),
+ "hello hello world world",
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 2,
+ "Correct element(s) on the stack"
+ );
+});
+
+
+test('string.gsub (number)', function (t) {
+ let luaCode = `
+ return string.gsub("hello world", "%w+", "%0 %0", 1)
+ `, L;
+
+ t.plan(4);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -2),
+ "hello hello world",
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 1,
+ "Correct element(s) on the stack"
+ );
+});
+
+
+test('string.gsub (pattern)', function (t) {
+ let luaCode = `
+ return string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
+ `, L;
+
+ t.plan(4);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -2),
+ "world hello Lua from",
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 2,
+ "Correct element(s) on the stack"
+ );
+});
+
+
+test('string.gsub (function)', function (t) {
+ let luaCode = `
+ return string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
+ return load(s)()
+ end)
+ `, L;
+
+ t.plan(4);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -2),
+ "4+5 = 9",
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 1,
+ "Correct element(s) on the stack"
+ );
+});
+
+
+
+test('string.gsub (table)', function (t) {
+ let luaCode = `
+ local t = {name="lua", version="5.3"}
+ return string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
+ `, L;
+
+ t.plan(4);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -2),
+ "lua-5.3.tar.gz",
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 2,
+ "Correct element(s) on the stack"
+ );
}); \ No newline at end of file