Permalink
Browse files

Add working JS function calling interface

  • Loading branch information...
xxuejie committed Dec 26, 2012
1 parent 88b2c8f commit 60016e969ed767540e3dad4dec7d2e1622c39c73
Showing with 97 additions and 10 deletions.
  1. +31 −3 js/mruby_js.js
  2. +2 −1 mrblib/mruby_js.rb
  3. +63 −5 src/mruby_js.c
  4. +1 −1 test/mruby_js.rb
View
@@ -1,5 +1,33 @@
mergeInto(LibraryManager.library, {
- js_func: function() {
- Module.print('Calling js func!');
- }
+ js_call: function (mrb, handle, name_p, argv_p, argc) {
+
+ // Supported types. Currently we are only considering
+ // false, true, number and string. Those are the
+ // primitive types specified in the JSON spec.
+ var TYPE_HANDLERS = {
+ 0: function() { return false; }, // MRB_TT_FALSE
+ 2: function() { return true; }, // MRB_TT_TRUE
+ 3: _mruby_js_get_integer, // MRB_TT_FIXNUM
+ 6: _mruby_js_get_float, // MRB_TT_FLOAT
+ 17: function() {
+ var str_p = _mruby_js_get_string.apply(this, arguments);
+ return Module.Pointer_stringify(str_p);
+ } // MRB_TT_STRING
+ }
+
+ // TODO: add code to specify base object
+ var base_object = (typeof window === 'object') ? (window) : (global);
+ var func = base_object[Module.Pointer_stringify(name_p)];
+ if (typeof func !== 'function') {
+ _mruby_js_name_error(mrb);
+ }
+
+ var i = 0, args = [], type_handler;
+ for (i = 0; i < argc; i++) {
+ type_handler = TYPE_HANDLERS[_mruby_js_argument_type(mrb, argv_p, i)];
+ args.push(type_handler(mrb, argv_p, i));
+ }
+
+ func.apply(this, args);
+ },
});
View
@@ -1,5 +1,6 @@
module MrubyJs
def self.test
- call_js
+ # TODO: this only serves as a test, change this later
+ call("test_js_func", "Hello from mruby!", 42, false, 3.14564, true, "Another string")
end
end
View
@@ -1,17 +1,75 @@
-#include <mruby.h>
#include <stdio.h>
+#include <string.h>
+
+#include <emscripten/emscripten.h>
+
+#include <mruby.h>
+#include <mruby/string.h>
+
+#define INVALID_HANDLE -1
+
+extern void js_call(mrb_state *mrb, int handle, const char* name, mrb_value* argv, int argc);
-extern void js_func();
+int EMSCRIPTEN_KEEPALIVE mruby_js_argument_type(mrb_state *mrb, mrb_value* argv, int idx)
+{
+ return argv[idx].tt;
+}
+
+char* EMSCRIPTEN_KEEPALIVE mruby_js_get_string(mrb_state *mrb, mrb_value* argv, int idx)
+{
+ struct RString *s;
+ /* TODO: well, let's come back to the auto-conversion later,
+ * since that involves changing the mruby_js_argument_type function
+ * as well.
+ */
+ if (mrb_type(argv[idx]) != MRB_TT_STRING) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Given argument is not a string!");
+ }
+ s = mrb_str_ptr(argv[idx]);
+ if (strlen(s->ptr) != s->len) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NULL!");
+ }
+ return s->ptr;
+}
+
+mrb_int EMSCRIPTEN_KEEPALIVE mruby_js_get_integer(mrb_state *mrb, mrb_value* argv, int idx)
+{
+ if (mrb_type(argv[idx]) != MRB_TT_FIXNUM) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Given argument is not an integer!");
+ }
+ return mrb_fixnum(argv[idx]);
+}
+
+mrb_float EMSCRIPTEN_KEEPALIVE mruby_js_get_float(mrb_state *mrb, mrb_value* argv, int idx)
+{
+ if (mrb_type(argv[idx]) != MRB_TT_FLOAT) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Given argument is not a float!");
+ }
+ return mrb_float(argv[idx]);
+}
+
+void EMSCRIPTEN_KEEPALIVE mruby_js_name_error(mrb_state *mrb)
+{
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Error occurs when locating the function to call!");
+}
static mrb_value
-mrb_call_js(mrb_state *mrb, mrb_value self)
+mrb_js_call(mrb_state *mrb, mrb_value self)
{
- js_func();
+ char* name = NULL;
+ mrb_value *argv = NULL;
+ int argc = 0;
+
+ /* TODO: block handling */
+ mrb_get_args(mrb, "z*", &name, &argv, &argc);
+ if (name != NULL) {
+ js_call(mrb, INVALID_HANDLE, name, argv, argc);
+ }
return self;
}
void
mrb_mruby_js_gem_init(mrb_state* mrb) {
struct RClass *class_cextension = mrb_define_module(mrb, "MrubyJs");
- mrb_define_class_method(mrb, class_cextension, "call_js", mrb_call_js, ARGS_NONE());
+ mrb_define_class_method(mrb, class_cextension, "call", mrb_js_call, ARGS_ANY());
}
View
@@ -3,5 +3,5 @@
end
assert('mruby-js test 2') do
- MrubyJs.respond_to? :call_js
+ MrubyJs.respond_to? :call
end

0 comments on commit 60016e9

Please sign in to comment.