| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  javascript_eval.cpp                                                  */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | #ifdef JAVASCRIPT_EVAL_ENABLED
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 01:33:48 +01:00
										 |  |  | #include "api/javascript_eval.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | #include "emscripten.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | extern "C" EMSCRIPTEN_KEEPALIVE uint8_t *resize_poolbytearray_and_open_write(PoolByteArray *p_arr, PoolByteArray::Write *r_write, int p_len) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p_arr->resize(p_len); | 
					
						
							|  |  |  | 	*r_write = p_arr->write(); | 
					
						
							|  |  |  | 	return r_write->ptr(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) { | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	union { | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 		bool b; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		double d; | 
					
						
							|  |  |  | 		char *s; | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 	} js_data; | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	PoolByteArray arr; | 
					
						
							|  |  |  | 	PoolByteArray::Write arr_write; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 20:00:04 +01:00
										 |  |  | 	/* clang-format off */ | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 	Variant::Type return_type = static_cast<Variant::Type>(EM_ASM_INT({ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 		const CODE = $0; | 
					
						
							|  |  |  | 		const USE_GLOBAL_EXEC_CONTEXT = $1; | 
					
						
							|  |  |  | 		const PTR = $2; | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 		const BYTEARRAY_PTR = $3; | 
					
						
							|  |  |  | 		const BYTEARRAY_WRITE_PTR = $4; | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 		var eval_ret; | 
					
						
							|  |  |  | 		try { | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 			if (USE_GLOBAL_EXEC_CONTEXT) { | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 				// indirect eval call grants global execution context
 | 
					
						
							|  |  |  | 				var global_eval = eval; | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 				eval_ret = global_eval(UTF8ToString(CODE)); | 
					
						
							| 
									
										
										
										
											2017-01-15 20:00:04 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 				eval_ret = eval(UTF8ToString(CODE)); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} catch (e) { | 
					
						
							| 
									
										
										
										
											2019-02-24 04:40:06 +01:00
										 |  |  | 			err(e); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 			eval_ret = null; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (typeof eval_ret) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 'boolean': | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 				setValue(PTR, eval_ret, 'i32'); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 				return 1; // BOOL
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 'number': | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 				setValue(PTR, eval_ret, 'double'); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 				return 3; // REAL
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 'string': | 
					
						
							|  |  |  | 				var array_len = lengthBytesUTF8(eval_ret)+1; | 
					
						
							|  |  |  | 				var array_ptr = _malloc(array_len); | 
					
						
							|  |  |  | 				try { | 
					
						
							|  |  |  | 					if (array_ptr===0) { | 
					
						
							|  |  |  | 						throw new Error('String allocation failed (probably out of memory)'); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 					setValue(PTR, array_ptr , '*'); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 					stringToUTF8(eval_ret, array_ptr, array_len); | 
					
						
							|  |  |  | 					return 4; // STRING
 | 
					
						
							|  |  |  | 				} catch (e) { | 
					
						
							|  |  |  | 					if (array_ptr!==0) { | 
					
						
							|  |  |  | 						_free(array_ptr) | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-02-24 04:40:06 +01:00
										 |  |  | 					err(e); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 					// fall through
 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 'object': | 
					
						
							|  |  |  | 				if (eval_ret === null) { | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 				if (ArrayBuffer.isView(eval_ret) && !(eval_ret instanceof Uint8Array)) { | 
					
						
							|  |  |  | 					eval_ret = new Uint8Array(eval_ret.buffer); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else if (eval_ret instanceof ArrayBuffer) { | 
					
						
							|  |  |  | 					eval_ret = new Uint8Array(eval_ret); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (eval_ret instanceof Uint8Array) { | 
					
						
							|  |  |  | 					var bytes_ptr = ccall('resize_poolbytearray_and_open_write', 'number', ['number', 'number' ,'number'], [BYTEARRAY_PTR, BYTEARRAY_WRITE_PTR, eval_ret.length]); | 
					
						
							|  |  |  | 					HEAPU8.set(eval_ret, bytes_ptr); | 
					
						
							|  |  |  | 					return 20; // POOL_BYTE_ARRAY
 | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0; // NIL
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 	}, p_code.utf8().get_data(), p_use_global_exec_context, &js_data, &arr, &arr_write)); | 
					
						
							| 
									
										
										
										
											2017-01-15 20:00:04 +01:00
										 |  |  | 	/* clang-format on */ | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (return_type) { | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 		case Variant::BOOL: | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 			return js_data.b; | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 		case Variant::REAL: | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 			return js_data.d; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		case Variant::STRING: { | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 			String str = String::utf8(js_data.s); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			/* clang-format off */ | 
					
						
							| 
									
										
										
										
											2017-11-25 15:38:02 +01:00
										 |  |  | 				EM_ASM_({ _free($0); }, js_data.s); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			/* clang-format on */ | 
					
						
							|  |  |  | 			return str; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-10-10 23:37:16 +02:00
										 |  |  | 		case Variant::POOL_BYTE_ARRAY: | 
					
						
							|  |  |  | 			arr_write = PoolByteArray::Write(); | 
					
						
							|  |  |  | 			return arr; | 
					
						
							| 
									
										
										
										
											2018-10-02 02:30:27 +02:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			return Variant(); | 
					
						
							| 
									
										
										
										
											2016-04-11 23:22:14 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // JAVASCRIPT_EVAL_ENABLED
 |