@@ -42,6 +42,7 @@ using v8::Number;
42
42
using v8::Object;
43
43
using v8::SideEffectType;
44
44
using v8::String;
45
+
using v8::TryCatch;
45
46
using v8::Uint8Array;
46
47
using v8::Value;
47
48
@@ -66,13 +67,14 @@ inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate,
66
67
const char* message) {
67
68
Local<String> js_msg;
68
69
Local<Object> e;
70
+
Environment* env = Environment::GetCurrent(isolate);
69
71
if (!String::NewFromUtf8(isolate, message).ToLocal(&js_msg) ||
70
72
!Exception::Error(js_msg)
71
73
->ToObject(isolate->GetCurrentContext())
72
74
.ToLocal(&e) ||
73
75
e->Set(isolate->GetCurrentContext(),
74
-
OneByteString(isolate, "code"),
75
-
OneByteString(isolate, "ERR_SQLITE_ERROR"))
76
+
env->code_string(),
77
+
env->err_sqlite_error_string())
76
78
.IsNothing()) {
77
79
return MaybeLocal<Object>();
78
80
}
@@ -85,15 +87,14 @@ inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate, sqlite3* db) {
85
87
const char* errmsg = sqlite3_errmsg(db);
86
88
Local<String> js_errmsg;
87
89
Local<Object> e;
90
+
Environment* env = Environment::GetCurrent(isolate);
88
91
if (!String::NewFromUtf8(isolate, errstr).ToLocal(&js_errmsg) ||
89
92
!CreateSQLiteError(isolate, errmsg).ToLocal(&e) ||
90
93
e->Set(isolate->GetCurrentContext(),
91
-
OneByteString(isolate, "errcode"),
94
+
env->errcode_string(),
92
95
Integer::New(isolate, errcode))
93
96
.IsNothing() ||
94
-
e->Set(isolate->GetCurrentContext(),
95
-
OneByteString(isolate, "errstr"),
96
-
js_errmsg)
97
+
e->Set(isolate->GetCurrentContext(), env->errstr_string(), js_errmsg)
97
98
.IsNothing()) {
98
99
return MaybeLocal<Object>();
99
100
}
@@ -114,6 +115,19 @@ inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, const char* message) {
114
115
}
115
116
}
116
117
118
+
inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, int errcode) {
119
+
const char* errstr = sqlite3_errstr(errcode);
120
+
121
+
Environment* env = Environment::GetCurrent(isolate);
122
+
auto error = CreateSQLiteError(isolate, errstr).ToLocalChecked();
123
+
error
124
+
->Set(isolate->GetCurrentContext(),
125
+
env->errcode_string(),
126
+
Integer::New(isolate, errcode))
127
+
.ToChecked();
128
+
isolate->ThrowException(error);
129
+
}
130
+
117
131
class UserDefinedFunction {
118
132
public:
119
133
explicit UserDefinedFunction(Environment* env,
@@ -731,11 +745,11 @@ void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) {
731
745
732
746
// the reason for using static functions here is that SQLite needs a
733
747
// function pointer
734
-
static std::function<int()> conflictCallback;
748
+
static std::function<int(int)> conflictCallback;
735
749
736
750
static int xConflict(void* pCtx, int eConflict, sqlite3_changeset_iter* pIter) {
737
751
if (!conflictCallback) return SQLITE_CHANGESET_ABORT;
738
-
return conflictCallback();
752
+
return conflictCallback(eConflict);
739
753
}
740
754
741
755
static std::function<bool(std::string)> filterCallback;
@@ -773,15 +787,27 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
773
787
options->Get(env->context(), env->onconflict_string()).ToLocalChecked();
774
788
775
789
if (!conflictValue->IsUndefined()) {
776
-
if (!conflictValue->IsNumber()) {
790
+
if (!conflictValue->IsFunction()) {
777
791
THROW_ERR_INVALID_ARG_TYPE(
778
792
env->isolate(),
779
-
"The \"options.onConflict\" argument must be a number.");
793
+
"The \"options.onConflict\" argument must be a function.");
780
794
return;
781
795
}
782
-
783
-
int conflictInt = conflictValue->Int32Value(env->context()).FromJust();
784
-
conflictCallback = [conflictInt]() -> int { return conflictInt; };
796
+
Local<Function> conflictFunc = conflictValue.As<Function>();
797
+
conflictCallback = [env, conflictFunc](int conflictType) -> int {
798
+
Local<Value> argv[] = {Integer::New(env->isolate(), conflictType)};
799
+
TryCatch try_catch(env->isolate());
800
+
Local<Value> result =
801
+
conflictFunc->Call(env->context(), Null(env->isolate()), 1, argv)
802
+
.FromMaybe(Local<Value>());
803
+
if (try_catch.HasCaught()) {
804
+
try_catch.ReThrow();
805
+
return SQLITE_CHANGESET_ABORT;
806
+
}
807
+
constexpr auto invalid_value = -1;
808
+
if (!result->IsInt32()) return invalid_value;
809
+
return result->Int32Value(env->context()).FromJust();
810
+
};
785
811
}
786
812
787
813
if (options->HasOwnProperty(env->context(), env->filter_string())
@@ -819,12 +845,16 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
819
845
xFilter,
820
846
xConflict,
821
847
nullptr);
848
+
if (r == SQLITE_OK) {
849
+
args.GetReturnValue().Set(true);
850
+
return;
851
+
}
822
852
if (r == SQLITE_ABORT) {
853
+
// this is not an error, return false
823
854
args.GetReturnValue().Set(false);
824
855
return;
825
856
}
826
-
CHECK_ERROR_OR_THROW(env->isolate(), db->connection_, r, SQLITE_OK, void());
827
-
args.GetReturnValue().Set(true);
857
+
THROW_ERR_SQLITE_ERROR(env->isolate(), r);
828
858
}
829
859
830
860
void DatabaseSync::EnableLoadExtension(
@@ -1662,6 +1692,12 @@ void DefineConstants(Local<Object> target) {
1662
1692
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_OMIT);
1663
1693
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_REPLACE);
1664
1694
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_ABORT);
1695
+
1696
+
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_DATA);
1697
+
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_NOTFOUND);
1698
+
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_CONFLICT);
1699
+
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_CONSTRAINT);
1700
+
NODE_DEFINE_CONSTANT(target, SQLITE_CHANGESET_FOREIGN_KEY);
1665
1701
}
1666
1702
1667
1703
static void Initialize(Local<Object> target,
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4