summaryrefslogtreecommitdiff
path: root/core/libdeno/api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'core/libdeno/api.cc')
-rw-r--r--core/libdeno/api.cc231
1 files changed, 231 insertions, 0 deletions
diff --git a/core/libdeno/api.cc b/core/libdeno/api.cc
new file mode 100644
index 000000000..fa1fe92f9
--- /dev/null
+++ b/core/libdeno/api.cc
@@ -0,0 +1,231 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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"
+
+#include "deno.h"
+#include "exceptions.h"
+#include "file_util.h"
+#include "internal.h"
+
+extern "C" {
+
+Deno* deno_new_snapshotter(deno_config config) {
+ CHECK(config.will_snapshot);
+ // TODO(ry) Support loading snapshots before snapshotting.
+ CHECK_NULL(config.load_snapshot.data_ptr);
+ auto* creator = new v8::SnapshotCreator(deno::external_references);
+ auto* isolate = creator->GetIsolate();
+ auto* d = new deno::DenoIsolate(config);
+ d->snapshot_creator_ = creator;
+ d->AddIsolate(isolate);
+ {
+ v8::Locker locker(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
+ auto context = v8::Context::New(isolate);
+ d->context_.Reset(isolate, context);
+
+ creator->SetDefaultContext(context,
+ v8::SerializeInternalFieldsCallback(
+ deno::SerializeInternalFields, nullptr));
+ deno::InitializeContext(isolate, context);
+ }
+ return reinterpret_cast<Deno*>(d);
+}
+
+Deno* deno_new(deno_config config) {
+ if (config.will_snapshot) {
+ return deno_new_snapshotter(config);
+ }
+ deno::DenoIsolate* d = new deno::DenoIsolate(config);
+ v8::Isolate::CreateParams params;
+ params.array_buffer_allocator = d->array_buffer_allocator_;
+ params.external_references = deno::external_references;
+
+ if (config.load_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));
+ if (!config.load_snapshot.data_ptr) {
+ // If no snapshot is provided, we initialize the context with empty
+ // main source code and source maps.
+ deno::InitializeContext(isolate, context);
+ }
+ d->context_.Reset(isolate, context);
+ }
+
+ return reinterpret_cast<Deno*>(d);
+}
+
+deno::DenoIsolate* unwrap(Deno* d_) {
+ return reinterpret_cast<deno::DenoIsolate*>(d_);
+}
+
+void deno_lock(Deno* d_) {
+ auto* d = unwrap(d_);
+ CHECK_NULL(d->locker_);
+ d->locker_ = new v8::Locker(d->isolate_);
+}
+
+void deno_unlock(Deno* d_) {
+ auto* d = unwrap(d_);
+ CHECK_NOT_NULL(d->locker_);
+ delete d->locker_;
+ d->locker_ = nullptr;
+}
+
+deno_buf deno_get_snapshot(Deno* d_) {
+ auto* d = unwrap(d_);
+ CHECK_NOT_NULL(d->snapshot_creator_);
+ d->ClearModules();
+ d->context_.Reset();
+
+ auto blob = d->snapshot_creator_->CreateBlob(
+ v8::SnapshotCreator::FunctionCodeHandling::kKeep);
+ return {nullptr, 0, reinterpret_cast<uint8_t*>(const_cast<char*>(blob.data)),
+ blob.raw_size, 0};
+}
+
+static std::unique_ptr<v8::Platform> platform;
+
+void deno_init() {
+ if (platform.get() == nullptr) {
+ platform = v8::platform::NewDefaultPlatform();
+ v8::V8::InitializePlatform(platform.get());
+ 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_);
+ if (d->last_exception_.length() > 0) {
+ return d->last_exception_.c_str();
+ } else {
+ return nullptr;
+ }
+}
+
+void 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_);
+ CHECK(!context.IsEmpty());
+ deno::Execute(context, js_filename, js_source);
+}
+
+void deno_zero_copy_release(Deno* d_, size_t zero_copy_id) {
+ auto* d = unwrap(d_);
+ v8::Isolate::Scope isolate_scope(d->isolate_);
+ v8::Locker locker(d->isolate_);
+ v8::HandleScope handle_scope(d->isolate_);
+ d->DeleteZeroCopyRef(zero_copy_id);
+}
+
+void deno_respond(Deno* d_, void* user_data, deno_buf buf) {
+ auto* d = unwrap(d_);
+ if (d->current_args_ != nullptr) {
+ // Synchronous response.
+ if (buf.data_ptr != nullptr) {
+ DCHECK_EQ(buf.zero_copy_id, 0);
+ auto ab = deno::ImportBuf(d, buf);
+ d->current_args_->GetReturnValue().Set(ab);
+ }
+ d->current_args_ = nullptr;
+ return;
+ }
+
+ // 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_);
+
+ auto recv_ = d->recv_.Get(d->isolate_);
+ if (recv_.IsEmpty()) {
+ d->last_exception_ = "Deno.core.recv has not been called.";
+ return;
+ }
+
+ v8::Local<v8::Value> args[1];
+ int argc = 0;
+
+ // You cannot use zero_copy_buf with deno_respond(). Use
+ // deno_zero_copy_release() instead.
+ DCHECK_EQ(buf.zero_copy_id, 0);
+ if (buf.data_ptr != nullptr) {
+ args[0] = deno::ImportBuf(d, buf);
+ argc = 1;
+ }
+
+ auto v = recv_->Call(context, context->Global(), argc, args);
+
+ if (try_catch.HasCaught()) {
+ CHECK(v.IsEmpty());
+ deno::HandleException(context, try_catch.Exception());
+ }
+}
+
+void deno_check_promise_errors(Deno* d_) {
+ auto* d = unwrap(d_);
+ if (d->pending_promise_map_.size() > 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);
+
+ auto it = d->pending_promise_map_.begin();
+ while (it != d->pending_promise_map_.end()) {
+ auto error = it->second.Get(isolate);
+ deno::HandleException(context, error);
+ it = d->pending_promise_map_.erase(it);
+ }
+ }
+}
+
+void deno_delete(Deno* d_) {
+ deno::DenoIsolate* d = reinterpret_cast<deno::DenoIsolate*>(d_);
+ delete d;
+}
+
+void deno_terminate_execution(Deno* d_) {
+ deno::DenoIsolate* d = reinterpret_cast<deno::DenoIsolate*>(d_);
+ d->isolate_->TerminateExecution();
+}
+}