@@ -45,6 +45,9 @@ typedef struct {
4545 JSValue inverse_func ; // to release (window functions only)
4646} functionjs_context ;
4747
48+ static char * sqlite_strdup (const char * str );
49+ static bool js_global_init (JSContext * ctx );
50+
4851#define SQLITEJS_VERSION "1.0.0"
4952static char gversion [128 ];
5053
@@ -54,8 +57,9 @@ static globaljs_context *globaljs_init (sqlite3 *db) {
5457 JSRuntime * rt = NULL ;
5558 JSContext * ctx = NULL ;
5659
57- globaljs_context * js = (globaljs_context * )calloc ( 1 , sizeof (globaljs_context ));
60+ globaljs_context * js = (globaljs_context * )sqlite3_malloc ( sizeof (globaljs_context ));
5861 if (!js ) return NULL ;
62+ bzero (js , sizeof (globaljs_context ));
5963
6064 rt = JS_NewRuntime ();
6165 if (!rt ) goto abort_init ;
@@ -66,9 +70,8 @@ static globaljs_context *globaljs_init (sqlite3 *db) {
6670 ctx = JS_NewContext (rt );
6771 if (!ctx ) goto abort_init ;
6872
69- JSValue global = JS_GetGlobalObject (ctx );
70- // add any global objects or functions here
71- JS_FreeValue (ctx , global );
73+ JS_SetContextOpaque (ctx , db );
74+ js_global_init (ctx );
7275
7376 js -> db = db ;
7477 js -> runtime = rt ;
@@ -78,7 +81,7 @@ static globaljs_context *globaljs_init (sqlite3 *db) {
7881abort_init :
7982 if (rt ) JS_FreeRuntime (rt );
8083 if (ctx ) JS_FreeContext (ctx );
81- if (js ) free (js );
84+ if (js ) sqlite3_free (js );
8285 return NULL ;
8386}
8487
@@ -87,7 +90,7 @@ static void globaljs_free (globaljs_context *js) {
8790
8891 if (js -> runtime ) JS_FreeRuntime (js -> runtime );
8992 if (js -> context ) JS_FreeContext (js -> context );
90- free (js );
93+ sqlite3_free (js );
9194}
9295
9396static functionjs_context * functionjs_init (globaljs_context * jsctx , const char * init_code , const char * step_code , const char * final_code , const char * value_code , const char * inverse_code ) {
@@ -99,31 +102,32 @@ static functionjs_context *functionjs_init (globaljs_context *jsctx, const char
99102 char * value_code_copy = NULL ;
100103 char * inverse_code_copy = NULL ;
101104
102- fctx = (functionjs_context * )calloc ( 1 , sizeof (functionjs_context ));
105+ fctx = (functionjs_context * )sqlite3_malloc ( sizeof (functionjs_context ));
103106 if (!fctx ) goto cleanup ;
107+ bzero (fctx , sizeof (functionjs_context ));
104108
105109 if (init_code ) {
106- init_code_copy = strdup (init_code );
110+ init_code_copy = sqlite_strdup (init_code );
107111 if (!init_code_copy ) goto cleanup ;
108112 }
109113
110114 if (step_code ) {
111- step_code_copy = strdup (step_code );
115+ step_code_copy = sqlite_strdup (step_code );
112116 if (!step_code_copy ) goto cleanup ;
113117 }
114118
115119 if (final_code ) {
116- final_code_copy = strdup (final_code );
120+ final_code_copy = sqlite_strdup (final_code );
117121 if (!final_code_copy ) goto cleanup ;
118122 }
119123
120124 if (value_code ) {
121- value_code_copy = strdup (value_code );
125+ value_code_copy = sqlite_strdup (value_code );
122126 if (!value_code_copy ) goto cleanup ;
123127 }
124128
125129 if (inverse_code ) {
126- inverse_code_copy = strdup (inverse_code );
130+ inverse_code_copy = sqlite_strdup (inverse_code );
127131 if (!inverse_code_copy ) goto cleanup ;
128132 }
129133
@@ -145,12 +149,12 @@ static functionjs_context *functionjs_init (globaljs_context *jsctx, const char
145149 return fctx ;
146150
147151cleanup :
148- if (init_code_copy ) free (init_code_copy );
149- if (step_code_copy ) free (step_code_copy );
150- if (final_code_copy ) free (final_code_copy );
151- if (value_code_copy ) free (value_code_copy );
152- if (inverse_code_copy ) free (inverse_code_copy );
153- if (fctx ) free (fctx );
152+ if (init_code_copy ) sqlite3_free (init_code_copy );
153+ if (step_code_copy ) sqlite3_free (step_code_copy );
154+ if (final_code_copy ) sqlite3_free (final_code_copy );
155+ if (value_code_copy ) sqlite3_free (value_code_copy );
156+ if (inverse_code_copy ) sqlite3_free (inverse_code_copy );
157+ if (fctx ) sqlite3_free (fctx );
154158 return NULL ;
155159}
156160
@@ -172,17 +176,15 @@ static void functionjs_free (functionjs_context *fctx, bool complete) {
172176 fctx -> agg_ctx = NULL ;
173177
174178 if (complete ) {
175- if (fctx -> init_code ) free ((void * )fctx -> init_code );
176- if (fctx -> step_code ) free ((void * )fctx -> step_code );
177- if (fctx -> final_code ) free ((void * )fctx -> final_code );
178- if (fctx -> value_code ) free ((void * )fctx -> value_code );
179- if (fctx -> inverse_code ) free ((void * )fctx -> inverse_code );
180- free (fctx );
179+ if (fctx -> init_code ) sqlite3_free ((void * )fctx -> init_code );
180+ if (fctx -> step_code ) sqlite3_free ((void * )fctx -> step_code );
181+ if (fctx -> final_code ) sqlite3_free ((void * )fctx -> final_code );
182+ if (fctx -> value_code ) sqlite3_free ((void * )fctx -> value_code );
183+ if (fctx -> inverse_code ) sqlite3_free ((void * )fctx -> inverse_code );
184+ sqlite3_free (fctx );
181185 }
182186}
183187
184- // MARK: - Utils -
185-
186188static void compute_version_string (void ) {
187189 const char * s1 = SQLITEJS_VERSION ;
188190 const char * s2 = JS_GetVersion ();
@@ -230,6 +232,52 @@ static void compute_version_string (void) {
230232 }
231233}
232234
235+ // MARK: - Utils -
236+
237+ static JSValue js_sqlite_exec (JSContext * ctx , sqlite3 * db , const char * sql ) {
238+ //int rc = sqlite3_prepare_v2(db, sql, -1, sqlite3_stmt **ppStmt, const char **pzTail)
239+ return JS_NewNumber (ctx , 3.1415 );
240+ }
241+
242+ static JSValue js_dbfunc_exec (JSContext * ctx , JSValueConst this_val , int argc , JSValueConst * argv ) {
243+ // check if we have at least one argument
244+ if (argc < 1 ) return JS_EXCEPTION ;
245+
246+ // get the SQL string from the first argument
247+ size_t len ;
248+ const char * sql = JS_ToCStringLen (ctx , & len , argv [0 ]);
249+ if (!sql ) return JS_EXCEPTION ;
250+
251+ // perform statement
252+ sqlite3 * db = (sqlite3 * )JS_GetContextOpaque (ctx );
253+ JSValue value = js_sqlite_exec (ctx , db , sql );
254+
255+ // free the string when done
256+ JS_FreeCString (ctx , sql );
257+
258+ return value ;
259+ }
260+
261+ static bool js_global_init (JSContext * ctx ) {
262+ // add any global objects or functions here
263+ JSValue global_obj = JS_GetGlobalObject (ctx );
264+
265+ // create a new db object
266+ JSValue db_obj = JS_NewObject (ctx );
267+
268+ // add the exec function to the db object
269+ JS_SetPropertyStr (ctx , db_obj , "exec" , JS_NewCFunction (ctx , js_dbfunc_exec , "exec" , 1 ));
270+
271+ // set the db object as a property of the global object
272+ JS_SetPropertyStr (ctx , global_obj , "db" , db_obj );
273+
274+ // release the global object reference
275+ JS_FreeValue (ctx , global_obj );
276+
277+ // we don't free db_obj because it's now owned by the global object
278+ return true;
279+ }
280+
233281static void js_dump_globals (JSContext * ctx ) {
234282 JSValue global_obj = JS_GetGlobalObject (ctx );
235283 JSPropertyEnum * props ;
@@ -360,6 +408,10 @@ static bool js_setup_aggregate (sqlite3_context *context, globaljs_context *js,
360408 return false;
361409 }
362410
411+ // setup global object
412+ JS_SetContextOpaque (ctx , sqlite3_context_db_handle (context ));
413+ js_global_init (ctx );
414+
363415 // init code is optional
364416 if (init_code ) {
365417 JSValue result = JS_Eval (ctx , init_code , strlen (init_code ), NULL , JS_EVAL_TYPE_GLOBAL );
@@ -455,6 +507,16 @@ static const char *sqlite_value_text (sqlite3_value *value) {
455507 return (const char * )sqlite3_value_text (value );
456508}
457509
510+ static char * sqlite_strdup (const char * str ) {
511+ if (!str ) return NULL ;
512+
513+ size_t len = strlen (str ) + 1 ;
514+ char * result = (char * )sqlite3_malloc ((int )len );
515+ if (result ) memcpy (result , str , len );
516+
517+ return result ;
518+ }
519+
458520// MARK: - Execution -
459521
460522static void js_execute_commong (sqlite3_context * context , int nvalues , sqlite3_value * * values , JSValue func , JSValue this_obj , bool return_value ) {
@@ -710,7 +772,7 @@ static void js_load_file (sqlite3_context *context, int argc, sqlite3_value **ar
710772 size_t length = (size_t )ftell (f );
711773 fseek (f , 0 , SEEK_SET );
712774
713- char * buffer = malloc ( length );
775+ char * buffer = ( char * ) sqlite3_malloc (( int ) length );
714776 if (!buffer ) {
715777 fclose (f );
716778 sqlite3_result_error_nomem (context );
@@ -719,10 +781,10 @@ static void js_load_file (sqlite3_context *context, int argc, sqlite3_value **ar
719781
720782 size_t nread = fread (buffer , length , 1 , f );
721783 if (nread == length ) {
722- (is_blob ) ? sqlite3_result_blob (context , buffer , (int )length , free ) : sqlite3_result_text (context , buffer , (int )length , free );
784+ (is_blob ) ? sqlite3_result_blob (context , buffer , (int )length , sqlite3_free ) : sqlite3_result_text (context , buffer , (int )length , sqlite3_free );
723785 } else {
724786 sqlite3_result_error (context , "Unable to correctly read the file" , -1 );
725- if (buffer ) free (buffer );
787+ if (buffer ) sqlite3_free (buffer );
726788 }
727789
728790 fclose (f );
0 commit comments