mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
libdeno: Expose snapshot creation.
This commit is contained in:
parent
6afe94b3c8
commit
61cda72881
6 changed files with 82 additions and 47 deletions
|
@ -42,10 +42,39 @@ Deno* deno_new(deno_buf snapshot, deno_recv_cb cb) {
|
|||
return reinterpret_cast<Deno*>(d);
|
||||
}
|
||||
|
||||
Deno* deno_new_snapshotter(deno_recv_cb cb, const char* js_filename,
|
||||
const char* js_source, const char* source_map) {
|
||||
auto* creator = new v8::SnapshotCreator(deno::external_references);
|
||||
auto* isolate = creator->GetIsolate();
|
||||
auto* d = new deno::DenoIsolate(deno::empty_buf, cb);
|
||||
d->snapshot_creator_ = creator;
|
||||
d->AddIsolate(isolate);
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
{
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
auto context = v8::Context::New(isolate);
|
||||
creator->SetDefaultContext(context,
|
||||
v8::SerializeInternalFieldsCallback(
|
||||
deno::SerializeInternalFields, nullptr));
|
||||
deno::InitializeContext(isolate, context, js_filename, js_source,
|
||||
source_map);
|
||||
}
|
||||
return reinterpret_cast<Deno*>(d);
|
||||
}
|
||||
|
||||
deno::DenoIsolate* unwrap(Deno* d_) {
|
||||
return reinterpret_cast<deno::DenoIsolate*>(d_);
|
||||
}
|
||||
|
||||
deno_buf deno_get_snapshot(Deno* d_) {
|
||||
auto* d = unwrap(d_);
|
||||
CHECK_NE(d->snapshot_creator_, nullptr);
|
||||
auto blob = d->snapshot_creator_->CreateBlob(
|
||||
v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
||||
return {nullptr, 0, reinterpret_cast<uint8_t*>(const_cast<char*>(blob.data)),
|
||||
blob.raw_size};
|
||||
}
|
||||
|
||||
void deno_init() {
|
||||
// v8::V8::InitializeICUDefaultLocation(argv[0]);
|
||||
// v8::V8::InitializeExternalStartupData(argv[0]);
|
||||
|
|
|
@ -30,6 +30,19 @@ void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
|
|||
deserialized_data.push_back(embedder_field);
|
||||
}
|
||||
|
||||
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
void* data) {
|
||||
DCHECK_EQ(data, nullptr);
|
||||
InternalFieldData* embedder_field = static_cast<InternalFieldData*>(
|
||||
holder->GetAlignedPointerFromInternalField(index));
|
||||
if (embedder_field == nullptr) return {nullptr, 0};
|
||||
int size = sizeof(*embedder_field);
|
||||
char* payload = new char[size];
|
||||
// We simply use memcpy to serialize the content.
|
||||
memcpy(payload, embedder_field, size);
|
||||
return {payload, size};
|
||||
}
|
||||
|
||||
DenoIsolate* FromIsolate(v8::Isolate* isolate) {
|
||||
return static_cast<DenoIsolate*>(isolate->GetData(0));
|
||||
}
|
||||
|
@ -433,8 +446,10 @@ bool Execute(v8::Local<v8::Context> context, const char* js_filename,
|
|||
}
|
||||
|
||||
void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
||||
const char* js_filename, const std::string& js_source,
|
||||
const std::string* source_map) {
|
||||
const char* js_filename, const char* js_source,
|
||||
const char* source_map) {
|
||||
CHECK_NE(js_source, nullptr);
|
||||
CHECK_NE(js_filename, nullptr);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
|
@ -483,7 +498,7 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|||
.FromJust());
|
||||
|
||||
{
|
||||
auto source = deno::v8_str(js_source.c_str());
|
||||
auto source = deno::v8_str(js_source);
|
||||
CHECK(
|
||||
deno_val->Set(context, deno::v8_str("mainSource"), source).FromJust());
|
||||
|
||||
|
@ -491,10 +506,10 @@ void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|||
CHECK(r);
|
||||
|
||||
if (source_map != nullptr) {
|
||||
CHECK_GT(source_map->length(), 1u);
|
||||
v8::TryCatch try_catch(isolate);
|
||||
v8::ScriptOrigin origin(v8_str("set_source_map.js"));
|
||||
std::string source_map_parens = "(" + *source_map + ")";
|
||||
std::string source_map_parens =
|
||||
std::string("(") + std::string(source_map) + std::string(")");
|
||||
auto source_map_v8_str = deno::v8_str(source_map_parens.c_str());
|
||||
auto script = v8::Script::Compile(context, source_map_v8_str, &origin);
|
||||
if (script.IsEmpty()) {
|
||||
|
|
|
@ -30,6 +30,11 @@ const char* deno_v8_version();
|
|||
void deno_set_v8_flags(int* argc, char** argv);
|
||||
|
||||
Deno* deno_new(deno_buf snapshot, deno_recv_cb cb);
|
||||
|
||||
Deno* deno_new_snapshotter(deno_recv_cb cb, const char* js_filename,
|
||||
const char* js_source, const char* source_map);
|
||||
deno_buf deno_get_snapshot(Deno* d);
|
||||
|
||||
void deno_delete(Deno* d);
|
||||
|
||||
// Returns false on error.
|
||||
|
|
|
@ -16,6 +16,7 @@ class DenoIsolate {
|
|||
DenoIsolate(deno_buf snapshot, deno_recv_cb cb)
|
||||
: isolate_(nullptr),
|
||||
current_args_(nullptr),
|
||||
snapshot_creator_(nullptr),
|
||||
global_import_buf_ptr_(nullptr),
|
||||
pending_promise_events_(0),
|
||||
cb_(cb),
|
||||
|
@ -30,8 +31,8 @@ class DenoIsolate {
|
|||
void AddIsolate(v8::Isolate* isolate);
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
// Put v8::Isolate::CreateParams here..
|
||||
const v8::FunctionCallbackInfo<v8::Value>* current_args_;
|
||||
v8::SnapshotCreator* snapshot_creator_;
|
||||
void* global_import_buf_ptr_;
|
||||
int32_t pending_promise_events_;
|
||||
deno_recv_cb cb_;
|
||||
|
@ -86,11 +87,13 @@ static intptr_t external_references[] = {
|
|||
reinterpret_cast<intptr_t>(SetPromiseErrorExaminer),
|
||||
0};
|
||||
|
||||
static const deno_buf empty_buf = {nullptr, 0, nullptr, 0};
|
||||
|
||||
Deno* NewFromSnapshot(void* user_data, deno_recv_cb cb);
|
||||
|
||||
void InitializeContext(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
||||
const char* js_filename, const std::string& js_source,
|
||||
const std::string* source_map);
|
||||
const char* js_filename, const char* js_source,
|
||||
const char* source_map);
|
||||
|
||||
void HandleException(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Value> exception);
|
||||
|
@ -98,6 +101,9 @@ void HandleException(v8::Local<v8::Context> context,
|
|||
void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
v8::StartupData payload, void* data);
|
||||
|
||||
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
void* data);
|
||||
|
||||
v8::Local<v8::Uint8Array> ImportBuf(DenoIsolate* d, deno_buf buf);
|
||||
|
||||
void DeleteDataRef(DenoIsolate* d, int32_t req_id);
|
||||
|
|
|
@ -16,6 +16,17 @@ TEST(LibDenoTest, InitializesCorrectlyWithoutSnapshot) {
|
|||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(LibDenoTest, Snapshotter) {
|
||||
Deno* d1 = deno_new_snapshotter(nullptr, "a.js", "a = 1 + 2", nullptr);
|
||||
deno_buf test_snapshot = deno_get_snapshot(d1);
|
||||
// TODO(ry) deno_delete(d1);
|
||||
|
||||
Deno* d2 = deno_new(test_snapshot, nullptr);
|
||||
EXPECT_TRUE(
|
||||
deno_execute(d2, nullptr, "b.js", "if (a != 3) throw Error('x');"));
|
||||
deno_delete(d2);
|
||||
}
|
||||
|
||||
TEST(LibDenoTest, CanCallFunction) {
|
||||
Deno* d = deno_new(snapshot, nullptr);
|
||||
EXPECT_TRUE(deno_execute(d, nullptr, "a.js",
|
||||
|
|
|
@ -7,42 +7,7 @@
|
|||
#include "third_party/v8/include/v8.h"
|
||||
#include "third_party/v8/src/base/logging.h"
|
||||
|
||||
namespace deno {
|
||||
|
||||
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
void* data) {
|
||||
DCHECK_EQ(data, nullptr);
|
||||
InternalFieldData* embedder_field = static_cast<InternalFieldData*>(
|
||||
holder->GetAlignedPointerFromInternalField(index));
|
||||
if (embedder_field == nullptr) return {nullptr, 0};
|
||||
int size = sizeof(*embedder_field);
|
||||
char* payload = new char[size];
|
||||
// We simply use memcpy to serialize the content.
|
||||
memcpy(payload, embedder_field, size);
|
||||
return {payload, size};
|
||||
}
|
||||
|
||||
v8::StartupData MakeSnapshot(const char* js_filename,
|
||||
const std::string& js_source,
|
||||
const std::string* source_map) {
|
||||
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);
|
||||
InitializeContext(isolate, context, js_filename, js_source, source_map);
|
||||
creator->SetDefaultContext(context, v8::SerializeInternalFieldsCallback(
|
||||
SerializeInternalFields, nullptr));
|
||||
}
|
||||
|
||||
auto snapshot_blob =
|
||||
creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
||||
|
||||
return snapshot_blob;
|
||||
}
|
||||
|
||||
} // namespace deno
|
||||
namespace deno {} // namespace deno
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char* snapshot_out_bin = argv[1];
|
||||
|
@ -64,9 +29,13 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
deno_init();
|
||||
auto snapshot_blob = deno::MakeSnapshot(
|
||||
js_fn, js_source, source_map_fn != nullptr ? &source_map : nullptr);
|
||||
std::string snapshot_str(snapshot_blob.data, snapshot_blob.raw_size);
|
||||
Deno* d = deno_new_snapshotter(
|
||||
nullptr, js_fn, js_source.c_str(),
|
||||
source_map_fn != nullptr ? source_map.c_str() : nullptr);
|
||||
|
||||
auto snapshot = deno_get_snapshot(d);
|
||||
std::string snapshot_str(reinterpret_cast<char*>(snapshot.data_ptr),
|
||||
snapshot.data_len);
|
||||
|
||||
std::ofstream file_(snapshot_out_bin, std::ios::binary);
|
||||
file_ << snapshot_str;
|
||||
|
|
Loading…
Reference in a new issue