Permalink
Browse files

SandBox, feat: support for refreshing module data.

  • Loading branch information...
xicilion committed Aug 15, 2018
1 parent 8abefb0 commit 295d66b50a417ad295d31e2a5ea12afd1f01dfec
View
@@ -30,6 +30,7 @@ class SandBox : public SandBox_base {
virtual result_t has(exlib::string id, bool& retVal);
virtual result_t clone(obj_ptr<SandBox_base>& retVal);
virtual result_t freeze();
virtual result_t refresh();
virtual result_t run(exlib::string fname, v8::Local<v8::Array> argv);
virtual result_t resolve(exlib::string id, exlib::string base, exlib::string& retVal);
virtual result_t require(exlib::string id, exlib::string base, v8::Local<v8::Value>& retVal);
@@ -67,15 +68,7 @@ class SandBox : public SandBox_base {
mods()->Set(isolate->NewString(fname), m);
}
v8::Local<v8::Value> get_module(v8::Local<v8::Object> mods, exlib::string id)
{
Isolate* isolate = holder();
v8::Local<v8::Value> m = mods->Get(isolate->NewString(id));
if (m->IsUndefined())
return m;
return v8::Local<v8::Object>::Cast(m)->Get(isolate->NewString("exports"));
}
v8::Local<v8::Value> get_module(v8::Local<v8::Object> mods, exlib::string id);
public:
class Context {
@@ -34,6 +34,7 @@ class SandBox_base : public object_base {
virtual result_t has(exlib::string id, bool& retVal) = 0;
virtual result_t clone(obj_ptr<SandBox_base>& retVal) = 0;
virtual result_t freeze() = 0;
virtual result_t refresh() = 0;
virtual result_t run(exlib::string fname, v8::Local<v8::Array> argv) = 0;
virtual result_t resolve(exlib::string id, exlib::string base, exlib::string& retVal) = 0;
virtual result_t require(exlib::string id, exlib::string base, v8::Local<v8::Value>& retVal) = 0;
@@ -53,6 +54,7 @@ class SandBox_base : public object_base {
static void s_has(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_clone(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_freeze(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_refresh(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_run(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_resolve(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_require(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -74,6 +76,7 @@ inline ClassInfo& SandBox_base::class_info()
{ "has", s_has, false },
{ "clone", s_clone, false },
{ "freeze", s_freeze, false },
{ "refresh", s_refresh, false },
{ "run", s_run, false },
{ "resolve", s_resolve, false },
{ "require", s_require, false },
@@ -240,6 +243,19 @@ inline void SandBox_base::s_freeze(const v8::FunctionCallbackInfo<v8::Value>& ar
METHOD_VOID();
}
inline void SandBox_base::s_refresh(const v8::FunctionCallbackInfo<v8::Value>& args)
{
METHOD_NAME("SandBox.refresh");
METHOD_INSTANCE(SandBox_base);
METHOD_ENTER();
METHOD_OVER(0, 0);
hr = pInst->refresh();
METHOD_VOID();
}
inline void SandBox_base::s_run(const v8::FunctionCallbackInfo<v8::Value>& args)
{
METHOD_NAME("SandBox.run");
@@ -11,6 +11,82 @@
namespace fibjs {
v8::Local<v8::Value> SandBox::get_module(v8::Local<v8::Object> mods, exlib::string id)
{
Isolate* isolate = holder();
v8::Local<v8::String> strEntry = isolate->NewString("entry");
v8::Local<v8::String> strExports = isolate->NewString("exports");
v8::Local<v8::Value> m = mods->Get(isolate->NewString(id));
if (m->IsUndefined())
return m;
v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(m);
v8::Local<v8::Value> v = module->GetPrivate(module->CreationContext(),
v8::Private::ForApi(isolate->m_isolate, strEntry))
.ToLocalChecked();
v8::Local<v8::Value> o = module->Get(strExports);
if (!o->IsUndefined() || !v->IsFunction())
return o;
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
v8::Local<v8::Value> args[6];
exlib::string pname;
path_base::dirname(id, pname);
Context context(this, id);
v8::Local<v8::Object> exports = v8::Object::New(isolate->m_isolate);
v8::Local<v8::Object> mod = v8::Object::New(isolate->m_isolate);
InstallModule(id, exports, mod);
args[0] = isolate->NewString(id);
args[1] = isolate->NewString(pname);
args[2] = context.m_fnRequest;
args[3] = context.m_fnRun;
args[4] = exports;
args[5] = mod;
mod->Set(strExports, exports);
mod->Set(isolate->NewString("require"), args[2]);
mod->Set(isolate->NewString("run"), args[3]);
mod->SetPrivate(mod->CreationContext(),
v8::Private::ForApi(isolate->m_isolate, strEntry), func);
v8::Local<v8::Object> glob = isolate->context()->Global();
v = func->Call(glob, 6, args);
if (v.IsEmpty()) {
remove(id);
return v;
}
return mod->Get(strExports);
}
result_t SandBox::refresh()
{
Isolate* isolate = holder();
v8::Local<v8::String> strEntry = isolate->NewString("entry");
v8::Local<v8::String> strExports = isolate->NewString("exports");
v8::Local<v8::Object> modules = mods();
v8::Local<v8::Array> names = modules->GetPropertyNames(modules->CreationContext()).ToLocalChecked();
for (int32_t i = 0; i < names->Length(); i++) {
v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(modules->Get(names->Get(i)));
v8::Local<v8::Value> v = module->GetPrivate(module->CreationContext(),
v8::Private::ForApi(isolate->m_isolate, strEntry))
.ToLocalChecked();
if (v->IsFunction())
module->Delete(strExports);
}
return 0;
}
result_t SandBox::installScript(exlib::string srcname, Buffer_base* script,
v8::Local<v8::Value>& retVal)
{
@@ -28,7 +104,6 @@ result_t SandBox::installScript(exlib::string srcname, Buffer_base* script,
v8::Local<v8::Object> exports;
// cache string
v8::Local<v8::String> strRequire = isolate->NewString("require");
v8::Local<v8::String> strExports = isolate->NewString("exports");
exports = v8::Object::New(isolate->m_isolate);
@@ -38,7 +113,8 @@ result_t SandBox::installScript(exlib::string srcname, Buffer_base* script,
// init module
mod->Set(strExports, exports);
mod->Set(strRequire, context.m_fnRequest);
mod->Set(isolate->NewString("require"), context.m_fnRequest);
mod->Set(isolate->NewString("run"), context.m_fnRun);
InstallModule(srcname, exports, mod);
@@ -42,12 +42,16 @@ result_t SandBox::ExtLoader::run_module(Context* ctx, Buffer_base* src, exlib::s
v8::Local<v8::Object> module, v8::Local<v8::Object> exports,
std::vector<arg>& extarg)
{
std::vector<v8::Local<v8::Value>> args;
Isolate* isolate = ctx->m_sb->holder();
std::vector<v8::Local<v8::Value>> args;
args.resize(extarg.size() + 6);
args[0] = v8::Local<v8::Value>();
args[1] = v8::Local<v8::Value>();
exlib::string pname;
path_base::dirname(name, pname);
args[0] = isolate->NewString(name);
args[1] = isolate->NewString(pname);
args[2] = ctx->m_fnRequest;
args[3] = ctx->m_fnRun;
args[4] = exports;
@@ -86,12 +90,11 @@ result_t SandBox::ExtLoader::run(Context* ctx, Buffer_base* src, exlib::string n
util_base::sync(func, true, func);
Isolate* isolate = ctx->m_sb->holder();
v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(args[5]);
module->SetPrivate(module->CreationContext(),
v8::Private::ForApi(isolate->m_isolate, isolate->NewString("entry")),
func);
exlib::string pname;
path_base::dirname(name, pname);
args[0] = isolate->NewString(name);
args[1] = isolate->NewString(pname);
v8::Local<v8::Object> glob = isolate->context()->Global();
v = func->Call(glob, (int32_t)args.size(), args.data());
if (v.IsEmpty())
@@ -11,20 +11,41 @@
#include "loaders.h"
namespace fibjs {
result_t JsonLoader::run(SandBox::Context* ctx, Buffer_base* src, exlib::string name,
exlib::string arg_names, std::vector<v8::Local<v8::Value>>& args)
void _json_loader(const v8::FunctionCallbackInfo<v8::Value>& args)
{
v8::Isolate* isolate = args.GetIsolate();
obj_ptr<Buffer_base> src = Buffer_base::getInstance(args.Data());
exlib::string strScript;
src->toString(strScript);
v8::Local<v8::Value> v;
src->toString(strScript);
result_t hr = json_base::decode(strScript, v);
if (hr < 0)
return hr;
if (hr < 0) {
ThrowResult(hr);
return;
}
v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(args[5]);
module->Set(NewString(isolate, "exports"), v);
}
result_t JsonLoader::run(SandBox::Context* ctx, Buffer_base* src, exlib::string name,
exlib::string arg_names, std::vector<v8::Local<v8::Value>>& args)
{
Isolate* isolate = ctx->m_sb->holder();
v8::Local<v8::Function> func = isolate->NewFunction("json_loader", _json_loader, src->wrap());
v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(args[5]);
module->Set(isolate->NewString("exports"), v);
module->SetPrivate(module->CreationContext(),
v8::Private::ForApi(isolate->m_isolate, isolate->NewString("entry")),
func);
v8::Local<v8::Object> glob = isolate->context()->Global();
v8::Local<v8::Value> v = func->Call(glob, (int32_t)args.size(), args.data());
if (v.IsEmpty())
return CALL_E_JAVASCRIPT;
return 0;
}
View
@@ -137,7 +137,6 @@ result_t util_base::deepFreeze(v8::Local<v8::Value> v)
v8::Local<v8::Array> names = obj->GetPropertyNames(obj->CreationContext())
.ToLocalChecked();
TryCatch try_catch;
for (int32_t i = 0; i < names->Length(); i++)
deepFreeze(obj->Get(names->Get(i)));
}
View
@@ -75,6 +75,9 @@ interface SandBox : object
/*! @brief 冻结当前沙箱,冻结后的沙箱,对 global 所做的修改将被忽略 */
freeze();
/*! @brief 重新加载沙箱内的模块,此操作只会重新初始化模块,复位模块内的变量,不更新模块代码 */
refresh();
/*! @brief 运行一个脚本
@param fname 指定要运行的脚本路径,此路径与当前运行脚本无关,必须为绝对路径
@param argv 指定要运行的参数,此参数可在脚本内使用 argv 获取
View
@@ -13,7 +13,7 @@ var isWin32 = process.platform === 'win32';
function unlink(pathname) {
try {
fs.rmdir(pathname);
} catch (e) { }
} catch (e) {}
}
var pathname = 'test_dir' + vmid;
@@ -31,7 +31,7 @@ describe('fs', () => {
after(() => {
try {
fs.unlink(path.join(__dirname, 'unzip_test.zip'));
} catch (e) { }
} catch (e) {}
});
it("stat", () => {
@@ -686,8 +686,9 @@ describe('fs', () => {
});
var sz = fl.length;
assert.greaterThan(sz, 3);
assert.equal(fl[sz - 2], 't1.js');
assert.equal(fl[sz - 1], 't2.js');
assert.equal(fl[sz - 3], 't1.js');
assert.equal(fl[sz - 2], 't2.js');
assert.equal(fl[sz - 1], 'test_refresh.js');
});
it("writeFile & appendFile", () => {
@@ -0,0 +1,3 @@
{
"a": 100,
"b": 200
View
@@ -70,6 +70,12 @@ describe("module", () => {
});
});
it("require error json", () => {
assert.throws(() => {
require('./module/data_err');
});
});
it("require .js module folder", () => {
assert.deepEqual(require('./module/p4.js'), {
"v": 100
Oops, something went wrong.

0 comments on commit 295d66b

Please sign in to comment.