mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
517ecb85f5
Problem: vim.json.encode escapes every slash in string values (for example in file paths), and is not optional. Use-case is for preventing HTML injections (eg. injecting `</script>` closing tag); in the context of Nvim this is rarely useful. Solution: - Add a `escape_slash` flag to `vim.json.encode`. - Defaults to `false`. (This is a "breaking" change, but more like a bug fix.)
233 lines
8.5 KiB
Lua
233 lines
8.5 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
|
|
local clear = n.clear
|
|
local exec_lua = n.exec_lua
|
|
local eq = t.eq
|
|
local pcall_err = t.pcall_err
|
|
|
|
describe('vim.json.decode()', function()
|
|
before_each(function()
|
|
clear()
|
|
end)
|
|
|
|
it('parses null, true, false', function()
|
|
eq(vim.NIL, exec_lua([[return vim.json.decode('null')]]))
|
|
eq(true, exec_lua([[return vim.json.decode('true')]]))
|
|
eq(false, exec_lua([[return vim.json.decode('false')]]))
|
|
end)
|
|
|
|
it('validation', function()
|
|
eq(
|
|
'Expected object key string but found invalid token at character 2',
|
|
pcall_err(exec_lua, [[return vim.json.decode('{a:"b"}')]])
|
|
)
|
|
end)
|
|
|
|
it('options', function()
|
|
local jsonstr = '{"arr":[1,2,null],"bar":[3,7],"foo":{"a":"b"},"baz":null}'
|
|
eq({
|
|
arr = { 1, 2, vim.NIL },
|
|
bar = { 3, 7 },
|
|
baz = vim.NIL,
|
|
foo = { a = 'b' },
|
|
}, exec_lua([[return vim.json.decode(..., {})]], jsonstr))
|
|
eq(
|
|
{
|
|
arr = { 1, 2, vim.NIL },
|
|
bar = { 3, 7 },
|
|
baz = vim.NIL,
|
|
foo = { a = 'b' },
|
|
},
|
|
exec_lua(
|
|
[[return vim.json.decode(..., { luanil = { array = false, object = false } })]],
|
|
jsonstr
|
|
)
|
|
)
|
|
eq({
|
|
arr = { 1, 2, vim.NIL },
|
|
bar = { 3, 7 },
|
|
-- baz = nil,
|
|
foo = { a = 'b' },
|
|
}, exec_lua([[return vim.json.decode(..., { luanil = { object = true } })]], jsonstr))
|
|
eq({
|
|
arr = { 1, 2 },
|
|
bar = { 3, 7 },
|
|
baz = vim.NIL,
|
|
foo = { a = 'b' },
|
|
}, exec_lua([[return vim.json.decode(..., { luanil = { array = true } })]], jsonstr))
|
|
eq(
|
|
{
|
|
arr = { 1, 2 },
|
|
bar = { 3, 7 },
|
|
-- baz = nil,
|
|
foo = { a = 'b' },
|
|
},
|
|
exec_lua(
|
|
[[return vim.json.decode(..., { luanil = { array = true, object = true } })]],
|
|
jsonstr
|
|
)
|
|
)
|
|
end)
|
|
|
|
it('parses integer numbers', function()
|
|
eq(100000, exec_lua([[return vim.json.decode('100000')]]))
|
|
eq(-100000, exec_lua([[return vim.json.decode('-100000')]]))
|
|
eq(100000, exec_lua([[return vim.json.decode(' 100000 ')]]))
|
|
eq(-100000, exec_lua([[return vim.json.decode(' -100000 ')]]))
|
|
eq(0, exec_lua([[return vim.json.decode('0')]]))
|
|
eq(0, exec_lua([[return vim.json.decode('-0')]]))
|
|
end)
|
|
|
|
it('parses floating-point numbers', function()
|
|
-- This behavior differs from vim.fn.json_decode, which return '100000.0'
|
|
eq('100000', exec_lua([[return tostring(vim.json.decode('100000.0'))]]))
|
|
eq(100000.5, exec_lua([[return vim.json.decode('100000.5')]]))
|
|
eq(-100000.5, exec_lua([[return vim.json.decode('-100000.5')]]))
|
|
eq(-100000.5e50, exec_lua([[return vim.json.decode('-100000.5e50')]]))
|
|
eq(100000.5e50, exec_lua([[return vim.json.decode('100000.5e50')]]))
|
|
eq(100000.5e50, exec_lua([[return vim.json.decode('100000.5e+50')]]))
|
|
eq(-100000.5e-50, exec_lua([[return vim.json.decode('-100000.5e-50')]]))
|
|
eq(100000.5e-50, exec_lua([[return vim.json.decode('100000.5e-50')]]))
|
|
eq(100000e-50, exec_lua([[return vim.json.decode('100000e-50')]]))
|
|
eq(0.5, exec_lua([[return vim.json.decode('0.5')]]))
|
|
eq(0.005, exec_lua([[return vim.json.decode('0.005')]]))
|
|
eq(0.005, exec_lua([[return vim.json.decode('0.00500')]]))
|
|
eq(0.5, exec_lua([[return vim.json.decode('0.00500e+002')]]))
|
|
eq(0.00005, exec_lua([[return vim.json.decode('0.00500e-002')]]))
|
|
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0.0')]]))
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0.0e0')]]))
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0.0e+0')]]))
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0.0e-0')]]))
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0e-0')]]))
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0e-2')]]))
|
|
eq(-0.0, exec_lua([[return vim.json.decode('-0e+2')]]))
|
|
|
|
eq(0.0, exec_lua([[return vim.json.decode('0.0')]]))
|
|
eq(0.0, exec_lua([[return vim.json.decode('0.0e0')]]))
|
|
eq(0.0, exec_lua([[return vim.json.decode('0.0e+0')]]))
|
|
eq(0.0, exec_lua([[return vim.json.decode('0.0e-0')]]))
|
|
eq(0.0, exec_lua([[return vim.json.decode('0e-0')]]))
|
|
eq(0.0, exec_lua([[return vim.json.decode('0e-2')]]))
|
|
eq(0.0, exec_lua([[return vim.json.decode('0e+2')]]))
|
|
end)
|
|
|
|
it('parses containers', function()
|
|
eq({ 1 }, exec_lua([[return vim.json.decode('[1]')]]))
|
|
eq({ vim.NIL, 1 }, exec_lua([[return vim.json.decode('[null, 1]')]]))
|
|
eq({ ['1'] = 2 }, exec_lua([[return vim.json.decode('{"1": 2}')]]))
|
|
eq(
|
|
{ ['1'] = 2, ['3'] = { { ['4'] = { ['5'] = { {}, 1 } } } } },
|
|
exec_lua([[return vim.json.decode('{"1": 2, "3": [{"4": {"5": [ [], 1]}}]}')]])
|
|
)
|
|
-- Empty string is a valid key. #20757
|
|
eq({ [''] = 42 }, exec_lua([[return vim.json.decode('{"": 42}')]]))
|
|
end)
|
|
|
|
it('parses strings properly', function()
|
|
eq('\n', exec_lua([=[return vim.json.decode([["\n"]])]=]))
|
|
eq('', exec_lua([=[return vim.json.decode([[""]])]=]))
|
|
eq('\\/"\t\b\n\r\f', exec_lua([=[return vim.json.decode([["\\\/\"\t\b\n\r\f"]])]=]))
|
|
eq('/a', exec_lua([=[return vim.json.decode([["\/a"]])]=]))
|
|
-- Unicode characters: 2-byte, 3-byte
|
|
eq('«', exec_lua([=[return vim.json.decode([["«"]])]=]))
|
|
eq('ફ', exec_lua([=[return vim.json.decode([["ફ"]])]=]))
|
|
end)
|
|
|
|
it('parses surrogate pairs properly', function()
|
|
eq('\240\144\128\128', exec_lua([[return vim.json.decode('"\\uD800\\uDC00"')]]))
|
|
end)
|
|
|
|
it('accepts all spaces in every position where space may be put', function()
|
|
local s =
|
|
' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
|
|
local str = ('%s{%s"key"%s:%s[%s"val"%s,%s"val2"%s]%s,%s"key2"%s:%s1%s}%s'):gsub('%%s', s)
|
|
eq({ key = { 'val', 'val2' }, key2 = 1 }, exec_lua([[return vim.json.decode(...)]], str))
|
|
end)
|
|
end)
|
|
|
|
describe('vim.json.encode()', function()
|
|
before_each(function()
|
|
clear()
|
|
end)
|
|
|
|
it('dumps strings with & without escaped slash', function()
|
|
-- With slash
|
|
eq('"Test\\/"', exec_lua([[return vim.json.encode('Test/', { escape_slash = true })]]))
|
|
eq(
|
|
'Test/',
|
|
exec_lua([[return vim.json.decode(vim.json.encode('Test/', { escape_slash = true }))]])
|
|
)
|
|
|
|
-- Without slash
|
|
eq('"Test/"', exec_lua([[return vim.json.encode('Test/')]]))
|
|
eq('"Test/"', exec_lua([[return vim.json.encode('Test/', {})]]))
|
|
eq('"Test/"', exec_lua([[return vim.json.encode('Test/', { _invalid = true })]]))
|
|
eq('"Test/"', exec_lua([[return vim.json.encode('Test/', { escape_slash = false })]]))
|
|
eq(
|
|
'"Test/"',
|
|
exec_lua([[return vim.json.encode('Test/', { _invalid = true, escape_slash = false })]])
|
|
)
|
|
eq(
|
|
'Test/',
|
|
exec_lua([[return vim.json.decode(vim.json.encode('Test/', { escape_slash = false }))]])
|
|
)
|
|
|
|
-- Checks for for global side-effects
|
|
eq(
|
|
'"Test/"',
|
|
exec_lua([[
|
|
vim.json.encode('Test/', { escape_slash = true })
|
|
return vim.json.encode('Test/')
|
|
]])
|
|
)
|
|
eq(
|
|
'"Test\\/"',
|
|
exec_lua([[
|
|
vim.json.encode('Test/', { escape_slash = false })
|
|
return vim.json.encode('Test/', { escape_slash = true })
|
|
]])
|
|
)
|
|
end)
|
|
|
|
it('dumps strings', function()
|
|
eq('"Test"', exec_lua([[return vim.json.encode('Test')]]))
|
|
eq('""', exec_lua([[return vim.json.encode('')]]))
|
|
eq('"\\t"', exec_lua([[return vim.json.encode('\t')]]))
|
|
eq('"\\n"', exec_lua([[return vim.json.encode('\n')]]))
|
|
-- vim.fn.json_encode return \\u001B
|
|
eq('"\\u001b"', exec_lua([[return vim.json.encode('\27')]]))
|
|
eq('"þÿþ"', exec_lua([[return vim.json.encode('þÿþ')]]))
|
|
end)
|
|
|
|
it('dumps numbers', function()
|
|
eq('0', exec_lua([[return vim.json.encode(0)]]))
|
|
eq('10', exec_lua([[return vim.json.encode(10)]]))
|
|
eq('-10', exec_lua([[return vim.json.encode(-10)]]))
|
|
end)
|
|
|
|
it('dumps floats', function()
|
|
eq('10.5', exec_lua([[return vim.json.encode(10.5)]]))
|
|
eq('-10.5', exec_lua([[return vim.json.encode(-10.5)]]))
|
|
eq('-1e-05', exec_lua([[return vim.json.encode(-1e-5)]]))
|
|
end)
|
|
|
|
it('dumps lists', function()
|
|
eq('[]', exec_lua([[return vim.json.encode({})]]))
|
|
eq('[[]]', exec_lua([[return vim.json.encode({{}})]]))
|
|
eq('[[],[]]', exec_lua([[return vim.json.encode({{}, {}})]]))
|
|
end)
|
|
|
|
it('dumps dictionaries', function()
|
|
eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict())]]))
|
|
eq('{"d":[]}', exec_lua([[return vim.json.encode({d={}})]]))
|
|
-- Empty string is a valid key. #20757
|
|
eq('{"":42}', exec_lua([[return vim.json.encode({['']=42})]]))
|
|
end)
|
|
|
|
it('dumps vim.NIL', function()
|
|
eq('null', exec_lua([[return vim.json.encode(vim.NIL)]]))
|
|
end)
|
|
end)
|