14
14
limitations under the License. */
15
15
16
16
#include <string.h>
17
+ #include <assert.h>
17
18
#include <erl_driver.h>
18
19
19
20
#include "spidermonkey.h"
@@ -32,6 +33,10 @@ typedef struct _spidermonkey_drv_t {
32
33
typedef struct _js_call_t {
33
34
spidermonkey_drv_t * driver_data ;
34
35
ErlDrvBinary * args ;
36
+ ErlDrvTermData return_terms [20 ];
37
+ char return_call_id [32 ];
38
+ int return_term_count ;
39
+ const char * return_string ;
35
40
} js_call ;
36
41
37
42
typedef void (* asyncfun )(void * );
@@ -42,6 +47,7 @@ static ErlDrvData start(ErlDrvPort port, char *cmd);
42
47
static int init ();
43
48
static void stop (ErlDrvData handle );
44
49
static void process (ErlDrvData handle , ErlIOVec * ev );
50
+ static void ready_async (ErlDrvData handle , ErlDrvThreadData async_data );
45
51
46
52
static ErlDrvEntry spidermonkey_drv_entry = {
47
53
init , /* init */
@@ -56,7 +62,7 @@ static ErlDrvEntry spidermonkey_drv_entry = {
56
62
NULL , /* control */
57
63
NULL , /* timeout */
58
64
process , /* process */
59
- NULL , /* ready_async */
65
+ ready_async , /* ready_async */
60
66
NULL , /* flush */
61
67
NULL , /* call */
62
68
NULL , /* event */
@@ -67,46 +73,67 @@ static ErlDrvEntry spidermonkey_drv_entry = {
67
73
};
68
74
69
75
70
- void send_output (ErlDrvPort port , ErlDrvTermData * terms , int term_count ) {
71
- driver_output_term (port , terms , term_count );
76
+ void send_immediate_ok_response (spidermonkey_drv_t * dd , const char * call_id ) {
77
+ ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY , (ErlDrvTermData ) call_id , strlen (call_id ),
78
+ ERL_DRV_ATOM , dd -> atom_ok ,
79
+ ERL_DRV_TUPLE , 2 };
80
+ driver_output_term (dd -> port , terms , sizeof (terms ) / sizeof (terms [0 ]));
72
81
}
73
82
74
- void send_ok_response (spidermonkey_drv_t * dd , const char * call_id ) {
75
- ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY , (ErlDrvTermData ) call_id , strlen (call_id ),
83
+ #define COPY_DATA (CD , CID , TERMS ) \
84
+ do { \
85
+ assert(strlen(CID) < sizeof(CD->return_call_id) - 1); \
86
+ strcpy(CD->return_call_id, CID); \
87
+ assert(sizeof(TERMS) <= sizeof(CD->return_terms)); \
88
+ memcpy(CD->return_terms, TERMS, sizeof(TERMS)); \
89
+ CD->return_term_count = sizeof(TERMS) / sizeof(TERMS[0]); \
90
+ } while (0)
91
+
92
+ void send_ok_response (spidermonkey_drv_t * dd , js_call * call_data ,
93
+ const char * call_id ) {
94
+ ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY ,
95
+ (ErlDrvTermData ) call_data -> return_call_id ,strlen (call_id ),
76
96
ERL_DRV_ATOM , dd -> atom_ok ,
77
97
ERL_DRV_TUPLE , 2 };
78
- send_output ( dd -> port , terms , sizeof ( terms ) / sizeof ( terms [ 0 ]) );
98
+ COPY_DATA ( call_data , call_id , terms );
79
99
}
80
100
81
- void send_error_string_response (spidermonkey_drv_t * dd , const char * call_id , const char * msg ) {
82
- ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY , (ErlDrvTermData ) call_id , strlen (call_id ),
101
+ void send_error_string_response (spidermonkey_drv_t * dd , js_call * call_data ,
102
+ const char * call_id , const char * msg ) {
103
+ ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY ,
104
+ (ErlDrvTermData ) call_data -> return_call_id ,strlen (call_id ),
83
105
ERL_DRV_ATOM , dd -> atom_error ,
84
106
ERL_DRV_BUF2BINARY , (ErlDrvTermData ) msg , strlen (msg ),
85
107
ERL_DRV_TUPLE , 3 };
86
- send_output (dd -> port , terms , sizeof (terms ) / sizeof (terms [0 ]));
108
+ COPY_DATA (call_data , call_id , terms );
109
+ call_data -> return_string = msg ;
87
110
}
88
111
89
- void send_string_response (spidermonkey_drv_t * dd , const char * call_id , const char * result ) {
90
- ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY , (ErlDrvTermData ) call_id , strlen (call_id ),
112
+ void send_string_response (spidermonkey_drv_t * dd , js_call * call_data ,
113
+ const char * call_id , const char * result ) {
114
+ ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY ,
115
+ (ErlDrvTermData ) call_data -> return_call_id ,strlen (call_id ),
91
116
ERL_DRV_ATOM , dd -> atom_ok ,
92
117
ERL_DRV_BUF2BINARY , (ErlDrvTermData ) result , strlen (result ),
93
118
ERL_DRV_TUPLE , 3 };
94
- send_output (dd -> port , terms , sizeof (terms ) / sizeof (terms [0 ]));
119
+ COPY_DATA (call_data , call_id , terms );
120
+ call_data -> return_string = result ;
95
121
}
96
122
97
- void unknown_command (spidermonkey_drv_t * dd , const char * call_id ) {
98
- ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY , (ErlDrvTermData ) call_id , strlen (call_id ),
123
+ void unknown_command (spidermonkey_drv_t * dd , js_call * call_data ,
124
+ const char * call_id ) {
125
+ ErlDrvTermData terms [] = {ERL_DRV_BUF2BINARY ,
126
+ (ErlDrvTermData ) call_data -> return_call_id ,strlen (call_id ),
99
127
ERL_DRV_ATOM , dd -> atom_error ,
100
128
ERL_DRV_ATOM , dd -> atom_unknown_cmd ,
101
129
ERL_DRV_TUPLE , 3 };
102
- send_output ( dd -> port , terms , sizeof ( terms ) / sizeof ( terms [ 0 ]) );
130
+ COPY_DATA ( call_data , call_id , terms );
103
131
}
104
132
105
133
void run_js (void * jsargs ) {
106
134
js_call * call_data = (js_call * ) jsargs ;
107
135
spidermonkey_drv_t * dd = call_data -> driver_data ;
108
136
ErlDrvBinary * args = call_data -> args ;
109
- driver_free (call_data );
110
137
char * data = args -> orig_bytes ;
111
138
char * command = read_command (& data );
112
139
char * call_id = read_string (& data );
@@ -116,39 +143,36 @@ void run_js(void *jsargs) {
116
143
char * code = read_string (& data );
117
144
result = sm_eval (dd -> vm , filename , code , 1 );
118
145
if ((strncmp (result , "[{\"error\":\"notfound\"}]" , 22 ) == 0 ) || (strncmp (result , "{\"error\"" , 8 ) == 0 )) {
119
- send_error_string_response (dd , call_id , result );
146
+ send_error_string_response (dd , call_data , call_id , result );
120
147
}
121
148
else {
122
- send_string_response (dd , call_id , result );
149
+ send_string_response (dd , call_data , call_id , result );
123
150
}
124
151
driver_free (filename );
125
152
driver_free (code );
126
- driver_free (result );
127
153
}
128
154
else if (strncmp (command , "dj" , 2 ) == 0 ) {
129
155
char * filename = read_string (& data );
130
156
char * code = read_string (& data );
131
157
result = sm_eval (dd -> vm , filename , code , 0 );
132
158
if (result == NULL ) {
133
- send_ok_response (dd , call_id );
159
+ send_ok_response (dd , call_data , call_id );
134
160
}
135
161
else {
136
- send_error_string_response (dd , call_id , result );
137
- driver_free (result );
162
+ send_error_string_response (dd , call_data , call_id , result );
138
163
}
139
164
driver_free (filename );
140
165
driver_free (code );
141
166
}
142
167
else if (strncmp (command , "sd" , 2 ) == 0 ) {
143
168
dd -> shutdown = 1 ;
144
- send_ok_response (dd , call_id );
169
+ send_ok_response (dd , call_data , call_id );
145
170
}
146
171
else {
147
- unknown_command (dd , call_id );
172
+ unknown_command (dd , call_data , call_id );
148
173
}
149
174
driver_free (command );
150
175
driver_free (call_id );
151
- driver_binary_dec_refc (args );
152
176
}
153
177
154
178
DRIVER_INIT (spidermonkey_drv ) {
@@ -183,6 +207,7 @@ static void stop(ErlDrvData handle) {
183
207
184
208
static void process (ErlDrvData handle , ErlIOVec * ev ) {
185
209
spidermonkey_drv_t * dd = (spidermonkey_drv_t * ) handle ;
210
+
186
211
char * data = ev -> binv [1 ]-> orig_bytes ;
187
212
char * command = read_command (& data );
188
213
if (strncmp (command , "ij" , 2 ) == 0 ) {
@@ -194,17 +219,35 @@ static void process(ErlDrvData handle, ErlIOVec *ev) {
194
219
thread_stack = thread_stack * (1024 * 1024 );
195
220
int heap_size = read_int32 (& data ) * (1024 * 1024 );
196
221
dd -> vm = sm_initialize (thread_stack , heap_size );
197
- send_ok_response (dd , call_id );
222
+ send_immediate_ok_response (dd , call_id );
198
223
driver_free (call_id );
199
224
}
200
225
else {
201
226
js_call * call_data = (js_call * ) driver_alloc (sizeof (js_call ));
202
227
call_data -> driver_data = dd ;
203
228
call_data -> args = ev -> binv [1 ];
229
+ call_data -> return_terms [0 ] = 0 ;
230
+ call_data -> return_term_count = 0 ;
231
+ call_data -> return_string = NULL ;
204
232
driver_binary_inc_refc (call_data -> args );
205
233
ErlDrvPort port = dd -> port ;
206
234
unsigned long thread_key = (unsigned long ) port ;
207
235
driver_async (dd -> port , (unsigned int * ) & thread_key , (asyncfun ) run_js , (void * ) call_data , NULL );
208
236
}
209
237
driver_free (command );
210
238
}
239
+
240
+ static void
241
+ ready_async (ErlDrvData handle , ErlDrvThreadData async_data )
242
+ {
243
+ spidermonkey_drv_t * dd = (spidermonkey_drv_t * ) handle ;
244
+ js_call * call_data = (js_call * ) async_data ;
245
+
246
+ driver_output_term (dd -> port ,
247
+ call_data -> return_terms , call_data -> return_term_count );
248
+ driver_binary_dec_refc (call_data -> args );
249
+ if (call_data -> return_string != NULL ) {
250
+ driver_free ((void * ) call_data -> return_string );
251
+ }
252
+ driver_free (call_data );
253
+ }
0 commit comments