Skip to content
This repository has been archived by the owner on May 6, 2021. It is now read-only.

Commit

Permalink
Upload V1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Hexcede authored Nov 2, 2019
1 parent 957c9cf commit 2bca473
Show file tree
Hide file tree
Showing 11 changed files with 605 additions and 0 deletions.
6 changes: 6 additions & 0 deletions default.project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "H3x",
"tree": {
"$className": "DataModel"
}
}
235 changes: 235 additions & 0 deletions src/H3xScriptSandbox/Context.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
-- H3x V1.2
local Context = {}

Context.Nil = newproxy()

local setmetatable = setmetatable
local next = next
local tostring = tostring
local setfenv = setfenv
local loadstring = loadstring
local getfenv = getfenv
local pairs = pairs
local coroutine = coroutine
local assert = assert
local require = require
local script = script
local print = print
local warn = warn
local error = error
local debug = debug

local _IS_SHUTDOWN = false
local threads = {}
local function captureThread()
local thread = coroutine.running()
threads[thread] = coroutine.status(thread)

if _IS_SHUTDOWN then
error("The script is shutdown.") -- Kill the thread
end
end

local function Pointer(...) -- A pointer function. For any arguments you give it it returns them back without using any tables or table functions.
local func
func = coroutine.wrap(function(...) -- Create a coroutine.
captureThread()
coroutine.yield(func) -- Yield the coroutine
return ...
end)
return func(...)
end

local function wrapFunction(func)
local f = coroutine.wrap(function(...)
captureThread()
local result = function()end
while true do
result = Pointer(func(coroutine.yield(result())))
end
end)
f()

return f
end
local context
local runSafe
local communicateShutdown
local function isCFunction(func)
return not pcall(coroutine.wrap, func)
end
local function threadWatch(env)
if env then
local funcs = {}
return setmetatable({}, {
__index = function(_, index)
captureThread()

local value = env[index]
return value
end,
__newindex = function(_, index, value)
captureThread()

env[index] = value
end,
__metatable = getmetatable(env)
})
end
end

if script.Name == "__Context" then -- We are in a new instance of Context
Context.Libraries = {}

context = coroutine.wrap(function()
captureThread()

local id = tostring(context):sub(#"function: "+1)

local function applyEnv(func, env, mergeMode)
if env then
--env = threadWatch(env)
if not mergeMode then
setfenv(0, env)
else
local cenv = getfenv(0)

for index, value in pairs(env) do
if value == Context.Nil then
value = nil
end
cenv[index] = value
end
end
end
if func then
setfenv(func, getfenv(0))
end
end

setfenv(0, threadWatch(getfenv(0)))
applyEnv(nil, coroutine.yield(getfenv(0)))

local __context_ = loadstring(coroutine.yield())

while true do
applyEnv(__context_, coroutine.yield(wrapFunction(__context_), getfenv(0)))
end
end)
context()

runSafe = coroutine.wrap(function()
captureThread()

local func
while true do
func = wrapFunction(coroutine.yield(func))
end
end)
runSafe()

communicateShutdown = coroutine.wrap(function()
_IS_SHUTDOWN = true

for thread, oldStatus in pairs(threads) do
spawn(function()
pcall(function()
local steps = 0
while coroutine.status(thread) ~= "dead" do -- Suspended, running, or normal.
if steps == 100 then
warn("A sandboxed thread may be inifitely yielding. Will try to invoke an error within ~30 seconds (900 resumes).")
elseif steps > 100 and steps < 1000 then
wait()
elseif steps >= 1000 then
warn("Failed to kill the thread allowing the thread to continue.")
return true
end

local success = pcall(function()
coroutine.resume(thread)
steps = steps + 1
end)
if not success then
wait()
end
end
end)
end)
end
end)
end
Context.ThreadWatcherImplemented = false -- Ignore me

Context.Pointer = Pointer -- For external use
function Context:Create(code, env, mergeMode)
local scr = script:Clone() -- Make a new Context script
scr.Name = "__Context" -- Signal to this script that it will be an instance of Context.
local ctx = require(scr) -- Require the new instance

if code then
assert(typeof(code) == "string", "The provided code must be a string.")
ctx:Load(code, env, mergeMode)
end

return ctx
end

function Context:Load(code, env, mergeMode)
assert(context, "Invalid context.")
self:SetEnvironment(env, mergeMode) -- Set the environment
Context.__context, Context.environment = context(code) -- Compile code and set the context
return Context.__context -- Return the context
end

function Context:Execute(...)
assert(context, "Invalid context.")
assert(Context.__context, "Context isn't loaded.")
local ptr = Pointer(Context.__context(...)) -- Create pointer for return arguments
Context.__context, Context.environment = context() -- Regenerate context
return ptr() -- Get pointer value
end

function Context:GetEnvironment()
assert(context, "Invalid context.")

return Context.environment
end

function Context:SetEnvironment(env, mergeMode)
assert(context, "Invalid context.")
Context.__context, Context.environment = context(env, mergeMode) -- Set the new context
end

function Context:GetFunction()
assert(Context.__context, "Invalid context")
return Context.__context
end

function Context:InjectFunction(func)
assert(context, "Invalid context.")
return runSafe(func)
end

function Context:AddLibrary(name, lib)
assert(context, "Invalid context.")
Context.Libraries[name] = lib
end

function Context:RemoveLibrary(name)
Context.Libraries[name] = nil
end

function Context:Destroy()
if not _IS_SHUTDOWN then
setmetatable(Context, {__mode = "kv"})
pcall(function()
self:GetEnvironment()() -- Gc environment
end)
self:SetEnvironment({})
context = nil
runSafe = nil
communicateShutdown()
end
end

return Context
1 change: 1 addition & 0 deletions src/H3xScriptSandbox/Runner/Dispatch/Shared.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return {}
12 changes: 12 additions & 0 deletions src/H3xScriptSandbox/Runner/Dispatch/init.server.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
local Shared = require(script:WaitForChild("Shared"))

while true do
Shared.DispatchEvent = Shared.DispatchEvent or Instance.new("BindableEvent")
local argPtr = Shared.DispatchEvent.Event:Wait()
if Shared.DispatchFunction and Shared.CompleteEvent then
coroutine.wrap(function()
Shared.CompleteEvent:Fire(Shared.DispatchFunction(argPtr()))
end)()
script.Disabled = true
end
end
84 changes: 84 additions & 0 deletions src/H3xScriptSandbox/Runner/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
-- H3x V1.2
local Context = require(script.Parent:WaitForChild("Context"))
local Dispatch = script:WaitForChild("Dispatch")
local Runner = {}

function Runner:LoadFunction(func, ctx)
assert(func, "Please provide a function to load.")
assert(typeof(func) == "function", "Provided value isn't a function.")
local Script = {}
local newScript = Dispatch:Clone()

local Shared = require(newScript:WaitForChild("Shared"))
Shared.Context = ctx

Script.ScriptInstance = newScript
Script.Shared = Shared

if ctx then
Script.Context = ctx
ctx.TargetScript = Script
end

Script.TargetFunction = func
function Script:Start(...)
return Runner:StartScript(self, ...)
end
function Script:Stop()
return Runner:StopScript(self)
end

newScript.Parent = script
return Script
end

function Runner:LoadScript(scr, env, mergeMode)
assert(scr, "Please provide a script.")
assert(scr.IsA and scr:IsA("Script"), "Provided value isn't a Script instance.")

assert(pcall(function()
return scr.Source
end), "The Runner cannot load scripts in this context. (Doesn't have permission to script source)")

local ctx = Context:Create()
ctx:Load(scr.Source, env, mergeMode)

return Runner:LoadContext(ctx)
end

function Runner:LoadContext(ctx)
assert(ctx, "Please provide a Context.")

return Runner:LoadFunction(ctx:GetFunction(), ctx)
end

function Runner:StopScript(scr)
if typeof(scr) == "Instance" then
scr = {ScriptInstance = scr}
end
assert(typeof(scr.ScriptInstance) == "Instance" and scr.ScriptInstance:IsA("Script"), "Not a valid script.")
scr.ScriptInstance.Disabled = true
end

function Runner:StartScript(scr, ...)
if typeof(scr) == "Instance" then
scr = {ScriptInstance = scr}
end
assert(typeof(scr.ScriptInstance) == "Instance" and scr.ScriptInstance:IsA("Script"), "Not a valid script.")
local Shared = scr.Shared

local argPtr = Context.Pointer(...) -- Used to performantly pass arguments
Shared.CompleteEvent = Shared.CompleteEvent or Instance.new("BindableEvent")
Shared.DispatchEvent = Shared.DispatchEvent or Instance.new("BindableEvent")
Shared.DispatchFunction = scr.TargetFunction

scr.ScriptInstance.Disabled = false -- Enable the script
spawn(function()
Shared.DispatchEvent:Fire(argPtr) -- Dispatch the script
end)
local returnPtr = Context.Pointer(Shared.CompleteEvent.Event:Wait()) -- Used to performantly (and easily) store return values

return returnPtr()
end

return Runner
Loading

0 comments on commit 2bca473

Please sign in to comment.