summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2016-02-13 19:55:41 +0800
committerruki <[email protected]>2016-02-15 19:10:27 +0800
commitbee6cc1eb08ce7f48b4f58b04effbdd707fc44b3 (patch)
tree9cd5668f4eb70f0e10a8131129032234b6d32b7d
parent46ddc77c6cc909a994d8ccc73bdafaf9094585a5 (diff)
get sandbox instance from modules and impl vformat
-rw-r--r--xmake/core/base/interpreter.lua13
-rw-r--r--xmake/core/base/sandbox.lua85
-rw-r--r--xmake/core/sandbox/builtin/string.lua26
3 files changed, 103 insertions, 21 deletions
diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua
index c2d94a2f8..30e79e907 100644
--- a/xmake/core/base/interpreter.lua
+++ b/xmake/core/base/interpreter.lua
@@ -752,19 +752,16 @@ function interpreter.api_register_set_script(self, scope_kind, prefix, ...)
-- define implementation
local implementation = function (self, scope, name, script)
- -- check
- if script == nil then
- utils.error("set_%s(\"%s\"): no script", scope, name)
- utils.abort()
- end
- if type(script) == "string" and not os.isfile(script) then
- utils.error("set_%s(\"%s\"): scriptfile(%s) not found!", scope, name, script)
+ -- bind script and get new script with sandbox
+ local newscript, errors = sandbox.bind(script, self._PRIVATE._FILTER)
+ if not newscript then
+ utils.error("set_%s(\"%s\"): %s", scope, name, errors)
utils.abort()
end
-- update script?
scope[name] = {}
- table.insert(scope[name], script)
+ table.insert(scope[name], newscript)
end
diff --git a/xmake/core/base/sandbox.lua b/xmake/core/base/sandbox.lua
index d1c1ab7f2..62b86b6fe 100644
--- a/xmake/core/base/sandbox.lua
+++ b/xmake/core/base/sandbox.lua
@@ -104,7 +104,7 @@ end
function sandbox._init()
-- init an sandbox instance
- local self = {_PUBLIC = {}}
+ local self = {_PUBLIC = {}, _PRIVATE = {}}
-- inherit the interfaces of sandbox
for k, v in pairs(sandbox) do
@@ -142,25 +142,42 @@ function sandbox._init()
-- register import() for importing the extensional sandbox modules
self:_api_register("import", sandbox._api_builtin_import)
+ -- save self
+ setmetatable(self._PUBLIC, { __index = function (tbl, key)
+ if type(key) == "string" and key == "_SANDBOX" and rawget(tbl, "_SANDBOX_READABLE") then
+ return self
+ end
+ return rawget(tbl, key)
+ end
+ , __newindex = function (tbl, key, val)
+ if type(key) == "string" and (key == "_SANDBOX" or key == "_SANDBOX_READABLE") then
+ return
+ end
+ rawset(tbl, key, val)
+ end})
+
-- ok?
return self
end
--- load script in the sandbox
-function sandbox.load(script, ...)
+-- bind script into the sandbox
+function sandbox.bind(script, filter)
-- init self
local self = sandbox._init()
-- check
- assert(self and self._PUBLIC)
+ assert(self and self._PUBLIC and self._PRIVATE)
+
+ -- save filter
+ self._PRIVATE._FILTER = filter
-- this script is file? load it first
if type(script) == "string" then
-- check
if not os.isfile(script) then
- return false, string.format("the script file(%s) not found!", script)
+ return nil, string.format("the script file(%s) not found!", script)
end
-- load it
@@ -176,26 +193,78 @@ function sandbox.load(script, ...)
script = script.main
end
else
- return false, errors
+ return nil, errors
end
end
-- no script?
if script == nil then
- return false, "no script!"
+ return nil, "no script!"
end
-- invalid script?
if script ~= nil and type(script) ~= "function" then
- return false, "invalid script!"
+ return nil, "invalid script!"
end
-- bind public scope
setfenv(script, self._PUBLIC)
+ -- ok
+ return script
+end
+
+-- load script in the sandbox
+function sandbox.load(script, ...)
+
-- load script
return xpcall(script, sandbox._traceback, ...)
end
+-- get filter from the given sandbox
+function sandbox.filter(self)
+
+ -- check
+ assert(self and self._PRIVATE)
+
+ -- get it
+ return self._PRIVATE._FILTER
+end
+
+-- get current instance in the sandbox modules
+function sandbox.instance()
+
+ -- find self instance for the current sandbox
+ local instance = nil
+ local level = 2
+ while level < 16 do
+
+ -- get scope
+ local scope = getfenv(level)
+ if scope then
+
+ -- enable to read _SANDBOX
+ rawset(scope, "_SANDBOX_READABLE", true)
+
+ -- attempt to get it
+ instance = scope._SANDBOX
+
+ -- disable to read _SANDBOX
+ rawset(scope, "_SANDBOX_READABLE", nil)
+ end
+
+ -- found?
+ if instance then
+ break
+ end
+
+ -- next
+ level = level + 1
+ end
+
+ -- ok?
+ return instance
+end
+
-- return module: sandbox
return sandbox
diff --git a/xmake/core/sandbox/builtin/string.lua b/xmake/core/sandbox/builtin/string.lua
index e996c24a3..1947e9f0a 100644
--- a/xmake/core/sandbox/builtin/string.lua
+++ b/xmake/core/sandbox/builtin/string.lua
@@ -21,8 +21,8 @@
--
-- load modules
-local string = require("base/string")
-local filter = require("base/filter")
+local string = require("base/string")
+local sandbox = require("base/sandbox")
-- define module
local sandbox_builtin_string = sandbox_builtin_string or {}
@@ -30,9 +30,25 @@ local sandbox_builtin_string = sandbox_builtin_string or {}
-- format string with the builtin variables
function sandbox_builtin_string.vformat(format, ...)
- -- TODO
- -- format and filter it
--- return filter.done(string.format(format, ...), filter.handler_for_project)
+ -- check
+ assert(format)
+
+ -- get the current sandbox instance
+ local instance = sandbox.instance()
+ assert(instance)
+
+ -- format string
+ local result = string.format(format, ...)
+ assert(result)
+
+ -- get filter from the current sandbox
+ local filter = instance:filter()
+ if filter then
+ result = filter:handle(result)
+ end
+
+ -- ok?
+ return result
end
-- inherit the public interfaces of string