comm.js
219 lines
| 7.2 KiB
| application/javascript
|
JavascriptLexer
Jonathan Frederic
|
r17198 | // Copyright (c) IPython Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||||
MinRK
|
r13189 | |||
Jonathan Frederic
|
r17198 | define([ | ||
'base/js/namespace', | ||||
Jonathan Frederic
|
r17200 | 'jquery', | ||
Jonathan Frederic
|
r17198 | 'base/js/utils', | ||
Jonathan Frederic
|
r18907 | ], function(IPython, $, utils) { | ||
MinRK
|
r13189 | "use strict"; | ||
//----------------------------------------------------------------------- | ||||
MinRK
|
r13195 | // CommManager class | ||
MinRK
|
r13189 | //----------------------------------------------------------------------- | ||
MinRK
|
r13195 | var CommManager = function (kernel) { | ||
this.comms = {}; | ||||
MinRK
|
r13204 | this.targets = {}; | ||
MinRK
|
r13189 | if (kernel !== undefined) { | ||
this.init_kernel(kernel); | ||||
} | ||||
}; | ||||
MinRK
|
r13195 | CommManager.prototype.init_kernel = function (kernel) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* connect the kernel, and register message handlers | ||||
*/ | ||||
MinRK
|
r13189 | this.kernel = kernel; | ||
MinRK
|
r13195 | var msg_types = ['comm_open', 'comm_msg', 'comm_close']; | ||
MinRK
|
r13189 | for (var i = 0; i < msg_types.length; i++) { | ||
var msg_type = msg_types[i]; | ||||
MinRK
|
r13191 | kernel.register_iopub_handler(msg_type, $.proxy(this[msg_type], this)); | ||
MinRK
|
r13189 | } | ||
}; | ||||
MinRK
|
r13233 | CommManager.prototype.new_comm = function (target_name, data, callbacks, metadata) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* Create a new Comm, register it, and open its Kernel-side counterpart | ||||
* Mimics the auto-registration in `Comm.__init__` in the IPython Comm | ||||
*/ | ||||
MinRK
|
r13233 | var comm = new Comm(target_name); | ||
MinRK
|
r13229 | this.register_comm(comm); | ||
comm.open(data, callbacks, metadata); | ||||
return comm; | ||||
}; | ||||
MinRK
|
r13204 | CommManager.prototype.register_target = function (target_name, f) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* Register a target function for a given target name | ||||
*/ | ||||
MinRK
|
r13204 | this.targets[target_name] = f; | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r13226 | CommManager.prototype.unregister_target = function (target_name, f) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* Unregister a target function for a given target name | ||||
*/ | ||||
MinRK
|
r13226 | delete this.targets[target_name]; | ||
}; | ||||
MinRK
|
r13227 | |||
MinRK
|
r13195 | CommManager.prototype.register_comm = function (comm) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* Register a comm in the mapping | ||||
*/ | ||||
Jonathan Frederic
|
r18914 | this.comms[comm.comm_id] = Promise.resolve(comm); | ||
MinRK
|
r13195 | comm.kernel = this.kernel; | ||
return comm.comm_id; | ||||
MinRK
|
r13192 | }; | ||
Sylvain Corlay
|
r17460 | CommManager.prototype.unregister_comm = function (comm) { | ||
Jonathan Frederic
|
r19176 | /** | ||
* Remove a comm from the mapping | ||||
*/ | ||||
Sylvain Corlay
|
r17460 | delete this.comms[comm.comm_id]; | ||
MinRK
|
r13192 | }; | ||
MinRK
|
r13195 | // comm message handlers | ||
MinRK
|
r13192 | |||
MinRK
|
r13195 | CommManager.prototype.comm_open = function (msg) { | ||
MinRK
|
r13189 | var content = msg.content; | ||
Thomas Kluyver
|
r18467 | var that = this; | ||
Jonathan Frederic
|
r18913 | var comm_id = content.comm_id; | ||
this.comms[comm_id] = utils.load_class(content.target_name, content.target_module, | ||||
Jonathan Frederic
|
r18895 | this.targets).then(function(target) { | ||
Jason Grout
|
r18984 | var comm = new Comm(content.target_name, comm_id); | ||
comm.kernel = that.kernel; | ||||
try { | ||||
var response = target(comm, msg); | ||||
} catch (e) { | ||||
comm.close(); | ||||
that.unregister_comm(comm); | ||||
var wrapped_error = new utils.WrappedError("Exception opening new comm", e); | ||||
console.error(wrapped_error); | ||||
return Promise.reject(wrapped_error); | ||||
Jonathan Frederic
|
r18914 | } | ||
Jason Grout
|
r18984 | // Regardless of the target return value, we need to | ||
// then return the comm | ||||
return Promise.resolve(response).then(function() {return comm;}); | ||||
}, utils.reject('Could not open comm', true)); | ||||
Jonathan Frederic
|
r18913 | return this.comms[comm_id]; | ||
MinRK
|
r13189 | }; | ||
Jonathan Frederic
|
r18913 | CommManager.prototype.comm_close = function(msg) { | ||
MinRK
|
r13189 | var content = msg.content; | ||
Jonathan Frederic
|
r18917 | if (this.comms[content.comm_id] === undefined) { | ||
Jonathan Frederic
|
r18913 | console.error('Comm promise not found for comm id ' + content.comm_id); | ||
MinRK
|
r13189 | return; | ||
} | ||||
Jason Grout
|
r19389 | var that = this; | ||
Jonathan Frederic
|
r18917 | this.comms[content.comm_id] = this.comms[content.comm_id].then(function(comm) { | ||
Jason Grout
|
r19389 | that.unregister_comm(comm); | ||
Jonathan Frederic
|
r18913 | try { | ||
comm.handle_close(msg); | ||||
} catch (e) { | ||||
console.log("Exception closing comm: ", e, e.stack, msg); | ||||
} | ||||
Jason Grout
|
r18984 | // don't return a comm, so that further .then() functions | ||
// get an undefined comm input | ||||
Jonathan Frederic
|
r18913 | }); | ||
Jason Grout
|
r20621 | return this.comms[content.comm_id]; | ||
MinRK
|
r13189 | }; | ||
Jonathan Frederic
|
r18913 | CommManager.prototype.comm_msg = function(msg) { | ||
MinRK
|
r13189 | var content = msg.content; | ||
Jonathan Frederic
|
r18917 | if (this.comms[content.comm_id] === undefined) { | ||
Jonathan Frederic
|
r18913 | console.error('Comm promise not found for comm id ' + content.comm_id); | ||
MinRK
|
r13189 | return; | ||
} | ||||
Jonathan Frederic
|
r18913 | |||
Jonathan Frederic
|
r18917 | this.comms[content.comm_id] = this.comms[content.comm_id].then(function(comm) { | ||
Jonathan Frederic
|
r18913 | try { | ||
comm.handle_msg(msg); | ||||
} catch (e) { | ||||
console.log("Exception handling comm msg: ", e, e.stack, msg); | ||||
} | ||||
Jason Grout
|
r18984 | return comm; | ||
Jonathan Frederic
|
r18913 | }); | ||
Jason Grout
|
r20621 | return this.comms[content.comm_id]; | ||
MinRK
|
r13189 | }; | ||
//----------------------------------------------------------------------- | ||||
MinRK
|
r13195 | // Comm base class | ||
MinRK
|
r13189 | //----------------------------------------------------------------------- | ||
MinRK
|
r13229 | var Comm = function (target_name, comm_id) { | ||
MinRK
|
r13204 | this.target_name = target_name; | ||
Jonathan Frederic
|
r17198 | this.comm_id = comm_id || utils.uuid(); | ||
MinRK
|
r13205 | this._msg_callback = this._close_callback = null; | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r13192 | // methods for sending messages | ||
MinRK
|
r13217 | Comm.prototype.open = function (data, callbacks, metadata) { | ||
MinRK
|
r13192 | var content = { | ||
MinRK
|
r13195 | comm_id : this.comm_id, | ||
MinRK
|
r13204 | target_name : this.target_name, | ||
MinRK
|
r13192 | data : data || {}, | ||
}; | ||||
MinRK
|
r13217 | return this.kernel.send_shell_message("comm_open", content, callbacks, metadata); | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r18332 | Comm.prototype.send = function (data, callbacks, metadata, buffers) { | ||
MinRK
|
r13189 | var content = { | ||
MinRK
|
r13195 | comm_id : this.comm_id, | ||
MinRK
|
r13192 | data : data || {}, | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r18332 | return this.kernel.send_shell_message("comm_msg", content, callbacks, metadata, buffers); | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r13217 | Comm.prototype.close = function (data, callbacks, metadata) { | ||
MinRK
|
r13189 | var content = { | ||
MinRK
|
r13195 | comm_id : this.comm_id, | ||
MinRK
|
r13192 | data : data || {}, | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r13217 | return this.kernel.send_shell_message("comm_close", content, callbacks, metadata); | ||
MinRK
|
r13189 | }; | ||
MinRK
|
r13198 | // methods for registering callbacks for incoming messages | ||
Comm.prototype._register_callback = function (key, callback) { | ||||
this['_' + key + '_callback'] = callback; | ||||
}; | ||||
Comm.prototype.on_msg = function (callback) { | ||||
this._register_callback('msg', callback); | ||||
}; | ||||
Comm.prototype.on_close = function (callback) { | ||||
this._register_callback('close', callback); | ||||
}; | ||||
MinRK
|
r13202 | |||
MinRK
|
r13192 | // methods for handling incoming messages | ||
Jonathan Frederic
|
r18917 | Comm.prototype._callback = function (key, msg) { | ||
MinRK
|
r13198 | var callback = this['_' + key + '_callback']; | ||
MinRK
|
r13230 | if (callback) { | ||
try { | ||||
callback(msg); | ||||
} catch (e) { | ||||
Jason Grout
|
r14486 | console.log("Exception in Comm callback", e, e.stack, msg); | ||
MinRK
|
r13230 | } | ||
} | ||||
MinRK
|
r13198 | }; | ||
MinRK
|
r13197 | Comm.prototype.handle_msg = function (msg) { | ||
Jonathan Frederic
|
r18917 | this._callback('msg', msg); | ||
MinRK
|
r13192 | }; | ||
MinRK
|
r13197 | Comm.prototype.handle_close = function (msg) { | ||
Jonathan Frederic
|
r18917 | this._callback('close', msg); | ||
MinRK
|
r13192 | }; | ||
Jonathan Frederic
|
r17198 | // For backwards compatability. | ||
MinRK
|
r13195 | IPython.CommManager = CommManager; | ||
IPython.Comm = Comm; | ||||
MinRK
|
r13189 | |||
Jonathan Frederic
|
r17198 | return { | ||
'CommManager': CommManager, | ||||
'Comm': Comm | ||||
}; | ||||
}); | ||||