mirror of
https://github.com/denoland/deno.git
synced 2025-02-01 12:16:11 -05:00
Add deno2 prototype from external repo.
This commit is contained in:
parent
fe9ea6dcf8
commit
110ddab670
24 changed files with 4668 additions and 0 deletions
38
deno2/.gclient
Normal file
38
deno2/.gclient
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
solutions = [{
|
||||||
|
'url': 'https://chromium.googlesource.com/v8/v8.git',
|
||||||
|
'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/tools/gyp': 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',
|
||||||
|
'name': 'third_party/protobuf',
|
||||||
|
'deps_file': 'DEPS'
|
||||||
|
}, {
|
||||||
|
'url':
|
||||||
|
'https://chromium.googlesource.com/chromium/src/tools/protoc_wrapper',
|
||||||
|
'name':
|
||||||
|
'tools/protoc_wrapper'
|
||||||
|
}, {
|
||||||
|
'url':
|
||||||
|
'https://chromium.googlesource.com/chromium/src/third_party/zlib',
|
||||||
|
'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"
|
||||||
|
#]
|
||||||
|
}
|
134
deno2/BUILD.gn
Normal file
134
deno2/BUILD.gn
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
import("//third_party/protobuf/proto_library.gni")
|
||||||
|
import("//v8/gni/v8.gni")
|
||||||
|
import("//v8/snapshot_toolchain.gni")
|
||||||
|
|
||||||
|
proto_library("msg_proto") {
|
||||||
|
sources = [
|
||||||
|
"msg.proto",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
action("run_parcel") {
|
||||||
|
sources = [
|
||||||
|
"js/main.ts",
|
||||||
|
]
|
||||||
|
outputs = [
|
||||||
|
"$target_gen_dir/main.js",
|
||||||
|
"$target_gen_dir/main.map",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Our script imports this Python file so we want to rebuild if it changes.
|
||||||
|
# inputs = [ "helper_library.py" ]
|
||||||
|
|
||||||
|
# Note that we have to manually pass the sources to our script if the
|
||||||
|
# script needs them as inputs.
|
||||||
|
script = "js/run_node.py"
|
||||||
|
root = root_build_dir + "/../../js"
|
||||||
|
args = [
|
||||||
|
"./node_modules/.bin/parcel",
|
||||||
|
"build",
|
||||||
|
"--log-level=1",
|
||||||
|
"--no-minify",
|
||||||
|
"--out-dir=" + rebase_path(target_gen_dir, root),
|
||||||
|
] + rebase_path(sources, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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) {
|
||||||
|
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||||
|
deps = [ ":snapshot_creator" ] + invoker.deps
|
||||||
|
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),
|
||||||
|
]
|
||||||
|
data = [
|
||||||
|
invoker.js,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generates $target_gen_dir/snapshot_bundle.cc
|
||||||
|
create_snapshot("deno") {
|
||||||
|
js = "$target_gen_dir/main.js"
|
||||||
|
deps = [
|
||||||
|
":run_parcel",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
v8_executable("snapshot_creator") {
|
||||||
|
sources = [
|
||||||
|
"deno.cc",
|
||||||
|
"deno.h",
|
||||||
|
"snapshot_creator.cc",
|
||||||
|
]
|
||||||
|
configs = [ "v8:libplatform_config" ]
|
||||||
|
deps = [
|
||||||
|
"v8:v8",
|
||||||
|
"v8:v8_libbase",
|
||||||
|
"v8:v8_libplatform",
|
||||||
|
"v8:v8_libsampler",
|
||||||
|
"//build/config:exe_and_shlib_deps",
|
||||||
|
"//build/win:default_exe_manifest",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
v8_executable("deno") {
|
||||||
|
sources = [
|
||||||
|
"deno.cc",
|
||||||
|
"deno.h",
|
||||||
|
"main.cc",
|
||||||
|
]
|
||||||
|
include_dirs = [ target_gen_dir ]
|
||||||
|
configs = [ "v8:libplatform_config" ]
|
||||||
|
deps = [
|
||||||
|
":create_snapshot_deno",
|
||||||
|
":msg_proto",
|
||||||
|
"v8:v8",
|
||||||
|
"v8:v8_libbase",
|
||||||
|
"v8:v8_libplatform",
|
||||||
|
"v8:v8_libsampler",
|
||||||
|
"//build/config:exe_and_shlib_deps",
|
||||||
|
"//build/win:default_exe_manifest",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
executable("deno_test") {
|
||||||
|
testonly = true
|
||||||
|
sources = [
|
||||||
|
"deno_test.cc",
|
||||||
|
]
|
||||||
|
deps = [
|
||||||
|
"//testing/gtest:gtest",
|
||||||
|
]
|
||||||
|
}
|
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 this
|
||||||
|
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
|
364
deno2/deno.cc
Normal file
364
deno2/deno.cc
Normal file
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
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.h"
|
||||||
|
|
||||||
|
#define CHECK(x) assert(x) // TODO(ry) use V8's CHECK.
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exits the process.
|
||||||
|
void HandleException(Deno* d, v8::Local<v8::Value> exception) {
|
||||||
|
v8::HandleScope handle_scope(d->isolate);
|
||||||
|
auto context = d->context.Get(d->isolate);
|
||||||
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
|
auto message = v8::Exception::CreateMessage(d->isolate, exception);
|
||||||
|
auto onerrorStr = v8::String::NewFromUtf8(d->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(d->isolate, exception);
|
||||||
|
printf("Unhandled Exception %s\n", ToCString(exceptionStr));
|
||||||
|
message->PrintCurrentStackTrace(d->isolate, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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();
|
||||||
|
HandleException(d, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||||
|
bool first = true;
|
||||||
|
auto* isolate = args.GetIsolate();
|
||||||
|
for (int i = 0; i < args.Length(); i++) {
|
||||||
|
v8::HandleScope handle_scope(isolate);
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
v8::String::Utf8Value str(isolate, args[i]);
|
||||||
|
const char* cstr = ToCString(str);
|
||||||
|
printf("%s", cstr);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the recv callback.
|
||||||
|
void Recv(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);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> v = args[0];
|
||||||
|
assert(v->IsFunction());
|
||||||
|
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(v);
|
||||||
|
|
||||||
|
d->recv.Reset(isolate, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from JavaScript, routes message to golang.
|
||||||
|
void Send(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);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> v = args[0];
|
||||||
|
assert(v->IsArrayBuffer());
|
||||||
|
|
||||||
|
auto ab = v8::Local<v8::ArrayBuffer>::Cast(v);
|
||||||
|
auto contents = ab->GetContents();
|
||||||
|
|
||||||
|
void* buf = contents.Data();
|
||||||
|
int buflen = static_cast<int>(contents.ByteLength());
|
||||||
|
|
||||||
|
auto retbuf = d->cb(d, DenoBuf{buf, buflen});
|
||||||
|
if (retbuf.data) {
|
||||||
|
auto ab = v8::ArrayBuffer::New(d->isolate, retbuf.data, retbuf.len,
|
||||||
|
v8::ArrayBufferCreationMode::kInternalized);
|
||||||
|
/*
|
||||||
|
// I'm slightly worried the above v8::ArrayBuffer construction leaks memory
|
||||||
|
// the following might be a safer way to do it.
|
||||||
|
auto ab = v8::ArrayBuffer::New(d->isolate, retbuf.len);
|
||||||
|
auto contents = ab->GetContents();
|
||||||
|
memcpy(contents.Data(), retbuf.data, retbuf.len);
|
||||||
|
free(retbuf.data);
|
||||||
|
*/
|
||||||
|
args.GetReturnValue().Set(handle_scope.Escape(ab));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t external_references[] = {reinterpret_cast<intptr_t>(Print),
|
||||||
|
reinterpret_cast<intptr_t>(Recv),
|
||||||
|
reinterpret_cast<intptr_t>(Send), 0};
|
||||||
|
|
||||||
|
const char* v8_version() { return v8::V8::GetVersion(); }
|
||||||
|
|
||||||
|
void v8_set_flags(int* argc, char** argv) {
|
||||||
|
v8::V8::SetFlagsFromCommandLine(argc, argv, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); }
|
||||||
|
|
||||||
|
int deno_load(Deno* d, const char* name_s, const char* source_s) {
|
||||||
|
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 name = v8_str(name_s);
|
||||||
|
auto source = v8_str(source_s);
|
||||||
|
|
||||||
|
v8::ScriptOrigin origin(name);
|
||||||
|
|
||||||
|
auto script = v8::Script::Compile(context, source, &origin);
|
||||||
|
|
||||||
|
if (script.IsEmpty()) {
|
||||||
|
assert(try_catch.HasCaught());
|
||||||
|
HandleException(d, try_catch.Exception());
|
||||||
|
assert(false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = script.ToLocalChecked()->Run(context);
|
||||||
|
|
||||||
|
if (result.IsEmpty()) {
|
||||||
|
assert(try_catch.HasCaught());
|
||||||
|
HandleException(d, try_catch.Exception());
|
||||||
|
assert(false);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from golang. Must route message to javascript lang.
|
||||||
|
// non-zero return value indicates error. check deno_last_exception().
|
||||||
|
int deno_send(Deno* d, DenoBuf buf) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
v8::Local<v8::Function> recv =
|
||||||
|
v8::Local<v8::Function>::New(d->isolate, d->recv);
|
||||||
|
if (recv.IsEmpty()) {
|
||||||
|
d->last_exception = "V8Deno2.recv has not been called.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[1];
|
||||||
|
args[0] = v8::ArrayBuffer::New(d->isolate, buf.data, buf.len,
|
||||||
|
v8::ArrayBufferCreationMode::kInternalized);
|
||||||
|
assert(!args[0].IsEmpty());
|
||||||
|
assert(!try_catch.HasCaught());
|
||||||
|
|
||||||
|
recv->Call(context->Global(), 1, args);
|
||||||
|
|
||||||
|
if (try_catch.HasCaught()) {
|
||||||
|
HandleException(d, try_catch.Exception());
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void v8_init() {
|
||||||
|
// v8::V8::InitializeICUDefaultLocation(argv[0]);
|
||||||
|
// v8::V8::InitializeExternalStartupData(argv[0]);
|
||||||
|
auto p = v8::platform::CreateDefaultPlatform();
|
||||||
|
v8::V8::InitializePlatform(p);
|
||||||
|
v8::V8::Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno* deno_new(void* data, RecvCallback cb) {
|
||||||
|
Deno* d = new Deno;
|
||||||
|
d->cb = cb;
|
||||||
|
d->data = data;
|
||||||
|
v8::Isolate::CreateParams params;
|
||||||
|
params.array_buffer_allocator =
|
||||||
|
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
|
||||||
|
v8::Isolate* isolate = v8::Isolate::New(params);
|
||||||
|
deno_add_isolate(d, isolate);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno* deno_from_snapshot(v8::StartupData* blob, void* data, RecvCallback cb) {
|
||||||
|
Deno* d = new Deno;
|
||||||
|
d->cb = cb;
|
||||||
|
d->data = data;
|
||||||
|
v8::Isolate::CreateParams params;
|
||||||
|
params.snapshot_blob = blob;
|
||||||
|
params.array_buffer_allocator =
|
||||||
|
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
|
||||||
|
params.external_references = external_references;
|
||||||
|
v8::Isolate* isolate = v8::Isolate::New(params);
|
||||||
|
deno_add_isolate(d, isolate);
|
||||||
|
|
||||||
|
v8::Isolate::Scope isolate_scope(isolate);
|
||||||
|
{
|
||||||
|
v8::HandleScope handle_scope(isolate);
|
||||||
|
auto context = v8::Context::New(isolate);
|
||||||
|
d->context.Reset(d->isolate, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deno_add_isolate(Deno* d, v8::Isolate* isolate) {
|
||||||
|
d->isolate = isolate;
|
||||||
|
// Leaving this code here because it will probably be useful later on, but
|
||||||
|
// disabling it now as I haven't got tests for the desired behavior.
|
||||||
|
// d->isolate->SetCaptureStackTraceForUncaughtExceptions(true);
|
||||||
|
// d->isolate->SetAbortOnUncaughtExceptionCallback(AbortOnUncaughtExceptionCallback);
|
||||||
|
// d->isolate->AddMessageListener(MessageCallback2);
|
||||||
|
// d->isolate->SetFatalErrorHandler(FatalErrorCallback2);
|
||||||
|
d->isolate->SetPromiseRejectCallback(ExitOnPromiseRejectCallback);
|
||||||
|
d->isolate->SetData(0, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::StartupData SerializeInternalField(v8::Local<v8::Object> holder, int index,
|
||||||
|
void* data) {
|
||||||
|
printf("SerializeInternalField %d\n", index);
|
||||||
|
v8::StartupData sd;
|
||||||
|
sd.data = "a";
|
||||||
|
sd.raw_size = 1;
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::StartupData deno_make_snapshot(const char* js_filename,
|
||||||
|
const char* js_source) {
|
||||||
|
auto creator = new v8::SnapshotCreator(external_references);
|
||||||
|
auto* isolate = creator->GetIsolate();
|
||||||
|
|
||||||
|
Deno* d = new Deno;
|
||||||
|
deno_add_isolate(d, isolate);
|
||||||
|
|
||||||
|
v8::Isolate::Scope isolate_scope(isolate);
|
||||||
|
{
|
||||||
|
v8::HandleScope handle_scope(isolate);
|
||||||
|
|
||||||
|
v8::Local<v8::Context> context = v8::Context::New(d->isolate);
|
||||||
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
|
d->context.Reset(d->isolate, context);
|
||||||
|
|
||||||
|
auto global = context->Global();
|
||||||
|
|
||||||
|
auto print_tmpl = v8::FunctionTemplate::New(isolate, Print);
|
||||||
|
auto print_val = print_tmpl->GetFunction(context).ToLocalChecked();
|
||||||
|
CHECK(global->Set(context, v8_str("deno_print"), print_val).FromJust());
|
||||||
|
|
||||||
|
auto recv_tmpl = v8::FunctionTemplate::New(isolate, Recv);
|
||||||
|
auto recv_val = recv_tmpl->GetFunction(context).ToLocalChecked();
|
||||||
|
CHECK(global->Set(context, v8_str("deno_recv"), recv_val).FromJust());
|
||||||
|
|
||||||
|
auto send_tmpl = v8::FunctionTemplate::New(isolate, Send);
|
||||||
|
auto send_val = send_tmpl->GetFunction(context).ToLocalChecked();
|
||||||
|
CHECK(global->Set(context, v8_str("deno_send"), send_val).FromJust());
|
||||||
|
|
||||||
|
creator->SetDefaultContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = deno_load(d, js_filename, js_source);
|
||||||
|
assert(r == 0);
|
||||||
|
|
||||||
|
d->context.Reset(); // Delete persistant handles.
|
||||||
|
d->recv.Reset(); // Delete persistant handles.
|
||||||
|
|
||||||
|
auto snapshot_blob =
|
||||||
|
creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
|
||||||
|
|
||||||
|
return snapshot_blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deno_dispose(Deno* d) {
|
||||||
|
d->isolate->Dispose();
|
||||||
|
delete (d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deno_terminate_execution(Deno* d) { d->isolate->TerminateExecution(); }
|
55
deno2/deno.h
Normal file
55
deno2/deno.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||||
|
// All rights reserved. MIT License.
|
||||||
|
#ifndef DENO_H_
|
||||||
|
#define DENO_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "v8/include/v8.h"
|
||||||
|
|
||||||
|
// Data that gets transmitted.
|
||||||
|
struct buf_s {
|
||||||
|
void* data;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
typedef struct buf_s DenoBuf;
|
||||||
|
// Deno = Wrapped Isolate.
|
||||||
|
struct deno_s;
|
||||||
|
typedef struct deno_s Deno;
|
||||||
|
// The callback from V8 when data is sent.
|
||||||
|
typedef DenoBuf (*RecvCallback)(Deno* d, DenoBuf buf);
|
||||||
|
struct deno_s {
|
||||||
|
v8::Isolate* isolate;
|
||||||
|
std::string last_exception;
|
||||||
|
v8::Persistent<v8::Function> recv;
|
||||||
|
v8::Persistent<v8::Context> context;
|
||||||
|
RecvCallback cb;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void v8_init();
|
||||||
|
const char* v8_version();
|
||||||
|
void v8_set_flags(int* argc, char** argv);
|
||||||
|
|
||||||
|
// Constructors:
|
||||||
|
Deno* deno_new(void* data, RecvCallback cb);
|
||||||
|
Deno* deno_from_snapshot(v8::StartupData* blob, void* data, RecvCallback cb);
|
||||||
|
|
||||||
|
v8::StartupData deno_make_snapshot(const char* js_filename,
|
||||||
|
const char* js_source);
|
||||||
|
|
||||||
|
void deno_add_isolate(Deno* d, v8::Isolate* isolate);
|
||||||
|
void* deno_get_data();
|
||||||
|
|
||||||
|
// Returns nonzero on error.
|
||||||
|
// Get error text with deno_last_exception().
|
||||||
|
int deno_load(Deno* d, const char* name_s, const char* source_s);
|
||||||
|
|
||||||
|
// Returns nonzero on error.
|
||||||
|
int deno_send(Deno* d, DenoBuf buf);
|
||||||
|
|
||||||
|
const char* deno_last_exception(Deno* d);
|
||||||
|
|
||||||
|
void deno_dispose(Deno* d);
|
||||||
|
void deno_terminate_execution(Deno* d);
|
||||||
|
|
||||||
|
#endif // DENO_H_
|
15
deno2/deno_test.cc
Normal file
15
deno2/deno_test.cc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||||
|
// All rights reserved. MIT License.
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "./deno.h"
|
||||||
|
|
||||||
|
TEST(SnapshotTest, InitializesCorrectly) {
|
||||||
|
EXPECT_TRUE(true);
|
||||||
|
// TODO(ry) add actual tests
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
7
deno2/js/main.ts
Normal file
7
deno2/js/main.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
const globalEval = eval;
|
||||||
|
const window = globalEval("this");
|
||||||
|
window['foo'] = () => {
|
||||||
|
deno_print("Hello world from foo");
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
|
6
deno2/js/package.json
Normal file
6
deno2/js/package.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"parcel-bundler": "^1.8.1",
|
||||||
|
"typescript": "^2.9.1"
|
||||||
|
}
|
||||||
|
}
|
14
deno2/js/run_node.py
Executable file
14
deno2/js/run_node.py
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
gn can only run python scripts.
|
||||||
|
Also Node programs except to be run with cwd = $root_dir/js so it can resolve
|
||||||
|
node_modules.
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
js_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
os.chdir(js_path)
|
||||||
|
args = ["node"] + sys.argv[1:]
|
||||||
|
sys.exit(subprocess.call(args))
|
3535
deno2/js/yarn.lock
Normal file
3535
deno2/js/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
33
deno2/main.cc
Normal file
33
deno2/main.cc
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||||
|
// All rights reserved. MIT License.
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "v8/include/v8.h"
|
||||||
|
|
||||||
|
#include "./deno.h"
|
||||||
|
#include "natives_deno.cc"
|
||||||
|
#include "snapshot_deno.cc"
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
v8_init();
|
||||||
|
|
||||||
|
auto natives_blob = *StartupBlob_natives();
|
||||||
|
printf("natives_blob %d bytes\n", natives_blob.raw_size);
|
||||||
|
|
||||||
|
auto snapshot_blob = *StartupBlob_snapshot();
|
||||||
|
printf("snapshot_blob %d bytes\n", snapshot_blob.raw_size);
|
||||||
|
|
||||||
|
v8::V8::SetNativesDataBlob(&natives_blob);
|
||||||
|
v8::V8::SetSnapshotDataBlob(&snapshot_blob);
|
||||||
|
|
||||||
|
Deno* d = deno_from_snapshot(&snapshot_blob, NULL, NULL);
|
||||||
|
int r = deno_load(d, "main2.js", "foo();");
|
||||||
|
if (r != 0) {
|
||||||
|
printf("Error! %s\n", deno_last_exception(d));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* v = v8::V8::GetVersion();
|
||||||
|
printf("Hello World. V8 version %s\n", v);
|
||||||
|
}
|
102
deno2/msg.proto
Normal file
102
deno2/msg.proto
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||||
|
// All rights reserved. MIT License.
|
||||||
|
syntax = "proto3";
|
||||||
|
package main;
|
||||||
|
option go_package = "deno";
|
||||||
|
|
||||||
|
message BaseMsg {
|
||||||
|
string channel = 1;
|
||||||
|
bytes payload = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Msg {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
Command command = 1;
|
||||||
|
|
||||||
|
// We avoid creating a message for each command (and use oneof or any types)
|
||||||
|
// In order to reduce code in the size of the generated javascript
|
||||||
|
// "msg.pb.js". It seems that each new message adds 20k and we want to
|
||||||
|
// potentially add many hundreds of commands. Therefore we just prefix command
|
||||||
|
// arguments by their name.
|
||||||
|
|
||||||
|
// ERROR
|
||||||
|
string error = 2;
|
||||||
|
|
||||||
|
// START
|
||||||
|
string start_cwd = 10;
|
||||||
|
repeated string start_argv = 11;
|
||||||
|
bool start_debug_flag = 12;
|
||||||
|
string start_main_js = 13; // The contents of dist/main.js
|
||||||
|
string start_main_map = 14; // The contents of dist/main.map
|
||||||
|
|
||||||
|
// CODE_FETCH
|
||||||
|
string code_fetch_module_specifier = 20;
|
||||||
|
string code_fetch_containing_file = 21;
|
||||||
|
|
||||||
|
// CODE_FETCH_RES
|
||||||
|
// If it's a non-http module, moduleName and filename will be the same.
|
||||||
|
// For http modules, moduleName is its resolved http URL, and filename
|
||||||
|
// is the location of the locally downloaded source code.
|
||||||
|
string code_fetch_res_module_name = 30;
|
||||||
|
string code_fetch_res_filename = 31;
|
||||||
|
string code_fetch_res_source_code = 32;
|
||||||
|
string code_fetch_res_output_code = 33; // Non-empty only if cached.
|
||||||
|
|
||||||
|
// CODE_CACHE
|
||||||
|
string code_cache_filename = 41;
|
||||||
|
string code_cache_source_code = 42;
|
||||||
|
string code_cache_output_code = 43;
|
||||||
|
|
||||||
|
// EXIT
|
||||||
|
int32 exit_code = 50;
|
||||||
|
|
||||||
|
// TIMER_START
|
||||||
|
int32 timer_start_id = 60;
|
||||||
|
bool timer_start_interval = 61;
|
||||||
|
int32 timer_start_duration = 62; // In milliseconds.
|
||||||
|
|
||||||
|
// TIMER_READY
|
||||||
|
int32 timer_ready_id = 70;
|
||||||
|
bool timer_ready_done = 71;
|
||||||
|
|
||||||
|
// TIMER_CLEAR
|
||||||
|
int32 timer_clear_id = 80;
|
||||||
|
|
||||||
|
// FETCH_REQ
|
||||||
|
int32 fetch_req_id = 90;
|
||||||
|
string fetch_req_url = 91;
|
||||||
|
// repeated string fetch_req_header_line = 91
|
||||||
|
|
||||||
|
// FETCH_RES
|
||||||
|
int32 fetch_res_id = 100;
|
||||||
|
int32 fetch_res_status = 101;
|
||||||
|
repeated string fetch_res_header_line = 102;
|
||||||
|
bytes fetch_res_body = 103;
|
||||||
|
|
||||||
|
// READ_FILE_SYNC
|
||||||
|
string read_file_sync_filename = 110;
|
||||||
|
|
||||||
|
// READ_FILE_SYNC_RES
|
||||||
|
bytes read_file_sync_data = 120;
|
||||||
|
|
||||||
|
// WRITE_FILE_SYNC
|
||||||
|
string write_file_sync_filename = 130;
|
||||||
|
bytes write_file_sync_data = 131;
|
||||||
|
uint32 write_file_sync_perm = 132;
|
||||||
|
// write_file_sync_perm specified by https://godoc.org/os#FileMode
|
||||||
|
}
|
145
deno2/snapshot_creator.cc
Normal file
145
deno2/snapshot_creator.cc
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
|
||||||
|
// All rights reserved. MIT License.
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "v8/include/v8.h"
|
||||||
|
|
||||||
|
#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_init();
|
||||||
|
|
||||||
|
auto js_data = ReadFile(js_fn);
|
||||||
|
auto natives_blob = ReadFile(natives_in_bin);
|
||||||
|
auto snapshot_in_blob = ReadFile(snapshot_in_bin);
|
||||||
|
|
||||||
|
v8::V8::SetNativesDataBlob(&natives_blob);
|
||||||
|
v8::V8::SetSnapshotDataBlob(&snapshot_in_blob);
|
||||||
|
|
||||||
|
auto snapshot_blob = deno_make_snapshot(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();
|
||||||
|
}
|
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()
|
6
deno2/tools/format.sh
Executable file
6
deno2/tools/format.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
cd `dirname "$0"`/..
|
||||||
|
clang-format -i -style Google *.cc *.h
|
||||||
|
gn format BUILD.gn
|
||||||
|
gn format .gn
|
||||||
|
yapf -i tools/*.py
|
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
|
||||||
|
cpplint *.cc *.h
|
Loading…
Add table
Reference in a new issue