diff options
| author | ruki <[email protected]> | 2016-02-13 19:55:41 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2016-02-15 19:10:27 +0800 |
| commit | bee6cc1eb08ce7f48b4f58b04effbdd707fc44b3 (patch) | |
| tree | 9cd5668f4eb70f0e10a8131129032234b6d32b7d | |
| parent | 46ddc77c6cc909a994d8ccc73bdafaf9094585a5 (diff) | |
get sandbox instance from modules and impl vformat
| -rw-r--r-- | xmake/core/base/interpreter.lua | 13 | ||||
| -rw-r--r-- | xmake/core/base/sandbox.lua | 85 | ||||
| -rw-r--r-- | xmake/core/sandbox/builtin/string.lua | 26 |
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 |
