1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

Demo protobufs in deno2.

Adds deno_set_response() to allow stack allocated responses.
This commit is contained in:
Ryan Dahl 2018-06-13 19:38:22 +02:00
parent f97216609d
commit 4ac67cf343
10 changed files with 88 additions and 35 deletions

View file

@ -8,6 +8,8 @@ executable("deno") {
]
deps = [
":libdeno",
":msg_proto",
"//third_party/protobuf:protoc_lib",
]
}
@ -45,7 +47,6 @@ source_set("deno_nosnapshot") {
]
include_dirs = [ "include/" ]
deps = [
":msg_proto",
"v8:v8",
"v8:v8_libbase",
"v8:v8_libplatform",
@ -66,6 +67,7 @@ proto_library("msg_proto") {
sources = [
"msg.proto",
]
generate_python = false
}
template("run_node") {
@ -78,13 +80,15 @@ template("run_node") {
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",
"js/msg.pb.d.ts",
"js/msg.pb.js",
]
outputs = [
out_dir + "main.js",
]
deps = [
":protobufjs",
":run_tsc",
]
args = [
@ -111,7 +115,6 @@ run_node("run_tsc") {
]
outputs = [
out_dir + "/main.js",
out_dir + "/main.map",
]
deps = [
":protobufjs",

View file

@ -154,15 +154,12 @@ void Pub(const v8::FunctionCallbackInfo<v8::Value>& args) {
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));
}
assert(d->currentArgs == nullptr);
d->currentArgs = &args;
d->cb(d, channel, buf);
d->currentArgs = nullptr;
}
bool Execute(v8::Local<v8::Context> context, const char* js_filename,
@ -334,6 +331,13 @@ bool deno_pub(Deno* d, const char* channel, deno_buf buf) {
return true;
}
void deno_set_response(Deno* d, deno_buf buf) {
// TODO(ry) Support zero-copy.
auto ab = v8::ArrayBuffer::New(d->isolate, buf.len);
memcpy(ab->GetContents().Data(), buf.data, buf.len);
d->currentArgs->GetReturnValue().Set(ab);
}
void deno_delete(Deno* d) {
d->isolate->Dispose();
delete d;

View file

@ -11,6 +11,7 @@ extern "C" {
// deno_s = Wrapped Isolate.
struct deno_s {
v8::Isolate* isolate;
const v8::FunctionCallbackInfo<v8::Value>* currentArgs;
std::string last_exception;
v8::Persistent<v8::Function> sub;
v8::Persistent<v8::Context> context;

View file

@ -45,6 +45,7 @@ Deno* NewFromSnapshot(void* data, deno_sub_cb cb) {
v8::DeserializeInternalFieldsCallback(DeserializeInternalFields, nullptr);
Deno* d = new Deno;
d->currentArgs = nullptr;
d->cb = cb;
d->data = data;
v8::Isolate::CreateParams params;

View file

@ -19,8 +19,7 @@ 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);
typedef void (*deno_sub_cb)(Deno* d, const char* channel, deno_buf buf);
void deno_init();
const char* deno_v8_version();
@ -37,6 +36,11 @@ bool deno_execute(Deno* d, const char* js_filename, const char* js_source);
// value indicates error. Check deno_last_exception() for exception text.
bool deno_pub(Deno* d, const char* channel, deno_buf buf);
// Call this inside a deno_sub_cb to respond synchronously to messages.
// If this is not called during the life time of a deno_sub_cb callback
// the denoPub() call in javascript will return null.
void deno_set_response(Deno* d, deno_buf buf);
const char* deno_last_exception(Deno* d);
void deno_terminate_execution(Deno* d);

View file

@ -4,11 +4,32 @@ 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";
const res = denoPub("startDeno2", emptyArrayBuffer());
//denoPrint(`after`);
const resUi8 = new Uint8Array(res);
denoPrint(`before`);
const msg = pb.Msg.decode(resUi8);
denoPrint(`after`);
const {
startCwd: cwd,
startArgv: argv,
startDebugFlag: debugFlag,
startMainJs: mainJs,
startMainMap: mainMap
} = msg;
denoPrint(`cwd: ${cwd}`);
};
function typedArrayToArrayBuffer(ta: Uint8Array): ArrayBuffer {
return ta.buffer.slice(
ta.byteOffset,
ta.byteOffset + ta.byteLength
) as ArrayBuffer;
}
function emptyArrayBuffer(): ArrayBuffer {
return typedArrayToArrayBuffer(new Uint8Array([]));
}

View file

@ -3,13 +3,33 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include "./msg.pb.h"
#include "include/deno.h"
void MessagesFromJS(Deno* d, const char* channel, deno_buf buf) {
printf("MessagesFromJS %s\n", channel);
char cwdbuf[1024];
std::string cwd(getcwd(cwdbuf, sizeof(cwdbuf)));
deno::Msg response;
response.set_command(deno::Msg_Command_START);
response.set_start_cwd(cwd);
std::string output;
assert(response.SerializeToString(&output) == true);
auto bufout = deno_buf{output.c_str(), output.length()};
deno_set_response(d, bufout);
}
int main(int argc, char** argv) {
deno_init();
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(NULL, MessagesFromJS);
bool r = deno_execute(d, "deno_main.js", "denoMain();");
if (!r) {
printf("Error! %s\n", deno_last_exception(d));

View file

@ -5,20 +5,20 @@
#include "include/deno.h"
TEST(MockRuntimeTest, InitializesCorrectly) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
EXPECT_TRUE(deno_execute(d, "a.js", "1 + 2"));
deno_delete(d);
}
TEST(MockRuntimeTest, CanCallFunction) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
EXPECT_TRUE(deno_execute(d, "a.js",
"if (CanCallFunction() != 'foo') throw Error();"));
deno_delete(d);
}
TEST(MockRuntimeTest, ErrorsCorrectly) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
EXPECT_FALSE(deno_execute(d, "a.js", "throw Error()"));
deno_delete(d);
}
@ -26,14 +26,14 @@ TEST(MockRuntimeTest, ErrorsCorrectly) {
deno_buf strbuf(const char* str) { return deno_buf{str, strlen(str)}; }
TEST(MockRuntimeTest, PubSuccess) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
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);
Deno* d = deno_new(nullptr, nullptr);
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")));
@ -41,7 +41,7 @@ TEST(MockRuntimeTest, PubByteLength) {
}
TEST(MockRuntimeTest, PubNoCallback) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
// We didn't call deno_sub(), pubing should fail.
EXPECT_FALSE(deno_pub(d, "PubNoCallback", strbuf("abc")));
deno_delete(d);
@ -49,14 +49,13 @@ TEST(MockRuntimeTest, PubNoCallback) {
TEST(MockRuntimeTest, SubReturnEmpty) {
static int count = 0;
Deno* d = deno_new(NULL, [](auto _, auto channel, auto buf) {
Deno* d = deno_new(nullptr, [](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);
@ -65,14 +64,14 @@ TEST(MockRuntimeTest, SubReturnEmpty) {
TEST(MockRuntimeTest, SubReturnBar) {
static int count = 0;
Deno* d = deno_new(NULL, [](auto _, auto channel, auto buf) {
Deno* d = deno_new(nullptr, [](auto deno, 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");
deno_set_response(deno, strbuf("bar"));
});
EXPECT_TRUE(deno_execute(d, "a.js", "SubReturnBar()"));
EXPECT_EQ(count, 1);
@ -80,13 +79,13 @@ TEST(MockRuntimeTest, SubReturnBar) {
}
TEST(MockRuntimeTest, DoubleSubFails) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
EXPECT_FALSE(deno_execute(d, "a.js", "DoubleSubFails()"));
deno_delete(d);
}
TEST(MockRuntimeTest, TypedArraySnapshots) {
Deno* d = deno_new(NULL, NULL);
Deno* d = deno_new(nullptr, nullptr);
EXPECT_TRUE(deno_execute(d, "a.js", "TypedArraySnapshots()"));
deno_delete(d);
}

View file

@ -136,8 +136,8 @@ int main(int argc, char** argv) {
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());
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();

View file

@ -1,4 +1,4 @@
#!/bin/sh
cd `dirname "$0"`/..
set -e -v
cpplint --repository=. *.cc *.h include/*.h
cpplint --filter=-build/include_subdir --repository=. *.cc *.h include/*.h