08-27-周三_17-09-29
This commit is contained in:
125
node_modules/dnode-protocol/index.js
generated
vendored
Normal file
125
node_modules/dnode-protocol/index.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var scrubber = require('./lib/scrub');
|
||||
var objectKeys = require('./lib/keys');
|
||||
var forEach = require('./lib/foreach');
|
||||
var isEnumerable = require('./lib/is_enum');
|
||||
|
||||
module.exports = function (cons, opts) {
|
||||
return new Proto(cons, opts);
|
||||
};
|
||||
|
||||
(function () { // browsers bleh
|
||||
for (var key in EventEmitter.prototype) {
|
||||
Proto.prototype[key] = EventEmitter.prototype[key];
|
||||
}
|
||||
})();
|
||||
|
||||
function Proto (cons, opts) {
|
||||
var self = this;
|
||||
EventEmitter.call(self);
|
||||
if (!opts) opts = {};
|
||||
|
||||
self.remote = {};
|
||||
self.callbacks = { local : [], remote : [] };
|
||||
self.wrap = opts.wrap;
|
||||
self.unwrap = opts.unwrap;
|
||||
|
||||
self.scrubber = scrubber(self.callbacks.local);
|
||||
|
||||
if (typeof cons === 'function') {
|
||||
self.instance = new cons(self.remote, self);
|
||||
}
|
||||
else self.instance = cons || {};
|
||||
}
|
||||
|
||||
Proto.prototype.start = function () {
|
||||
this.request('methods', [ this.instance ]);
|
||||
};
|
||||
|
||||
Proto.prototype.cull = function (id) {
|
||||
delete this.callbacks.remote[id];
|
||||
this.emit('request', {
|
||||
method : 'cull',
|
||||
arguments : [ id ]
|
||||
});
|
||||
};
|
||||
|
||||
Proto.prototype.request = function (method, args) {
|
||||
var scrub = this.scrubber.scrub(args);
|
||||
|
||||
this.emit('request', {
|
||||
method : method,
|
||||
arguments : scrub.arguments,
|
||||
callbacks : scrub.callbacks,
|
||||
links : scrub.links
|
||||
});
|
||||
};
|
||||
|
||||
Proto.prototype.handle = function (req) {
|
||||
var self = this;
|
||||
var args = self.scrubber.unscrub(req, function (id) {
|
||||
if (self.callbacks.remote[id] === undefined) {
|
||||
// create a new function only if one hasn't already been created
|
||||
// for a particular id
|
||||
var cb = function () {
|
||||
self.request(id, [].slice.apply(arguments));
|
||||
};
|
||||
self.callbacks.remote[id] = self.wrap ? self.wrap(cb, id) : cb;
|
||||
return cb;
|
||||
}
|
||||
return self.unwrap
|
||||
? self.unwrap(self.callbacks.remote[id], id)
|
||||
: self.callbacks.remote[id]
|
||||
;
|
||||
});
|
||||
|
||||
if (req.method === 'methods') {
|
||||
self.handleMethods(args[0]);
|
||||
}
|
||||
else if (req.method === 'cull') {
|
||||
forEach(args, function (id) {
|
||||
delete self.callbacks.local[id];
|
||||
});
|
||||
}
|
||||
else if (typeof req.method === 'string') {
|
||||
if (isEnumerable(self.instance, req.method)) {
|
||||
self.apply(self.instance[req.method], args);
|
||||
}
|
||||
else {
|
||||
self.emit('fail', new Error(
|
||||
'request for non-enumerable method: ' + req.method
|
||||
));
|
||||
}
|
||||
}
|
||||
else if (typeof req.method == 'number') {
|
||||
var fn = self.callbacks.local[req.method];
|
||||
if (!fn) {
|
||||
self.emit('fail', new Error('no such method'));
|
||||
}
|
||||
else self.apply(fn, args);
|
||||
}
|
||||
};
|
||||
|
||||
Proto.prototype.handleMethods = function (methods) {
|
||||
var self = this;
|
||||
if (typeof methods != 'object') {
|
||||
methods = {};
|
||||
}
|
||||
|
||||
// copy since assignment discards the previous refs
|
||||
forEach(objectKeys(self.remote), function (key) {
|
||||
delete self.remote[key];
|
||||
});
|
||||
|
||||
forEach(objectKeys(methods), function (key) {
|
||||
self.remote[key] = methods[key];
|
||||
});
|
||||
|
||||
self.emit('remote', self.remote);
|
||||
self.emit('ready');
|
||||
};
|
||||
|
||||
Proto.prototype.apply = function (f, args) {
|
||||
try { f.apply(undefined, args) }
|
||||
catch (err) { this.emit('error', err) }
|
||||
};
|
Reference in New Issue
Block a user