mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
Merge branch 'deno2'
This commit is contained in:
commit
5c7ba22f22
33 changed files with 6811 additions and 2 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -4,5 +4,5 @@ dist/
|
|||
deno
|
||||
assets.go
|
||||
msg.pb.go
|
||||
msg.pb.js
|
||||
msg.pb.d.ts
|
||||
/msg.pb.js
|
||||
/msg.pb.d.ts
|
||||
|
|
37
deno2/.gclient
Normal file
37
deno2/.gclient
Normal file
|
@ -0,0 +1,37 @@
|
|||
solutions = [{
|
||||
'url': 'https://chromium.googlesource.com/v8/v8.git@2530a044126ae6a1d3dff0d8c61999762847d9f0',
|
||||
'custom_vars': {
|
||||
'build_for_node': True
|
||||
},
|
||||
'name': 'v8',
|
||||
'deps_file': 'DEPS',
|
||||
'custom_deps': {
|
||||
'v8/third_party/catapult': None,
|
||||
'v8/third_party/colorama/src': None,
|
||||
'v8/testing/gmock': None,
|
||||
'v8/tools/swarming_client': None,
|
||||
'v8/third_party/instrumented_libraries': None,
|
||||
'v8/third_party/android_tools': None,
|
||||
'v8/test/wasm-js': None,
|
||||
'v8/test/benchmarks/data': None,
|
||||
'v8/test/mozilla/data': None,
|
||||
'v8/third_party/icu': None,
|
||||
'v8/test/test262/data': None,
|
||||
'v8/test/test262/harness': None,
|
||||
'v8/tools/luci-go': None
|
||||
}
|
||||
}, {
|
||||
'url': 'https://github.com/ry/protobuf_chromium.git@e62249df45c2a0a9c38e4017e8ab604020b986c5',
|
||||
'name': 'third_party/protobuf',
|
||||
'deps_file': 'DEPS'
|
||||
}, {
|
||||
'url':
|
||||
'https://chromium.googlesource.com/chromium/src/tools/protoc_wrapper@9af82fef8cb9ca3ccc13e2ed958f58f2c21f449b',
|
||||
'name':
|
||||
'tools/protoc_wrapper'
|
||||
}, {
|
||||
'url':
|
||||
'https://chromium.googlesource.com/chromium/src/third_party/zlib@39b4a6260702da4c089eca57136abf40a39667e9',
|
||||
'name':
|
||||
'third_party/zlib'
|
||||
}]
|
8
deno2/.gitignore
vendored
Normal file
8
deno2/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
out/
|
||||
js/.cache/
|
||||
js/node_modules/
|
||||
v8/
|
||||
tools/protoc_wrapper/
|
||||
third_party/protobuf/
|
||||
third_party/zlib/
|
||||
.gclient_entries
|
61
deno2/.gn
Normal file
61
deno2/.gn
Normal file
|
@ -0,0 +1,61 @@
|
|||
# This file is used by the GN meta build system to find the root of the source
|
||||
# tree and to set startup options. For documentation on the values set in this
|
||||
# file, run "gn help dotfile" at the command line.
|
||||
|
||||
import("//v8/build/dotfile_settings.gni")
|
||||
|
||||
# The location of the build configuration file.
|
||||
buildconfig = "//v8/build/config/BUILDCONFIG.gn"
|
||||
|
||||
# The secondary source root is a parallel directory tree where
|
||||
# GN build files are placed when they can not be placed directly
|
||||
# in the source tree, e.g. for third party source trees.
|
||||
secondary_source = "//v8/"
|
||||
|
||||
# These are the targets to check headers for by default. The files in targets
|
||||
# matching these patterns (see "gn help label_pattern" for format) will have
|
||||
# their includes checked for proper dependencies when you run either
|
||||
# "gn check" or "gn gen --check".
|
||||
check_targets = []
|
||||
|
||||
# These are the list of GN files that run exec_script. This whitelist exists
|
||||
# to force additional review for new uses of exec_script, which is strongly
|
||||
# discouraged except for gypi_to_gn calls.
|
||||
exec_script_whitelist = build_dotfile_settings.exec_script_whitelist + []
|
||||
|
||||
default_args = {
|
||||
# Default to release builds for this project.
|
||||
is_component_build = false
|
||||
is_debug = false
|
||||
libcpp_is_static = false
|
||||
symbol_level = 1
|
||||
treat_warnings_as_errors = false
|
||||
use_custom_libcxx = false
|
||||
use_sysroot = false
|
||||
v8_deprecation_warnings = false
|
||||
|
||||
#v8_embedder_string = ""
|
||||
v8_enable_gdbjit = false
|
||||
v8_enable_i18n_support = false
|
||||
v8_enable_test_features = false
|
||||
v8_experimental_extra_library_files = []
|
||||
v8_extra_library_files = []
|
||||
v8_imminent_deprecation_warnings = false
|
||||
v8_monolithic = false
|
||||
v8_static_library = false
|
||||
v8_target_cpu = "x64"
|
||||
v8_untrusted_code_mitigations = false
|
||||
|
||||
# This tells V8 to write out/Default/gen/v8/snapshot.bin
|
||||
# Which we can use to build our own snapshot.
|
||||
v8_use_external_startup_data = true
|
||||
v8_use_snapshot = true
|
||||
|
||||
# Snapshot the dist/main.js bundle into V8.
|
||||
# Is ".gn" really the most appropriate place to specify this important
|
||||
# value? This is how they do it in Chrome.
|
||||
# https://cs.chromium.org/chromium/src/.gn?l=37&rcl=f1c8c3cf8bd4a63da6433ee67e2ff5ecbbdb4316
|
||||
|
||||
# "$target_gen_dir/main.js"
|
||||
#]
|
||||
}
|
216
deno2/BUILD.gn
Normal file
216
deno2/BUILD.gn
Normal file
|
@ -0,0 +1,216 @@
|
|||
import("//third_party/protobuf/proto_library.gni")
|
||||
import("//v8/gni/v8.gni")
|
||||
import("//v8/snapshot_toolchain.gni")
|
||||
|
||||
executable("deno") {
|
||||
sources = [
|
||||
"main.cc",
|
||||
]
|
||||
deps = [
|
||||
":libdeno",
|
||||
]
|
||||
}
|
||||
|
||||
executable("mock_runtime_test") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"from_snapshot.cc",
|
||||
"mock_runtime_test.cc",
|
||||
]
|
||||
deps = [
|
||||
":create_snapshot_mock_runtime",
|
||||
":deno_nosnapshot",
|
||||
"//testing/gtest:gtest",
|
||||
]
|
||||
include_dirs = [ target_gen_dir ]
|
||||
defines = [ "DENO_MOCK_RUNTIME" ]
|
||||
}
|
||||
|
||||
component("libdeno") {
|
||||
sources = [
|
||||
"from_snapshot.cc",
|
||||
]
|
||||
deps = [
|
||||
":create_snapshot_deno",
|
||||
":deno_nosnapshot",
|
||||
]
|
||||
include_dirs = [ target_gen_dir ]
|
||||
}
|
||||
|
||||
source_set("deno_nosnapshot") {
|
||||
sources = [
|
||||
"deno.cc",
|
||||
"deno_internal.h",
|
||||
"include/deno.h",
|
||||
]
|
||||
include_dirs = [ "include/" ]
|
||||
deps = [
|
||||
":msg_proto",
|
||||
"v8:v8",
|
||||
"v8:v8_libbase",
|
||||
"v8:v8_libplatform",
|
||||
"v8:v8_libsampler",
|
||||
]
|
||||
}
|
||||
|
||||
executable("snapshot_creator") {
|
||||
sources = [
|
||||
"snapshot_creator.cc",
|
||||
]
|
||||
deps = [
|
||||
":deno_nosnapshot",
|
||||
]
|
||||
}
|
||||
|
||||
proto_library("msg_proto") {
|
||||
sources = [
|
||||
"msg.proto",
|
||||
]
|
||||
}
|
||||
|
||||
template("run_node") {
|
||||
action(target_name) {
|
||||
forward_variables_from(invoker, "*")
|
||||
script = "js/run_node.py"
|
||||
}
|
||||
}
|
||||
|
||||
run_node("bundle") {
|
||||
out_dir = "$target_gen_dir/bundle/"
|
||||
sources = [
|
||||
"$target_gen_dir/tsc_dist/main.js", # Not real input. See run_tsc comment.
|
||||
"js/main.ts",
|
||||
]
|
||||
outputs = [
|
||||
out_dir + "main.js",
|
||||
]
|
||||
deps = [
|
||||
":run_tsc",
|
||||
]
|
||||
args = [
|
||||
"./node_modules/parcel-bundler/bin/cli.js",
|
||||
"build",
|
||||
"--no-minify",
|
||||
"--out-dir",
|
||||
rebase_path(out_dir, root_build_dir),
|
||||
rebase_path("js/main.ts", root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
# Due to bugs in Parcel we must run TSC independently in order to catch errors.
|
||||
# https://github.com/parcel-bundler/parcel/issues/954
|
||||
run_node("run_tsc") {
|
||||
main = "js/main.ts"
|
||||
tsconfig = "js/tsconfig.json"
|
||||
out_dir = "$target_gen_dir/tsc_dist/"
|
||||
sources = [
|
||||
"js/msg.pb.d.ts",
|
||||
"js/msg.pb.js",
|
||||
main,
|
||||
tsconfig,
|
||||
]
|
||||
outputs = [
|
||||
out_dir + "/main.js",
|
||||
out_dir + "/main.map",
|
||||
]
|
||||
deps = [
|
||||
":protobufjs",
|
||||
]
|
||||
args = [
|
||||
"./node_modules/typescript/bin/tsc",
|
||||
"--project",
|
||||
rebase_path(tsconfig, root_build_dir),
|
||||
"--outDir",
|
||||
rebase_path(out_dir, root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
# Generates protobufjs code.
|
||||
# TODO(ry) Ideally protobufjs output files should be written into
|
||||
# target_gen_dir, but its difficult to get this working in a way that the
|
||||
# bundler can resolve their location. (The bundler does not support NODE_PATH?)
|
||||
# Therefore this hack: write the generated msg.pb.js and msg.pb.d.ts outputs
|
||||
# into the js/ folder, and we check them into the repo. Hopefully this hack can
|
||||
# be removed at some point. If msg.proto is changed, commit changes to the
|
||||
# generated JS files. The stamp file is just to make gn work.
|
||||
action("protobufjs") {
|
||||
script = "js/pbjs_hack.py"
|
||||
sources = [
|
||||
"msg.proto",
|
||||
]
|
||||
outputs = [
|
||||
"$target_gen_dir/pbjs_hack.stamp",
|
||||
]
|
||||
args = [
|
||||
rebase_path(sources[0], root_build_dir),
|
||||
rebase_path(outputs[0], root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
# Template to generate different V8 snapshots based on different runtime flags.
|
||||
# Can be invoked with run_mksnapshot(<name>). The target will resolve to
|
||||
# run_mksnapshot_<name>. If <name> is "default", no file suffixes will be used.
|
||||
# Otherwise files are suffixed, e.g. embedded_<name>.cc and
|
||||
# snapshot_blob_<name>.bin.
|
||||
#
|
||||
# The template exposes the variables:
|
||||
# args: additional flags for mksnapshots
|
||||
# embedded_suffix: a camel case suffix for method names in the embedded
|
||||
# snapshot.
|
||||
template("create_snapshot") {
|
||||
name = target_name
|
||||
suffix = "_$name"
|
||||
action("create_snapshot_" + name) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"testonly",
|
||||
"deps",
|
||||
])
|
||||
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||
deps += [ ":snapshot_creator" ]
|
||||
script = "v8/tools/run.py"
|
||||
data = []
|
||||
exe = rebase_path(get_label_info(":snapshot_creator", "root_out_dir") +
|
||||
"/snapshot_creator")
|
||||
natives_in_bin = "$root_out_dir/natives_blob.bin"
|
||||
snapshot_in_bin = "$root_out_dir/snapshot_blob.bin"
|
||||
natives_out_cc = "$target_gen_dir/natives${suffix}.cc"
|
||||
snapshot_out_cc = "$target_gen_dir/snapshot${suffix}.cc"
|
||||
sources = [
|
||||
invoker.js,
|
||||
]
|
||||
outputs = [
|
||||
natives_out_cc,
|
||||
snapshot_out_cc,
|
||||
]
|
||||
args = [
|
||||
exe,
|
||||
rebase_path(invoker.js, root_build_dir),
|
||||
rebase_path(natives_in_bin, root_build_dir),
|
||||
rebase_path(snapshot_in_bin, root_build_dir),
|
||||
rebase_path(natives_out_cc, root_build_dir),
|
||||
rebase_path(snapshot_out_cc, root_build_dir),
|
||||
]
|
||||
|
||||
# To debug snapshotting problems:
|
||||
# args += ["--trace-serializer"]
|
||||
data = [
|
||||
invoker.js,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# Generates $target_gen_dir/snapshot_deno.cc
|
||||
create_snapshot("deno") {
|
||||
js = "$target_gen_dir/bundle/main.js"
|
||||
deps = [
|
||||
":bundle",
|
||||
]
|
||||
}
|
||||
|
||||
# Generates $target_gen_dir/snapshot_mock_runtime.cc
|
||||
create_snapshot("mock_runtime") {
|
||||
testonly = true
|
||||
js = "js/mock_runtime.js"
|
||||
deps = []
|
||||
}
|
68
deno2/README.md
Normal file
68
deno2/README.md
Normal file
|
@ -0,0 +1,68 @@
|
|||
# Deno Prototype 2
|
||||
|
||||
## Status
|
||||
|
||||
This code is a rewrite of the unprivileged parts of Deno. It will soon become
|
||||
the root of the project.
|
||||
|
||||
There are several goals:
|
||||
|
||||
* Use the gn build system for fast builds, sane configuration, and easy
|
||||
linking into Chrome.
|
||||
|
||||
* Use V8 snapshots to improve startup time.
|
||||
|
||||
* Remove Golang. Although it has been working nicely, I am concerned the
|
||||
double GC will become a problem sometime down the road.
|
||||
|
||||
* Distribute a C++ library called libdeno, containing the snapshotted
|
||||
typescript runtime.
|
||||
|
||||
* Test the message passing and other functionality at that layer before
|
||||
involving higher level languages.
|
||||
|
||||
The contenders for building the unprivileged part of Deno are Rust and C++.
|
||||
Thanks to Chrome and gn, using C++ to link into high level libraries is not
|
||||
untenable. However, there's a lot of interest in Rust in the JS community and
|
||||
it seems like a reasonable choice. TBD.
|
||||
|
||||
There are many people exploring the project, so care will be taken to keep the
|
||||
original code functional while this is developed. However, once it's ready
|
||||
the code in this deno2/ directory will be moved to the root.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Get Depot Tools and make sure it's in your path.
|
||||
http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up
|
||||
|
||||
For linux you need these prereqs:
|
||||
|
||||
sudo apt-get install libgtk-3-dev pkg-config ccache
|
||||
|
||||
|
||||
## Build
|
||||
|
||||
First install the javascript deps.
|
||||
|
||||
cd js; yarn install
|
||||
|
||||
TODO(ry) Remove the above step by a deps submodule.
|
||||
|
||||
Wrapper around the gclient/gn/ninja for end users. Try this first:
|
||||
|
||||
./tools/build.py --use_ccache --debug
|
||||
|
||||
If that doesn't work, or you need more control, try calling gn manually:
|
||||
|
||||
gn gen out/Debug --args='cc_wrapper="ccache" is_debug=true '
|
||||
|
||||
Then build with ninja:
|
||||
|
||||
ninja -C out/Debug/ deno
|
||||
|
||||
|
||||
Other useful commands:
|
||||
|
||||
gn args out/Debug/ --list # List build args
|
||||
gn args out/Debug/ # Modify args in $EDITOR
|
1
deno2/build
Symbolic link
1
deno2/build
Symbolic link
|
@ -0,0 +1 @@
|
|||
v8/build
|
340
deno2/deno.cc
Normal file
340
deno2/deno.cc
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
Copyright 2018 Ryan Dahl <ry@tinyclouds.org>. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#include "v8/include/libplatform/libplatform.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
#include "./deno_internal.h"
|
||||
#include "include/deno.h"
|
||||
|
||||
#define CHECK(x) assert(x) // TODO(ry) use V8's CHECK.
|
||||
|
||||
namespace deno {
|
||||
|
||||
// Extracts a C string from a v8::V8 Utf8Value.
|
||||
const char* ToCString(const v8::String::Utf8Value& value) {
|
||||
return *value ? *value : "<string conversion failed>";
|
||||
}
|
||||
|
||||
static inline v8::Local<v8::String> v8_str(const char* x) {
|
||||
return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x,
|
||||
v8::NewStringType::kNormal)
|
||||
.ToLocalChecked();
|
||||
}
|
||||
|
||||
void HandleException(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Value> exception) {
|
||||
auto* isolate = context->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
auto message = v8::Exception::CreateMessage(isolate, exception);
|
||||
auto onerrorStr = v8::String::NewFromUtf8(isolate, "onerror");
|
||||
auto onerror = context->Global()->Get(onerrorStr);
|
||||
|
||||
if (onerror->IsFunction()) {
|
||||
auto func = v8::Local<v8::Function>::Cast(onerror);
|
||||
v8::Local<v8::Value> args[5];
|
||||
auto origin = message->GetScriptOrigin();
|
||||
args[0] = exception->ToString();
|
||||
args[1] = message->GetScriptResourceName();
|
||||
args[2] = origin.ResourceLineOffset();
|
||||
args[3] = origin.ResourceColumnOffset();
|
||||
args[4] = exception;
|
||||
func->Call(context->Global(), 5, args);
|
||||
/* message, source, lineno, colno, error */
|
||||
} else {
|
||||
v8::String::Utf8Value exceptionStr(isolate, exception);
|
||||
printf("Unhandled Exception %s\n", ToCString(exceptionStr));
|
||||
message->PrintCurrentStackTrace(isolate, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bool AbortOnUncaughtExceptionCallback(v8::Isolate* isolate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageCallback2(Local<Message> message, v8::Local<v8::Value> data) {
|
||||
printf("MessageCallback2\n\n");
|
||||
}
|
||||
|
||||
void FatalErrorCallback2(const char* location, const char* message) {
|
||||
printf("FatalErrorCallback2\n");
|
||||
}
|
||||
*/
|
||||
|
||||
void ExitOnPromiseRejectCallback(
|
||||
v8::PromiseRejectMessage promise_reject_message) {
|
||||
auto* isolate = v8::Isolate::GetCurrent();
|
||||
Deno* d = static_cast<Deno*>(isolate->GetData(0));
|
||||
assert(d->isolate == isolate);
|
||||
v8::HandleScope handle_scope(d->isolate);
|
||||
auto exception = promise_reject_message.GetValue();
|
||||
auto context = d->context.Get(d->isolate);
|
||||
HandleException(context, exception);
|
||||
}
|
||||
|
||||
void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
assert(args.Length() == 1);
|
||||
auto* isolate = args.GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::String::Utf8Value str(isolate, args[0]);
|
||||
const char* cstr = ToCString(str);
|
||||
printf("%s\n", cstr);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// Sets the sub callback.
|
||||
void Sub(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
Deno* d = reinterpret_cast<Deno*>(isolate->GetData(0));
|
||||
assert(d->isolate == isolate);
|
||||
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
if (!d->sub.IsEmpty()) {
|
||||
isolate->ThrowException(v8_str("denoSub already called."));
|
||||
return;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> v = args[0];
|
||||
assert(v->IsFunction());
|
||||
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
|
||||
|
||||
d->sub.Reset(isolate, func);
|
||||
}
|
||||
|
||||
void Pub(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
Deno* d = static_cast<Deno*>(isolate->GetData(0));
|
||||
assert(d->isolate == isolate);
|
||||
|
||||
v8::Locker locker(d->isolate);
|
||||
v8::EscapableHandleScope handle_scope(isolate);
|
||||
|
||||
assert(args.Length() == 2);
|
||||
v8::Local<v8::Value> channel_v = args[0];
|
||||
assert(channel_v->IsString());
|
||||
v8::String::Utf8Value channel_vstr(isolate, channel_v);
|
||||
const char* channel = *channel_vstr;
|
||||
|
||||
v8::Local<v8::Value> ab_v = args[1];
|
||||
assert(ab_v->IsArrayBuffer());
|
||||
|
||||
auto ab = v8::Local<v8::ArrayBuffer>::Cast(ab_v);
|
||||
auto contents = ab->GetContents();
|
||||
|
||||
// data is only a valid pointer until the end of this call.
|
||||
const char* data =
|
||||
const_cast<const char*>(reinterpret_cast<char*>(contents.Data()));
|
||||
deno_buf buf{data, contents.ByteLength()};
|
||||
|
||||
auto retbuf = d->cb(d, channel, buf);
|
||||
if (retbuf.data) {
|
||||
// TODO(ry) Support zero-copy.
|
||||
auto ab = v8::ArrayBuffer::New(d->isolate, retbuf.len);
|
||||
memcpy(ab->GetContents().Data(), retbuf.data, retbuf.len);
|
||||
args.GetReturnValue().Set(handle_scope.Escape(ab));
|
||||
} else {
|
||||
args.GetReturnValue().Set(v8::Null(d->isolate));
|
||||
}
|
||||
}
|
||||
|
||||
bool Execute(v8::Local<v8::Context> context, const char* js_filename,
|
||||
const char* js_source) {
|
||||
auto* isolate = context->GetIsolate();
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
v8::TryCatch try_catch(isolate);
|
||||
|
||||
auto name = v8_str(js_filename);
|
||||
auto source = v8_str(js_source);
|
||||
|
||||
v8::ScriptOrigin origin(name);
|
||||
|
||||
auto script = v8::Script::Compile(context, source, &origin);
|
||||
|
||||
if (script.IsEmpty()) {
|
||||
assert(try_catch.HasCaught());
|
||||
HandleException(context, try_catch.Exception());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = script.ToLocalChecked()->Run(context);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
assert(try_catch.HasCaught());
|
||||
HandleException(context, try_catch.Exception());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
void* data) {
|
||||
assert(data == nullptr); // TODO(ry) pass Deno* object here.
|
||||
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(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();
|
||||
// TODO(ry) Add a global namespace object "deno" and move print, sub, and
|
||||
// pub inside that object.
|
||||
auto print_tmpl = v8::FunctionTemplate::New(isolate, Print);
|
||||
auto print_val = print_tmpl->GetFunction(context).ToLocalChecked();
|
||||
CHECK(
|
||||
global->Set(context, deno::v8_str("denoPrint"), print_val).FromJust());
|
||||
|
||||
auto sub_tmpl = v8::FunctionTemplate::New(isolate, Sub);
|
||||
auto sub_val = sub_tmpl->GetFunction(context).ToLocalChecked();
|
||||
CHECK(global->Set(context, deno::v8_str("denoSub"), sub_val).FromJust());
|
||||
|
||||
auto pub_tmpl = v8::FunctionTemplate::New(isolate, Pub);
|
||||
auto pub_val = pub_tmpl->GetFunction(context).ToLocalChecked();
|
||||
CHECK(global->Set(context, deno::v8_str("denoPub"), pub_val).FromJust());
|
||||
|
||||
bool r = Execute(context, js_filename, js_source);
|
||||
CHECK(r);
|
||||
|
||||
creator->SetDefaultContext(context, v8::SerializeInternalFieldsCallback(
|
||||
SerializeInternalFields, nullptr));
|
||||
}
|
||||
|
||||
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* deno_v8_version() { return v8::V8::GetVersion(); }
|
||||
|
||||
void deno_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 deno_execute(Deno* d, const char* js_filename, const char* js_source) {
|
||||
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 deno::Execute(context, js_filename, js_source);
|
||||
}
|
||||
|
||||
bool deno_pub(Deno* d, const char* channel, deno_buf buf) {
|
||||
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 sub = d->sub.Get(d->isolate);
|
||||
if (sub.IsEmpty()) {
|
||||
d->last_exception = "deno_sub has not been called.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(ry) support zero-copy.
|
||||
auto ab = v8::ArrayBuffer::New(d->isolate, buf.len);
|
||||
memcpy(ab->GetContents().Data(), buf.data, buf.len);
|
||||
|
||||
v8::Local<v8::Value> args[2];
|
||||
args[0] = deno::v8_str(channel);
|
||||
args[1] = ab;
|
||||
|
||||
sub->Call(context->Global(), 1, args);
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
deno::HandleException(context, try_catch.Exception());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void deno_delete(Deno* d) {
|
||||
d->isolate->Dispose();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void deno_terminate_execution(Deno* d) { d->isolate->TerminateExecution(); }
|
||||
|
||||
} // extern "C"
|
44
deno2/deno_internal.h
Normal file
44
deno2/deno_internal.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
#ifndef DENO_INTERNAL_H_
|
||||
#define DENO_INTERNAL_H_
|
||||
|
||||
#include <string>
|
||||
#include "include/deno.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
extern "C" {
|
||||
// deno_s = Wrapped Isolate.
|
||||
struct deno_s {
|
||||
v8::Isolate* isolate;
|
||||
std::string last_exception;
|
||||
v8::Persistent<v8::Function> sub;
|
||||
v8::Persistent<v8::Context> context;
|
||||
deno_sub_cb cb;
|
||||
void* data;
|
||||
};
|
||||
}
|
||||
|
||||
namespace deno {
|
||||
|
||||
struct InternalFieldData {
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
void Sub(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
void Pub(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static intptr_t external_references[] = {reinterpret_cast<intptr_t>(Print),
|
||||
reinterpret_cast<intptr_t>(Sub),
|
||||
reinterpret_cast<intptr_t>(Pub), 0};
|
||||
|
||||
Deno* NewFromSnapshot(void* data, deno_sub_cb 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_
|
78
deno2/from_snapshot.cc
Normal file
78
deno2/from_snapshot.cc
Normal file
|
@ -0,0 +1,78 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
#include "./deno_internal.h"
|
||||
#include "include/deno.h"
|
||||
|
||||
namespace deno {
|
||||
|
||||
#ifdef DENO_MOCK_RUNTIME
|
||||
#include "natives_mock_runtime.cc"
|
||||
#include "snapshot_mock_runtime.cc"
|
||||
#else
|
||||
#include "natives_deno.cc"
|
||||
#include "snapshot_deno.cc"
|
||||
#endif
|
||||
|
||||
std::vector<InternalFieldData*> deserialized_data;
|
||||
|
||||
void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
v8::StartupData payload, void* data) {
|
||||
assert(data == nullptr); // TODO(ry) pass Deno* object here.
|
||||
if (payload.raw_size == 0) {
|
||||
holder->SetAlignedPointerInInternalField(index, nullptr);
|
||||
return;
|
||||
}
|
||||
InternalFieldData* embedder_field = new InternalFieldData{0};
|
||||
memcpy(embedder_field, payload.data, payload.raw_size);
|
||||
holder->SetAlignedPointerInInternalField(index, embedder_field);
|
||||
deserialized_data.push_back(embedder_field);
|
||||
}
|
||||
|
||||
Deno* NewFromSnapshot(void* data, deno_sub_cb cb) {
|
||||
auto natives_blob = *StartupBlob_natives();
|
||||
auto snapshot_blob = *StartupBlob_snapshot();
|
||||
|
||||
v8::V8::SetNativesDataBlob(&natives_blob);
|
||||
v8::V8::SetSnapshotDataBlob(&snapshot_blob);
|
||||
v8::DeserializeInternalFieldsCallback(DeserializeInternalFields, nullptr);
|
||||
|
||||
Deno* d = new Deno;
|
||||
d->cb = cb;
|
||||
d->data = data;
|
||||
v8::Isolate::CreateParams params;
|
||||
params.array_buffer_allocator =
|
||||
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
|
||||
params.external_references = external_references;
|
||||
v8::Isolate* isolate = v8::Isolate::New(params);
|
||||
AddIsolate(d, 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(
|
||||
DeserializeInternalFields, nullptr));
|
||||
d->context.Reset(d->isolate, context);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
} // namespace deno
|
||||
|
||||
extern "C" {
|
||||
Deno* deno_new(void* data, deno_sub_cb cb) {
|
||||
return deno::NewFromSnapshot(data, cb);
|
||||
}
|
||||
}
|
47
deno2/include/deno.h
Normal file
47
deno2/include/deno.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
#ifndef INCLUDE_DENO_H_
|
||||
#define INCLUDE_DENO_H_
|
||||
// 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.
|
||||
typedef struct {
|
||||
const char* data;
|
||||
size_t len;
|
||||
} deno_buf;
|
||||
|
||||
struct deno_s;
|
||||
typedef struct deno_s Deno;
|
||||
|
||||
// A callback to receive a message from deno_pub javascript call.
|
||||
// buf is valid only for the lifetime of the call.
|
||||
// The returned deno_buf is returned from deno_pub in javascript.
|
||||
typedef deno_buf (*deno_sub_cb)(Deno* d, const char* channel, deno_buf buf);
|
||||
|
||||
void deno_init();
|
||||
const char* deno_v8_version();
|
||||
void deno_set_flags(int* argc, char** argv);
|
||||
|
||||
Deno* deno_new(void* data, deno_sub_cb cb);
|
||||
void deno_delete(Deno* d);
|
||||
|
||||
// Returns false on error.
|
||||
// Get error text with deno_last_exception().
|
||||
bool deno_execute(Deno* d, const char* js_filename, const char* js_source);
|
||||
|
||||
// Routes message to the javascript callback set with deno_sub(). A false return
|
||||
// value indicates error. Check deno_last_exception() for exception text.
|
||||
bool deno_pub(Deno* d, const char* channel, deno_buf buf);
|
||||
|
||||
const char* deno_last_exception(Deno* d);
|
||||
|
||||
void deno_terminate_execution(Deno* d);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // INCLUDE_DENO_H_
|
6
deno2/js/deno.d.ts
vendored
Normal file
6
deno2/js/deno.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
type MessageCallback = (msg: ArrayBuffer) => void;
|
||||
declare function denoSub(channel: string, cb: MessageCallback): void;
|
||||
declare function denoPub(channel: string, msg: ArrayBuffer): null | ArrayBuffer;
|
||||
declare function denoPrint(x: string): void;
|
14
deno2/js/main.ts
Normal file
14
deno2/js/main.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/// <reference path="deno.d.ts" />
|
||||
import { main as pb } from "./msg.pb";
|
||||
import * as ts from "typescript";
|
||||
|
||||
const globalEval = eval;
|
||||
const window = globalEval("this");
|
||||
window["denoMain"] = () => {
|
||||
denoPrint("Hello world");
|
||||
const msg = pb.Msg.fromObject({});
|
||||
denoPrint(`msg.command: ${msg.command}`);
|
||||
denoPrint(`ts.version: ${ts.version}`);
|
||||
denoPrint("Hello world from foo");
|
||||
return "foo";
|
||||
};
|
69
deno2/js/mock_runtime.js
Normal file
69
deno2/js/mock_runtime.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
// A simple runtime that doesn't involve typescript or protobufs to test
|
||||
// libdeno. Invoked by mock_runtime_test.cc
|
||||
const window = eval("this");
|
||||
|
||||
function assert(cond) {
|
||||
if (!cond) throw Error("mock_runtime.js assert failed");
|
||||
}
|
||||
|
||||
function typedArrayToArrayBuffer(ta) {
|
||||
return ta.buffer.slice(ta.byteOffset, ta.byteOffset + ta.byteLength);
|
||||
}
|
||||
|
||||
function CanCallFunction() {
|
||||
denoPrint("Hello world from foo");
|
||||
return "foo";
|
||||
}
|
||||
|
||||
// This object is created to test snapshotting.
|
||||
// See DeserializeInternalFieldsCallback and SerializeInternalFieldsCallback.
|
||||
const snapshotted = new Uint8Array([1, 3, 3, 7]);
|
||||
|
||||
function TypedArraySnapshots() {
|
||||
assert(snapshotted[0] === 1);
|
||||
assert(snapshotted[1] === 3);
|
||||
assert(snapshotted[2] === 3);
|
||||
assert(snapshotted[3] === 7);
|
||||
}
|
||||
|
||||
function PubSuccess() {
|
||||
denoSub((channel, msg) => {
|
||||
assert(channel === "PubSuccess");
|
||||
denoPrint("PubSuccess: ok");
|
||||
});
|
||||
}
|
||||
|
||||
function PubByteLength() {
|
||||
denoSub((channel, msg) => {
|
||||
assert(channel === "PubByteLength");
|
||||
assert(msg instanceof ArrayBuffer);
|
||||
assert(msg.byteLength === 3);
|
||||
});
|
||||
}
|
||||
|
||||
function SubReturnEmpty() {
|
||||
const ui8 = new Uint8Array("abc".split("").map(c => c.charCodeAt(0)));
|
||||
const ab = typedArrayToArrayBuffer(ui8);
|
||||
let r = denoPub("SubReturnEmpty", ab);
|
||||
assert(r == null);
|
||||
r = denoPub("SubReturnEmpty", ab);
|
||||
assert(r == null);
|
||||
}
|
||||
|
||||
function SubReturnBar() {
|
||||
const ui8 = new Uint8Array("abc".split("").map(c => c.charCodeAt(0)));
|
||||
const ab = typedArrayToArrayBuffer(ui8);
|
||||
const r = denoPub("SubReturnBar", ab);
|
||||
assert(r instanceof ArrayBuffer);
|
||||
assert(r.byteLength === 3);
|
||||
const rui8 = new Uint8Array(r);
|
||||
const rstr = String.fromCharCode(...rui8);
|
||||
assert(rstr === "bar");
|
||||
}
|
||||
|
||||
function DoubleSubFails() {
|
||||
// denoSub is an internal function and should only be called once from the
|
||||
// runtime.
|
||||
denoSub((channel, msg) => assert(false));
|
||||
denoSub((channel, msg) => assert(false));
|
||||
}
|
410
deno2/js/msg.pb.d.ts
vendored
Normal file
410
deno2/js/msg.pb.d.ts
vendored
Normal file
|
@ -0,0 +1,410 @@
|
|||
import * as $protobuf from "protobufjs";
|
||||
|
||||
/** Namespace main. */
|
||||
export namespace main {
|
||||
|
||||
/** Properties of a BaseMsg. */
|
||||
interface IBaseMsg {
|
||||
|
||||
/** BaseMsg channel */
|
||||
channel?: (string|null);
|
||||
|
||||
/** BaseMsg payload */
|
||||
payload?: (Uint8Array|null);
|
||||
}
|
||||
|
||||
/** Represents a BaseMsg. */
|
||||
class BaseMsg implements IBaseMsg {
|
||||
|
||||
/**
|
||||
* Constructs a new BaseMsg.
|
||||
* @param [properties] Properties to set
|
||||
*/
|
||||
constructor(properties?: main.IBaseMsg);
|
||||
|
||||
/** BaseMsg channel. */
|
||||
public channel: string;
|
||||
|
||||
/** BaseMsg payload. */
|
||||
public payload: Uint8Array;
|
||||
|
||||
/**
|
||||
* Creates a new BaseMsg instance using the specified properties.
|
||||
* @param [properties] Properties to set
|
||||
* @returns BaseMsg instance
|
||||
*/
|
||||
public static create(properties?: main.IBaseMsg): main.BaseMsg;
|
||||
|
||||
/**
|
||||
* Encodes the specified BaseMsg message. Does not implicitly {@link main.BaseMsg.verify|verify} messages.
|
||||
* @param message BaseMsg message or plain object to encode
|
||||
* @param [writer] Writer to encode to
|
||||
* @returns Writer
|
||||
*/
|
||||
public static encode(message: main.IBaseMsg, writer?: $protobuf.Writer): $protobuf.Writer;
|
||||
|
||||
/**
|
||||
* Encodes the specified BaseMsg message, length delimited. Does not implicitly {@link main.BaseMsg.verify|verify} messages.
|
||||
* @param message BaseMsg message or plain object to encode
|
||||
* @param [writer] Writer to encode to
|
||||
* @returns Writer
|
||||
*/
|
||||
public static encodeDelimited(message: main.IBaseMsg, writer?: $protobuf.Writer): $protobuf.Writer;
|
||||
|
||||
/**
|
||||
* Decodes a BaseMsg message from the specified reader or buffer.
|
||||
* @param reader Reader or buffer to decode from
|
||||
* @param [length] Message length if known beforehand
|
||||
* @returns BaseMsg
|
||||
* @throws {Error} If the payload is not a reader or valid buffer
|
||||
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||
*/
|
||||
public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): main.BaseMsg;
|
||||
|
||||
/**
|
||||
* Decodes a BaseMsg message from the specified reader or buffer, length delimited.
|
||||
* @param reader Reader or buffer to decode from
|
||||
* @returns BaseMsg
|
||||
* @throws {Error} If the payload is not a reader or valid buffer
|
||||
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||
*/
|
||||
public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): main.BaseMsg;
|
||||
|
||||
/**
|
||||
* Verifies a BaseMsg message.
|
||||
* @param message Plain object to verify
|
||||
* @returns `null` if valid, otherwise the reason why it is not
|
||||
*/
|
||||
public static verify(message: { [k: string]: any }): (string|null);
|
||||
|
||||
/**
|
||||
* Creates a BaseMsg message from a plain object. Also converts values to their respective internal types.
|
||||
* @param object Plain object
|
||||
* @returns BaseMsg
|
||||
*/
|
||||
public static fromObject(object: { [k: string]: any }): main.BaseMsg;
|
||||
|
||||
/**
|
||||
* Creates a plain object from a BaseMsg message. Also converts values to other types if specified.
|
||||
* @param message BaseMsg
|
||||
* @param [options] Conversion options
|
||||
* @returns Plain object
|
||||
*/
|
||||
public static toObject(message: main.BaseMsg, options?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||
|
||||
/**
|
||||
* Converts this BaseMsg to JSON.
|
||||
* @returns JSON object
|
||||
*/
|
||||
public toJSON(): { [k: string]: any };
|
||||
}
|
||||
|
||||
/** Properties of a Msg. */
|
||||
interface IMsg {
|
||||
|
||||
/** Msg command */
|
||||
command?: (main.Msg.Command|null);
|
||||
|
||||
/** Msg error */
|
||||
error?: (string|null);
|
||||
|
||||
/** Msg startCwd */
|
||||
startCwd?: (string|null);
|
||||
|
||||
/** Msg startArgv */
|
||||
startArgv?: (string[]|null);
|
||||
|
||||
/** Msg startDebugFlag */
|
||||
startDebugFlag?: (boolean|null);
|
||||
|
||||
/** Msg startMainJs */
|
||||
startMainJs?: (string|null);
|
||||
|
||||
/** Msg startMainMap */
|
||||
startMainMap?: (string|null);
|
||||
|
||||
/** Msg codeFetchModuleSpecifier */
|
||||
codeFetchModuleSpecifier?: (string|null);
|
||||
|
||||
/** Msg codeFetchContainingFile */
|
||||
codeFetchContainingFile?: (string|null);
|
||||
|
||||
/** Msg codeFetchResModuleName */
|
||||
codeFetchResModuleName?: (string|null);
|
||||
|
||||
/** Msg codeFetchResFilename */
|
||||
codeFetchResFilename?: (string|null);
|
||||
|
||||
/** Msg codeFetchResSourceCode */
|
||||
codeFetchResSourceCode?: (string|null);
|
||||
|
||||
/** Msg codeFetchResOutputCode */
|
||||
codeFetchResOutputCode?: (string|null);
|
||||
|
||||
/** Msg codeCacheFilename */
|
||||
codeCacheFilename?: (string|null);
|
||||
|
||||
/** Msg codeCacheSourceCode */
|
||||
codeCacheSourceCode?: (string|null);
|
||||
|
||||
/** Msg codeCacheOutputCode */
|
||||
codeCacheOutputCode?: (string|null);
|
||||
|
||||
/** Msg exitCode */
|
||||
exitCode?: (number|null);
|
||||
|
||||
/** Msg timerStartId */
|
||||
timerStartId?: (number|null);
|
||||
|
||||
/** Msg timerStartInterval */
|
||||
timerStartInterval?: (boolean|null);
|
||||
|
||||
/** Msg timerStartDelay */
|
||||
timerStartDelay?: (number|null);
|
||||
|
||||
/** Msg timerReadyId */
|
||||
timerReadyId?: (number|null);
|
||||
|
||||
/** Msg timerReadyDone */
|
||||
timerReadyDone?: (boolean|null);
|
||||
|
||||
/** Msg timerClearId */
|
||||
timerClearId?: (number|null);
|
||||
|
||||
/** Msg fetchReqId */
|
||||
fetchReqId?: (number|null);
|
||||
|
||||
/** Msg fetchReqUrl */
|
||||
fetchReqUrl?: (string|null);
|
||||
|
||||
/** Msg fetchResId */
|
||||
fetchResId?: (number|null);
|
||||
|
||||
/** Msg fetchResStatus */
|
||||
fetchResStatus?: (number|null);
|
||||
|
||||
/** Msg fetchResHeaderLine */
|
||||
fetchResHeaderLine?: (string[]|null);
|
||||
|
||||
/** Msg fetchResBody */
|
||||
fetchResBody?: (Uint8Array|null);
|
||||
|
||||
/** Msg readFileSyncFilename */
|
||||
readFileSyncFilename?: (string|null);
|
||||
|
||||
/** Msg readFileSyncData */
|
||||
readFileSyncData?: (Uint8Array|null);
|
||||
|
||||
/** Msg writeFileSyncFilename */
|
||||
writeFileSyncFilename?: (string|null);
|
||||
|
||||
/** Msg writeFileSyncData */
|
||||
writeFileSyncData?: (Uint8Array|null);
|
||||
|
||||
/** Msg writeFileSyncPerm */
|
||||
writeFileSyncPerm?: (number|null);
|
||||
}
|
||||
|
||||
/** Represents a Msg. */
|
||||
class Msg implements IMsg {
|
||||
|
||||
/**
|
||||
* Constructs a new Msg.
|
||||
* @param [properties] Properties to set
|
||||
*/
|
||||
constructor(properties?: main.IMsg);
|
||||
|
||||
/** Msg command. */
|
||||
public command: main.Msg.Command;
|
||||
|
||||
/** Msg error. */
|
||||
public error: string;
|
||||
|
||||
/** Msg startCwd. */
|
||||
public startCwd: string;
|
||||
|
||||
/** Msg startArgv. */
|
||||
public startArgv: string[];
|
||||
|
||||
/** Msg startDebugFlag. */
|
||||
public startDebugFlag: boolean;
|
||||
|
||||
/** Msg startMainJs. */
|
||||
public startMainJs: string;
|
||||
|
||||
/** Msg startMainMap. */
|
||||
public startMainMap: string;
|
||||
|
||||
/** Msg codeFetchModuleSpecifier. */
|
||||
public codeFetchModuleSpecifier: string;
|
||||
|
||||
/** Msg codeFetchContainingFile. */
|
||||
public codeFetchContainingFile: string;
|
||||
|
||||
/** Msg codeFetchResModuleName. */
|
||||
public codeFetchResModuleName: string;
|
||||
|
||||
/** Msg codeFetchResFilename. */
|
||||
public codeFetchResFilename: string;
|
||||
|
||||
/** Msg codeFetchResSourceCode. */
|
||||
public codeFetchResSourceCode: string;
|
||||
|
||||
/** Msg codeFetchResOutputCode. */
|
||||
public codeFetchResOutputCode: string;
|
||||
|
||||
/** Msg codeCacheFilename. */
|
||||
public codeCacheFilename: string;
|
||||
|
||||
/** Msg codeCacheSourceCode. */
|
||||
public codeCacheSourceCode: string;
|
||||
|
||||
/** Msg codeCacheOutputCode. */
|
||||
public codeCacheOutputCode: string;
|
||||
|
||||
/** Msg exitCode. */
|
||||
public exitCode: number;
|
||||
|
||||
/** Msg timerStartId. */
|
||||
public timerStartId: number;
|
||||
|
||||
/** Msg timerStartInterval. */
|
||||
public timerStartInterval: boolean;
|
||||
|
||||
/** Msg timerStartDelay. */
|
||||
public timerStartDelay: number;
|
||||
|
||||
/** Msg timerReadyId. */
|
||||
public timerReadyId: number;
|
||||
|
||||
/** Msg timerReadyDone. */
|
||||
public timerReadyDone: boolean;
|
||||
|
||||
/** Msg timerClearId. */
|
||||
public timerClearId: number;
|
||||
|
||||
/** Msg fetchReqId. */
|
||||
public fetchReqId: number;
|
||||
|
||||
/** Msg fetchReqUrl. */
|
||||
public fetchReqUrl: string;
|
||||
|
||||
/** Msg fetchResId. */
|
||||
public fetchResId: number;
|
||||
|
||||
/** Msg fetchResStatus. */
|
||||
public fetchResStatus: number;
|
||||
|
||||
/** Msg fetchResHeaderLine. */
|
||||
public fetchResHeaderLine: string[];
|
||||
|
||||
/** Msg fetchResBody. */
|
||||
public fetchResBody: Uint8Array;
|
||||
|
||||
/** Msg readFileSyncFilename. */
|
||||
public readFileSyncFilename: string;
|
||||
|
||||
/** Msg readFileSyncData. */
|
||||
public readFileSyncData: Uint8Array;
|
||||
|
||||
/** Msg writeFileSyncFilename. */
|
||||
public writeFileSyncFilename: string;
|
||||
|
||||
/** Msg writeFileSyncData. */
|
||||
public writeFileSyncData: Uint8Array;
|
||||
|
||||
/** Msg writeFileSyncPerm. */
|
||||
public writeFileSyncPerm: number;
|
||||
|
||||
/**
|
||||
* Creates a new Msg instance using the specified properties.
|
||||
* @param [properties] Properties to set
|
||||
* @returns Msg instance
|
||||
*/
|
||||
public static create(properties?: main.IMsg): main.Msg;
|
||||
|
||||
/**
|
||||
* Encodes the specified Msg message. Does not implicitly {@link main.Msg.verify|verify} messages.
|
||||
* @param message Msg message or plain object to encode
|
||||
* @param [writer] Writer to encode to
|
||||
* @returns Writer
|
||||
*/
|
||||
public static encode(message: main.IMsg, writer?: $protobuf.Writer): $protobuf.Writer;
|
||||
|
||||
/**
|
||||
* Encodes the specified Msg message, length delimited. Does not implicitly {@link main.Msg.verify|verify} messages.
|
||||
* @param message Msg message or plain object to encode
|
||||
* @param [writer] Writer to encode to
|
||||
* @returns Writer
|
||||
*/
|
||||
public static encodeDelimited(message: main.IMsg, writer?: $protobuf.Writer): $protobuf.Writer;
|
||||
|
||||
/**
|
||||
* Decodes a Msg message from the specified reader or buffer.
|
||||
* @param reader Reader or buffer to decode from
|
||||
* @param [length] Message length if known beforehand
|
||||
* @returns Msg
|
||||
* @throws {Error} If the payload is not a reader or valid buffer
|
||||
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||
*/
|
||||
public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): main.Msg;
|
||||
|
||||
/**
|
||||
* Decodes a Msg message from the specified reader or buffer, length delimited.
|
||||
* @param reader Reader or buffer to decode from
|
||||
* @returns Msg
|
||||
* @throws {Error} If the payload is not a reader or valid buffer
|
||||
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||
*/
|
||||
public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): main.Msg;
|
||||
|
||||
/**
|
||||
* Verifies a Msg message.
|
||||
* @param message Plain object to verify
|
||||
* @returns `null` if valid, otherwise the reason why it is not
|
||||
*/
|
||||
public static verify(message: { [k: string]: any }): (string|null);
|
||||
|
||||
/**
|
||||
* Creates a Msg message from a plain object. Also converts values to their respective internal types.
|
||||
* @param object Plain object
|
||||
* @returns Msg
|
||||
*/
|
||||
public static fromObject(object: { [k: string]: any }): main.Msg;
|
||||
|
||||
/**
|
||||
* Creates a plain object from a Msg message. Also converts values to other types if specified.
|
||||
* @param message Msg
|
||||
* @param [options] Conversion options
|
||||
* @returns Plain object
|
||||
*/
|
||||
public static toObject(message: main.Msg, options?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||
|
||||
/**
|
||||
* Converts this Msg to JSON.
|
||||
* @returns JSON object
|
||||
*/
|
||||
public toJSON(): { [k: string]: any };
|
||||
}
|
||||
|
||||
namespace Msg {
|
||||
|
||||
/** Command enum. */
|
||||
enum Command {
|
||||
ERROR = 0,
|
||||
START = 1,
|
||||
CODE_FETCH = 2,
|
||||
CODE_FETCH_RES = 3,
|
||||
CODE_CACHE = 4,
|
||||
EXIT = 5,
|
||||
TIMER_START = 6,
|
||||
TIMER_READY = 7,
|
||||
TIMER_CLEAR = 8,
|
||||
FETCH_REQ = 9,
|
||||
FETCH_RES = 10,
|
||||
READ_FILE_SYNC = 11,
|
||||
READ_FILE_SYNC_RES = 12,
|
||||
WRITE_FILE_SYNC = 13
|
||||
}
|
||||
}
|
||||
}
|
1313
deno2/js/msg.pb.js
Normal file
1313
deno2/js/msg.pb.js
Normal file
File diff suppressed because it is too large
Load diff
7
deno2/js/package.json
Normal file
7
deno2/js/package.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"parcel-bundler": "^1.8.1",
|
||||
"protobufjs": "^6.8.6",
|
||||
"typescript": "^2.9.1"
|
||||
}
|
||||
}
|
54
deno2/js/pbjs_hack.py
Executable file
54
deno2/js/pbjs_hack.py
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
gn can only run python scripts.
|
||||
|
||||
Generates protobufjs code.
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
# TODO(ry) Ideally protobufjs output files should be written into
|
||||
# target_gen_dir, but its difficult to get this working in a way that parcel can
|
||||
# resolve their location. (Parcel does not support NODE_PATH.) Therefore this
|
||||
# hack: write the generated msg.pb.js and msg.pb.d.ts outputs into the js/
|
||||
# folder, and we check them into the repo. Hopefully this hack can be removed at
|
||||
# some point. If msg.proto is changed, commit changes to the generated JS
|
||||
# files.
|
||||
|
||||
js_path = os.path.dirname(os.path.realpath(__file__))
|
||||
pbjs_path = os.path.join(js_path, "node_modules", "protobufjs", "bin")
|
||||
pbjs_bin = os.path.join(pbjs_path, "pbjs")
|
||||
pbts_bin = os.path.join(pbjs_path, "pbts")
|
||||
msg_pbjs_out = os.path.join(js_path, "msg.pb.js")
|
||||
msg_pbts_out = os.path.join(js_path, "msg.pb.d.ts")
|
||||
assert os.path.exists(pbjs_bin)
|
||||
assert os.path.exists(pbts_bin)
|
||||
|
||||
proto_in = sys.argv[1]
|
||||
stamp_file = sys.argv[2]
|
||||
|
||||
def touch(fname):
|
||||
if os.path.exists(fname):
|
||||
os.utime(fname, None)
|
||||
else:
|
||||
open(fname, 'a').close()
|
||||
|
||||
subprocess.check_call([
|
||||
"node",
|
||||
pbjs_bin,
|
||||
"--target=static-module",
|
||||
"--wrapper=commonjs",
|
||||
"--out=" + msg_pbjs_out,
|
||||
proto_in
|
||||
])
|
||||
assert os.path.exists(msg_pbjs_out)
|
||||
|
||||
subprocess.check_call([
|
||||
"node",
|
||||
pbts_bin,
|
||||
"--out=" + msg_pbts_out,
|
||||
msg_pbjs_out
|
||||
])
|
||||
assert os.path.exists(msg_pbts_out)
|
||||
|
||||
touch(stamp_file)
|
32
deno2/js/run_node.py
Executable file
32
deno2/js/run_node.py
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
gn can only run python scripts. This launches a subprocess Node process.
|
||||
The working dir of this program is out/Debug/ (AKA root_build_dir)
|
||||
Before running node, we symlink js/node_modules to out/Debug/node_modules.
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
def symlink(target, name, target_is_dir=False):
|
||||
if os.name == "nt":
|
||||
from ctypes import windll, WinError
|
||||
CreateSymbolicLinkW = windll.kernel32.CreateSymbolicLinkW
|
||||
flags = 0x02 # SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
|
||||
if (target_is_dir):
|
||||
flags |= 0x01 # SYMBOLIC_LINK_FLAG_DIRECTORY
|
||||
if not CreateSymbolicLinkW(name.encode('utf-16le'),
|
||||
target.encode('utf-16le'),
|
||||
flags):
|
||||
raise WinError()
|
||||
else:
|
||||
os.symlink(target, name)
|
||||
|
||||
js_path = os.path.dirname(os.path.realpath(__file__))
|
||||
node_modules_path = os.path.join(js_path, "node_modules")
|
||||
|
||||
if not os.path.exists("node_modules"):
|
||||
symlink(node_modules_path, "node_modules", True)
|
||||
|
||||
args = ["node"] + sys.argv[1:]
|
||||
sys.exit(subprocess.call(args))
|
18
deno2/js/tsconfig.json
Normal file
18
deno2/js/tsconfig.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": true,
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"target": "es2017",
|
||||
"noImplicitReturns": true,
|
||||
"pretty": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"allowUnreachableCode": false,
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.js"],
|
||||
"exclude": ["mock_runtime.js", "node_modules"]
|
||||
}
|
3629
deno2/js/yarn.lock
Normal file
3629
deno2/js/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
19
deno2/main.cc
Normal file
19
deno2/main.cc
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "include/deno.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
deno_init();
|
||||
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
bool r = deno_execute(d, "deno_main.js", "denoMain();");
|
||||
if (!r) {
|
||||
printf("Error! %s\n", deno_last_exception(d));
|
||||
exit(1);
|
||||
}
|
||||
deno_delete(d);
|
||||
}
|
98
deno2/mock_runtime_test.cc
Normal file
98
deno2/mock_runtime_test.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "include/deno.h"
|
||||
|
||||
TEST(MockRuntimeTest, InitializesCorrectly) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_TRUE(deno_execute(d, "a.js", "1 + 2"));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, CanCallFunction) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_TRUE(deno_execute(d, "a.js",
|
||||
"if (CanCallFunction() != 'foo') throw Error();"));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, ErrorsCorrectly) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_FALSE(deno_execute(d, "a.js", "throw Error()"));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
deno_buf strbuf(const char* str) { return deno_buf{str, strlen(str)}; }
|
||||
|
||||
TEST(MockRuntimeTest, PubSuccess) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_TRUE(deno_execute(d, "a.js", "PubSuccess()"));
|
||||
EXPECT_TRUE(deno_pub(d, "PubSuccess", strbuf("abc")));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, PubByteLength) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_TRUE(deno_execute(d, "a.js", "PubByteLength()"));
|
||||
// We pub the wrong sized message, it should throw.
|
||||
EXPECT_FALSE(deno_pub(d, "PubByteLength", strbuf("abcd")));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, PubNoCallback) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
// We didn't call deno_sub(), pubing should fail.
|
||||
EXPECT_FALSE(deno_pub(d, "PubNoCallback", strbuf("abc")));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, SubReturnEmpty) {
|
||||
static int count = 0;
|
||||
Deno* d = deno_new(NULL, [](auto _, auto channel, auto buf) {
|
||||
count++;
|
||||
EXPECT_STREQ(channel, "SubReturnEmpty");
|
||||
EXPECT_EQ(static_cast<size_t>(3), buf.len);
|
||||
EXPECT_EQ(buf.data[0], 'a');
|
||||
EXPECT_EQ(buf.data[1], 'b');
|
||||
EXPECT_EQ(buf.data[2], 'c');
|
||||
return deno_buf{nullptr, 0};
|
||||
});
|
||||
EXPECT_TRUE(deno_execute(d, "a.js", "SubReturnEmpty()"));
|
||||
EXPECT_EQ(count, 2);
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, SubReturnBar) {
|
||||
static int count = 0;
|
||||
Deno* d = deno_new(NULL, [](auto _, auto channel, auto buf) {
|
||||
count++;
|
||||
EXPECT_STREQ(channel, "SubReturnBar");
|
||||
EXPECT_EQ(static_cast<size_t>(3), buf.len);
|
||||
EXPECT_EQ(buf.data[0], 'a');
|
||||
EXPECT_EQ(buf.data[1], 'b');
|
||||
EXPECT_EQ(buf.data[2], 'c');
|
||||
return strbuf("bar");
|
||||
});
|
||||
EXPECT_TRUE(deno_execute(d, "a.js", "SubReturnBar()"));
|
||||
EXPECT_EQ(count, 1);
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, DoubleSubFails) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_FALSE(deno_execute(d, "a.js", "DoubleSubFails()"));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
TEST(MockRuntimeTest, TypedArraySnapshots) {
|
||||
Deno* d = deno_new(NULL, NULL);
|
||||
EXPECT_TRUE(deno_execute(d, "a.js", "TypedArraySnapshots()"));
|
||||
deno_delete(d);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
deno_init();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
1
deno2/msg.proto
Symbolic link
1
deno2/msg.proto
Symbolic link
|
@ -0,0 +1 @@
|
|||
../msg.proto
|
148
deno2/snapshot_creator.cc
Normal file
148
deno2/snapshot_creator.cc
Normal file
|
@ -0,0 +1,148 @@
|
|||
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||
// All rights reserved. MIT License.
|
||||
// Hint: --trace_serializer is a useful debugging flag.
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
#include "./deno_internal.h"
|
||||
#include "include/deno.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<unsigned char>(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<char>((std::istreambuf_iterator<char>(input)),
|
||||
(std::istreambuf_iterator<char>()));
|
||||
v8::StartupData sd;
|
||||
sd.data = buffer->data();
|
||||
sd.raw_size = static_cast<int>(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];
|
||||
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
|
||||
auto js_data = ReadFile(js_fn);
|
||||
// Ensure js_source is null-terminated.
|
||||
std::string js_source(js_data.data, js_data.raw_size);
|
||||
auto natives_blob = ReadFile(natives_in_bin);
|
||||
auto snapshot_in_blob = ReadFile(snapshot_in_bin);
|
||||
|
||||
deno_init();
|
||||
auto snapshot_blob =
|
||||
deno::MakeSnapshot(&natives_blob, &snapshot_in_blob, js_fn, js_source.c_str());
|
||||
|
||||
StartupDataCppWriter nativesWriter("natives", natives_out_cc, natives_blob);
|
||||
nativesWriter.Write();
|
||||
|
||||
StartupDataCppWriter snapshotWriter("snapshot", snapshot_out_cc,
|
||||
snapshot_blob);
|
||||
snapshotWriter.Write();
|
||||
}
|
1
deno2/testing
Symbolic link
1
deno2/testing
Symbolic link
|
@ -0,0 +1 @@
|
|||
v8/testing
|
1
deno2/third_party/googletest
vendored
Symbolic link
1
deno2/third_party/googletest
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../v8/third_party/googletest/
|
1
deno2/third_party/jinja2
vendored
Symbolic link
1
deno2/third_party/jinja2
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../v8/third_party/jinja2/
|
1
deno2/third_party/llvm-build
vendored
Symbolic link
1
deno2/third_party/llvm-build
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../v8/third_party/llvm-build/
|
1
deno2/third_party/markupsafe
vendored
Symbolic link
1
deno2/third_party/markupsafe
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../v8/third_party/markupsafe/
|
67
deno2/tools/build.py
Executable file
67
deno2/tools/build.py
Executable file
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python
|
||||
# Get Depot Tools and make sure it's in your path.
|
||||
# http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up
|
||||
# Use .gclient to modify the deps.
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
TARGET = "deno"
|
||||
|
||||
parser = argparse.ArgumentParser(description="build.py")
|
||||
parser.add_argument('--debug', dest='debug', action='store_true')
|
||||
parser.add_argument('--use_ccache', dest='use_ccache', action='store_true')
|
||||
parser.add_argument('--sync', dest='sync', action='store_true')
|
||||
parser.set_defaults(debug=False, use_ccache=False, sync=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
root_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(root_path)
|
||||
buildName = "Debug" if args.debug else "Default"
|
||||
buildDir = os.path.join(root_path, "out", buildName)
|
||||
# Run sync if any of the dep dirs don't exist.
|
||||
# Or the user supplied the --sync flag.
|
||||
if args.sync or dirsMissing():
|
||||
run(["gclient", "sync", "--no-history"])
|
||||
|
||||
# Run gn gen out/Default if out doesn't exist.
|
||||
if not os.path.exists(buildDir):
|
||||
gn_gen = ["gn", "gen", buildDir]
|
||||
gn_args = []
|
||||
if args.debug:
|
||||
gn_args.append("is_debug=true")
|
||||
if args.use_ccache:
|
||||
gn_args.append("cc_wrapper=\"ccache\"")
|
||||
if len(gn_args) > 0:
|
||||
gn_gen += ["--args=%s" % " ".join(gn_args)]
|
||||
run(gn_gen)
|
||||
|
||||
# Always run ninja.
|
||||
run(["ninja", "-C", buildDir, TARGET])
|
||||
|
||||
|
||||
def run(args):
|
||||
print " ".join(args)
|
||||
env = os.environ.copy()
|
||||
subprocess.check_call(args, env=env)
|
||||
|
||||
|
||||
def dirsMissing():
|
||||
dirsToLoad = [
|
||||
"v8",
|
||||
"third_party/protobuf",
|
||||
"tools/protoc_wrapper",
|
||||
"third_party/zlib",
|
||||
]
|
||||
for d in dirsToLoad:
|
||||
if not os.path.exists(d):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if '__main__' == __name__:
|
||||
main()
|
15
deno2/tools/format.sh
Executable file
15
deno2/tools/format.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
cd `dirname "$0"`/..
|
||||
clang-format -i -style Google *.cc *.h include/*.h
|
||||
gn format BUILD.gn
|
||||
gn format .gn
|
||||
yapf -i tools/*.py
|
||||
prettier --write \
|
||||
js/deno.d.ts \
|
||||
js/main.ts \
|
||||
js/mock_runtime.js \
|
||||
js/package.json \
|
||||
js/tsconfig.json
|
||||
# Do not format these.
|
||||
# js/msg.pb.js
|
||||
# js/msg.pb.d.ts
|
4
deno2/tools/lint.sh
Executable file
4
deno2/tools/lint.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd `dirname "$0"`/..
|
||||
set -e -v
|
||||
cpplint --repository=. *.cc *.h include/*.h
|
Loading…
Reference in a new issue