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:
		
							
								
								
									
										74
									
								
								core/app.js
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								core/app.js
									
									
									
									
									
								
							| @@ -1,7 +1,10 @@ | |||||||
| import * as auth from './auth.js'; | import * as auth from './auth.js'; | ||||||
| import * as core from './core.js'; | import * as core from './core.js'; | ||||||
|  |  | ||||||
| var gSessionIndex = 0; | let g_next_id = 1; | ||||||
|  | let g_calls = {}; | ||||||
|  |  | ||||||
|  | let gSessionIndex = 0; | ||||||
|  |  | ||||||
| function makeSessionId() { | function makeSessionId() { | ||||||
| 	return (gSessionIndex++).toString(); | 	return (gSessionIndex++).toString(); | ||||||
| @@ -19,31 +22,45 @@ App.prototype.readOutput = function(callback) { | |||||||
|  |  | ||||||
| App.prototype.makeFunction = function(api) { | App.prototype.makeFunction = function(api) { | ||||||
| 	let self = this; | 	let self = this; | ||||||
|  | 	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 result = function() { | ||||||
| 		let message = {action: api[0]}; | 		let message = { | ||||||
| 		for (let i = 1; i < api.length; i++) { | 			message: 'tfrpc', | ||||||
| 			message[api[i]] = arguments[i - 1]; | 			method: api[0], | ||||||
| 		} | 			params: [...arguments], | ||||||
|  | 			id: id, | ||||||
|  | 		}; | ||||||
| 		self.send(message); | 		self.send(message); | ||||||
|  | 		return promise; | ||||||
| 	}; | 	}; | ||||||
| 	Object.defineProperty(result, 'name', {value: api[0], writable: false}); | 	Object.defineProperty(result, 'name', {value: api[0], writable: false}); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| App.prototype.send = function(message) { | App.prototype.send = function(message) { | ||||||
| 	if (message) { | 	if (this._send_queue) { | ||||||
| 		this._send_queue.push(message); | 		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) { | 	if (message && this._on_output) { | ||||||
| 		this._send_queue.forEach(message => this._on_output(message)); | 		this._on_output(message); | ||||||
| 		this._send_queue = []; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| function socket(request, response, client) { | function socket(request, response, client) { | ||||||
| 	var process; | 	let process; | ||||||
| 	var options = {}; | 	let options = {}; | ||||||
| 	var credentials = auth.query(request.headers); | 	let credentials = auth.query(request.headers); | ||||||
|  |  | ||||||
| 	response.onClose = async function() { | 	response.onClose = async function() { | ||||||
| 		if (process && process.task) { | 		if (process && process.task) { | ||||||
| @@ -59,7 +76,7 @@ function socket(request, response, client) { | |||||||
|  |  | ||||||
| 	response.onMessage = async function(event) { | 	response.onMessage = async function(event) { | ||||||
| 		if (event.opCode == 0x1 || event.opCode == 0x2) { | 		if (event.opCode == 0x1 || event.opCode == 0x2) { | ||||||
| 			var message; | 			let message; | ||||||
| 			try { | 			try { | ||||||
| 				message = JSON.parse(event.data); | 				message = JSON.parse(event.data); | ||||||
| 			} catch (error) { | 			} catch (error) { | ||||||
| @@ -67,11 +84,11 @@ function socket(request, response, client) { | |||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 			if (message.action == "hello") { | 			if (message.action == "hello") { | ||||||
| 				var packageOwner; | 				let packageOwner; | ||||||
| 				var packageName; | 				let packageName; | ||||||
| 				var blobId; | 				let blobId; | ||||||
| 				var match; | 				let match; | ||||||
| 				var parentApp; | 				let parentApp; | ||||||
| 				if (match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path)) { | 				if (match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path)) { | ||||||
| 					blobId = match[1]; | 					blobId = match[1]; | ||||||
| 				} else if (match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path)) { | 				} else if (match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path)) { | ||||||
| @@ -83,7 +100,7 @@ function socket(request, response, client) { | |||||||
| 						return; | 						return; | ||||||
| 					} | 					} | ||||||
| 					if (packageOwner != 'core') { | 					if (packageOwner != 'core') { | ||||||
| 						var coreId = await new Database('core').get('path:' + packageName); | 						let coreId = await new Database('core').get('path:' + packageName); | ||||||
| 						parentApp = { | 						parentApp = { | ||||||
| 							path: '/~core/' + packageName + '/', | 							path: '/~core/' + packageName + '/', | ||||||
| 							id: coreId, | 							id: coreId, | ||||||
| @@ -101,7 +118,7 @@ function socket(request, response, client) { | |||||||
| 				options.credentials = credentials; | 				options.credentials = credentials; | ||||||
| 				options.packageOwner = packageOwner; | 				options.packageOwner = packageOwner; | ||||||
| 				options.packageName = packageName; | 				options.packageName = packageName; | ||||||
| 				var sessionId = makeSessionId(); | 				let sessionId = makeSessionId(); | ||||||
| 				if (blobId) { | 				if (blobId) { | ||||||
| 					process = await core.getSessionProcessBlob(blobId, sessionId, options); | 					process = await core.getSessionProcessBlob(blobId, sessionId, options); | ||||||
| 				} | 				} | ||||||
| @@ -112,9 +129,9 @@ function socket(request, response, client) { | |||||||
| 					process.app.send(); | 					process.app.send(); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				var ping = function() { | 				let ping = function() { | ||||||
| 					var now = Date.now(); | 					let now = Date.now(); | ||||||
| 					var again = true; | 					let again = true; | ||||||
| 					if (now - process.lastActive < process.timeout) { | 					if (now - process.lastActive < process.timeout) { | ||||||
| 						// Active. | 						// Active. | ||||||
| 					} else if (process.lastPing > process.lastActive) { | 					} else if (process.lastPing > process.lastActive) { | ||||||
| @@ -143,6 +160,15 @@ function socket(request, response, client) { | |||||||
| 				} | 				} | ||||||
| 			} else if (message.action == 'permission') { | 			} else if (message.action == 'permission') { | ||||||
| 				core.setPermission(process, message.id, message.granted); | 				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 { | 			} else { | ||||||
| 				if (process && process.eventHandlers['message']) { | 				if (process && process.eventHandlers['message']) { | ||||||
| 					await core.invoke(process.eventHandlers['message'], [message]); | 					await core.invoke(process.eventHandlers['message'], [message]); | ||||||
|   | |||||||
| @@ -438,7 +438,7 @@ function api_localStorageSet(key, value) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function api_localStorageGet(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) { | function api_requestPermission(permission, id) { | ||||||
| @@ -594,10 +594,24 @@ function receive(message) { | |||||||
| 			} | 			} | ||||||
| 			timeseries.append(now, message.stats[key]); | 			timeseries.append(now, message.stats[key]); | ||||||
| 		} | 		} | ||||||
| 	} else if (message && message.action) { | 	} else if (message && | ||||||
| 		let api = k_api[message.action]; | 		message.message === 'tfrpc' && | ||||||
|  | 		message.method) { | ||||||
|  | 		let api = k_api[message.method]; | ||||||
| 		if (api) { | 		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) { | function make_rpc(target, prop, receiver) { | ||||||
| 	return function() { | 	return function() { | ||||||
| 		let id = g_next_id++; | 		let id = g_next_id++; | ||||||
|  | 		while (!id || g_calls[id]) { | ||||||
|  | 			id = g_next_id++; | ||||||
|  | 		} | ||||||
| 		let promise = new Promise(function(resolve, reject) { | 		let promise = new Promise(function(resolve, reject) { | ||||||
| 			g_calls[id] = {resolve: resolve, reject: reject}; | 			g_calls[id] = {resolve: resolve, reject: reject}; | ||||||
| 		}); | 		}); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user