Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More flatbuffers work in TS/C++. Demonstrate linking rust lib into deno_cc. #334

Merged
merged 2 commits into from
Jul 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import("//build_extra/rust/rust.gni")
config("deno_config") {
include_dirs = [ "third_party/v8" ] # This allows us to v8/src/base/ libraries.
configs = [ "third_party/v8:external_config" ]
if (is_debug) {
defines = [ "DEBUG" ]
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the DCHECK below

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprising that DEBUG wasn't already set...

}

rust_executable("deno") {
Expand All @@ -26,14 +29,21 @@ rust_component("libc") {
]
}

rust_component("handlers") {
source_root = "src/handlers.rs"
extern = [ ":libc" ]
}

executable("deno_cc") {
sources = [
"src/main.cc",
]
deps = [
":flatbufferjs",
":handlers",
":libdeno",
":msg_cpp",
"//build_extra/rust:stdlib",
]
configs += [ ":deno_config" ]
}
Expand Down Expand Up @@ -69,10 +79,10 @@ static_library("libdeno") {
v8_source_set("deno_nosnapshot") {
sources = [
"src/binding.cc",
"src/internal.h",
"src/deno.h",
"src/file_util.cc",
"src/file_util.h",
"src/deno.h",
"src/internal.h",
]
deps = [
"third_party/v8:v8_monolith",
Expand All @@ -99,8 +109,16 @@ flatbuffer("msg_cpp") {
run_node("bundle") {
out_dir = "$target_gen_dir/bundle/"
sources = [
"js/console.ts",
"js/deno.d.ts",
"js/dispatch.ts",
"js/globals.ts",
"js/main.ts",
"js/msg_generated.ts",
"js/os.ts",
"js/runtime.ts",
"js/types.ts",
"js/util.ts",
"package.json", # The `browserslist` field controls Babel behavior.
]
outputs = [
Expand Down
6 changes: 2 additions & 4 deletions js/console.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const print = V8Worker2.print;

// tslint:disable-next-line:no-any
type ConsoleContext = Set<any>;

Expand Down Expand Up @@ -102,15 +100,15 @@ function stringifyArgs(args: any[]): string {
export class Console {
// tslint:disable-next-line:no-any
log(...args: any[]): void {
print(stringifyArgs(args));
deno.print(stringifyArgs(args));
}

debug = this.log;
info = this.log;

// tslint:disable-next-line:no-any
warn(...args: any[]): void {
print(`ERROR: ${stringifyArgs(args)}`);
deno.print(`ERROR: ${stringifyArgs(args)}`);
}

error = this.warn;
Expand Down
4 changes: 2 additions & 2 deletions js/deno.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright 2018 Ryan Dahl <[email protected]>
// All rights reserved. MIT License.
type MessageCallback = (msg: ArrayBuffer) => void;
type MessageCallback = (channel: string, msg: ArrayBuffer) => void;

interface Deno {
recv(channel: string, cb: MessageCallback): void;
recv(cb: MessageCallback): void;
send(channel: string, msg: ArrayBuffer): null | ArrayBuffer;
print(x: string): void;
}
Expand Down
55 changes: 6 additions & 49 deletions js/dispatch.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// Copyright 2018 Ryan Dahl <[email protected]>
// All rights reserved. MIT License.
import { typedArrayToArrayBuffer } from "./util";
import { _global } from "./globals";
import { deno as pb } from "./msg.pb";
import { deno as fbs } from "./msg_generated";

export type MessageCallback = (msg: Uint8Array) => void;
//type MessageStructCallback = (msg: pb.IMsg) => void;

const send = V8Worker2.send;
const channels = new Map<string, MessageCallback[]>();

export function sub(channel: string, cb: MessageCallback): void {
Expand All @@ -19,55 +17,14 @@ export function sub(channel: string, cb: MessageCallback): void {
subscribers.push(cb);
}

/*
export function subMsg(channel: string, cb: MessageStructCallback): void {
sub(channel, (payload: Uint8Array) => {
const msg = pb.Msg.decode(payload);
if (msg.error != null) {
f.onError(new Error(msg.error));
} else {
cb(msg);
}
});
}
*/

export function pub(channel: string, payload: Uint8Array): null | ArrayBuffer {
const msg = pb.BaseMsg.fromObject({ channel, payload });
const ui8 = pb.BaseMsg.encode(msg).finish();
const ab = typedArrayToArrayBuffer(ui8);
return send(ab);
}

// Internal version of "pub".
// TODO add internal version of "sub"
export function pubInternal(channel: string, obj: pb.IMsg): null | pb.Msg {
const msg = pb.Msg.fromObject(obj);
const ui8 = pb.Msg.encode(msg).finish();
const resBuf = pub(channel, ui8);
if (resBuf != null && resBuf.byteLength > 0) {
const res = pb.Msg.decode(new Uint8Array(resBuf));
if (res != null && res.error != null && res.error.length > 0) {
throw Error(res.error);
}
return res;
} else {
return null;
}
}

V8Worker2.recv((ab: ArrayBuffer) => {
const msg = pb.BaseMsg.decode(new Uint8Array(ab));
const subscribers = channels.get(msg.channel);
deno.recv((channel: string, ab: ArrayBuffer) => {
const subscribers = channels.get(channel);
if (subscribers == null) {
throw Error(`No subscribers for channel "${msg.channel}".`);
throw Error(`No subscribers for channel "${channel}".`);
}

const ui8 = new Uint8Array(ab);
for (const subscriber of subscribers) {
subscriber(msg.payload);
subscriber(ui8);
}
});

// Delete the V8Worker2 from the global object, so that no one else can receive
// messages.
_global["V8Worker2"] = null;
28 changes: 14 additions & 14 deletions js/globals.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright 2018 Ryan Dahl <[email protected]>
// All rights reserved. MIT License.
import * as timer from "./timers";

// If you use the eval function indirectly, by invoking it via a reference
// other than eval, as of ECMAScript 5 it works in the global scope rather than
Expand All @@ -11,22 +10,23 @@ export const globalEval = eval;

// A reference to the global object.
// TODO The underscore is because it's conflicting with @types/node.
export const _global = globalEval("this");
export const window = globalEval("this");

_global["window"] = _global; // Create a window object.
import "./url";
window["window"] = window; // Create a window object.
// import "./url";

_global["setTimeout"] = timer.setTimeout;
_global["setInterval"] = timer.setInterval;
_global["clearTimeout"] = timer.clearTimer;
_global["clearInterval"] = timer.clearTimer;
// import * as timer from "./timers";
// window["setTimeout"] = timer.setTimeout;
// window["setInterval"] = timer.setInterval;
// window["clearTimeout"] = timer.clearTimer;
// window["clearInterval"] = timer.clearTimer;

import { Console } from "./console";
_global["console"] = new Console();
window["console"] = new Console();

import { fetch } from "./fetch";
_global["fetch"] = fetch;
// import { fetch } from "./fetch";
// window["fetch"] = fetch;

import { TextEncoder, TextDecoder } from "text-encoding";
_global["TextEncoder"] = TextEncoder;
_global["TextDecoder"] = TextDecoder;
// import { TextEncoder, TextDecoder } from "text-encoding";
// window["TextEncoder"] = TextEncoder;
// window["TextDecoder"] = TextDecoder;
55 changes: 40 additions & 15 deletions js/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,59 @@ import * as ts from "typescript";

import { flatbuffers } from "flatbuffers";
import { deno as fbs } from "./msg_generated";
import { assert } from "./util";

// import * as runtime from "./runtime";

const globalEval = eval;
const window = globalEval("this");

function startMsg(): ArrayBuffer {
const builder = new flatbuffers.Builder();
const msg = fbs.Start.createStart(builder, 0);
fbs.Base.startBase(builder);
fbs.Base.addMsg(builder, msg);
fbs.Base.addMsgType(builder, fbs.Any.Start);
builder.finish(fbs.Base.endBase(builder));
return typedArrayToArrayBuffer(builder.asUint8Array());
}

window["denoMain"] = () => {
deno.print(`ts.version: ${ts.version}`);
const res = deno.send("startDeno2", emptyArrayBuffer());
// deno.print(`after`);
const resUi8 = new Uint8Array(res);

const bb = new flatbuffers.ByteBuffer(resUi8);
const msg = fbs.Msg.getRootAsMsg(bb);
// First we send an empty "Start" message to let the privlaged side know we
// are ready. The response should be a "StartRes" message containing the CLI
// argv and other info.
const res = deno.send("start", startMsg());

// TODO(ry) Remove this conditional once main.rs gets up to speed.
if (res == null) {
console.log(`The 'Start' message got a null response. Normally this would
be an error but main.rs currently does this."); Exiting without error.`);
return;
}

// startDebugFlag: debugFlag,
// startMainJs: mainJs,
// startMainMap: mainMap
const cwd = msg.startCwd();
// Deserialize res into startResMsg.
const bb = new flatbuffers.ByteBuffer(new Uint8Array(res));
const base = fbs.Base.getRootAsBase(bb);
assert(fbs.Any.StartRes === base.msgType());
const startResMsg = new fbs.StartRes();
assert(base.msg(startResMsg) != null);

const cwd = startResMsg.cwd();
deno.print(`cwd: ${cwd}`);

const argv: string[] = [];
for (let i = 0; i < msg.startArgvLength(); i++) {
argv.push(msg.startArgv(i));
for (let i = 0; i < startResMsg.argvLength(); i++) {
argv.push(startResMsg.argv(i));
}
deno.print(`argv ${argv}`);

/* TODO(ry) Uncomment to test further message passing.
const inputFn = argv[0];
const mod = runtime.resolveModule(inputFn, `${cwd}/`);
mod.compileAndRun();
*/
};

function typedArrayToArrayBuffer(ta: Uint8Array): ArrayBuffer {
Expand All @@ -36,7 +65,3 @@ function typedArrayToArrayBuffer(ta: Uint8Array): ArrayBuffer {
ta.byteOffset + ta.byteLength
) as ArrayBuffer;
}

function emptyArrayBuffer(): ArrayBuffer {
return typedArrayToArrayBuffer(new Uint8Array([]));
}
Loading