summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn2
-rw-r--r--libdeno/api.cc162
-rw-r--r--libdeno/binding.cc293
-rw-r--r--libdeno/deno.h1
-rw-r--r--libdeno/internal.h98
-rw-r--r--libdeno/new.cc67
6 files changed, 328 insertions, 295 deletions
diff --git a/BUILD.gn b/BUILD.gn
index e4ce1c9b5..b70db0f05 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -211,12 +211,12 @@ v8_executable("test_cc") {
static_library("libdeno") {
complete_static_lib = true
sources = [
+ "libdeno/api.cc",
"libdeno/binding.cc",
"libdeno/deno.h",
"libdeno/file_util.cc",
"libdeno/file_util.h",
"libdeno/internal.h",
- "libdeno/new.cc",
]
public_deps = [
"third_party/v8:v8_monolith",
diff --git a/libdeno/api.cc b/libdeno/api.cc
new file mode 100644
index 000000000..e01f95e82
--- /dev/null
+++ b/libdeno/api.cc
@@ -0,0 +1,162 @@
+// Copyright 2018 the Deno authors. All rights reserved. MIT license.
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+#include "third_party/v8/include/libplatform/libplatform.h"
+#include "third_party/v8/include/v8.h"
+#include "third_party/v8/src/base/logging.h"
+
+#include "deno.h"
+#include "internal.h"
+
+extern "C" {
+
+Deno* deno_new(deno_buf snapshot, deno_recv_cb cb) {
+ deno::DenoIsolate* d = new deno::DenoIsolate(snapshot, cb);
+ v8::Isolate::CreateParams params;
+ params.array_buffer_allocator =
+ v8::ArrayBuffer::Allocator::NewDefaultAllocator();
+ params.external_references = deno::external_references;
+
+ if (snapshot.data_ptr) {
+ params.snapshot_blob = &d->snapshot_;
+ }
+
+ v8::Isolate* isolate = v8::Isolate::New(params);
+ d->AddIsolate(isolate);
+
+ v8::Locker locker(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ {
+ v8::HandleScope handle_scope(isolate);
+ auto context =
+ v8::Context::New(isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
+ v8::MaybeLocal<v8::Value>(),
+ v8::DeserializeInternalFieldsCallback(
+ deno::DeserializeInternalFields, nullptr));
+ d->context_.Reset(isolate, context);
+ }
+
+ return reinterpret_cast<Deno*>(d);
+}
+
+deno::DenoIsolate* unwrap(Deno* d_) {
+ return reinterpret_cast<deno::DenoIsolate*>(d_);
+}
+
+void deno_init() {
+ // v8::V8::InitializeICUDefaultLocation(argv[0]);
+ // v8::V8::InitializeExternalStartupData(argv[0]);
+ auto* p = v8::platform::CreateDefaultPlatform();
+ v8::V8::InitializePlatform(p);
+ v8::V8::Initialize();
+}
+
+const char* deno_v8_version() { return v8::V8::GetVersion(); }
+
+void deno_set_v8_flags(int* argc, char** argv) {
+ v8::V8::SetFlagsFromCommandLine(argc, argv, true);
+}
+
+const char* deno_last_exception(Deno* d_) {
+ auto* d = unwrap(d_);
+ return d->last_exception_.c_str();
+}
+
+int deno_execute(Deno* d_, void* user_data_, const char* js_filename,
+ const char* js_source) {
+ auto* d = unwrap(d_);
+ deno::UserDataScope user_data_scope(d, user_data_);
+ auto* isolate = d->isolate_;
+ v8::Locker locker(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
+ auto context = d->context_.Get(d->isolate_);
+ return deno::Execute(context, js_filename, js_source) ? 1 : 0;
+}
+
+int deno_respond(Deno* d_, void* user_data_, int32_t req_id, deno_buf buf) {
+ auto* d = unwrap(d_);
+ if (d->current_args_ != nullptr) {
+ // Synchronous response.
+ auto ab = deno::ImportBuf(d, buf);
+ d->current_args_->GetReturnValue().Set(ab);
+ d->current_args_ = nullptr;
+ return 0;
+ }
+
+ // Asynchronous response.
+ deno::UserDataScope user_data_scope(d, user_data_);
+ v8::Locker locker(d->isolate_);
+ v8::Isolate::Scope isolate_scope(d->isolate_);
+ v8::HandleScope handle_scope(d->isolate_);
+
+ auto context = d->context_.Get(d->isolate_);
+ v8::Context::Scope context_scope(context);
+
+ v8::TryCatch try_catch(d->isolate_);
+
+ deno::DeleteDataRef(d, req_id);
+
+ auto recv_ = d->recv_.Get(d->isolate_);
+ if (recv_.IsEmpty()) {
+ d->last_exception_ = "libdeno.recv_ has not been called.";
+ return 1;
+ }
+
+ v8::Local<v8::Value> args[1];
+ args[0] = deno::ImportBuf(d, buf);
+ recv_->Call(context->Global(), 1, args);
+
+ if (try_catch.HasCaught()) {
+ deno::HandleException(context, try_catch.Exception());
+ return 1;
+ }
+
+ return 0;
+}
+
+void deno_check_promise_errors(Deno* d_) {
+ auto* d = unwrap(d_);
+ if (d->pending_promise_events_ > 0) {
+ auto* isolate = d->isolate_;
+ v8::Locker locker(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
+
+ auto context = d->context_.Get(d->isolate_);
+ v8::Context::Scope context_scope(context);
+
+ v8::TryCatch try_catch(d->isolate_);
+ auto promise_error_examiner_ = d->promise_error_examiner_.Get(d->isolate_);
+ if (promise_error_examiner_.IsEmpty()) {
+ d->last_exception_ =
+ "libdeno.setPromiseErrorExaminer has not been called.";
+ return;
+ }
+ v8::Local<v8::Value> args[0];
+ auto result = promise_error_examiner_->Call(context->Global(), 0, args);
+ if (try_catch.HasCaught()) {
+ deno::HandleException(context, try_catch.Exception());
+ }
+ d->pending_promise_events_ = 0; // reset
+ if (!result->BooleanValue(context).FromJust()) {
+ // Has uncaught promise reject error, exiting...
+ exit(1);
+ }
+ }
+}
+
+void deno_delete(Deno* d_) {
+ deno::DenoIsolate* d = reinterpret_cast<deno::DenoIsolate*>(d_);
+ d->isolate_->Dispose();
+ delete d;
+}
+
+void deno_terminate_execution(Deno* d_) {
+ deno::DenoIsolate* d = reinterpret_cast<deno::DenoIsolate*>(d_);
+ d->isolate_->TerminateExecution();
+}
+}
diff --git a/libdeno/binding.cc b/libdeno/binding.cc
index 3a3f171e6..9fca3814c 100644
--- a/libdeno/binding.cc
+++ b/libdeno/binding.cc
@@ -5,7 +5,6 @@
#include <iostream>
#include <string>
-#include "third_party/v8/include/libplatform/libplatform.h"
#include "third_party/v8/include/v8.h"
#include "third_party/v8/src/base/logging.h"
@@ -16,21 +15,36 @@
namespace deno {
-Deno* FromIsolate(v8::Isolate* isolate) {
- return static_cast<Deno*>(isolate->GetData(0));
+std::vector<InternalFieldData*> deserialized_data;
+
+void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
+ v8::StartupData payload, void* data) {
+ DCHECK_EQ(data, nullptr);
+ if (payload.raw_size == 0) {
+ holder->SetAlignedPointerInInternalField(index, nullptr);
+ return;
+ }
+ InternalFieldData* embedder_field = new InternalFieldData{0};
+ memcpy(embedder_field, payload.data, payload.raw_size);
+ holder->SetAlignedPointerInInternalField(index, embedder_field);
+ deserialized_data.push_back(embedder_field);
}
-void AddDataRef(Deno* d, int32_t req_id, v8::Local<v8::Value> data_v) {
- d->async_data_map.emplace(std::piecewise_construct, std::make_tuple(req_id),
- std::make_tuple(d->isolate, data_v));
+DenoIsolate* FromIsolate(v8::Isolate* isolate) {
+ return static_cast<DenoIsolate*>(isolate->GetData(0));
}
-void DeleteDataRef(Deno* d, int32_t req_id) {
+void AddDataRef(DenoIsolate* d, int32_t req_id, v8::Local<v8::Value> data_v) {
+ d->async_data_map_.emplace(std::piecewise_construct, std::make_tuple(req_id),
+ std::make_tuple(d->isolate_, data_v));
+}
+
+void DeleteDataRef(DenoIsolate* d, int32_t req_id) {
// Delete persistent reference to data ArrayBuffer.
- auto it = d->async_data_map.find(req_id);
- if (it != d->async_data_map.end()) {
+ auto it = d->async_data_map_.find(req_id);
+ if (it != d->async_data_map_.end()) {
it->second.Reset();
- d->async_data_map.erase(it);
+ d->async_data_map_.erase(it);
}
}
@@ -49,7 +63,7 @@ void HandleExceptionStr(v8::Local<v8::Context> context,
v8::Local<v8::Value> exception,
std::string* exception_str) {
auto* isolate = context->GetIsolate();
- Deno* d = FromIsolate(isolate);
+ DenoIsolate* d = FromIsolate(isolate);
v8::HandleScope handle_scope(isolate);
v8::Context::Scope context_scope(context);
@@ -61,10 +75,10 @@ void HandleExceptionStr(v8::Local<v8::Context> context,
auto column =
v8::Integer::New(isolate, message->GetStartColumn(context).FromJust());
- auto global_error_handler = d->global_error_handler.Get(isolate);
+ auto global_error_handler_ = d->global_error_handler_.Get(isolate);
- if (!global_error_handler.IsEmpty()) {
- // global_error_handler is set so we try to handle the exception in
+ if (!global_error_handler_.IsEmpty()) {
+ // global_error_handler_ is set so we try to handle the exception in
// javascript.
v8::Local<v8::Value> args[5];
args[0] = exception->ToString(context).ToLocalChecked();
@@ -72,7 +86,7 @@ void HandleExceptionStr(v8::Local<v8::Context> context,
args[2] = line;
args[3] = column;
args[4] = exception;
- global_error_handler->Call(context->Global(), 5, args);
+ global_error_handler_->Call(context->Global(), 5, args);
/* message, source, lineno, colno, error */
return;
@@ -81,7 +95,7 @@ void HandleExceptionStr(v8::Local<v8::Context> context,
char buf[12 * 1024];
if (!stack_trace.IsEmpty()) {
// No javascript error handler, but we do have a stack trace. Format it
- // into a string and add to last_exception.
+ // into a string and add to last_exception_.
std::string msg;
v8::String::Utf8Value exceptionStr(isolate, exception);
msg += ToCString(exceptionStr);
@@ -98,7 +112,7 @@ void HandleExceptionStr(v8::Local<v8::Context> context,
*exception_str += msg;
} else {
// No javascript error handler, no stack trace. Format the little info we
- // have into a string and add to last_exception.
+ // have into a string and add to last_exception_.
v8::String::Utf8Value exceptionStr(isolate, exception);
v8::String::Utf8Value script_name(isolate,
message->GetScriptResourceName());
@@ -113,11 +127,11 @@ void HandleExceptionStr(v8::Local<v8::Context> context,
void HandleException(v8::Local<v8::Context> context,
v8::Local<v8::Value> exception) {
v8::Isolate* isolate = context->GetIsolate();
- Deno* d = FromIsolate(isolate);
+ DenoIsolate* d = FromIsolate(isolate);
std::string exception_str;
HandleExceptionStr(context, exception, &exception_str);
if (d != nullptr) {
- d->last_exception = exception_str;
+ d->last_exception_ = exception_str;
} else {
std::cerr << "Pre-Deno Exception " << exception_str << std::endl;
exit(1);
@@ -139,16 +153,16 @@ const char* PromiseRejectStr(enum v8::PromiseRejectEvent e) {
void PromiseRejectCallback(v8::PromiseRejectMessage promise_reject_message) {
auto* isolate = v8::Isolate::GetCurrent();
- Deno* d = static_cast<Deno*>(isolate->GetData(0));
- DCHECK_EQ(d->isolate, isolate);
- v8::HandleScope handle_scope(d->isolate);
+ DenoIsolate* d = static_cast<DenoIsolate*>(isolate->GetData(0));
+ DCHECK_EQ(d->isolate_, isolate);
+ v8::HandleScope handle_scope(d->isolate_);
auto exception = promise_reject_message.GetValue();
- auto context = d->context.Get(d->isolate);
+ auto context = d->context_.Get(d->isolate_);
auto promise = promise_reject_message.GetPromise();
auto event = promise_reject_message.GetEvent();
v8::Context::Scope context_scope(context);
- auto promise_reject_handler = d->promise_reject_handler.Get(isolate);
+ auto promise_reject_handler = d->promise_reject_handler_.Get(isolate);
if (!promise_reject_handler.IsEmpty()) {
v8::Local<v8::Value> args[3];
@@ -156,22 +170,22 @@ void PromiseRejectCallback(v8::PromiseRejectMessage promise_reject_message) {
args[2] = promise;
/* error, event, promise */
if (event == v8::PromiseRejectEvent::kPromiseRejectWithNoHandler) {
- d->pending_promise_events++;
+ d->pending_promise_events_++;
// exception only valid for kPromiseRejectWithNoHandler
args[0] = exception;
} else if (event ==
v8::PromiseRejectEvent::kPromiseHandlerAddedAfterReject) {
- d->pending_promise_events--; // unhandled event cancelled
- if (d->pending_promise_events < 0) {
- d->pending_promise_events = 0;
+ d->pending_promise_events_--; // unhandled event cancelled
+ if (d->pending_promise_events_ < 0) {
+ d->pending_promise_events_ = 0;
}
// Placeholder, not actually used
args[0] = v8_str("Promise handler added");
} else if (event == v8::PromiseRejectEvent::kPromiseResolveAfterResolved) {
- d->pending_promise_events++;
+ d->pending_promise_events_++;
args[0] = v8_str("Promise resolved after resolved");
} else if (event == v8::PromiseRejectEvent::kPromiseRejectAfterResolved) {
- d->pending_promise_events++;
+ d->pending_promise_events_++;
args[0] = v8_str("Promise rejected after resolved");
}
promise_reject_handler->Call(context->Global(), 3, args);
@@ -183,8 +197,8 @@ void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK_GE(args.Length(), 1);
CHECK_LE(args.Length(), 2);
auto* isolate = args.GetIsolate();
- Deno* d = static_cast<Deno*>(isolate->GetData(0));
- auto context = d->context.Get(d->isolate);
+ DenoIsolate* d = FromIsolate(isolate);
+ auto context = d->context_.Get(d->isolate_);
v8::HandleScope handle_scope(isolate);
v8::String::Utf8Value str(isolate, args[0]);
bool is_err =
@@ -194,7 +208,7 @@ void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
stream << cstr << std::endl;
}
-static v8::Local<v8::Uint8Array> ImportBuf(Deno* d, deno_buf buf) {
+v8::Local<v8::Uint8Array> ImportBuf(DenoIsolate* d, deno_buf buf) {
if (buf.alloc_ptr == nullptr) {
// If alloc_ptr isn't set, we memcpy.
// This is currently used for flatbuffers created in Rust.
@@ -207,28 +221,28 @@ static v8::Local<v8::Uint8Array> ImportBuf(Deno* d, deno_buf buf) {
void* data;
if (buf.data_len > GLOBAL_IMPORT_BUF_SIZE) {
// Simple case. We allocate a new ArrayBuffer for this.
- ab = v8::ArrayBuffer::New(d->isolate, buf.data_len);
+ ab = v8::ArrayBuffer::New(d->isolate_, buf.data_len);
data = ab->GetContents().Data();
} else {
// Fast case. We reuse the global ArrayBuffer.
- if (d->global_import_buf.IsEmpty()) {
+ if (d->global_import_buf_.IsEmpty()) {
// Lazily initialize it.
- DCHECK_EQ(d->global_import_buf_ptr, nullptr);
- ab = v8::ArrayBuffer::New(d->isolate, GLOBAL_IMPORT_BUF_SIZE);
- d->global_import_buf.Reset(d->isolate, ab);
- d->global_import_buf_ptr = ab->GetContents().Data();
+ DCHECK_EQ(d->global_import_buf_ptr_, nullptr);
+ ab = v8::ArrayBuffer::New(d->isolate_, GLOBAL_IMPORT_BUF_SIZE);
+ d->global_import_buf_.Reset(d->isolate_, ab);
+ d->global_import_buf_ptr_ = ab->GetContents().Data();
} else {
- DCHECK(d->global_import_buf_ptr);
- ab = d->global_import_buf.Get(d->isolate);
+ DCHECK(d->global_import_buf_ptr_);
+ ab = d->global_import_buf_.Get(d->isolate_);
}
- data = d->global_import_buf_ptr;
+ data = d->global_import_buf_ptr_;
}
memcpy(data, buf.data_ptr, buf.data_len);
auto view = v8::Uint8Array::New(ab, 0, buf.data_len);
return view;
} else {
auto ab = v8::ArrayBuffer::New(
- d->isolate, reinterpret_cast<void*>(buf.alloc_ptr), buf.alloc_len,
+ d->isolate_, reinterpret_cast<void*>(buf.alloc_ptr), buf.alloc_len,
v8::ArrayBufferCreationMode::kInternalized);
auto view =
v8::Uint8Array::New(ab, buf.data_ptr - buf.alloc_ptr, buf.data_len);
@@ -248,16 +262,16 @@ static deno_buf GetContents(v8::Isolate* isolate,
return buf;
}
-// Sets the recv callback.
+// Sets the recv_ callback.
void Recv(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
- Deno* d = reinterpret_cast<Deno*>(isolate->GetData(0));
- DCHECK_EQ(d->isolate, isolate);
+ DenoIsolate* d = FromIsolate(isolate);
+ DCHECK_EQ(d->isolate_, isolate);
v8::HandleScope handle_scope(isolate);
- if (!d->recv.IsEmpty()) {
- isolate->ThrowException(v8_str("libdeno.recv already called."));
+ if (!d->recv_.IsEmpty()) {
+ isolate->ThrowException(v8_str("libdeno.recv_ already called."));
return;
}
@@ -265,19 +279,19 @@ void Recv(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(v->IsFunction());
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
- d->recv.Reset(isolate, func);
+ d->recv_.Reset(isolate, func);
}
void Send(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
- Deno* d = static_cast<Deno*>(isolate->GetData(0));
- DCHECK_EQ(d->isolate, isolate);
+ DenoIsolate* d = FromIsolate(isolate);
+ DCHECK_EQ(d->isolate_, isolate);
- v8::Locker locker(d->isolate);
+ v8::Locker locker(d->isolate_);
v8::EscapableHandleScope handle_scope(isolate);
- CHECK_EQ(d->currentArgs, nullptr); // libdeno.send re-entry forbidden.
- int32_t req_id = d->next_req_id++;
+ CHECK_EQ(d->current_args_, nullptr); // libdeno.send re-entry forbidden.
+ int32_t req_id = d->next_req_id_++;
v8::Local<v8::Value> control_v = args[0];
CHECK(control_v->IsArrayBufferView());
@@ -294,16 +308,16 @@ void Send(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK_EQ(args.Length(), 1);
}
- DCHECK_EQ(d->currentArgs, nullptr);
- d->currentArgs = &args;
+ DCHECK_EQ(d->current_args_, nullptr);
+ d->current_args_ = &args;
- d->cb(d->user_data, req_id, control, data);
+ d->cb_(d->user_data_, req_id, control, data);
- if (d->currentArgs == nullptr) {
+ if (d->current_args_ == nullptr) {
// This indicates that deno_repond() was called already.
} else {
// Asynchronous.
- d->currentArgs = nullptr;
+ d->current_args_ = nullptr;
// If the data ArrayBuffer was given, we must maintain a strong reference
// to it until deno_respond is called.
if (!data_v.IsEmpty()) {
@@ -315,12 +329,12 @@ void Send(const v8::FunctionCallbackInfo<v8::Value>& args) {
// Sets the global error handler.
void SetGlobalErrorHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
- Deno* d = reinterpret_cast<Deno*>(isolate->GetData(0));
- DCHECK_EQ(d->isolate, isolate);
+ DenoIsolate* d = FromIsolate(isolate);
+ DCHECK_EQ(d->isolate_, isolate);
v8::HandleScope handle_scope(isolate);
- if (!d->global_error_handler.IsEmpty()) {
+ if (!d->global_error_handler_.IsEmpty()) {
isolate->ThrowException(
v8_str("libdeno.setGlobalErrorHandler already called."));
return;
@@ -330,18 +344,18 @@ void SetGlobalErrorHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(v->IsFunction());
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
- d->global_error_handler.Reset(isolate, func);
+ d->global_error_handler_.Reset(isolate, func);
}
// Sets the promise uncaught reject handler
void SetPromiseRejectHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
- Deno* d = reinterpret_cast<Deno*>(isolate->GetData(0));
- DCHECK_EQ(d->isolate, isolate);
+ DenoIsolate* d = FromIsolate(isolate);
+ DCHECK_EQ(d->isolate_, isolate);
v8::HandleScope handle_scope(isolate);
- if (!d->promise_reject_handler.IsEmpty()) {
+ if (!d->promise_reject_handler_.IsEmpty()) {
isolate->ThrowException(
v8_str("libdeno.setPromiseRejectHandler already called."));
return;
@@ -351,18 +365,18 @@ void SetPromiseRejectHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(v->IsFunction());
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
- d->promise_reject_handler.Reset(isolate, func);
+ d->promise_reject_handler_.Reset(isolate, func);
}
// Sets the promise uncaught reject handler
void SetPromiseErrorExaminer(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
- Deno* d = reinterpret_cast<Deno*>(isolate->GetData(0));
- DCHECK_EQ(d->isolate, isolate);
+ DenoIsolate* d = FromIsolate(isolate);
+ DCHECK_EQ(d->isolate_, isolate);
v8::HandleScope handle_scope(isolate);
- if (!d->promise_error_examiner.IsEmpty()) {
+ if (!d->promise_error_examiner_.IsEmpty()) {
isolate->ThrowException(
v8_str("libdeno.setPromiseErrorExaminer already called."));
return;
@@ -372,7 +386,7 @@ void SetPromiseErrorExaminer(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(v->IsFunction());
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
- d->promise_error_examiner.Reset(isolate, func);
+ d->promise_error_examiner_.Reset(isolate, func);
}
bool ExecuteV8StringSource(v8::Local<v8::Context> context,
@@ -502,145 +516,16 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
}
}
-void AddIsolate(Deno* d, v8::Isolate* isolate) {
- d->pending_promise_events = 0;
- d->next_req_id = 0;
- d->global_import_buf_ptr = nullptr;
- d->isolate = isolate;
+void DenoIsolate::AddIsolate(v8::Isolate* isolate) {
+ isolate_ = isolate;
// Leaving this code here because it will probably be useful later on, but
// disabling it now as I haven't got tests for the desired behavior.
// d->isolate->SetCaptureStackTraceForUncaughtExceptions(true);
// d->isolate->SetAbortOnUncaughtExceptionCallback(AbortOnUncaughtExceptionCallback);
// d->isolate->AddMessageListener(MessageCallback2);
// d->isolate->SetFatalErrorHandler(FatalErrorCallback2);
- d->isolate->SetPromiseRejectCallback(deno::PromiseRejectCallback);
- d->isolate->SetData(0, d);
+ isolate_->SetPromiseRejectCallback(deno::PromiseRejectCallback);
+ isolate_->SetData(0, this);
}
-class UserDataScope {
- Deno* deno;
- void* prev_data;
- void* data; // Not necessary; only for sanity checking.
-
- public:
- UserDataScope(Deno* deno_, void* data_) : deno(deno_), data(data_) {
- CHECK(deno->user_data == nullptr || deno->user_data == data_);
- prev_data = deno->user_data;
- deno->user_data = data;
- }
-
- ~UserDataScope() {
- CHECK(deno->user_data == data);
- deno->user_data = prev_data;
- }
-};
-
} // namespace deno
-
-extern "C" {
-
-void deno_init() {
- // v8::V8::InitializeICUDefaultLocation(argv[0]);
- // v8::V8::InitializeExternalStartupData(argv[0]);
- auto* p = v8::platform::CreateDefaultPlatform();
- v8::V8::InitializePlatform(p);
- v8::V8::Initialize();
-}
-
-const char* deno_v8_version() { return v8::V8::GetVersion(); }
-
-void deno_set_v8_flags(int* argc, char** argv) {
- v8::V8::SetFlagsFromCommandLine(argc, argv, true);
-}
-
-const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); }
-
-int deno_execute(Deno* d, void* user_data, const char* js_filename,
- const char* js_source) {
- deno::UserDataScope user_data_scope(d, user_data);
- auto* isolate = d->isolate;
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- auto context = d->context.Get(d->isolate);
- return deno::Execute(context, js_filename, js_source) ? 1 : 0;
-}
-
-int deno_respond(Deno* d, void* user_data, int32_t req_id, deno_buf buf) {
- if (d->currentArgs != nullptr) {
- // Synchronous response.
- auto ab = deno::ImportBuf(d, buf);
- d->currentArgs->GetReturnValue().Set(ab);
- d->currentArgs = nullptr;
- return 0;
- }
-
- // Asynchronous response.
- deno::UserDataScope user_data_scope(d, user_data);
- v8::Locker locker(d->isolate);
- v8::Isolate::Scope isolate_scope(d->isolate);
- v8::HandleScope handle_scope(d->isolate);
-
- auto context = d->context.Get(d->isolate);
- v8::Context::Scope context_scope(context);
-
- v8::TryCatch try_catch(d->isolate);
-
- deno::DeleteDataRef(d, req_id);
-
- auto recv = d->recv.Get(d->isolate);
- if (recv.IsEmpty()) {
- d->last_exception = "libdeno.recv has not been called.";
- return 1;
- }
-
- v8::Local<v8::Value> args[1];
- args[0] = deno::ImportBuf(d, buf);
- recv->Call(context->Global(), 1, args);
-
- if (try_catch.HasCaught()) {
- deno::HandleException(context, try_catch.Exception());
- return 1;
- }
-
- return 0;
-}
-
-void deno_check_promise_errors(Deno* d) {
- if (d->pending_promise_events > 0) {
- auto* isolate = d->isolate;
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
-
- auto context = d->context.Get(d->isolate);
- v8::Context::Scope context_scope(context);
-
- v8::TryCatch try_catch(d->isolate);
- auto promise_error_examiner = d->promise_error_examiner.Get(d->isolate);
- if (promise_error_examiner.IsEmpty()) {
- d->last_exception =
- "libdeno.setPromiseErrorExaminer has not been called.";
- return;
- }
- v8::Local<v8::Value> args[0];
- auto result = promise_error_examiner->Call(context->Global(), 0, args);
- if (try_catch.HasCaught()) {
- deno::HandleException(context, try_catch.Exception());
- }
- d->pending_promise_events = 0; // reset
- if (!result->BooleanValue(context).FromJust()) {
- // Has uncaught promise reject error, exiting...
- exit(1);
- }
- }
-}
-
-void deno_delete(Deno* d) {
- d->isolate->Dispose();
- delete d;
-}
-
-void deno_terminate_execution(Deno* d) { d->isolate->TerminateExecution(); }
-
-} // extern "C"
diff --git a/libdeno/deno.h b/libdeno/deno.h
index e93b2e7f4..f833bd541 100644
--- a/libdeno/deno.h
+++ b/libdeno/deno.h
@@ -17,7 +17,6 @@ typedef struct {
size_t data_len; // Length of logical contents.
} deno_buf;
-struct deno_s;
typedef struct deno_s Deno;
// A callback to receive a message from a libdeno.send() javascript call.
diff --git a/libdeno/internal.h b/libdeno/internal.h
index be9651010..d71b36048 100644
--- a/libdeno/internal.h
+++ b/libdeno/internal.h
@@ -6,31 +6,66 @@
#include <string>
#include "deno.h"
#include "third_party/v8/include/v8.h"
+#include "third_party/v8/src/base/logging.h"
+
+namespace deno {
-extern "C" {
// deno_s = Wrapped Isolate.
-struct deno_s {
- v8::Isolate* isolate;
- const v8::FunctionCallbackInfo<v8::Value>* currentArgs;
- std::string last_exception;
- v8::Persistent<v8::Function> recv;
- v8::Persistent<v8::Function> global_error_handler;
- v8::Persistent<v8::Function> promise_reject_handler;
- v8::Persistent<v8::Function> promise_error_examiner;
- v8::StartupData snapshot;
- v8::Persistent<v8::ArrayBuffer> global_import_buf;
- void* global_import_buf_ptr;
-
- int32_t pending_promise_events;
- v8::Persistent<v8::Context> context;
- std::map<int32_t, v8::Persistent<v8::Value>> async_data_map;
- deno_recv_cb cb;
- int32_t next_req_id;
- void* user_data;
+class DenoIsolate {
+ public:
+ DenoIsolate(deno_buf snapshot, deno_recv_cb cb)
+ : isolate_(nullptr),
+ current_args_(nullptr),
+ global_import_buf_ptr_(nullptr),
+ pending_promise_events_(0),
+ cb_(cb),
+ next_req_id_(0),
+ user_data_(nullptr) {
+ if (snapshot.data_ptr) {
+ snapshot_.data = reinterpret_cast<const char*>(snapshot.data_ptr);
+ snapshot_.raw_size = static_cast<int>(snapshot.data_len);
+ }
+ }
+
+ void AddIsolate(v8::Isolate* isolate);
+
+ v8::Isolate* isolate_;
+ // Put v8::Isolate::CreateParams here..
+ const v8::FunctionCallbackInfo<v8::Value>* current_args_;
+ void* global_import_buf_ptr_;
+ int32_t pending_promise_events_;
+ deno_recv_cb cb_;
+ int32_t next_req_id_;
+ void* user_data_;
+
+ v8::Persistent<v8::Context> context_;
+ std::map<int32_t, v8::Persistent<v8::Value>> async_data_map_;
+ std::string last_exception_;
+ v8::Persistent<v8::Function> recv_;
+ v8::Persistent<v8::Function> global_error_handler_;
+ v8::Persistent<v8::Function> promise_reject_handler_;
+ v8::Persistent<v8::Function> promise_error_examiner_;
+ v8::StartupData snapshot_;
+ v8::Persistent<v8::ArrayBuffer> global_import_buf_;
};
-}
-namespace deno {
+class UserDataScope {
+ DenoIsolate* deno;
+ void* prev_data;
+ void* data; // Not necessary; only for sanity checking.
+
+ public:
+ UserDataScope(DenoIsolate* deno_, void* data_) : deno(deno_), data(data_) {
+ CHECK(deno->user_data_ == nullptr || deno->user_data_ == data_);
+ prev_data = deno->user_data_;
+ deno->user_data_ = data;
+ }
+
+ ~UserDataScope() {
+ CHECK(deno->user_data_ == data);
+ deno->user_data_ = prev_data;
+ }
+};
struct InternalFieldData {
uint32_t data;
@@ -57,7 +92,26 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
const char* js_filename, const std::string& js_source,
const std::string* source_map);
-void AddIsolate(Deno* d, v8::Isolate* isolate);
+void HandleException(v8::Local<v8::Context> context,
+ v8::Local<v8::Value> exception);
+
+void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
+ v8::StartupData payload, void* data);
+
+v8::Local<v8::Uint8Array> ImportBuf(DenoIsolate* d, deno_buf buf);
+
+void DeleteDataRef(DenoIsolate* d, int32_t req_id);
+
+bool Execute(v8::Local<v8::Context> context, const char* js_filename,
+ const char* js_source);
} // namespace deno
+
+extern "C" {
+// This is just to workaround the linker.
+struct deno_s {
+ deno::DenoIsolate isolate;
+};
+}
+
#endif // INTERNAL_H_
diff --git a/libdeno/new.cc b/libdeno/new.cc
deleted file mode 100644
index 5223f0604..000000000
--- a/libdeno/new.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2018 the Deno authors. All rights reserved. MIT license.
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-
-#include "third_party/v8/include/v8.h"
-#include "third_party/v8/src/base/logging.h"
-
-#include "deno.h"
-#include "internal.h"
-
-namespace deno {
-
-std::vector<InternalFieldData*> deserialized_data;
-
-void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
- v8::StartupData payload, void* data) {
- DCHECK_EQ(data, nullptr);
- if (payload.raw_size == 0) {
- holder->SetAlignedPointerInInternalField(index, nullptr);
- return;
- }
- InternalFieldData* embedder_field = new InternalFieldData{0};
- memcpy(embedder_field, payload.data, payload.raw_size);
- holder->SetAlignedPointerInInternalField(index, embedder_field);
- deserialized_data.push_back(embedder_field);
-}
-
-} // namespace deno
-
-extern "C" {
-
-Deno* deno_new(deno_buf snapshot, deno_recv_cb cb) {
- Deno* d = new Deno;
- d->currentArgs = nullptr;
- d->cb = cb;
- d->user_data = nullptr;
- v8::Isolate::CreateParams params;
- params.array_buffer_allocator =
- v8::ArrayBuffer::Allocator::NewDefaultAllocator();
- params.external_references = deno::external_references;
-
- if (snapshot.data_ptr) {
- d->snapshot.data = reinterpret_cast<const char*>(snapshot.data_ptr);
- d->snapshot.raw_size = static_cast<int>(snapshot.data_len);
- params.snapshot_blob = &d->snapshot;
- }
-
- v8::Isolate* isolate = v8::Isolate::New(params);
- deno::AddIsolate(d, isolate);
-
- v8::Locker locker(isolate);
- v8::Isolate::Scope isolate_scope(isolate);
- {
- v8::HandleScope handle_scope(isolate);
- auto context =
- v8::Context::New(isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
- v8::MaybeLocal<v8::Value>(),
- v8::DeserializeInternalFieldsCallback(
- deno::DeserializeInternalFields, nullptr));
- d->context.Reset(d->isolate, context);
- }
-
- return d;
-}
-}