// Copyright 2018 Ryan Dahl // All rights reserved. MIT License. #include #include #include #include #include #include #include "v8/include/v8.h" #include "include/deno.h" #include "./deno_internal.h" class StartupDataCppWriter { public: StartupDataCppWriter(const char* name, const char* filename, v8::StartupData sd) : name_(name), filename_(filename), sd_(sd), file_(filename_, std::ios::binary) {} void Write() { WritePrefix(); WriteData(); WriteSuffix(); file_.close(); if (file_.bad()) { printf("Unable to open file \"%s\" for writing.\n", filename_); exit(1); } printf("Wrote %s %d %s \n", name_, sd_.raw_size, filename_); } private: void WritePrefix() { file_ << "// Autogenerated snapshot file. Do not edit.\n\n"; file_ << "#include \"v8/include/v8.h\"\n\n"; } void WriteSuffix() { char buffer[500]; snprintf(buffer, sizeof(buffer), "const v8::StartupData* StartupBlob_%s() {\n", name_); file_ << buffer; snprintf(buffer, sizeof(buffer), " return &%s_blob;\n", name_); file_ << buffer; file_ << "}\n\n"; } void WriteBinaryContentsAsCArray() { char buffer[5]; for (int i = 0; i < sd_.raw_size; i++) { if ((i & 0x1F) == 0x1F) file_ << "\n"; if (i > 0) file_ << ","; snprintf(buffer, sizeof(buffer), "%u", static_cast(sd_.data[i])); file_ << buffer; } file_ << "\n"; } void WriteData() { char buffer[500]; snprintf(buffer, sizeof(buffer), "static const char %s_blob_data[] = {\n", name_); file_ << buffer; WriteBinaryContentsAsCArray(); file_ << "};\n"; snprintf(buffer, sizeof(buffer), "static const int %s_blob_size = %d;\n", name_, sd_.raw_size); file_ << buffer; snprintf(buffer, sizeof(buffer), "static const v8::StartupData %s_blob =\n", name_); file_ << buffer; snprintf(buffer, sizeof(buffer), "{ (const char*) %s_blob_data, %s_blob_size };\n", name_, name_); file_ << buffer; } const char* name_; const char* filename_; v8::StartupData sd_; std::ofstream file_; }; // Caller must free returned value. static v8::StartupData ReadFile(const char* fn) { std::ifstream input(fn, std::ios::binary); if (input.bad()) { printf("Error reading %s\n", fn); exit(1); } // Note the allocated buffer is intentionally not freed in this program. // It may show up as a memory leak some day, but other than that it's // harmless. auto* buffer = new std::vector((std::istreambuf_iterator(input)), (std::istreambuf_iterator())); v8::StartupData sd; sd.data = buffer->data(); sd.raw_size = static_cast(buffer->size()); if (input.bad()) { printf("Error reading %s\n", fn); exit(1); } return sd; } void WriteFile(const char* fn, v8::StartupData startup_data) { std::ofstream output(fn, std::ios::binary); output.write(startup_data.data, startup_data.raw_size); output.close(); if (output.bad()) { printf("Error writing %s\n", fn); exit(1); } } int main(int argc, char** argv) { // The only documentation for this programs arguments is right here. const char* js_fn = argv[1]; const char* natives_in_bin = argv[2]; const char* snapshot_in_bin = argv[3]; const char* natives_out_cc = argv[4]; const char* snapshot_out_cc = argv[5]; auto js_data = ReadFile(js_fn); 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); StartupDataCppWriter nativesWriter("natives", natives_out_cc, natives_blob); nativesWriter.Write(); StartupDataCppWriter snapshotWriter("snapshot", snapshot_out_cc, snapshot_blob); snapshotWriter.Write(); }