diff --git a/c_src/to_erl.c b/c_src/to_erl.c index 04592db..aad97f5 100644 --- a/c_src/to_erl.c +++ b/c_src/to_erl.c @@ -8,6 +8,13 @@ #define OK 1 #define ERROR 0 +#ifndef JSID_VOID +#include +#define JSID_VOID JSVAL_VOID +#endif + + + int to_erl_intern(ErlNifEnv* env, JSContext* cx, jsval val, ERL_NIF_TERM* term); int @@ -26,7 +33,7 @@ to_erl_string(ErlNifEnv* env, JSContext* cx, jsval val, ERL_NIF_TERM* term) size_t len; str = JS_ValueToString(cx, val); - data = JS_GetStringBytesZ(cx, str); + data = JS_EncodeString(cx, str); if(data == NULL) return ERROR; len = strlen(data); @@ -106,7 +113,7 @@ to_erl_object(ErlNifEnv* env, JSContext* cx, JSObject* obj, ERL_NIF_TERM* term) length = 0; while(JS_NextProperty(cx, iter, &idp)) { - if(idp == JSVAL_VOID) break; + if(idp == JSID_VOID) break; length += 1; } @@ -119,7 +126,7 @@ to_erl_object(ErlNifEnv* env, JSContext* cx, JSObject* obj, ERL_NIF_TERM* term) index = 0; while(JS_NextProperty(cx, iter, &idp)) { - if(idp == JSVAL_VOID) + if(idp == JSID_VOID) { list = enif_make_list_from_array(env, array, length); *term = enif_make_tuple1(env, list); diff --git a/c_src/vm.c b/c_src/vm.c index 246c9d2..b1b3293 100644 --- a/c_src/vm.c +++ b/c_src/vm.c @@ -8,6 +8,7 @@ #include "util.h" #include "vm.h" + typedef enum { job_unknown, @@ -45,13 +46,18 @@ struct vm_t int alive; }; + static JSClass global_class = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, +#ifdef JS185 + JS_StrictPropertyStub, +#else JS_PropertyStub, +#endif JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, @@ -59,6 +65,7 @@ static JSClass global_class = { JSCLASS_NO_OPTIONAL_MEMBERS }; + void* vm_run(void* arg); ENTERM vm_eval(JSContext* cx, JSObject* gl, job_ptr job); ENTERM vm_call(JSContext* cx, JSObject* gl, job_ptr job); @@ -109,7 +116,11 @@ static JSClass jserl_class = { JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, +#ifdef JS185 + JS_StrictPropertyStub, +#else JS_PropertyStub, +#endif JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, @@ -117,13 +128,15 @@ static JSClass jserl_class = { JSCLASS_NO_OPTIONAL_MEMBERS }; +#ifdef JS185 static JSBool -jserl_send(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) +jserl_send(JSContext* cx, uintN argc, jsval* vp) { vm_ptr vm = (vm_ptr) JS_GetContextPrivate(cx); ErlNifEnv* env; job_ptr job; ENTERM mesg; + jsval* argv = JS_ARGV(cx, vp); if(argc < 0) { @@ -153,12 +166,54 @@ jserl_send(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) } assert(job->type == job_response && "Invalid message response."); + JS_SET_RVAL(cx, vp, to_js(job->env, cx, job->args)); + job_destroy(job); + + return JS_TRUE; +} +#else +static JSBool +jserl_send(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) +{ + vm_ptr vm = (vm_ptr) JS_GetContextPrivate(cx); + ErlNifEnv* env; + job_ptr job; + ENTERM mesg; + + if(argc < 0) + { + return JS_FALSE; + } + + assert(vm != NULL && "Context has no vm."); + + env = enif_alloc_env(); + mesg = vm_mk_message(env, to_erl(env, cx, argv[0])); + + // If pid is not alive, raise an error. + // XXX: Can I make this uncatchable? + if(!enif_send(NULL, &(vm->curr_job->pid), env, mesg)) + { + JS_ReportError(cx, "Context closing."); + return JS_FALSE; + } + + job = queue_receive(vm->jobs); + if(job->type == job_close) + { + // XXX: Can I make this uncatchable? + job_destroy(job); + JS_ReportError(cx, "Context closing."); + return JS_FALSE; + } + assert(job->type == job_response && "Invalid message response."); *rval = to_js(job->env, cx, job->args); job_destroy(job); return JS_TRUE; } +#endif int install_jserl(JSContext* cx, JSObject* gl) @@ -257,8 +312,12 @@ vm_run(void* arg) flags |= JSOPTION_COMPILE_N_GO; flags |= JSOPTION_XML; JS_SetOptions(cx, JS_GetOptions(cx) | flags); - + +#ifdef JS185 + gl = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL); +#else gl = JS_NewObject(cx, &global_class, NULL, NULL); +#endif if(gl == NULL) { fprintf(stderr, "Failed to create global object.\n"); @@ -430,7 +489,7 @@ vm_call(JSContext* cx, JSObject* gl, job_ptr job) jsval rval; jsid idp; int argc; - + // Get the function object. func = to_js(job->env, cx, job->name); diff --git a/c_src/vm.h b/c_src/vm.h index 57232cf..2b7d55b 100644 --- a/c_src/vm.h +++ b/c_src/vm.h @@ -9,6 +9,11 @@ #include "alias.h" + +#ifdef JS_NewCompartmentAndGlobalObject +#define JS185 1 +#endif + typedef struct vm_t* vm_ptr; vm_ptr vm_init(ErlNifResourceType* res_type, JSRuntime* runtime, size_t stack_size); diff --git a/test/004-basic-calls.t b/test/004-basic-calls.t index 1f326b4..3d28e22 100755 --- a/test/004-basic-calls.t +++ b/test/004-basic-calls.t @@ -1,5 +1,5 @@ #!/usr/bin/env escript -%%! -pa ./test/ -pa ./ebin/ +%%! -smp +K true -pa ./test/ -pa ./ebin/ % This file is part of Emonk released under the MIT license. % See the LICENSE file for more information. diff --git a/test/005-erl-to-js.t b/test/005-erl-to-js.t index 6fed28a..aa45103 100755 --- a/test/005-erl-to-js.t +++ b/test/005-erl-to-js.t @@ -1,5 +1,5 @@ #!/usr/bin/env escript -%%! -pa ./test/ -pa ./ebin/ +%%! -smp +K true -pa ./test/ -pa ./ebin/ % This file is part of Emonk released under the MIT license. % See the LICENSE file for more information. diff --git a/test/006-js-to-erl.t b/test/006-js-to-erl.t index cf7c27e..f4ba89c 100755 --- a/test/006-js-to-erl.t +++ b/test/006-js-to-erl.t @@ -1,5 +1,5 @@ #!/usr/bin/env escript -%%! -pa ./test/ -pa ./ebin/ +%%! -smp +K true -pa ./test/ -pa ./ebin/ % This file is part of Emonk released under the MIT license. % See the LICENSE file for more information. diff --git a/test/007-js-send-message.t b/test/007-js-send-message.t index d5c6eda..e3399cf 100755 --- a/test/007-js-send-message.t +++ b/test/007-js-send-message.t @@ -1,5 +1,5 @@ #!/usr/bin/env escript -%%! -pa ./test/ -pa ./ebin/ +%%! -smp +K true -pa ./test/ -pa ./ebin/ % This file is part of Emonk released under the MIT license. % See the LICENSE file for more information.