forked from cory/tildefriends
		
	Do app -> client communication more like tfrpc so that it's easier to get responses.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3956 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										72
									
								
								core/app.js
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								core/app.js
									
									
									
									
									
								
							| @@ -1,7 +1,10 @@ | ||||
| import * as auth from './auth.js'; | ||||
| import * as core from './core.js'; | ||||
|  | ||||
| var gSessionIndex = 0; | ||||
| let g_next_id = 1; | ||||
| let g_calls = {}; | ||||
|  | ||||
| let gSessionIndex = 0; | ||||
|  | ||||
| function makeSessionId() { | ||||
| 	return (gSessionIndex++).toString(); | ||||
| @@ -19,31 +22,45 @@ App.prototype.readOutput = function(callback) { | ||||
|  | ||||
| App.prototype.makeFunction = function(api) { | ||||
| 	let self = this; | ||||
| 	let result = function() { | ||||
| 		let message = {action: api[0]}; | ||||
| 		for (let i = 1; i < api.length; i++) { | ||||
| 			message[api[i]] = arguments[i - 1]; | ||||
| 	let id = g_next_id++; | ||||
| 	while (!id || g_calls[id]) { | ||||
| 		id = g_next_id++; | ||||
| 	} | ||||
| 	let promise = new Promise(function(resolve, reject) { | ||||
| 		g_calls[id] = {resolve: resolve, reject: reject}; | ||||
| 	}); | ||||
| 	let result = function() { | ||||
| 		let message = { | ||||
| 			message: 'tfrpc', | ||||
| 			method: api[0], | ||||
| 			params: [...arguments], | ||||
| 			id: id, | ||||
| 		}; | ||||
| 		self.send(message); | ||||
| 		return promise; | ||||
| 	}; | ||||
| 	Object.defineProperty(result, 'name', {value: api[0], writable: false}); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| App.prototype.send = function(message) { | ||||
| 	if (message) { | ||||
| 	if (this._send_queue) { | ||||
| 		if (this._on_output) { | ||||
| 			this._send_queue.forEach(x => this._on_output(x)); | ||||
| 			this._send_queue = null; | ||||
| 		} else if (message) { | ||||
| 			this._send_queue.push(message); | ||||
| 		} | ||||
| 	if (this._on_output) { | ||||
| 		this._send_queue.forEach(message => this._on_output(message)); | ||||
| 		this._send_queue = []; | ||||
| 	} | ||||
| 	if (message && this._on_output) { | ||||
| 		this._on_output(message); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function socket(request, response, client) { | ||||
| 	var process; | ||||
| 	var options = {}; | ||||
| 	var credentials = auth.query(request.headers); | ||||
| 	let process; | ||||
| 	let options = {}; | ||||
| 	let credentials = auth.query(request.headers); | ||||
|  | ||||
| 	response.onClose = async function() { | ||||
| 		if (process && process.task) { | ||||
| @@ -59,7 +76,7 @@ function socket(request, response, client) { | ||||
|  | ||||
| 	response.onMessage = async function(event) { | ||||
| 		if (event.opCode == 0x1 || event.opCode == 0x2) { | ||||
| 			var message; | ||||
| 			let message; | ||||
| 			try { | ||||
| 				message = JSON.parse(event.data); | ||||
| 			} catch (error) { | ||||
| @@ -67,11 +84,11 @@ function socket(request, response, client) { | ||||
| 				return; | ||||
| 			} | ||||
| 			if (message.action == "hello") { | ||||
| 				var packageOwner; | ||||
| 				var packageName; | ||||
| 				var blobId; | ||||
| 				var match; | ||||
| 				var parentApp; | ||||
| 				let packageOwner; | ||||
| 				let packageName; | ||||
| 				let blobId; | ||||
| 				let match; | ||||
| 				let parentApp; | ||||
| 				if (match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path)) { | ||||
| 					blobId = match[1]; | ||||
| 				} else if (match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path)) { | ||||
| @@ -83,7 +100,7 @@ function socket(request, response, client) { | ||||
| 						return; | ||||
| 					} | ||||
| 					if (packageOwner != 'core') { | ||||
| 						var coreId = await new Database('core').get('path:' + packageName); | ||||
| 						let coreId = await new Database('core').get('path:' + packageName); | ||||
| 						parentApp = { | ||||
| 							path: '/~core/' + packageName + '/', | ||||
| 							id: coreId, | ||||
| @@ -101,7 +118,7 @@ function socket(request, response, client) { | ||||
| 				options.credentials = credentials; | ||||
| 				options.packageOwner = packageOwner; | ||||
| 				options.packageName = packageName; | ||||
| 				var sessionId = makeSessionId(); | ||||
| 				let sessionId = makeSessionId(); | ||||
| 				if (blobId) { | ||||
| 					process = await core.getSessionProcessBlob(blobId, sessionId, options); | ||||
| 				} | ||||
| @@ -112,9 +129,9 @@ function socket(request, response, client) { | ||||
| 					process.app.send(); | ||||
| 				} | ||||
|  | ||||
| 				var ping = function() { | ||||
| 					var now = Date.now(); | ||||
| 					var again = true; | ||||
| 				let ping = function() { | ||||
| 					let now = Date.now(); | ||||
| 					let again = true; | ||||
| 					if (now - process.lastActive < process.timeout) { | ||||
| 						// Active. | ||||
| 					} else if (process.lastPing > process.lastActive) { | ||||
| @@ -143,6 +160,15 @@ function socket(request, response, client) { | ||||
| 				} | ||||
| 			} else if (message.action == 'permission') { | ||||
| 				core.setPermission(process, message.id, message.granted); | ||||
| 			} else if (message.message == 'tfrpc') { | ||||
| 				if (message.id && g_calls[message.id]) { | ||||
| 					if (message.error !== undefined) { | ||||
| 						g_calls[message.id].reject(message.error); | ||||
| 					} else { | ||||
| 						g_calls[message.id].resolve(message.result); | ||||
| 					} | ||||
| 					delete g_calls[message.id]; | ||||
| 				} | ||||
| 			} else { | ||||
| 				if (process && process.eventHandlers['message']) { | ||||
| 					await core.invoke(process.eventHandlers['message'], [message]); | ||||
|   | ||||
| @@ -438,7 +438,7 @@ function api_localStorageSet(key, value) { | ||||
| } | ||||
|  | ||||
| function api_localStorageGet(key, value) { | ||||
| 	send({message: 'localStorage', key: key, value: window.localStorage.getItem('app:' + key)}); | ||||
| 	return window.localStorage.getItem('app:' + key); | ||||
| } | ||||
|  | ||||
| function api_requestPermission(permission, id) { | ||||
| @@ -594,10 +594,24 @@ function receive(message) { | ||||
| 			} | ||||
| 			timeseries.append(now, message.stats[key]); | ||||
| 		} | ||||
| 	} else if (message && message.action) { | ||||
| 		let api = k_api[message.action]; | ||||
| 	} else if (message && | ||||
| 		message.message === 'tfrpc' && | ||||
| 		message.method) { | ||||
| 		let api = k_api[message.method]; | ||||
| 		if (api) { | ||||
| 			api.func(...api.args.map(x => message[x])); | ||||
| 			Promise.resolve(api.func(...message.params)).then(function(result) { | ||||
| 				send({ | ||||
| 					message: 'tfrpc', | ||||
| 					id: message.id, | ||||
| 					result: result, | ||||
| 				}); | ||||
| 			}).catch(function(error) { | ||||
| 				send({ | ||||
| 					message: 'tfrpc', | ||||
| 					id: message.id, | ||||
| 					error: error, | ||||
| 				}); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,9 @@ if (k_is_browser) { | ||||
| function make_rpc(target, prop, receiver) { | ||||
| 	return function() { | ||||
| 		let id = g_next_id++; | ||||
| 		while (!id || g_calls[id]) { | ||||
| 			id = g_next_id++; | ||||
| 		} | ||||
| 		let promise = new Promise(function(resolve, reject) { | ||||
| 			g_calls[id] = {resolve: resolve, reject: reject}; | ||||
| 		}); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user