forked from cory/tildefriends
		
	Add a helper for app <-> browser communication.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3908 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		| @@ -410,7 +410,7 @@ function api_error(error) { | ||||
| 		if (typeof(error) == 'string') { | ||||
| 			setStatusMessage('⚠️ ' + error, '#f00'); | ||||
| 		} else { | ||||
| 			setStatusMessage('⚠️ ' + merror.message + '\n' + error.stack, '#f00'); | ||||
| 			setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, '#f00'); | ||||
| 		} | ||||
| 	} | ||||
| 	console.log('error', error); | ||||
|   | ||||
| @@ -225,6 +225,7 @@ async function getProcessBlob(blobId, key, options) { | ||||
| 					var id = appObject.files[appSourceName]; | ||||
| 					var blob = await getBlobOrContent(id); | ||||
| 					appSource = utf8Decode(blob); | ||||
| 					await process.task.loadFile(['/tfrpc.js', await File.readFile('core/tfrpc.js')]); | ||||
| 					await Promise.all(Object.keys(appObject.files).map(async function(f) { | ||||
| 						await process.task.loadFile([f, await getBlobOrContent(appObject.files[f])]); | ||||
| 					})); | ||||
| @@ -264,6 +265,7 @@ var kStaticFiles = [ | ||||
| 	{uri: '/style.css', type: 'text/css; charset=UTF-8'}, | ||||
| 	{uri: '/favicon.png', type: 'image/png'}, | ||||
| 	{uri: '/client.js', type: 'text/javascript; charset=UTF-8'}, | ||||
| 	{uri: '/tfrpc.js', type: 'text/javascript; charset=UTF-8', headers: {'Access-Control-Allow-Origin': 'null'}}, | ||||
| 	{uri: '/robots.txt', type: 'text/plain; charset=UTF-8'}, | ||||
| ]; | ||||
|  | ||||
| @@ -285,7 +287,7 @@ async function staticFileHandler(request, response, blobId, uri) { | ||||
| 			var path = kStaticFiles[i].path || uri.substring(1); | ||||
| 			var type = kStaticFiles[i].type || guessType(path); | ||||
| 			var data = await File.readFile("core/" + path); | ||||
| 			response.writeHead(200, {"Content-Type": type, "Content-Length": data.byteLength}); | ||||
| 			response.writeHead(200, Object.assign({"Content-Type": type, "Content-Length": data.byteLength}, kStaticFiles[i].headers || {})); | ||||
| 			response.end(data); | ||||
| 			return; | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										78
									
								
								core/tfrpc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								core/tfrpc.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| const k_is_browser = get_is_browser(); | ||||
| let g_api = {}; | ||||
| let g_next_id = 1; | ||||
| let g_calls = {}; | ||||
|  | ||||
| function get_is_browser() { | ||||
| 	try { return window !== undefined && console !== undefined; } catch { return false; } | ||||
| } | ||||
|  | ||||
| if (k_is_browser) { | ||||
| 	print = console.log; | ||||
| } | ||||
|  | ||||
| function make_rpc(target, prop, receiver) { | ||||
| 	return function() { | ||||
| 		let id = g_next_id++; | ||||
| 		let promise = new Promise(function(resolve, reject) { | ||||
| 			g_calls[id] = {resolve: resolve, reject: reject}; | ||||
| 		}); | ||||
| 		if (k_is_browser) { | ||||
| 			window.parent.postMessage({message: 'tfrpc', method: prop, params: [...arguments], id: id}, '*'); | ||||
| 			return promise; | ||||
| 		} else { | ||||
| 			return app.postMessage({message: 'tfrpc', method: prop, params: [...arguments], id: id}).then(x => promise); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function call_rpc(message) { | ||||
| 	if (message && message.message === 'tfrpc') { | ||||
| 		if (message.method) { | ||||
| 			let method = g_api[message.method]; | ||||
| 			if (method) { | ||||
| 				let response = {message: 'tfrpc', id: message.id}; | ||||
| 				try { | ||||
| 					response.result = method(...message.params); | ||||
| 				} catch (error) { | ||||
| 					response.error = error; | ||||
| 				} | ||||
| 				if (k_is_browser) { | ||||
| 					window.parent.postMessage(response, '*'); | ||||
| 				} else { | ||||
| 					app.postMessage(response); | ||||
| 				} | ||||
| 			} else { | ||||
| 				throw new Error(message.method + ' not found.'); | ||||
| 			} | ||||
| 		} else if (message.result !== undefined) { | ||||
| 			if (g_calls[message.id]) { | ||||
| 				g_calls[message.id].resolve(message.result); | ||||
| 			} else { | ||||
| 				throw new Error(message.id + ' not found to reply.'); | ||||
| 			} | ||||
| 		} else if (message.error !== undefined) { | ||||
| 			if (g_calls[message.id]) { | ||||
| 				g_calls[message.id].reject(message.error); | ||||
| 			} else { | ||||
| 				throw new Error(message.id + ' not found to reply.'); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| if (k_is_browser) { | ||||
| 	window.addEventListener('message', function(event) { | ||||
| 		call_rpc(event.data); | ||||
| 	}); | ||||
| } else { | ||||
| 	core.register('message', function(message) { | ||||
| 		call_rpc(message?.message); | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| export let rpc = new Proxy({}, {get: make_rpc}); | ||||
|  | ||||
| export function register(method) { | ||||
| 	g_api[method.name] = method; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user