Permalink
Browse files

sandbox, feat: normalize implementation of custom_loader with the oth…

…er standard loaders, then rename 'SandBox::setModuleLoader' to 'SandBox::setModuleCompiler'. (#459)
  • Loading branch information...
richardo2016 authored and xicilion committed Aug 14, 2018
1 parent 926286d commit 7da2020d90c5a21e7583abecb47686285ae7eb45
View
@@ -32,7 +32,7 @@ class SandBox : public SandBox_base {
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);
virtual result_t setModuleLoader(exlib::string extname, v8::Local<v8::Function> once_require_func);
virtual result_t setModuleCompiler(exlib::string extname, v8::Local<v8::Function> compiler);
virtual result_t get_global(v8::Local<v8::Object>& retVal);
virtual result_t get_modules(v8::Local<v8::Object>& retVal);
@@ -36,7 +36,7 @@ class SandBox_base : public object_base {
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;
virtual result_t setModuleLoader(exlib::string extname, v8::Local<v8::Function> once_require_func) = 0;
virtual result_t setModuleCompiler(exlib::string extname, v8::Local<v8::Function> compiler) = 0;
virtual result_t get_global(v8::Local<v8::Object>& retVal) = 0;
virtual result_t get_modules(v8::Local<v8::Object>& retVal) = 0;
@@ -54,7 +54,7 @@ class SandBox_base : public object_base {
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);
static void s_setModuleLoader(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_setModuleCompiler(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_get_global(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& args);
static void s_get_modules(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& args);
};
@@ -74,7 +74,7 @@ inline ClassInfo& SandBox_base::class_info()
{ "run", s_run, false },
{ "resolve", s_resolve, false },
{ "require", s_require, false },
{ "setModuleLoader", s_setModuleLoader, false }
{ "setModuleCompiler", s_setModuleCompiler, false }
};
static ClassData::ClassProperty s_property[] = {
@@ -276,9 +276,9 @@ inline void SandBox_base::s_require(const v8::FunctionCallbackInfo<v8::Value>& a
METHOD_RETURN();
}
inline void SandBox_base::s_setModuleLoader(const v8::FunctionCallbackInfo<v8::Value>& args)
inline void SandBox_base::s_setModuleCompiler(const v8::FunctionCallbackInfo<v8::Value>& args)
{
METHOD_NAME("SandBox.setModuleLoader");
METHOD_NAME("SandBox.setModuleCompiler");
METHOD_INSTANCE(SandBox_base);
METHOD_ENTER();
@@ -287,7 +287,7 @@ inline void SandBox_base::s_setModuleLoader(const v8::FunctionCallbackInfo<v8::V
ARG(exlib::string, 0);
ARG(v8::Local<v8::Function>, 1);
hr = pInst->setModuleLoader(v0, v1);
hr = pInst->setModuleCompiler(v0, v1);
METHOD_VOID();
}
@@ -180,7 +180,7 @@ static const char* predefine_exts[] = {
".json",
".wasm"
};
result_t SandBox::setModuleLoader(exlib::string extname, v8::Local<v8::Function> once_require_func)
result_t SandBox::setModuleCompiler(exlib::string extname, v8::Local<v8::Function> compiler)
{
if (extname.empty())
return CALL_E_INVALIDARG;
@@ -200,7 +200,7 @@ result_t SandBox::setModuleLoader(exlib::string extname, v8::Local<v8::Function>
loader = new CustomExtLoader(extname);
m_loaders.push_back(loader);
}
SetPrivate(SandBox::_get_extloader_pname(extname), once_require_func);
SetPrivate(SandBox::_get_extloader_pname(extname), compiler);
return 0;
}
@@ -8,58 +8,40 @@
#include "Buffer.h"
#include "SandBox.h"
#include "ifs/util.h"
#include "loaders.h"
#include "object.h"
#include "path.h"
namespace fibjs {
result_t CustomExtLoader::run(SandBox::Context* ctx, Buffer_base* src, exlib::string name,
exlib::string arg_names, std::vector<v8::Local<v8::Value>>& args)
result_t CustomExtLoader::compile(SandBox::Context* ctx, Buffer_base* src, exlib::string name,
exlib::string arg_names, v8::Local<v8::Script>& script)
{
Isolate* isolate = ctx->m_sb->holder();
v8::Local<v8::String> filename = isolate->NewString(name);
exlib::string pname;
path_base::dirname(name, pname);
v8::Local<v8::String> soname = isolate->NewString(name);
v8::Local<v8::Value> require_fn = ctx->m_sb->GetPrivate(SandBox::_get_extloader_pname(m_ext));
// read filecontent :start
std::vector<v8::Local<v8::Value>> transpileArgs;
transpileArgs.resize(2);
exlib::string strScript;
// read filecontent and compile to strScript :start
v8::Local<v8::Value> transpileArgs[2];
src->valueOf(transpileArgs[0]);
v8::Local<v8::Object> requireInfo = v8::Object::New(isolate->m_isolate);
transpileArgs[1] = requireInfo;
obj_ptr<NObject> requireInfo = new NObject();
requireInfo->add("dirname", pname);
requireInfo->add("filename", name);
v8::Local<v8::Value> callbackObj;
requireInfo->valueOf(callbackObj);
transpileArgs[1] = callbackObj;
requireInfo->Set(isolate->NewString("filename"), isolate->NewString(name));
src->valueOf(transpileArgs[0]);
v8::Local<v8::Value> fileContent = v8::Local<v8::Function>::Cast(require_fn)->Call(v8::Undefined(isolate->m_isolate), 2, transpileArgs);
if (fileContent.IsEmpty())
return CALL_E_JAVASCRIPT;
TryCatch try_catch;
v8::Local<v8::Value> fileContent = v8::Local<v8::Function>::Cast(require_fn)
->Call(v8::Undefined(isolate->m_isolate),
(int32_t)transpileArgs.size(), transpileArgs.data());
if (try_catch.HasCaught()) {
v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
isolate->m_isolate, 1, v8::StackTrace::kScriptId);
if (stackTrace->GetFrameCount() > 0) {
try_catch.ReThrow();
return CALL_E_JAVASCRIPT;
} else
return CHECK_ERROR(Runtime::setError(GetException(try_catch, 0)));
}
// read filecontent :end
result_t hr = GetArgumentValue(fileContent, strScript, true);
if (hr < 0)
return CHECK_ERROR(hr);
// read filecontent and compile to strScript :end
v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(args[5]);
module->Set(isolate->NewString("exports"), fileContent);
obj_ptr<Buffer_base> buf = new Buffer(strScript);
return 0;
};
return JsLoader::compile(ctx, buf, name, arg_names, script);
}
} // namespace fibjs
@@ -48,16 +48,17 @@ class JsonLoader : public SandBox::ExtLoader {
exlib::string arg_names, std::vector<v8::Local<v8::Value>>& args);
};
class CustomExtLoader : public SandBox::ExtLoader {
class CustomExtLoader : public JsLoader {
public:
CustomExtLoader(exlib::string t_extname)
: ExtLoader(t_extname.c_str())
CustomExtLoader(exlib::string extname)
: JsLoader()
{
m_ext = extname;
}
public:
virtual result_t run(SandBox::Context* ctx, Buffer_base* src, exlib::string name,
exlib::string arg_names, std::vector<v8::Local<v8::Value>>& args);
virtual result_t compile(SandBox::Context* ctx, Buffer_base* src, exlib::string name,
exlib::string arg_names, v8::Local<v8::Script>& script);
};
} /* namespace fibjs */
View
@@ -92,11 +92,38 @@ interface SandBox : object
*/
Value require(String id, String base);
/*! @brief 对指定的 extname 添加特定的 resolve 方法
/*! @brief 对指定的 extname 添加 compiler, extname 不可为系统内置扩展名 (包括 {'.js', '.json', '.jsc', '.wasm'}), compiler 需返回有效的 javascript 脚本.
```JavaScript
var vm = require('vm');
var sbox = new vm.SandBox({
});
// 编译 typescript 脚本为 js 并加载
sbox.setModuleCompiler('.ts', tsCompiler);
var mod_ts = sbox.require('./a.ts');
// 编译 coffee 脚本为 js 并加载
sbox.setModuleCompiler('.coffee', cafeCompiler);
var mod_coffee = sbox.require('./a.coffee');
// 编译 jsx 脚本为 js 并加载
sbox.setModuleCompiler('.jsx', reactCompiler);
var mod_react = sbox.require('./a.jsx');
// 编译 yml 脚本为自定义的内容(如 API 集合) 并加载
sbox.setModuleCompiler('.yml', yaml2Rest)
sbox.setModuleCompiler('.yaml', yaml2Rest)
// 编译 markdown 为自定义的内容(如 html 字符串或 XmlDocument 对象) 并加载
sbox.setModuleCompiler('.md', mdCompiler)
sbox.setModuleCompiler('.markdown', mdCompiler)
```
@param extname 指定的 extname, 必须以 '.' 开头, 且为非系统内置扩展名
@param once_require_func 一次性引入函数, 所有带 extname 的文件仅会 require 一次
@param compiler 编译回调函数, 所有带 extname 的文件仅会 require 一次. 该回调函数格式为 `compiler(buf, requireInfo)`, buf 为读取到的文件 Buffer, requireInfo 结构为 `{filename: string}`.
*/
setModuleLoader(String extname, Function once_require_func);
setModuleCompiler(String extname, Function compiler);
/*! @brief 查询沙箱的 global 对象 */
readonly Object global;
Oops, something went wrong.

0 comments on commit 7da2020

Please sign in to comment.