Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions lib/lua/vm/stdlib.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,27 @@ defmodule Lua.VM.Stdlib do
|> Lua.VM.Stdlib.String.install()
|> Lua.VM.Stdlib.Math.install()
|> Lua.VM.Stdlib.Table.install()
|> install_global_g()
end

# Install _G global table - a table that references the global environment
defp install_global_g(state) do
# Create a table containing all current globals
# Copy all globals into the _G table
g_data = state.globals

{{:tref, _id} = g_ref, state} = State.alloc_table(state, g_data)

# Set _G to point to this table
state = State.set_global(state, "_G", g_ref)

# Also add _G to itself so _G._G == _G
state =
State.update_table(state, g_ref, fn table ->
%{table | data: Map.put(table.data, "_G", g_ref)}
end)

state
end

# type(v) — returns the type of v as a string
Expand Down
46 changes: 46 additions & 0 deletions test/lua_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,52 @@ defmodule LuaTest do
end
end

describe "_G global table" do
setup do
%{lua: Lua.new(sandboxed: [])}
end

test "_G references the global environment", %{lua: lua} do
# _G should be a table that contains itself
assert {[true], _} = Lua.eval!(lua, "return _G ~= nil")
assert {[true], _} = Lua.eval!(lua, "return type(_G) == 'table'")
end

test "_G contains global functions", %{lua: lua} do
# Standard functions should be accessible via _G
assert {[true], _} = Lua.eval!(lua, "return _G.print == print")
assert {[true], _} = Lua.eval!(lua, "return _G.type == type")
assert {[true], _} = Lua.eval!(lua, "return _G.tostring == tostring")
end

test "_G contains itself", %{lua: lua} do
# _G._G should reference _G
assert {[true], _} = Lua.eval!(lua, "return _G._G == _G")
end

@tag :skip
test "can set globals via _G", %{lua: lua} do
# Requires _G to be a live reference with __index/__newindex metamethods
code = """
_G.myvar = 42
return myvar
"""

assert {[42], _} = Lua.eval!(lua, code)
end

@tag :skip
test "can read globals via _G", %{lua: lua} do
# Requires _G to be a live reference with __index metamethods
code = """
myvar = 123
return _G.myvar
"""

assert {[123], _} = Lua.eval!(lua, code)
end
end

defp test_file(name) do
Path.join(["test", "fixtures", name])
end
Expand Down