From 9296b21b87eec3f01bee465fcb2b64c4ea14514b Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Sun, 10 Jun 2018 14:18:15 +0200 Subject: [PATCH] Use C linkage in deno.h --- deno2/deno.cc | 155 ++++++++++++++++++++------------------ deno2/deno_internal.h | 31 ++++---- deno2/from_snapshot.cc | 11 ++- deno2/include/deno.h | 27 ++++--- deno2/main.cc | 8 +- deno2/snapshot_creator.cc | 8 +- 6 files changed, 130 insertions(+), 110 deletions(-) diff --git a/deno2/deno.cc b/deno2/deno.cc index feb081489d..0afda5e908 100644 --- a/deno2/deno.cc +++ b/deno2/deno.cc @@ -28,7 +28,7 @@ IN THE SOFTWARE. #include "v8/include/libplatform/libplatform.h" #include "v8/include/v8.h" -#include "deno_internal.h" +#include "./deno_internal.h" #include "include/deno.h" #define CHECK(x) assert(x) // TODO(ry) use V8's CHECK. @@ -145,7 +145,7 @@ void Send(const v8::FunctionCallbackInfo& args) { void* buf = contents.Data(); int buflen = static_cast(contents.ByteLength()); - auto retbuf = d->cb(d, DenoBuf{buf, buflen}); + auto retbuf = d->cb(d, deno_buf{buf, buflen}); if (retbuf.data) { auto ab = v8::ArrayBuffer::New(d->isolate, retbuf.data, retbuf.len, v8::ArrayBufferCreationMode::kInternalized); @@ -161,15 +161,7 @@ void Send(const v8::FunctionCallbackInfo& args) { } } -const char* v8_version() { return v8::V8::GetVersion(); } - -void v8_set_flags(int* argc, char** argv) { - v8::V8::SetFlagsFromCommandLine(argc, argv, true); -} - -const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); } - -bool load(v8::Local context, const char* name_s, +bool Load(v8::Local context, const char* name_s, const char* source_s) { auto isolate = context->GetIsolate(); v8::Isolate::Scope isolate_scope(isolate); @@ -205,18 +197,91 @@ bool load(v8::Local context, const char* name_s, return true; } +v8::StartupData MakeSnapshot(v8::StartupData* prev_natives_blob, + v8::StartupData* prev_snapshot_blob, + const char* js_filename, const char* js_source) { + v8::V8::SetNativesDataBlob(prev_natives_blob); + v8::V8::SetSnapshotDataBlob(prev_snapshot_blob); + + auto creator = new v8::SnapshotCreator(external_references); + auto* isolate = creator->GetIsolate(); + v8::Isolate::Scope isolate_scope(isolate); + { + v8::HandleScope handle_scope(isolate); + auto context = v8::Context::New(isolate); + v8::Context::Scope context_scope(context); + + auto global = context->Global(); + + auto print_tmpl = v8::FunctionTemplate::New(isolate, Print); + auto print_val = print_tmpl->GetFunction(context).ToLocalChecked(); + CHECK( + global->Set(context, deno::v8_str("deno_print"), print_val).FromJust()); + + auto recv_tmpl = v8::FunctionTemplate::New(isolate, Recv); + auto recv_val = recv_tmpl->GetFunction(context).ToLocalChecked(); + CHECK(global->Set(context, deno::v8_str("deno_recv"), recv_val).FromJust()); + + auto send_tmpl = v8::FunctionTemplate::New(isolate, Send); + auto send_val = send_tmpl->GetFunction(context).ToLocalChecked(); + CHECK(global->Set(context, deno::v8_str("deno_send"), send_val).FromJust()); + + bool r = Load(context, js_filename, js_source); + assert(r); + + creator->SetDefaultContext(context); + } + + auto snapshot_blob = + creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep); + + return snapshot_blob; +} + +void AddIsolate(Deno* d, v8::Isolate* isolate) { + d->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::ExitOnPromiseRejectCallback); + d->isolate->SetData(0, d); +} + +} // 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* v8_version() { return v8::V8::GetVersion(); } + +void v8_set_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_load(Deno* d, const char* name_s, const char* source_s) { 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 load(context, name_s, source_s) ? 0 : 1; + return deno::Load(context, name_s, source_s) ? 0 : 1; } // Called from golang. Must route message to javascript lang. // non-zero return value indicates error. check deno_last_exception(). -int deno_send(Deno* d, DenoBuf buf) { +int deno_send(Deno* d, deno_buf buf) { v8::Locker locker(d->isolate); v8::Isolate::Scope isolate_scope(d->isolate); v8::HandleScope handle_scope(d->isolate); @@ -242,73 +307,13 @@ int deno_send(Deno* d, DenoBuf buf) { recv->Call(context->Global(), 1, args); if (try_catch.HasCaught()) { - HandleException(context, try_catch.Exception()); + deno::HandleException(context, try_catch.Exception()); return 2; } return 0; } -void v8_init() { - // v8::V8::InitializeICUDefaultLocation(argv[0]); - // v8::V8::InitializeExternalStartupData(argv[0]); - auto p = v8::platform::CreateDefaultPlatform(); - v8::V8::InitializePlatform(p); - v8::V8::Initialize(); -} - -void deno_add_isolate(Deno* d, v8::Isolate* isolate) { - d->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(ExitOnPromiseRejectCallback); - d->isolate->SetData(0, d); -} - -v8::StartupData make_snapshot(v8::StartupData* prev_natives_blob, - v8::StartupData* prev_snapshot_blob, - const char* js_filename, const char* js_source) { - v8::V8::SetNativesDataBlob(prev_natives_blob); - v8::V8::SetSnapshotDataBlob(prev_snapshot_blob); - - auto creator = new v8::SnapshotCreator(external_references); - auto* isolate = creator->GetIsolate(); - v8::Isolate::Scope isolate_scope(isolate); - { - v8::HandleScope handle_scope(isolate); - auto context = v8::Context::New(isolate); - v8::Context::Scope context_scope(context); - - auto global = context->Global(); - - auto print_tmpl = v8::FunctionTemplate::New(isolate, Print); - auto print_val = print_tmpl->GetFunction(context).ToLocalChecked(); - CHECK(global->Set(context, v8_str("deno_print"), print_val).FromJust()); - - auto recv_tmpl = v8::FunctionTemplate::New(isolate, Recv); - auto recv_val = recv_tmpl->GetFunction(context).ToLocalChecked(); - CHECK(global->Set(context, v8_str("deno_recv"), recv_val).FromJust()); - - auto send_tmpl = v8::FunctionTemplate::New(isolate, Send); - auto send_val = send_tmpl->GetFunction(context).ToLocalChecked(); - CHECK(global->Set(context, v8_str("deno_send"), send_val).FromJust()); - - bool r = load(context, js_filename, js_source); - assert(r); - - creator->SetDefaultContext(context); - } - - auto snapshot_blob = - creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep); - - return snapshot_blob; -} - void deno_dispose(Deno* d) { d->isolate->Dispose(); delete (d); @@ -316,4 +321,4 @@ void deno_dispose(Deno* d) { void deno_terminate_execution(Deno* d) { d->isolate->TerminateExecution(); } -} // namespace deno +} // extern "C" diff --git a/deno2/deno_internal.h b/deno2/deno_internal.h index 35a20bdc0b..92f891af38 100644 --- a/deno2/deno_internal.h +++ b/deno2/deno_internal.h @@ -7,18 +7,7 @@ #include "include/deno.h" #include "v8/include/v8.h" -namespace deno { - -void Print(const v8::FunctionCallbackInfo& args); -void Recv(const v8::FunctionCallbackInfo& args); -void Send(const v8::FunctionCallbackInfo& args); -static intptr_t external_references[] = {reinterpret_cast(Print), - reinterpret_cast(Recv), - reinterpret_cast(Send), 0}; - -v8::StartupData make_snapshot(v8::StartupData* prev_natives_blob, - v8::StartupData* prev_snapshot_blob, - const char* js_filename, const char* js_source); +extern "C" { // deno_s = Wrapped Isolate. struct deno_s { @@ -29,8 +18,24 @@ struct deno_s { RecvCallback cb; void* data; }; +} -void deno_add_isolate(Deno* d, v8::Isolate* isolate); +namespace deno { + +void Print(const v8::FunctionCallbackInfo& args); +void Recv(const v8::FunctionCallbackInfo& args); +void Send(const v8::FunctionCallbackInfo& args); +static intptr_t external_references[] = {reinterpret_cast(Print), + reinterpret_cast(Recv), + reinterpret_cast(Send), 0}; + +Deno* NewFromSnapshot(void* data, RecvCallback cb); + +v8::StartupData MakeSnapshot(v8::StartupData* prev_natives_blob, + v8::StartupData* prev_snapshot_blob, + const char* js_filename, const char* js_source); + +void AddIsolate(Deno* d, v8::Isolate* isolate); } // namespace deno #endif // DENO_INTERNAL_H_ diff --git a/deno2/from_snapshot.cc b/deno2/from_snapshot.cc index b743b441fb..6702aa4197 100644 --- a/deno2/from_snapshot.cc +++ b/deno2/from_snapshot.cc @@ -17,7 +17,7 @@ namespace deno { #include "natives_deno.cc" #include "snapshot_deno.cc" -Deno* from_snapshot(void* data, RecvCallback cb) { +Deno* NewFromSnapshot(void* data, RecvCallback cb) { auto natives_blob = *StartupBlob_natives(); printf("natives_blob %d bytes\n", natives_blob.raw_size); @@ -35,7 +35,7 @@ Deno* from_snapshot(void* data, RecvCallback cb) { v8::ArrayBuffer::Allocator::NewDefaultAllocator(); params.external_references = external_references; v8::Isolate* isolate = v8::Isolate::New(params); - deno_add_isolate(d, isolate); + AddIsolate(d, isolate); v8::Isolate::Scope isolate_scope(isolate); { @@ -48,3 +48,10 @@ Deno* from_snapshot(void* data, RecvCallback cb) { } } // namespace deno + +extern "C" { + +Deno* deno_new(void* data, RecvCallback cb) { + return deno::NewFromSnapshot(data, cb); +} +} diff --git a/deno2/include/deno.h b/deno2/include/deno.h index d2bdca9002..5dd4e68536 100644 --- a/deno2/include/deno.h +++ b/deno2/include/deno.h @@ -2,28 +2,30 @@ // All rights reserved. MIT License. #ifndef INCLUDE_DENO_H_ #define INCLUDE_DENO_H_ - -namespace deno { +// Neither Rust nor Go support calling directly into C++ functions, therefore +// the public interface to libdeno is done in C. +#ifdef __cplusplus +extern "C" { +#endif // Data that gets transmitted. -struct buf_s { +typedef struct { void* data; size_t len; -}; -typedef struct buf_s DenoBuf; +} deno_buf; struct deno_s; typedef struct deno_s Deno; // The callback from V8 when data is sent. -typedef DenoBuf (*RecvCallback)(Deno* d, DenoBuf buf); +typedef deno_buf (*RecvCallback)(Deno* d, deno_buf buf); -void v8_init(); +void deno_init(); const char* v8_version(); void v8_set_flags(int* argc, char** argv); -// Constructors: -Deno* from_snapshot(void* data, RecvCallback cb); +// Constructor +Deno* deno_new(void* data, RecvCallback cb); void* deno_get_data(); @@ -32,13 +34,14 @@ void* deno_get_data(); int deno_load(Deno* d, const char* name_s, const char* source_s); // Returns nonzero on error. -int deno_send(Deno* d, DenoBuf buf); +int deno_send(Deno* d, deno_buf buf); const char* deno_last_exception(Deno* d); void deno_dispose(Deno* d); void deno_terminate_execution(Deno* d); -} // namespace deno - +#ifdef __cplusplus +} // extern "C" +#endif #endif // INCLUDE_DENO_H_ diff --git a/deno2/main.cc b/deno2/main.cc index 29aacc4e62..d16dd44ba8 100644 --- a/deno2/main.cc +++ b/deno2/main.cc @@ -6,12 +6,12 @@ #include "include/deno.h" int main(int argc, char** argv) { - deno::v8_init(); + deno_init(); - deno::Deno* d = deno::from_snapshot(NULL, NULL); - int r = deno::deno_load(d, "main2.js", "foo();"); + Deno* d = deno_new(NULL, NULL); + int r = deno_load(d, "main2.js", "foo();"); if (r != 0) { - printf("Error! %s\n", deno::deno_last_exception(d)); + printf("Error! %s\n", deno_last_exception(d)); exit(1); } } diff --git a/deno2/snapshot_creator.cc b/deno2/snapshot_creator.cc index f904e6679e..fc43783e25 100644 --- a/deno2/snapshot_creator.cc +++ b/deno2/snapshot_creator.cc @@ -9,8 +9,8 @@ #include "v8/include/v8.h" -#include "include/deno.h" #include "./deno_internal.h" +#include "include/deno.h" class StartupDataCppWriter { public: @@ -130,9 +130,9 @@ int main(int argc, char** argv) { auto natives_blob = ReadFile(natives_in_bin); auto snapshot_in_blob = ReadFile(snapshot_in_bin); - deno::v8_init(); - auto snapshot_blob = deno::make_snapshot(&natives_blob, &snapshot_in_blob, - js_fn, js_data.data); + deno_init(); + auto snapshot_blob = + deno::MakeSnapshot(&natives_blob, &snapshot_in_blob, js_fn, js_data.data); StartupDataCppWriter nativesWriter("natives", natives_out_cc, natives_blob); nativesWriter.Write();