summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2019-06-04 19:35:51 +0200
committerRyan Dahl <ry@tinyclouds.org>2019-07-08 18:18:28 -0400
commitd641782c823317a2d2f64d646a0d5b8b6c22b771 (patch)
treea03beb0939a46333636d0de68eee052978103cfe
parent79c3439f269f1e0e24003518e363988fa4f1da33 (diff)
Rewrite snapshot_creator in Rust
-rw-r--r--cli/BUILD.gn2
-rw-r--r--cli/deno.gni (renamed from deno.gni)6
-rw-r--r--core/BUILD.gn12
-rw-r--r--core/Cargo.toml4
-rw-r--r--core/libdeno/BUILD.gn27
-rw-r--r--core/libdeno/api.cc1
-rw-r--r--core/libdeno/file_util.cc90
-rw-r--r--core/libdeno/file_util.h14
-rw-r--r--core/libdeno/file_util_test.cc46
-rw-r--r--core/libdeno/snapshot_creator.cc46
-rw-r--r--core/libdeno/test.cc46
-rw-r--r--core/snapshot_creator.rs44
12 files changed, 98 insertions, 240 deletions
diff --git a/cli/BUILD.gn b/cli/BUILD.gn
index 20a5b2dee..7f19f8b95 100644
--- a/cli/BUILD.gn
+++ b/cli/BUILD.gn
@@ -5,7 +5,7 @@ import("//build_extra/flatbuffers/rust/rust_flatbuffer.gni")
import("//build_extra/rust/rust.gni")
import("//third_party/v8/gni/snapshot_toolchain.gni")
import("//third_party/v8/gni/v8.gni")
-import("../deno.gni")
+import("deno.gni")
main_extern = [
{
diff --git a/deno.gni b/cli/deno.gni
index a260edd11..dabcd43ca 100644
--- a/deno.gni
+++ b/cli/deno.gni
@@ -16,7 +16,8 @@ template("bundle") {
]
depfile = out_dir + out_name + ".d"
args = [
- rebase_path("//third_party/node_modules/rollup/bin/rollup", root_build_dir),
+ rebase_path("//third_party/node_modules/rollup/bin/rollup",
+ root_build_dir),
"-c",
rebase_path("//rollup.config.js", root_build_dir),
"-i",
@@ -45,8 +46,7 @@ template("snapshot") {
"testonly",
"deps",
])
- # TODO(ry) Rewrite snapshot_creator in Rust.
- tool = "//core/libdeno:snapshot_creator"
+ tool = "//core:snapshot_creator"
visibility = [ ":*" ] # Only targets in this file can depend on this.
snapshot_out_bin = "$target_gen_dir/$target_name.bin"
inputs = [
diff --git a/core/BUILD.gn b/core/BUILD.gn
index bf9d910c0..0f1eba8ca 100644
--- a/core/BUILD.gn
+++ b/core/BUILD.gn
@@ -7,6 +7,7 @@ group("default") {
":deno_core_http_bench",
":deno_core_http_bench_test",
":deno_core_test",
+ ":snapshot_creator",
]
}
@@ -77,3 +78,14 @@ rust_test("deno_core_http_bench_test") {
extern = http_bench_extern
extern_rlib = http_bench_extern_rlib
}
+
+rust_executable("snapshot_creator") {
+ source_root = "snapshot_creator.rs"
+ extern = [
+ {
+ label = ":deno"
+ crate_name = "deno"
+ crate_type = "rlib"
+ },
+ ]
+}
diff --git a/core/Cargo.toml b/core/Cargo.toml
index b22bf7fe9..c41863da0 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -13,6 +13,10 @@ repository = "https://github.com/denoland/deno"
[lib]
path = "lib.rs"
+[[bin]]
+name = "snapshot_creator"
+path = "snapshot_creator.rs"
+
[dependencies]
futures = "0.1.27"
lazy_static = "1.3.0"
diff --git a/core/libdeno/BUILD.gn b/core/libdeno/BUILD.gn
index 31a5be640..10ec4bf91 100644
--- a/core/libdeno/BUILD.gn
+++ b/core/libdeno/BUILD.gn
@@ -1,5 +1,4 @@
# Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-import("//deno.gni")
import("//third_party/v8/gni/v8.gni")
config("deno_config") {
@@ -50,8 +49,6 @@ v8_source_set("libdeno") {
"deno.h",
"exceptions.cc",
"exceptions.h",
- "file_util.cc",
- "file_util.h",
"internal.h",
"modules.cc",
]
@@ -71,39 +68,21 @@ v8_static_library("libdeno_static_lib") {
configs = [ ":deno_config" ]
}
-v8_executable("snapshot_creator") {
- sources = [
- "snapshot_creator.cc",
- ]
- deps = [
- ":libdeno",
- ]
- configs = [ ":deno_config" ]
-}
-
v8_executable("libdeno_test") {
testonly = true
sources = [
- "file_util_test.cc",
"libdeno_test.cc",
"modules_test.cc",
"test.cc",
]
deps = [
":libdeno",
- ":snapshot_test",
"//testing/gtest:gtest",
]
data = [
- "$target_gen_dir/snapshot_test.bin",
+ "libdeno_test.js",
]
- snapshot_path = rebase_path(data[0], root_build_dir)
- defines = [ "SNAPSHOT_PATH=\"$snapshot_path\"" ]
+ js_path = rebase_path(data[0])
+ defines = [ "JS_PATH=\"$js_path\"" ]
configs = [ ":deno_config" ]
}
-
-# Generates $target_gen_dir/snapshot_test.bin
-snapshot("snapshot_test") {
- testonly = true
- source_root = "libdeno_test.js"
-}
diff --git a/core/libdeno/api.cc b/core/libdeno/api.cc
index 13057aeae..1515bca51 100644
--- a/core/libdeno/api.cc
+++ b/core/libdeno/api.cc
@@ -11,7 +11,6 @@
#include "deno.h"
#include "exceptions.h"
-#include "file_util.h"
#include "internal.h"
extern "C" {
diff --git a/core/libdeno/file_util.cc b/core/libdeno/file_util.cc
deleted file mode 100644
index 256f4f257..000000000
--- a/core/libdeno/file_util.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-#include <inttypes.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <fstream>
-#include <iterator>
-#include <string>
-
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include "file_util.h"
-
-namespace deno {
-
-bool ReadFileToString(const char* fn, std::string* contents) {
- std::ifstream file(fn, std::ios::binary);
- if (file.fail()) {
- return false;
- }
- contents->assign(std::istreambuf_iterator<char>{file}, {});
- return !file.fail();
-}
-
-std::string Basename(std::string const& filename) {
- for (auto it = filename.rbegin(); it != filename.rend(); ++it) {
- char ch = *it;
- if (ch == '\\' || ch == '/') {
- return std::string(it.base(), filename.end());
- }
- }
- return filename;
-}
-
-// Returns the directory component from a filename. The returned path always
-// ends with a slash. This function does not understand Windows drive letters.
-std::string Dirname(std::string const& filename) {
- for (auto it = filename.rbegin(); it != filename.rend(); ++it) {
- char ch = *it;
- if (ch == '\\' || ch == '/') {
- return std::string(filename.begin(), it.base());
- }
- }
- return std::string("./");
-}
-
-// Returns the full path the currently running executable.
-// This implementation is very basic. Caveats:
-// * OS X: fails if buffer is too small, does not retry with a bigger buffer.
-// * Windows: ANSI only, no unicode. Fails if path is longer than 260 chars.
-bool ExePath(std::string* path) {
-#ifdef _WIN32
- // Windows only.
- char exe_buf[MAX_PATH];
- DWORD len = GetModuleFileNameA(NULL, exe_buf, sizeof exe_buf);
- if (len == 0 || len == sizeof exe_buf) {
- return false;
- }
-#else
-#ifdef __APPLE__
- // OS X only.
- char link_buf[PATH_MAX * 2]; // Exe may be longer than MAX_PATH, says Apple.
- uint32_t len = sizeof link_buf;
- if (_NSGetExecutablePath(link_buf, &len) < 0) {
- return false;
- }
-#else
- // Linux only.
- static const char* link_buf = "/proc/self/exe";
-#endif
- // Linux and OS X.
- char exe_buf[PATH_MAX];
- char* r = realpath(link_buf, exe_buf);
- if (r == NULL) {
- return false;
- }
-#endif
- // All platforms.
- path->assign(exe_buf);
- return true;
-}
-
-} // namespace deno
diff --git a/core/libdeno/file_util.h b/core/libdeno/file_util.h
deleted file mode 100644
index 0177f2c94..000000000
--- a/core/libdeno/file_util.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-#ifndef FILE_UTIL_H_
-#define FILE_UTIL_H_
-
-#include <string>
-
-namespace deno {
-bool ReadFileToString(const char* fn, std::string* contents);
-std::string Basename(std::string const& filename);
-std::string Dirname(std::string const& filename);
-bool ExePath(std::string* path);
-} // namespace deno
-
-#endif // FILE_UTIL_H_
diff --git a/core/libdeno/file_util_test.cc b/core/libdeno/file_util_test.cc
deleted file mode 100644
index 863a31d48..000000000
--- a/core/libdeno/file_util_test.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "file_util.h"
-
-TEST(FileUtilTest, ReadFileToStringFileNotExist) {
- std::string output;
- EXPECT_FALSE(deno::ReadFileToString("/should_error_out.txt", &output));
-}
-
-TEST(FileUtilTest, Basename) {
- EXPECT_EQ("foo.txt", deno::Basename("foo.txt"));
- EXPECT_EQ("foo.txt", deno::Basename("/foo.txt"));
- EXPECT_EQ("", deno::Basename("/foo/"));
- EXPECT_EQ("", deno::Basename("foo/"));
- EXPECT_EQ("", deno::Basename("/"));
- EXPECT_EQ("foo.txt", deno::Basename(".\\foo.txt"));
- EXPECT_EQ("foo.txt", deno::Basename("/home/ryan/foo.txt"));
- EXPECT_EQ("foo.txt", deno::Basename("C:\\home\\ryan\\foo.txt"));
-}
-
-TEST(FileUtilTest, Dirname) {
- EXPECT_EQ("home/dank/", deno::Dirname("home/dank/memes.gif"));
- EXPECT_EQ("/home/dank/", deno::Dirname("/home/dank/memes.gif"));
- EXPECT_EQ("/home/dank/", deno::Dirname("/home/dank/"));
- EXPECT_EQ("home/dank/", deno::Dirname("home/dank/memes.gif"));
- EXPECT_EQ("/", deno::Dirname("/"));
- EXPECT_EQ(".\\", deno::Dirname(".\\memes.gif"));
- EXPECT_EQ("c:\\", deno::Dirname("c:\\stuff"));
- EXPECT_EQ("./", deno::Dirname("nothing"));
- EXPECT_EQ("./", deno::Dirname(""));
-}
-
-TEST(FileUtilTest, ExePath) {
- std::string exe_path;
- EXPECT_TRUE(deno::ExePath(&exe_path));
- // Path is absolute.
- EXPECT_TRUE(exe_path.find("/") == 0 || exe_path.find(":\\") == 1);
- // FIlename is the name of the test binary.
- std::string exe_filename = deno::Basename(exe_path);
- EXPECT_EQ(exe_filename.find("libdeno_test"), 0u);
- // Path exists (also tests ReadFileToString).
- std::string contents;
- EXPECT_TRUE(deno::ReadFileToString(exe_path.c_str(), &contents));
- EXPECT_NE(contents.find("Inception :)"), std::string::npos);
-}
diff --git a/core/libdeno/snapshot_creator.cc b/core/libdeno/snapshot_creator.cc
deleted file mode 100644
index bd3c8081d..000000000
--- a/core/libdeno/snapshot_creator.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-// Hint: --trace_serializer is a useful debugging flag.
-#include <fstream>
-#include <iostream>
-#include "deno.h"
-#include "file_util.h"
-#include "internal.h"
-#include "third_party/v8/include/v8.h"
-#include "third_party/v8/src/base/logging.h"
-
-int main(int argc, char** argv) {
- const char* snapshot_out_bin = argv[1];
- const char* js_fn = argv[2];
-
- deno_set_v8_flags(&argc, argv);
-
- CHECK_NOT_NULL(js_fn);
- CHECK_NOT_NULL(snapshot_out_bin);
-
- std::string js_source;
- CHECK(deno::ReadFileToString(js_fn, &js_source));
-
- deno_init();
- deno_config config = {1, deno::empty_snapshot, deno::empty_buf, nullptr,
- nullptr};
- Deno* d = deno_new(config);
-
- deno_execute(d, nullptr, js_fn, js_source.c_str());
- if (deno_last_exception(d) != nullptr) {
- std::cerr << "Snapshot Exception " << std::endl;
- std::cerr << deno_last_exception(d) << std::endl;
- deno_delete(d);
- return 1;
- }
-
- auto snapshot = deno_snapshot_new(d);
-
- std::ofstream file_(snapshot_out_bin, std::ios::binary);
- file_.write(reinterpret_cast<char*>(snapshot.data_ptr), snapshot.data_len);
- file_.close();
-
- deno_snapshot_delete(snapshot);
- deno_delete(d);
-
- return file_.bad();
-}
diff --git a/core/libdeno/test.cc b/core/libdeno/test.cc
index 3d022c904..0bfe374ef 100644
--- a/core/libdeno/test.cc
+++ b/core/libdeno/test.cc
@@ -1,28 +1,44 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
#include "test.h"
+#include <fstream>
#include <string>
-#include "file_util.h"
+#include "internal.h"
deno_snapshot snapshot = {nullptr, 0};
-int main(int argc, char** argv) {
- // Locate the snapshot.
- std::string exe_path;
- if (!deno::ExePath(&exe_path)) {
- std::cerr << "deno::ExePath() failed" << std::endl;
- return 1;
+bool ReadFileToString(const char* fn, std::string* contents) {
+ std::ifstream file(fn, std::ios::binary);
+ if (file.fail()) {
+ return false;
}
- std::string snapshot_path = deno::Dirname(exe_path) + SNAPSHOT_PATH;
+ contents->assign(std::istreambuf_iterator<char>{file}, {});
+ return !file.fail();
+}
+
+int main(int argc, char** argv) {
+ // All of the JS code in libdeno_test.js is tested after being snapshotted.
+ // We create that snapshot now at runtime, rather than at compile time to
+ // simplify the build process. So we load and execute the libdeno_test.js
+ // file, without running any of the tests and store the result in the global
+ // "snapshot" variable, which will be used later in the tests.
+ std::string js_fn = JS_PATH;
+ std::string js_source;
+ CHECK(ReadFileToString(js_fn.c_str(), &js_source));
+
+ deno_init();
+ deno_config config = {1, deno::empty_snapshot, deno::empty_buf, nullptr,
+ nullptr};
+ Deno* d = deno_new(config);
- // Load the snapshot.
- std::string contents;
- if (!deno::ReadFileToString(snapshot_path.c_str(), &contents)) {
- std::cerr << "Failed to read snapshot from " << snapshot_path << std::endl;
+ deno_execute(d, nullptr, js_fn.c_str(), js_source.c_str());
+ if (deno_last_exception(d) != nullptr) {
+ std::cerr << "Snapshot Exception " << std::endl;
+ std::cerr << deno_last_exception(d) << std::endl;
+ deno_delete(d);
return 1;
}
- snapshot.data_ptr =
- reinterpret_cast<uint8_t*>(const_cast<char*>(contents.c_str()));
- snapshot.data_len = contents.size();
+
+ snapshot = deno_snapshot_new(d);
testing::InitGoogleTest(&argc, argv);
deno_init();
diff --git a/core/snapshot_creator.rs b/core/snapshot_creator.rs
new file mode 100644
index 000000000..1d43b9174
--- /dev/null
+++ b/core/snapshot_creator.rs
@@ -0,0 +1,44 @@
+// Note: This is a nearly identical rewrite of core/libdeno/snapshot_creator.cc
+// but in Rust.
+//
+// This snapshot program is considered "basic" because the code being
+// snapshotted cannot call ops.
+
+extern crate deno;
+
+use deno::js_check;
+use deno::Isolate;
+use deno::StartupData;
+use std::env;
+use std::io::Write;
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+ // NOTE: `--help` arg will display V8 help and exit
+ let args = deno::v8_set_flags(args);
+
+ let (snapshot_out_bin, js_filename) = if args.len() == 3 {
+ (args[1].clone(), args[2].clone())
+ } else {
+ eprintln!("Usage: snapshot_creator <out_filename> <js_filename>");
+ std::process::exit(1);
+ };
+
+ let js_source =
+ std::fs::read(&js_filename).expect("couldn't read js_filename");
+ let js_source_str = std::str::from_utf8(&js_source).unwrap();
+
+ let will_snapshot = true;
+ let mut isolate = Isolate::new(StartupData::None, will_snapshot);
+
+ js_check(isolate.execute(&js_filename, js_source_str));
+
+ let snapshot = isolate.snapshot().expect("error snapshotting");
+
+ let mut out_file = std::fs::File::create(snapshot_out_bin).unwrap();
+ let snapshot_slice =
+ unsafe { std::slice::from_raw_parts(snapshot.data_ptr, snapshot.data_len) };
+ out_file
+ .write_all(snapshot_slice)
+ .expect("Failed to write snapshot file");
+}