summaryrefslogtreecommitdiff
path: root/src/node_contextify.cc
diff options
context:
space:
mode:
authorUjjwal Sharma <usharma1998@gmail.com>2018-06-28 12:05:19 +0530
committerMichaƫl Zasso <targos@protonmail.com>2018-08-29 16:41:01 +0200
commit1abbe0a2123e8333922894258389c2d5c1568472 (patch)
tree606df1005680a3769966b19f98c740ff5576f748 /src/node_contextify.cc
parent1a25f9639a9668d8ea90022b0f3d3b47d29971b6 (diff)
downloadandroid-node-v8-1abbe0a2123e8333922894258389c2d5c1568472.tar.gz
android-node-v8-1abbe0a2123e8333922894258389c2d5c1568472.tar.bz2
android-node-v8-1abbe0a2123e8333922894258389c2d5c1568472.zip
vm: add bindings for v8::CompileFunctionInContext
Adds a method compileFunction to the vm module, which serves as a binding for v8::CompileFunctionInContext with appropriate args for specifying the details, and provide params for the wrapper. Eventually, we would be changing Module._compile to use this internally over the standard Module.wrap PR-URL: https://github.com/nodejs/node/pull/21571 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src/node_contextify.cc')
-rw-r--r--src/node_contextify.cc139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
index ce9f5eb2f7..070c6bab60 100644
--- a/src/node_contextify.cc
+++ b/src/node_contextify.cc
@@ -209,6 +209,7 @@ void ContextifyContext::Init(Environment* env, Local<Object> target) {
env->SetMethod(target, "makeContext", MakeContext);
env->SetMethod(target, "isContext", IsContext);
+ env->SetMethod(target, "compileFunction", CompileFunction);
}
@@ -987,6 +988,144 @@ class ContextifyScript : public BaseObject {
};
+void ContextifyContext::CompileFunction(
+ const FunctionCallbackInfo<Value>& args) {
+ Environment* env = Environment::GetCurrent(args);
+ Isolate* isolate = env->isolate();
+ Local<Context> context = env->context();
+
+ // Argument 1: source code
+ CHECK(args[0]->IsString());
+ Local<String> code = args[0].As<String>();
+
+ // Argument 2: filename
+ CHECK(args[1]->IsString());
+ Local<String> filename = args[1].As<String>();
+
+ // Argument 3: line offset
+ CHECK(args[2]->IsNumber());
+ Local<Integer> line_offset = args[2].As<Integer>();
+
+ // Argument 4: column offset
+ CHECK(args[3]->IsNumber());
+ Local<Integer> column_offset = args[3].As<Integer>();
+
+ // Argument 5: cached data (optional)
+ Local<Uint8Array> cached_data_buf;
+ if (!args[4]->IsUndefined()) {
+ CHECK(args[4]->IsUint8Array());
+ cached_data_buf = args[4].As<Uint8Array>();
+ }
+
+ // Argument 6: produce cache data
+ CHECK(args[5]->IsBoolean());
+ bool produce_cached_data = args[5]->IsTrue();
+
+ // Argument 7: parsing context (optional)
+ Local<Context> parsing_context;
+ if (!args[6]->IsUndefined()) {
+ CHECK(args[6]->IsObject());
+ ContextifyContext* sandbox =
+ ContextifyContext::ContextFromContextifiedSandbox(
+ env, args[6].As<Object>());
+ CHECK_NOT_NULL(sandbox);
+ parsing_context = sandbox->context();
+ } else {
+ parsing_context = context;
+ }
+
+ // Argument 8: context extensions (optional)
+ Local<Array> context_extensions_buf;
+ if (!args[7]->IsUndefined()) {
+ CHECK(args[7]->IsArray());
+ context_extensions_buf = args[7].As<Array>();
+ }
+
+ // Argument 9: params for the function (optional)
+ Local<Array> params_buf;
+ if (!args[8]->IsUndefined()) {
+ CHECK(args[8]->IsArray());
+ params_buf = args[8].As<Array>();
+ }
+
+ // Read cache from cached data buffer
+ ScriptCompiler::CachedData* cached_data = nullptr;
+ if (!cached_data_buf.IsEmpty()) {
+ ArrayBuffer::Contents contents = cached_data_buf->Buffer()->GetContents();
+ uint8_t* data = static_cast<uint8_t*>(contents.Data());
+ cached_data = new ScriptCompiler::CachedData(
+ data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength());
+ }
+
+ ScriptOrigin origin(filename, line_offset, column_offset);
+ ScriptCompiler::Source source(code, origin, cached_data);
+ ScriptCompiler::CompileOptions options;
+ if (source.GetCachedData() == nullptr) {
+ options = ScriptCompiler::kNoCompileOptions;
+ } else {
+ options = ScriptCompiler::kConsumeCodeCache;
+ }
+
+ TryCatch try_catch(isolate);
+ Context::Scope scope(parsing_context);
+
+ // Read context extensions from buffer
+ std::vector<Local<Object>> context_extensions;
+ if (!context_extensions_buf.IsEmpty()) {
+ for (uint32_t n = 0; n < context_extensions_buf->Length(); n++) {
+ Local<Value> val;
+ if (!context_extensions_buf->Get(context, n).ToLocal(&val)) return;
+ CHECK(val->IsObject());
+ context_extensions.push_back(val.As<Object>());
+ }
+ }
+
+ // Read params from params buffer
+ std::vector<Local<String>> params;
+ if (!params_buf.IsEmpty()) {
+ for (uint32_t n = 0; n < params_buf->Length(); n++) {
+ Local<Value> val;
+ if (!params_buf->Get(context, n).ToLocal(&val)) return;
+ CHECK(val->IsString());
+ params.push_back(val.As<String>());
+ }
+ }
+
+ MaybeLocal<Function> maybe_fun = ScriptCompiler::CompileFunctionInContext(
+ context, &source, params.size(), params.data(),
+ context_extensions.size(), context_extensions.data(), options);
+
+ Local<Function> fun;
+ if (maybe_fun.IsEmpty() || !maybe_fun.ToLocal(&fun)) {
+ ContextifyScript::DecorateErrorStack(env, try_catch);
+ try_catch.ReThrow();
+ return;
+ }
+
+ if (produce_cached_data) {
+ const std::unique_ptr<ScriptCompiler::CachedData>
+ cached_data(ScriptCompiler::CreateCodeCacheForFunction(fun, code));
+ bool cached_data_produced = cached_data != nullptr;
+ if (cached_data_produced) {
+ MaybeLocal<Object> buf = Buffer::Copy(
+ env,
+ reinterpret_cast<const char*>(cached_data->data),
+ cached_data->length);
+ if (fun->Set(
+ parsing_context,
+ env->cached_data_string(),
+ buf.ToLocalChecked()).IsNothing()) return;
+ }
+ if (fun->Set(
+ parsing_context,
+ env->cached_data_produced_string(),
+ Boolean::New(isolate, cached_data_produced)).IsNothing()) return;
+ }
+
+ args.GetReturnValue().Set(fun);
+}
+
+
void Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context) {