Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18c54885f4 | ||
|
|
644e5e4a4d | ||
|
|
ca17e686f2 | ||
|
|
a2ed298d34 | ||
|
|
8509161f7c | ||
|
|
b88ab5a305 | ||
|
|
ac4c2574a6 | ||
|
|
0ba69aec95 | ||
|
|
7ef8da3d79 | ||
|
|
0e9376071e | ||
|
|
d75642d0e8 | ||
|
|
6eb94df293 | ||
|
|
544bf09271 | ||
|
|
b45f75c8f9 | ||
|
|
752d3cdffd | ||
|
|
0371c68bcd | ||
|
|
ae6f591602 | ||
|
|
81aeebf181 | ||
|
|
0cc5054ea2 | ||
|
|
cdda439e4a | ||
|
|
932e589f36 | ||
|
|
46fd0a8b6e | ||
|
|
5e8c4c0b1b | ||
|
|
7ab91af445 | ||
|
|
05644ec31b | ||
|
|
28de5052c0 | ||
|
|
c720781a5f | ||
|
|
d8de1b49ad | ||
|
|
4df200effa | ||
|
|
cbb3ab40fb | ||
|
|
eae9c1c54b | ||
|
|
1abd120c12 | ||
|
|
ca30a96c1c | ||
|
|
d2f4c72d64 | ||
|
|
202e13c66f | ||
|
|
a3e975d43c | ||
|
|
f1e9306cd6 | ||
|
|
c6fe3c2624 | ||
|
|
7fb9018515 | ||
|
|
742d6b5b79 | ||
|
|
ec1721f298 | ||
|
|
5aeffa328a |
No files matched your search
@@ -22,7 +22,7 @@ messages from complete Javascript objects. This actually makes the library
|
|||||||
somewhat nicer syntactically than it would be otherwise, but it is not fast.
|
somewhat nicer syntactically than it would be otherwise, but it is not fast.
|
||||||
|
|
||||||
A pure-Javascript implementation would likely be much faster. See
|
A pure-Javascript implementation would likely be much faster. See
|
||||||
[capnp-js](https://github.com/capnp-js/serialization) for such an
|
[capnp-js](https://github.com/capnp-js) for such an
|
||||||
implementation. Unfortunately, that implementation is incomplete and does not
|
implementation. Unfortunately, that implementation is incomplete and does not
|
||||||
support [RPC](https://github.com/capnp-js/rpc) just yet. Hence, this hack was
|
support [RPC](https://github.com/capnp-js/rpc) just yet. Hence, this hack was
|
||||||
created for short-term use.
|
created for short-term use.
|
||||||
@@ -47,11 +47,11 @@ you must have development headers for Cap'n Proto and Node.js installed, along
|
|||||||
with the `node-gyp` tool and a GCC new enough for Cap'n Proto (at least 4.7).
|
with the `node-gyp` tool and a GCC new enough for Cap'n Proto (at least 4.7).
|
||||||
On Debian/Ubuntu, you can install these like so:
|
On Debian/Ubuntu, you can install these like so:
|
||||||
|
|
||||||
sudo apt-get install nodejs-dev nodejs-legacy capnproto-dev g++
|
sudo apt-get install nodejs-dev nodejs-legacy libcapnp-dev g++
|
||||||
|
|
||||||
### Form source
|
### From source
|
||||||
|
|
||||||
git clone git://github.com/kenton/node-capnp.git
|
git clone git://github.com/capnproto/node-capnp.git
|
||||||
cd node-capnp
|
cd node-capnp
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
@@ -118,6 +118,25 @@ we copied.)
|
|||||||
// object containing the results by name.
|
// object containing the results by name.
|
||||||
promise.then(function(response) {
|
promise.then(function(response) {
|
||||||
console.log(response.namedResult);
|
console.log(response.namedResult);
|
||||||
|
})
|
||||||
|
// If the remote object throws an rpc exception, the promise will be
|
||||||
|
// rejected. The error returned will have a property `kjType`, which
|
||||||
|
// will be a string representation of the exception's `type` field.
|
||||||
|
.catch(function(error) {
|
||||||
|
switch(error.kjType) {
|
||||||
|
case 'failed':
|
||||||
|
console.log("A generic problem occurred:", error.message);
|
||||||
|
break;
|
||||||
|
case 'overloaded':
|
||||||
|
console.log("Resource overload on the remote end:", error.message);
|
||||||
|
break;
|
||||||
|
case 'disconnected':
|
||||||
|
// ...
|
||||||
|
break;
|
||||||
|
case 'unimplemented':
|
||||||
|
// ...
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
### Pipelining
|
### Pipelining
|
||||||
@@ -196,6 +215,22 @@ then use that:
|
|||||||
In this case, the library only wraps `myFoo` as a capability once, and then
|
In this case, the library only wraps `myFoo` as a capability once, and then
|
||||||
calls `close()` once all copies of that reference have been dropped.
|
calls `close()` once all copies of that reference have been dropped.
|
||||||
|
|
||||||
|
If one of your methods throws an exception, or returns a promise which
|
||||||
|
is subsequently rejected, it will be converted to a capnproto rpc
|
||||||
|
exception. If the exception has a `kjType` property, that will be used
|
||||||
|
for the exception's `type` field, otherwise the type will be `failed`.
|
||||||
|
|
||||||
|
var myBar = {
|
||||||
|
bar: function(foo) {
|
||||||
|
if(!bazAvailable()) {
|
||||||
|
var err = new Error("The baz is busy; try again later.");
|
||||||
|
err.kjType = 'overloaded';
|
||||||
|
throw(err);
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
### Exporting a bootstrap capability
|
### Exporting a bootstrap capability
|
||||||
|
|
||||||
// Connect to another server and export `myFoo` as a bootstrap capability.
|
// Connect to another server and export `myFoo` as a bootstrap capability.
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
capnp.node
|
||||||
+2
-2
@@ -4,12 +4,12 @@
|
|||||||
'target_name': 'capnp',
|
'target_name': 'capnp',
|
||||||
'sources': ['src/node-capnp/capnp.cc'],
|
'sources': ['src/node-capnp/capnp.cc'],
|
||||||
'libraries': ['-lkj', '-lkj-async', '-lcapnp', '-lcapnpc', '-lcapnp-rpc'],
|
'libraries': ['-lkj', '-lkj-async', '-lcapnp', '-lcapnpc', '-lcapnp-rpc'],
|
||||||
'cflags_cc': ['-std=c++11'],
|
'cflags_cc': ['-std=c++14'],
|
||||||
'cflags_cc!': ['-fno-rtti', '-fno-exceptions'],
|
'cflags_cc!': ['-fno-rtti', '-fno-exceptions'],
|
||||||
'conditions': [
|
'conditions': [
|
||||||
[ 'OS=="mac"', {
|
[ 'OS=="mac"', {
|
||||||
'xcode_settings': {
|
'xcode_settings': {
|
||||||
'OTHER_CPLUSPLUSFLAGS' : ['-std=c++11','-stdlib=libc++'],
|
'OTHER_CPLUSPLUSFLAGS' : ['-std=c++14','-stdlib=libc++'],
|
||||||
'OTHER_LDFLAGS': ['-stdlib=libc++'],
|
'OTHER_LDFLAGS': ['-stdlib=libc++'],
|
||||||
'GCC_ENABLE_CPP_RTTI': 'YES',
|
'GCC_ENABLE_CPP_RTTI': 'YES',
|
||||||
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
||||||
|
|||||||
@@ -72,10 +72,13 @@ if (!force) {
|
|||||||
|
|
||||||
// Build it
|
// Build it
|
||||||
function build() {
|
function build() {
|
||||||
cp.spawn(
|
var sp = cp.spawn(
|
||||||
process.platform === 'win32' ? 'node-gyp.cmd' : 'node-gyp',
|
process.platform === 'win32' ? 'node-gyp.cmd' : 'node-gyp',
|
||||||
['rebuild'].concat(args),
|
['rebuild'].concat(args),
|
||||||
{customFds: [0, 1, 2]})
|
{customFds: [0, 1, 2]});
|
||||||
|
|
||||||
|
sp
|
||||||
|
.on('close', function(){ afterBuild(); })
|
||||||
.on('exit', function(err) {
|
.on('exit', function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err === 127) {
|
if (err === 127) {
|
||||||
@@ -88,8 +91,9 @@ function build() {
|
|||||||
}
|
}
|
||||||
return process.exit(err);
|
return process.exit(err);
|
||||||
}
|
}
|
||||||
afterBuild();
|
|
||||||
});
|
});
|
||||||
|
sp.stdout.pipe(process.stdout);
|
||||||
|
sp.stderr.pipe(process.stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move it to expected location
|
// Move it to expected location
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("capnp").importSystem("capnp/c++.capnp");
|
||||||
+7
-4
@@ -1,8 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "capnp",
|
"name": "capnp",
|
||||||
"version": "0.2.0",
|
"version": "0.5.0",
|
||||||
"description": "A wrapper for the C++ Cap'n Proto library",
|
"description": "A wrapper for the C++ Cap'n Proto library",
|
||||||
"keywords": [ "capnproto", "serialization" ],
|
"keywords": [
|
||||||
|
"capnproto",
|
||||||
|
"serialization"
|
||||||
|
],
|
||||||
"homepage": "http://capnproto.org",
|
"homepage": "http://capnproto.org",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Kenton Varda",
|
"name": "Kenton Varda",
|
||||||
@@ -15,8 +18,8 @@
|
|||||||
"email": "jparyani@gmail.com"
|
"email": "jparyani@gmail.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
"main": "src/node-capnp/capnp.js",
|
"main": "src/node-capnp/capnp.js",
|
||||||
|
"types": "src/node-capnp/capnp.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install": "node ./build.js",
|
"install": "node ./build.js",
|
||||||
"test": "node src/node-capnp/capnp-test.js"
|
"test": "node src/node-capnp/capnp-test.js"
|
||||||
@@ -26,7 +29,7 @@
|
|||||||
"url": "git://github.com/kentonv/node-capnp.git"
|
"url": "git://github.com/kentonv/node-capnp.git"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12"
|
"node": ">=10.0"
|
||||||
},
|
},
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("capnp").importSystem("capnp/persistent.capnp");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("capnp").importSystem("capnp/rpc-twoparty.capnp");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("capnp").importSystem("capnp/rpc.capnp");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("capnp").importSystem("capnp/schema.capnp");
|
||||||
@@ -263,31 +263,48 @@ child.stdio[1].once("readable", function() {
|
|||||||
closed: false
|
closed: false
|
||||||
};
|
};
|
||||||
|
|
||||||
var localCap = new capnp.Capability(pow, Calculator.Function);
|
function usePow(pow) {
|
||||||
assert.equal(9, wait(localCap.call([3, 2])).value);
|
var localCap = new capnp.Capability(pow, Calculator.Function);
|
||||||
assert(!pow.closed);
|
assert.equal(9, wait(localCap.call([3, 2])).value);
|
||||||
localCap.close();
|
assert(!pow.closed);
|
||||||
assert(pow.closed);
|
localCap.close();
|
||||||
|
assert(pow.closed);
|
||||||
|
|
||||||
var promise = calc.evaluate(
|
var promise = calc.evaluate(
|
||||||
{call: {"function": subtract, params: [
|
{call: {"function": subtract, params: [
|
||||||
{call: {"function": add, params: [
|
{call: {"function": add, params: [
|
||||||
{literal: 123}, {literal: 456}]}},
|
{literal: 123}, {literal: 456}]}},
|
||||||
{literal: 321}]}});
|
{literal: 321}]}});
|
||||||
|
|
||||||
var value = promise.value;
|
var value = promise.value;
|
||||||
assert.equal(258, wait(value.read()).value);
|
assert.equal(258, wait(value.read()).value);
|
||||||
value.close();
|
value.close();
|
||||||
|
|
||||||
pow.closed = false;
|
pow.closed = false;
|
||||||
value = calc.evaluate(
|
value = calc.evaluate(
|
||||||
{call: {"function": pow, params: [{literal: 2}, {literal: 4}]}}).value;
|
{call: {"function": pow, params: [{literal: 2}, {literal: 4}]}}).value;
|
||||||
assert.equal(16, wait(value.read()).value);
|
assert.equal(16, wait(value.read()).value);
|
||||||
|
|
||||||
// Wait a moment to give the capability a chance to be dropped.
|
// Wait a moment to give the capability a chance to be dropped.
|
||||||
wait(new Promise((resolve, reject) => setTimeout(resolve, 10)));
|
wait(new Promise((resolve, reject) => setTimeout(resolve, 10)));
|
||||||
assert(pow.closed);
|
assert(pow.closed);
|
||||||
value.close();
|
value.close();
|
||||||
|
}
|
||||||
|
usePow(pow);
|
||||||
|
|
||||||
|
// Try using a class.
|
||||||
|
class PowClass {
|
||||||
|
constructor() {
|
||||||
|
this.closed = false
|
||||||
|
}
|
||||||
|
call(params) {
|
||||||
|
return Math.pow(params[0], params[1]);
|
||||||
|
}
|
||||||
|
close() {
|
||||||
|
this.closed = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
usePow(new PowClass());
|
||||||
|
|
||||||
// Try wrapping a promise as a capability -- calls are queued until resolution.
|
// Try wrapping a promise as a capability -- calls are queued until resolution.
|
||||||
var resolvePromisedCalc;
|
var resolvePromisedCalc;
|
||||||
|
|||||||
+361
-247
File diff suppressed because it is too large.
Load diff
Vendored
+45
@@ -0,0 +1,45 @@
|
|||||||
|
declare module Capnp {
|
||||||
|
type Id = string;
|
||||||
|
|
||||||
|
abstract class StructSchema<Builder, Reader> {
|
||||||
|
// A schema for a struct type. The `Builder` parameter is what users of
|
||||||
|
// the library specify in order to create a value; it may be missing fields,
|
||||||
|
// which will be filled in with defaults. A `Reader` is what is is returned
|
||||||
|
// when parsing a value, and is guaranteed to have all known fields set.
|
||||||
|
|
||||||
|
typeId: Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class InterfaceSchema<Server, Client> {
|
||||||
|
// A schema for an interface type. Similarly to `StructSchema`, the `Server`
|
||||||
|
// and `Client` parameters represent objects which may have missing
|
||||||
|
// methods (for servers), and ones which do not (for clients, though calling
|
||||||
|
// the method may still throw unimplemented).
|
||||||
|
|
||||||
|
typeId: Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnyServer {
|
||||||
|
close?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnyClient {
|
||||||
|
close(): void;
|
||||||
|
closed: boolean;
|
||||||
|
castAs<Server, Client>(schema: InterfaceSchema<Server, Client>): Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Capability: {
|
||||||
|
new<Server, Client>(server: Server, schema: InterfaceSchema<Server, Client>): Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Connection {
|
||||||
|
restore<Server, Client>(exportName: string, type: InterfaceSchema<Server, Client>): Client;
|
||||||
|
close(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse<Builder, Reader>(type: StructSchema<Builder, Reader>, buffer: Buffer): Reader;
|
||||||
|
function serialize<Builder, Reader>(type: StructSchema<Builder, Reader>, builder: Builder): Buffer;
|
||||||
|
function connect(addr: string): Connection;
|
||||||
|
}
|
||||||
|
export default Capnp;
|
||||||
+13
-11
@@ -192,16 +192,20 @@ function wrapLocalMethod(self, method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function LocalCapWrapper(obj) {
|
function LocalCapWrapper(obj) {
|
||||||
for (var name in obj) {
|
var type = obj;
|
||||||
if (name === "close") {
|
while (type && type !== Object.prototype) {
|
||||||
// Not an RPC method. Called when the capability has no clients.
|
Object.getOwnPropertyNames(type).forEach(name => {
|
||||||
this.close = obj.close.bind(obj);
|
if (name === "close") {
|
||||||
} else {
|
// Not an RPC method. Called when the capability has no clients.
|
||||||
var method = obj[name];
|
this.close = obj.close.bind(obj);
|
||||||
if (typeof method === "function") {
|
} else {
|
||||||
this[name] = wrapLocalMethod(obj, method);
|
var method = obj[name];
|
||||||
|
if (typeof method === "function") {
|
||||||
|
this[name] = wrapLocalMethod(obj, method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
type = Object.getPrototypeOf(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,5 +302,3 @@ exports.bytesToPreorder = function(schema, buf, options) {
|
|||||||
|
|
||||||
if (v8capnp.matchPowerboxQuery) exports.matchPowerboxQuery = v8capnp.matchPowerboxQuery;
|
if (v8capnp.matchPowerboxQuery) exports.matchPowerboxQuery = v8capnp.matchPowerboxQuery;
|
||||||
if (v8capnp.chacha20) exports.chacha20 = v8capnp.chacha20;
|
if (v8capnp.chacha20) exports.chacha20 = v8capnp.chacha20;
|
||||||
|
|
||||||
exports.dumpLocalCapTypeCounts = v8capnp.dumpLocalCapTypeCounts;
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("capnp").importSystem("capnp/stream.capnp");
|
||||||
Reference in new issue
Block a user