summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2016-08-30 14:52:35 +0200
committerGitHub <noreply@github.com>2016-08-30 14:52:35 +0200
commit5efe47fb0bd08bba569ec951ed6b6e40d4b264f1 (patch)
tree6df3ee875980c83ceb65a4753cae14816213614d
parent445c7455da85d3505d7d9572052f22281fa95581 (diff)
parent913361928fe2b917def749af774c94228a840524 (diff)
Merge pull request #4376 from eska014/js-eval
Add JavaScript eval interface to web export
-rw-r--r--platform/javascript/SCsub3
-rw-r--r--platform/javascript/detect.py7
-rw-r--r--platform/javascript/javascript_eval.cpp169
-rw-r--r--platform/javascript/javascript_eval.h55
-rw-r--r--platform/javascript/os_javascript.cpp5
-rw-r--r--platform/javascript/os_javascript.h5
6 files changed, 242 insertions, 2 deletions
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index cd96cf4f31..fc70d45a04 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -4,7 +4,8 @@ javascript_files = [
"os_javascript.cpp",
"audio_driver_javascript.cpp",
"javascript_main.cpp",
- "audio_server_javascript.cpp"
+ "audio_server_javascript.cpp",
+ "javascript_eval.cpp"
]
#obj = env.SharedObject('godot_javascript.cpp')
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index d76a20bea7..aeff5a1a34 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -18,7 +18,8 @@ def can_build():
def get_opts():
return [
- ['compress','Compress JS Executable','no']
+ ['compress','Compress JS Executable','no'],
+ ['javascript_eval','Enable JavaScript eval interface','yes']
]
def get_flags():
@@ -89,6 +90,10 @@ def configure(env):
env.Append(CPPFLAGS=['-s','ASM_JS=1'])
env.Append(CPPFLAGS=['-s','FULL_ES2=1'])
# env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED','-DMPC_FIXED_POINT'])
+
+ if env['javascript_eval'] == 'yes':
+ env.Append(CPPFLAGS=['-DJAVASCRIPT_EVAL_ENABLED'])
+
if (env["compress"]=="yes"):
lzma_binpath = em_path+"/third_party/lzma.js/lzma-native"
lzma_decoder = em_path+"/third_party/lzma.js/lzma-decoder.js"
diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp
new file mode 100644
index 0000000000..e642300bda
--- /dev/null
+++ b/platform/javascript/javascript_eval.cpp
@@ -0,0 +1,169 @@
+/*************************************************************************/
+/* javascript_eval.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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. */
+/*************************************************************************/
+#ifdef JAVASCRIPT_EVAL_ENABLED
+
+#include "javascript_eval.h"
+#include "emscripten.h"
+
+JavaScript *JavaScript::singleton=NULL;
+
+JavaScript *JavaScript::get_singleton() {
+
+ return singleton;
+}
+
+Variant JavaScript::eval(const String& p_code, bool p_use_global_exec_context) {
+
+ union { int i; double d; char* s; } js_data[4];
+ Variant::Type return_type = static_cast<Variant::Type>(EM_ASM_INT({
+
+ var eval_ret;
+ try {
+ if ($3) { // p_use_global_exec_context
+ // indirect eval call grants global execution context
+ var global_eval = eval;
+ eval_ret = global_eval(UTF8ToString($2));
+ }
+ else {
+ eval_ret = eval(UTF8ToString($2));
+ }
+ } catch (e) {
+ Module.printErr(e);
+ eval_ret = null;
+ }
+
+ switch (typeof eval_ret) {
+
+ case 'boolean':
+ // bitwise op yields 32-bit int
+ setValue($0, eval_ret|0, 'i32');
+ return 1; // BOOL
+
+ case 'number':
+ if ((eval_ret|0)===eval_ret) {
+ setValue($0, eval_ret|0, 'i32');
+ return 2; // INT
+ }
+ setValue($0, eval_ret, 'double');
+ 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)');
+ }
+ setValue($0, array_ptr|0 , '*');
+ stringToUTF8(eval_ret, array_ptr, array_len);
+ return 4; // STRING
+ } catch (e) {
+ if (array_ptr!==0) {
+ _free(array_ptr)
+ }
+ Module.printErr(e);
+ // fall through
+ }
+ break;
+
+ case 'object':
+ if (eval_ret === null) {
+ break;
+ }
+
+ else if (typeof eval_ret.x==='number' && typeof eval_ret.y==='number') {
+ setValue($0, eval_ret.x, 'double');
+ setValue($0+$1, eval_ret.y, 'double');
+ if (typeof eval_ret.z==='number') {
+ setValue($0+$1*2, eval_ret.z, 'double');
+ return 7; // VECTOR3
+ }
+ else if (typeof eval_ret.width==='number' && typeof eval_ret.height==='number') {
+ setValue($0+$1*2, eval_ret.width, 'double');
+ setValue($0+$1*3, eval_ret.height, 'double');
+ return 6; // RECT2
+ }
+ return 5; // VECTOR2
+ }
+
+ else if (typeof eval_ret.r==='number' && typeof eval_ret.g==='number' && typeof eval_ret.b==='number') {
+ // assume 8-bit rgb components since we're on the web
+ setValue($0, eval_ret.r, 'double');
+ setValue($0+$1, eval_ret.g, 'double');
+ setValue($0+$1*2, eval_ret.b, 'double');
+ setValue($0+$1*3, typeof eval_ret.a==='number' ? eval_ret.a : 1, 'double');
+ return 14; // COLOR
+ }
+ break;
+ }
+ return 0; // NIL
+
+ }, js_data, sizeof *js_data, p_code.utf8().get_data(), p_use_global_exec_context));
+
+ switch(return_type) {
+ case Variant::BOOL:
+ return !!js_data->i;
+ case Variant::INT:
+ return js_data->i;
+ case Variant::REAL:
+ return js_data->d;
+ case Variant::STRING:
+ {
+ String str = String::utf8(js_data->s);
+ EM_ASM_({ _free($0); }, js_data->s);
+ return str;
+ }
+ case Variant::VECTOR2:
+ return Vector2(js_data[0].d, js_data[1].d);
+ case Variant::VECTOR3:
+ return Vector3(js_data[0].d, js_data[1].d, js_data[2].d);
+ case Variant::RECT2:
+ return Rect2(js_data[0].d, js_data[1].d, js_data[2].d, js_data[3].d);
+ case Variant::COLOR:
+ return Color(js_data[0].d/255., js_data[1].d/255., js_data[2].d/255., js_data[3].d);
+ }
+ return Variant();
+}
+
+void JavaScript::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("eval", "code", "use_global_execution_context"), &JavaScript::eval, false);
+}
+
+JavaScript::JavaScript() {
+
+ ERR_FAIL_COND(singleton != NULL);
+ singleton = this;
+}
+
+JavaScript::~JavaScript() {
+
+}
+
+#endif // JAVASCRIPT_EVAL_ENABLED
diff --git a/platform/javascript/javascript_eval.h b/platform/javascript/javascript_eval.h
new file mode 100644
index 0000000000..e5f6268076
--- /dev/null
+++ b/platform/javascript/javascript_eval.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* javascript_eval.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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. */
+/*************************************************************************/
+#ifdef JAVASCRIPT_EVAL_ENABLED
+
+#ifndef JAVASCRIPT_EVAL_H
+#define JAVASCRIPT_EVAL_H
+
+#include "object.h"
+
+class JavaScript : public Object {
+private:
+ OBJ_TYPE( JavaScript, Object );
+
+ static JavaScript *singleton;
+
+
+protected:
+ static void _bind_methods();
+
+public:
+ Variant eval(const String& p_code, bool p_use_global_exec_context = false);
+
+ static JavaScript *get_singleton();
+ JavaScript();
+ ~JavaScript();
+};
+
+#endif // JAVASCRIPT_EVAL_H
+#endif // JAVASCRIPT_EVAL_ENABLED
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 1defcb7cb2..e802a7e9cb 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -230,6 +230,11 @@ void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int
if (result!=EMSCRIPTEN_RESULT_SUCCESS) {
ERR_PRINTS( "Error while setting Emscripten gamepaddisconnected callback: Code " + itos(result) );
}
+
+#ifdef JAVASCRIPT_EVAL_ENABLED
+ javascript_eval = memnew(JavaScript);
+ Globals::get_singleton()->add_singleton(Globals::Singleton("JavaScript", javascript_eval));
+#endif
}
void OS_JavaScript::set_main_loop( MainLoop * p_main_loop ) {
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 16e4781d15..5b7904805b 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -42,6 +42,7 @@
#include "audio_driver_javascript.h"
#include "main/input_default.h"
#include "emscripten/html5.h"
+#include "javascript_eval.h"
typedef void (*GFXInitFunc)(void *ud,bool gl2,int w, int h, bool fs);
typedef int (*OpenURIFunc)(const String&);
@@ -88,6 +89,10 @@ private:
GetDataDirFunc get_data_dir_func;
GetLocaleFunc get_locale_func;
+#ifdef JAVASCRIPT_EVAL_ENABLED
+ JavaScript* javascript_eval;
+#endif
+
static void _close_notification_funcs(const String& p_file,int p_flags);
void process_joysticks();