@bullet./paraql 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +39 -36
  2. package/binding.c +279 -119
  3. package/index.js +66 -28
  4. package/lib/codecs.js +12 -30
  5. package/lib/constants.js +36 -3
  6. package/lib/statement.d.ts +2 -10
  7. package/lib/statement.js +13 -27
  8. package/lib/vfs.js +54 -64
  9. package/package.json +1 -1
  10. package/prebuilds/android-arm/bullet.__paraql.bare +0 -0
  11. package/prebuilds/android-arm/bullet.__paraql.node +0 -0
  12. package/prebuilds/android-arm64/bullet.__paraql.bare +0 -0
  13. package/prebuilds/android-arm64/bullet.__paraql.node +0 -0
  14. package/prebuilds/android-ia32/bullet.__paraql.bare +0 -0
  15. package/prebuilds/android-ia32/bullet.__paraql.node +0 -0
  16. package/prebuilds/android-x64/bullet.__paraql.bare +0 -0
  17. package/prebuilds/android-x64/bullet.__paraql.node +0 -0
  18. package/prebuilds/darwin-arm64/bullet.__paraql.bare +0 -0
  19. package/prebuilds/darwin-arm64/bullet.__paraql.node +0 -0
  20. package/prebuilds/darwin-x64/bullet.__paraql.bare +0 -0
  21. package/prebuilds/darwin-x64/bullet.__paraql.node +0 -0
  22. package/prebuilds/ios-arm64/bullet.__paraql.bare +0 -0
  23. package/prebuilds/ios-arm64-simulator/bullet.__paraql.bare +0 -0
  24. package/prebuilds/ios-x64-simulator/bullet.__paraql.bare +0 -0
  25. package/prebuilds/linux-arm64/bullet.__paraql.bare +0 -0
  26. package/prebuilds/linux-arm64/bullet.__paraql.node +0 -0
  27. package/prebuilds/linux-x64/bullet.__paraql.bare +0 -0
  28. package/prebuilds/linux-x64/bullet.__paraql.node +0 -0
  29. package/prebuilds/win32-arm64/bullet.__paraql.bare +0 -0
  30. package/prebuilds/win32-arm64/bullet.__paraql.node +0 -0
  31. package/prebuilds/win32-x64/bullet.__paraql.bare +0 -0
  32. package/prebuilds/win32-x64/bullet.__paraql.node +0 -0
package/binding.c CHANGED
@@ -3,6 +3,7 @@
3
3
  #include <js.h>
4
4
  #include <sqlite3.h>
5
5
  #include <stdbool.h>
6
+ #include <stddef.h>
6
7
  #include <stdint.h>
7
8
  #include <stdlib.h>
8
9
  #include <string.h>
@@ -100,29 +101,40 @@ typedef struct {
100
101
  int status;
101
102
  } paravfs_delete_t;
102
103
 
103
- typedef struct paraql_statement_s paraql_statement_t;
104
-
105
104
  typedef struct {
106
105
  sqlite3 *handle;
107
106
 
108
107
  js_env_t *env;
108
+ js_ref_t *ctx;
109
109
 
110
- paraql_statement_t *statements;
110
+ js_threadsafe_function_t *on_auth;
111
111
  } paraql_t;
112
112
 
113
- struct paraql_statement_s {
113
+ typedef struct {
114
+ int action;
115
+
116
+ const char *param1;
117
+ const char *param2;
118
+ const char *param3;
119
+ const char *param4;
120
+
121
+ uv_sem_t done;
122
+
123
+ int status;
124
+ } paraql_auth_t;
125
+
126
+ typedef struct {
114
127
  sqlite3_stmt *handle;
115
128
 
116
129
  paraql_t *db;
117
- paraql_statement_t *prev;
118
- paraql_statement_t *next;
119
- };
130
+ } paraql_statement_t;
120
131
 
121
132
  typedef struct {
122
133
  uv_work_t handle;
123
134
 
124
135
  paraql_t *db;
125
136
 
137
+ js_ref_t *ref;
126
138
  js_deferred_t *deferred;
127
139
 
128
140
  paraql_path_t name;
@@ -160,6 +172,7 @@ typedef struct {
160
172
 
161
173
  paraql_t *db;
162
174
 
175
+ js_ref_t *ref;
163
176
  js_deferred_t *deferred;
164
177
 
165
178
  utf8_t *sql;
@@ -276,6 +289,22 @@ typedef struct {
276
289
  const char *errmsg;
277
290
  } paraql_run_t;
278
291
 
292
+ typedef struct {
293
+ uv_work_t handle;
294
+
295
+ js_env_t *env;
296
+
297
+ js_deferred_t *deferred;
298
+
299
+ paraql_t *db;
300
+
301
+ sqlite3_int64 size;
302
+ unsigned char *data;
303
+
304
+ int errcode;
305
+ const char *errmsg;
306
+ } paraql_serialize_t;
307
+
279
308
  static const size_t paraql__queue_limit = 64;
280
309
 
281
310
  static int
@@ -1048,53 +1077,6 @@ paravfs_destroy(js_env_t *env, js_callback_info_t *info) {
1048
1077
  return NULL;
1049
1078
  }
1050
1079
 
1051
- static void
1052
- paraql__insert_statement(paraql_t *db, paraql_statement_t *stmt) {
1053
- stmt->db = db;
1054
- stmt->prev = NULL;
1055
- stmt->next = db->statements;
1056
-
1057
- if (db->statements != NULL) db->statements->prev = stmt;
1058
-
1059
- db->statements = stmt;
1060
- }
1061
-
1062
- static void
1063
- paraql__remove_statement(paraql_statement_t *stmt) {
1064
- if (stmt->db == NULL) return;
1065
-
1066
- if (stmt->prev != NULL) stmt->prev->next = stmt->next;
1067
- else stmt->db->statements = stmt->next;
1068
-
1069
- if (stmt->next != NULL) stmt->next->prev = stmt->prev;
1070
-
1071
- stmt->db = NULL;
1072
- stmt->prev = NULL;
1073
- stmt->next = NULL;
1074
- }
1075
-
1076
- static void
1077
- paraql__finalize_statements(paraql_t *db) {
1078
- paraql_statement_t *stmt = db->statements;
1079
-
1080
- while (stmt != NULL) {
1081
- paraql_statement_t *next = stmt->next;
1082
-
1083
- if (stmt->handle != NULL) {
1084
- sqlite3_finalize(stmt->handle);
1085
- stmt->handle = NULL;
1086
- }
1087
-
1088
- stmt->db = NULL;
1089
- stmt->prev = NULL;
1090
- stmt->next = NULL;
1091
-
1092
- stmt = next;
1093
- }
1094
-
1095
- db->statements = NULL;
1096
- }
1097
-
1098
1080
  static const char *
1099
1081
  paraql__code(int errcode) {
1100
1082
  switch (errcode & 0xff) {
@@ -1150,72 +1132,108 @@ paraql__make_error(js_env_t *env, int errcode, const char *errmsg, js_value_t **
1150
1132
  return js_create_error(env, code, message, error);
1151
1133
  }
1152
1134
 
1153
- static void
1154
- paraql__on_after_finalize_db(uv_work_t *handle, int status) {
1155
- free(handle);
1156
- }
1135
+ static js_value_t *
1136
+ paraql__on_auth_done(js_env_t *env, js_callback_info_t *info) {
1137
+ int err;
1157
1138
 
1158
- static void
1159
- paraql__on_before_finalize_db(uv_work_t *handle) {
1160
- paraql_t *db = (paraql_t *) handle->data;
1139
+ paraql_auth_t *data;
1161
1140
 
1162
- paraql__finalize_statements(db);
1141
+ size_t argc = 1;
1142
+ js_value_t *argv[1];
1163
1143
 
1164
- if (db->handle != NULL) sqlite3_close_v2(db->handle);
1144
+ err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &data);
1145
+ assert(err == 0);
1165
1146
 
1166
- free(db);
1147
+ assert(argc == 1);
1148
+
1149
+ bool result;
1150
+ err = js_get_value_bool(env, argv[0], &result);
1151
+ assert(err == 0);
1152
+
1153
+ data->status = result ? SQLITE_OK : SQLITE_DENY;
1154
+
1155
+ uv_sem_post(&data->done);
1156
+
1157
+ return NULL;
1167
1158
  }
1168
1159
 
1169
1160
  static void
1170
- paraql__on_finalize_db(js_env_t *env, void *data, void *hint) {
1161
+ paraql__on_auth_call(js_env_t *env, js_value_t *on_auth, void *context, void *arg) {
1171
1162
  int err;
1172
1163
 
1173
- paraql_t *db = (paraql_t *) data;
1164
+ paraql_t *db = (paraql_t *) context;
1174
1165
 
1175
- uv_loop_t *loop;
1176
- err = js_get_env_loop(env, &loop);
1166
+ paraql_auth_t *data = (paraql_auth_t *) arg;
1167
+
1168
+ js_value_t *ctx;
1169
+ err = js_get_reference_value(env, db->ctx, &ctx);
1177
1170
  assert(err == 0);
1178
1171
 
1179
- uv_work_t *handle = malloc(sizeof(uv_work_t));
1172
+ js_value_t *args[6];
1180
1173
 
1181
- handle->data = (void *) db;
1174
+ err = js_create_int32(env, data->action, &args[0]);
1175
+ assert(err == 0);
1182
1176
 
1183
- err = uv_queue_work(loop, handle, paraql__on_before_finalize_db, paraql__on_after_finalize_db);
1177
+ if (data->param1 != NULL) {
1178
+ err = js_create_string_utf8(env, (utf8_t *) data->param1, -1, &args[1]);
1179
+ } else {
1180
+ err = js_get_null(env, &args[1]);
1181
+ }
1184
1182
  assert(err == 0);
1185
- }
1186
1183
 
1187
- static void
1188
- paraql__on_after_finalize_statement(uv_work_t *handle, int status) {
1189
- free(handle);
1190
- }
1184
+ if (data->param2 != NULL) {
1185
+ err = js_create_string_utf8(env, (utf8_t *) data->param2, -1, &args[2]);
1186
+ } else {
1187
+ err = js_get_null(env, &args[2]);
1188
+ }
1189
+ assert(err == 0);
1191
1190
 
1192
- static void
1193
- paraql__on_before_finalize_statement(uv_work_t *handle) {
1194
- paraql_statement_t *stmt = (paraql_statement_t *) handle->data;
1191
+ if (data->param3 != NULL) {
1192
+ err = js_create_string_utf8(env, (utf8_t *) data->param3, -1, &args[3]);
1193
+ } else {
1194
+ err = js_get_null(env, &args[3]);
1195
+ }
1196
+ assert(err == 0);
1195
1197
 
1196
- if (stmt->handle != NULL) sqlite3_finalize(stmt->handle);
1198
+ if (data->param4 != NULL) {
1199
+ err = js_create_string_utf8(env, (utf8_t *) data->param4, -1, &args[4]);
1200
+ } else {
1201
+ err = js_get_null(env, &args[4]);
1202
+ }
1203
+ assert(err == 0);
1197
1204
 
1198
- paraql__remove_statement(stmt);
1205
+ err = js_create_function(env, "done", -1, paraql__on_auth_done, (void *) data, &args[5]);
1206
+ assert(err == 0);
1199
1207
 
1200
- free(stmt);
1208
+ err = js_call_function(env, ctx, on_auth, 6, args, NULL);
1209
+ assert(err == 0);
1201
1210
  }
1202
1211
 
1203
- static void
1204
- paraql__on_finalize_statement(js_env_t *env, void *data, void *hint) {
1212
+ int
1213
+ paraql__on_auth(void *context, int action, const char *param1, const char *param2, const char *param3, const char *param4) {
1205
1214
  int err;
1206
1215
 
1207
- paraql_statement_t *stmt = (paraql_statement_t *) data;
1216
+ paraql_t *db = (paraql_t *) context;
1208
1217
 
1209
- uv_loop_t *loop;
1210
- err = js_get_env_loop(env, &loop);
1218
+ paraql_auth_t data = {
1219
+ action,
1220
+ param1,
1221
+ param2,
1222
+ param3,
1223
+ param4,
1224
+ };
1225
+
1226
+ err = uv_sem_init(&data.done, 0);
1211
1227
  assert(err == 0);
1212
1228
 
1213
- uv_work_t *handle = malloc(sizeof(uv_work_t));
1229
+ err = js_call_threadsafe_function(db->on_auth, (void *) &data, js_threadsafe_function_blocking);
1230
+ assert(err == 0);
1214
1231
 
1215
- handle->data = stmt;
1232
+ uv_sem_wait(&data.done);
1216
1233
 
1217
- err = uv_queue_work(loop, handle, paraql__on_before_finalize_statement, paraql__on_after_finalize_statement);
1218
- assert(err == 0);
1234
+ uv_sem_destroy(&data.done);
1235
+
1236
+ return data.status;
1219
1237
  }
1220
1238
 
1221
1239
  static void
@@ -1241,13 +1259,16 @@ paraql__on_after_open(uv_work_t *handle, int status) {
1241
1259
  assert(err == 0);
1242
1260
  } else {
1243
1261
  js_value_t *result;
1244
- err = js_create_external(env, db, paraql__on_finalize_db, NULL, &result);
1262
+ err = js_get_reference_value(env, req->ref, &result);
1245
1263
  assert(err == 0);
1246
1264
 
1247
1265
  err = js_resolve_deferred(env, req->deferred, result);
1248
1266
  assert(err == 0);
1249
1267
  }
1250
1268
 
1269
+ err = js_delete_reference(env, req->ref);
1270
+ assert(err == 0);
1271
+
1251
1272
  err = js_close_handle_scope(env, scope);
1252
1273
  assert(err == 0);
1253
1274
 
@@ -1269,6 +1290,12 @@ paraql__on_before_open(uv_work_t *handle) {
1269
1290
  req->errmsg = errmsg;
1270
1291
 
1271
1292
  if (db->handle != NULL) sqlite3_close_v2(db->handle);
1293
+
1294
+ return;
1295
+ }
1296
+
1297
+ if (db->on_auth != NULL) {
1298
+ sqlite3_set_authorizer(db->handle, paraql__on_auth, (void *) db);
1272
1299
  }
1273
1300
  }
1274
1301
 
@@ -1276,29 +1303,47 @@ static js_value_t *
1276
1303
  paraql_open(js_env_t *env, js_callback_info_t *info) {
1277
1304
  int err;
1278
1305
 
1279
- size_t argc = 1;
1280
- js_value_t *argv[1];
1306
+ size_t argc = 3;
1307
+ js_value_t *argv[3];
1281
1308
 
1282
1309
  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
1283
1310
  assert(err == 0);
1284
1311
 
1285
- assert(argc == 1);
1312
+ assert(argc == 3);
1286
1313
 
1287
1314
  uv_loop_t *loop;
1288
1315
  err = js_get_env_loop(env, &loop);
1289
1316
  assert(err == 0);
1290
1317
 
1318
+ js_value_t *handle;
1319
+ paraql_t *db;
1320
+ err = js_create_arraybuffer(env, sizeof(paraql_t), (void **) &db, &handle);
1321
+
1322
+ db->env = env;
1323
+
1324
+ err = js_create_reference(env, argv[0], 1, &db->ctx);
1325
+ assert(err == 0);
1326
+
1291
1327
  paraql_path_t name;
1292
- err = js_get_value_string_utf8(env, argv[0], name, sizeof(name), NULL);
1328
+ err = js_get_value_string_utf8(env, argv[1], name, sizeof(name), NULL);
1293
1329
  assert(err == 0);
1294
1330
 
1295
- paraql_t *db = malloc(sizeof(paraql_t));
1331
+ bool no_auth;
1332
+ err = js_is_null(env, argv[2], &no_auth);
1333
+ assert(err == 0);
1296
1334
 
1297
- db->env = env;
1298
- db->statements = NULL;
1335
+ if (no_auth) {
1336
+ db->on_auth = NULL;
1337
+ } else {
1338
+ err = js_create_threadsafe_function(env, argv[2], paraql__queue_limit, 1, NULL, NULL, (void *) db, paraql__on_auth_call, &db->on_auth);
1339
+ assert(err == 0);
1340
+ }
1299
1341
 
1300
1342
  paraql_open_t *req = malloc(sizeof(paraql_open_t));
1301
1343
 
1344
+ err = js_create_reference(env, handle, 1, &req->ref);
1345
+ assert(err == 0);
1346
+
1302
1347
  req->db = db;
1303
1348
  req->errcode = 0;
1304
1349
  req->db->env = env;
@@ -1327,6 +1372,14 @@ paraql__on_after_close(uv_work_t *handle, int status) {
1327
1372
 
1328
1373
  js_env_t *env = db->env;
1329
1374
 
1375
+ err = js_delete_reference(env, db->ctx);
1376
+ assert(err == 0);
1377
+
1378
+ if (db->on_auth != NULL) {
1379
+ err = js_release_threadsafe_function(db->on_auth, js_threadsafe_function_release);
1380
+ assert(err == 0);
1381
+ }
1382
+
1330
1383
  js_handle_scope_t *scope;
1331
1384
  err = js_open_handle_scope(env, &scope);
1332
1385
  assert(err == 0);
@@ -1391,7 +1444,7 @@ paraql_close(js_env_t *env, js_callback_info_t *info) {
1391
1444
 
1392
1445
  req->errcode = 0;
1393
1446
 
1394
- err = js_get_value_external(env, argv[0], (void **) &req->db);
1447
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &req->db, NULL);
1395
1448
  assert(err == 0);
1396
1449
 
1397
1450
  req->handle.data = (void *) req;
@@ -1503,7 +1556,7 @@ paraql_exec(js_env_t *env, js_callback_info_t *info) {
1503
1556
  assert(err == 0);
1504
1557
 
1505
1558
  paraql_t *db;
1506
- err = js_get_value_external(env, argv[0], (void **) &db);
1559
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &db, NULL);
1507
1560
  assert(err == 0);
1508
1561
 
1509
1562
  size_t sql_len;
@@ -1545,8 +1598,6 @@ paraql__on_after_prepare(uv_work_t *handle, int status) {
1545
1598
 
1546
1599
  js_env_t *env = db->env;
1547
1600
 
1548
- paraql_statement_t *stmt = req->stmt;
1549
-
1550
1601
  js_handle_scope_t *scope;
1551
1602
  err = js_open_handle_scope(env, &scope);
1552
1603
  assert(err == 0);
@@ -1560,13 +1611,16 @@ paraql__on_after_prepare(uv_work_t *handle, int status) {
1560
1611
  assert(err == 0);
1561
1612
  } else {
1562
1613
  js_value_t *result;
1563
- err = js_create_external(env, stmt, paraql__on_finalize_statement, NULL, &result);
1614
+ err = js_get_reference_value(env, req->ref, &result);
1564
1615
  assert(err == 0);
1565
1616
 
1566
1617
  err = js_resolve_deferred(env, req->deferred, result);
1567
1618
  assert(err == 0);
1568
1619
  }
1569
1620
 
1621
+ err = js_delete_reference(env, req->ref);
1622
+ assert(err == 0);
1623
+
1570
1624
  err = js_close_handle_scope(env, scope);
1571
1625
  assert(err == 0);
1572
1626
 
@@ -1579,7 +1633,7 @@ paraql__on_before_prepare(uv_work_t *handle) {
1579
1633
 
1580
1634
  paraql_t *db = req->db;
1581
1635
 
1582
- paraql_statement_t *stmt = malloc(sizeof(paraql_statement_t));
1636
+ paraql_statement_t *stmt = req->stmt;
1583
1637
 
1584
1638
  int status = sqlite3_prepare_v2(db->handle, (const char *) req->sql, -1, &stmt->handle, NULL);
1585
1639
 
@@ -1590,13 +1644,7 @@ paraql__on_before_prepare(uv_work_t *handle) {
1590
1644
  req->errmsg = sqlite3_errmsg(db->handle);
1591
1645
 
1592
1646
  if (stmt->handle != NULL) sqlite3_finalize(stmt->handle);
1593
-
1594
- return;
1595
1647
  }
1596
-
1597
- paraql__insert_statement(db, stmt);
1598
-
1599
- req->stmt = stmt;
1600
1648
  }
1601
1649
 
1602
1650
  static js_value_t *
@@ -1616,7 +1664,7 @@ paraql_prepare(js_env_t *env, js_callback_info_t *info) {
1616
1664
  assert(err == 0);
1617
1665
 
1618
1666
  paraql_t *db;
1619
- err = js_get_value_external(env, argv[0], (void **) &db);
1667
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &db, NULL);
1620
1668
  assert(err == 0);
1621
1669
 
1622
1670
  size_t sql_len;
@@ -1632,9 +1680,17 @@ paraql_prepare(js_env_t *env, js_callback_info_t *info) {
1632
1680
 
1633
1681
  paraql_prepare_t *req = malloc(sizeof(paraql_prepare_t));
1634
1682
 
1683
+ js_value_t *handle;
1684
+ err = js_create_arraybuffer(env, sizeof(paraql_statement_t), (void **) &req->stmt, &handle);
1685
+ assert(err == 0);
1686
+
1687
+ err = js_create_reference(env, handle, 1, &req->ref);
1688
+ assert(err == 0);
1689
+
1635
1690
  req->errcode = 0;
1636
1691
  req->db = db;
1637
1692
  req->sql = sql;
1693
+ req->stmt->db = db;
1638
1694
 
1639
1695
  req->handle.data = (void *) req;
1640
1696
 
@@ -1683,8 +1739,6 @@ paraql__on_before_finalize(uv_work_t *handle) {
1683
1739
  sqlite3_finalize(stmt->handle);
1684
1740
  stmt->handle = NULL;
1685
1741
  }
1686
-
1687
- paraql__remove_statement(stmt);
1688
1742
  }
1689
1743
 
1690
1744
  static js_value_t *
@@ -1704,7 +1758,7 @@ paraql_finalize(js_env_t *env, js_callback_info_t *info) {
1704
1758
  assert(err == 0);
1705
1759
 
1706
1760
  paraql_statement_t *stmt;
1707
- err = js_get_value_external(env, argv[0], (void **) &stmt);
1761
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &stmt, NULL);
1708
1762
  assert(err == 0);
1709
1763
 
1710
1764
  paraql_finalize_t *req = malloc(sizeof(paraql_finalize_t));
@@ -1790,7 +1844,7 @@ paraql_reset(js_env_t *env, js_callback_info_t *info) {
1790
1844
  assert(err == 0);
1791
1845
 
1792
1846
  paraql_statement_t *stmt;
1793
- err = js_get_value_external(env, argv[0], (void **) &stmt);
1847
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &stmt, NULL);
1794
1848
  assert(err == 0);
1795
1849
 
1796
1850
  paraql_reset_t *req = malloc(sizeof(paraql_reset_t));
@@ -2279,7 +2333,7 @@ paraql_bind(js_env_t *env, js_callback_info_t *info) {
2279
2333
  assert(err == 0);
2280
2334
 
2281
2335
  paraql_statement_t *stmt;
2282
- err = js_get_value_external(env, argv[0], (void **) &stmt);
2336
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &stmt, NULL);
2283
2337
  assert(err == 0);
2284
2338
 
2285
2339
  js_ref_t *named;
@@ -2480,7 +2534,7 @@ paraql_step(js_env_t *env, js_callback_info_t *info) {
2480
2534
  assert(err == 0);
2481
2535
 
2482
2536
  paraql_statement_t *stmt;
2483
- err = js_get_value_external(env, argv[0], (void **) &stmt);
2537
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &stmt, NULL);
2484
2538
  assert(err == 0);
2485
2539
 
2486
2540
  paraql_step_t *req = malloc(sizeof(paraql_step_t));
@@ -2592,7 +2646,7 @@ paraql_run(js_env_t *env, js_callback_info_t *info) {
2592
2646
  assert(err == 0);
2593
2647
 
2594
2648
  paraql_statement_t *stmt;
2595
- err = js_get_value_external(env, argv[0], (void **) &stmt);
2649
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &stmt, NULL);
2596
2650
  assert(err == 0);
2597
2651
 
2598
2652
  paraql_run_t *req = malloc(sizeof(paraql_run_t));
@@ -2613,6 +2667,111 @@ paraql_run(js_env_t *env, js_callback_info_t *info) {
2613
2667
  return promise;
2614
2668
  }
2615
2669
 
2670
+ static void
2671
+ paraql__on_finalize_serialized(js_env_t *env, void *data, void *hint) {
2672
+ sqlite3_free(data);
2673
+ }
2674
+
2675
+ static void
2676
+ paraql__on_after_serialize(uv_work_t *handle, int status) {
2677
+ int err;
2678
+
2679
+ paraql_serialize_t *req = (paraql_serialize_t *) handle->data;
2680
+
2681
+ js_env_t *env = req->env;
2682
+
2683
+ js_handle_scope_t *scope;
2684
+ err = js_open_handle_scope(env, &scope);
2685
+ assert(err == 0);
2686
+
2687
+ if (req->errcode) {
2688
+ js_value_t *error;
2689
+ err = paraql__make_error(env, req->errcode, req->errmsg, &error);
2690
+ assert(err == 0);
2691
+
2692
+ err = js_reject_deferred(env, req->deferred, error);
2693
+ assert(err == 0);
2694
+ } else {
2695
+ if (req->size > 0) {
2696
+ js_value_t *result;
2697
+ err = js_create_external_arraybuffer(env, (void *) req->data, (size_t) req->size, paraql__on_finalize_serialized, NULL, &result);
2698
+ assert(err == 0);
2699
+
2700
+ err = js_resolve_deferred(env, req->deferred, result);
2701
+ assert(err == 0);
2702
+ } else {
2703
+ js_value_t *result;
2704
+ err = js_create_arraybuffer(env, 0, NULL, &result);
2705
+ assert(err == 0);
2706
+
2707
+ err = js_resolve_deferred(env, req->deferred, result);
2708
+ assert(err == 0);
2709
+ }
2710
+ }
2711
+
2712
+ err = js_close_handle_scope(env, scope);
2713
+ assert(err == 0);
2714
+
2715
+ free(req);
2716
+ }
2717
+
2718
+ static void
2719
+ paraql__on_before_serialize(uv_work_t *handle) {
2720
+ paraql_serialize_t *req = (paraql_serialize_t *) handle->data;
2721
+
2722
+ paraql_t *db = req->db;
2723
+
2724
+ sqlite3_int64 size = 0;
2725
+ req->data = sqlite3_serialize(db->handle, "main", &size, 0);
2726
+
2727
+ if (req->data == NULL && size != 0) {
2728
+ req->errcode = sqlite3_extended_errcode(db->handle);
2729
+ req->errmsg = sqlite3_errmsg(db->handle);
2730
+
2731
+ return;
2732
+ }
2733
+
2734
+ req->size = size;
2735
+ }
2736
+
2737
+ static js_value_t *
2738
+ paraql_serialize(js_env_t *env, js_callback_info_t *info) {
2739
+ int err;
2740
+
2741
+ size_t argc = 1;
2742
+ js_value_t *argv[1];
2743
+
2744
+ err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
2745
+ assert(err == 0);
2746
+
2747
+ assert(argc == 1);
2748
+
2749
+ uv_loop_t *loop;
2750
+ err = js_get_env_loop(env, &loop);
2751
+ assert(err == 0);
2752
+
2753
+ paraql_t *db;
2754
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &db, NULL);
2755
+ assert(err == 0);
2756
+
2757
+ paraql_serialize_t *req = malloc(sizeof(paraql_serialize_t));
2758
+
2759
+ req->errcode = 0;
2760
+ req->env = env;
2761
+ req->db = db;
2762
+
2763
+ req->handle.data = (void *) req;
2764
+
2765
+ js_value_t *promise;
2766
+ err = js_create_promise(env, &req->deferred, &promise);
2767
+ assert(err == 0);
2768
+
2769
+ err = uv_queue_work(loop, &req->handle, paraql__on_before_serialize, paraql__on_after_serialize);
2770
+ assert(err == 0);
2771
+
2772
+ return promise;
2773
+ }
2774
+
2616
2775
  static js_value_t *
2617
2776
  paraql_exports(js_env_t *env, js_value_t *exports) {
2618
2777
  int err;
@@ -2638,6 +2797,7 @@ paraql_exports(js_env_t *env, js_value_t *exports) {
2638
2797
  V("bind", paraql_bind)
2639
2798
  V("step", paraql_step)
2640
2799
  V("run", paraql_run)
2800
+ V("serialize", paraql_serialize)
2641
2801
  #undef V
2642
2802
 
2643
2803
  return exports;