| 1 | class Binder { |
| 2 | public: |
| 3 | |
| 4 | explicit Binder(sqlite3_stmt* _handle) { |
| 5 | handle = _handle; |
| 6 | param_count = sqlite3_bind_parameter_count(_handle); |
| 7 | anon_index = 0; |
| 8 | success = true; |
| 9 | } |
| 10 | |
| 11 | bool Bind(NODE_ARGUMENTS info, int argc, Statement* stmt) { |
| 12 | assert(anon_index == 0); |
| 13 | Napi::Env env = info.Env(); |
| 14 | Result result = BindArgs(info, argc, stmt); |
| 15 | if (success && result.count != param_count) { |
| 16 | if (result.count < param_count) { |
| 17 | if (!result.bound_object && stmt->GetBindMap(env).GetSize()) { |
| 18 | Fail(ThrowTypeError, env, "Missing named parameters"); |
| 19 | } else { |
| 20 | Fail(ThrowRangeError, env, "Too few parameter values were provided"); |
| 21 | } |
| 22 | } else { |
| 23 | Fail(ThrowRangeError, env, "Too many parameter values were provided"); |
| 24 | } |
| 25 | } |
| 26 | return success; |
| 27 | } |
| 28 | |
| 29 | private: |
| 30 | |
| 31 | struct Result { |
| 32 | int count; |
| 33 | bool bound_object; |
| 34 | }; |
| 35 | |
| 36 | static Napi::Value GetPrototype(Napi::Env env, Napi::Object obj) { |
| 37 | napi_value proto; |
| 38 | // This can fail (e.g., a Proxy whose getPrototypeOf trap throws), in |
| 39 | // which case an empty value is returned and an exception is pending. |
| 40 | if (napi_get_prototype(env, obj, &proto) != napi_ok) return Napi::Value(); |
| 41 | return Napi::Value(env, proto); |
| 42 | } |
| 43 | |
| 44 | // An object is "plain" if its prototype is null or a top-level prototype |
| 45 | // (i.e., some realm's Object.prototype). Rather than comparing against the |
| 46 | // current realm's Object.prototype -- which would reject plain objects from |
| 47 | // other contexts, such as the "vm" module -- we walk to the top of the |
| 48 | // prototype chain. A plain object's chain is exactly "obj -> proto -> null", |
| 49 | // so its immediate prototype must itself have a null prototype. This mirrors |
| 50 | // the cross-realm heuristic used by lodash's isPlainObject. |
| 51 | static bool IsPlainObject(Napi::Env env, Napi::Object obj) { |
| 52 | Napi::Value proto = GetPrototype(env, obj); |
| 53 | if (proto.IsEmpty()) return false; |
| 54 | if (proto.IsNull()) return true; |
| 55 | Napi::Value grandproto = GetPrototype(env, proto.As<Napi::Object>()); |
| 56 | if (grandproto.IsEmpty()) return false; |
| 57 | return grandproto.IsNull(); |
| 58 | } |
| 59 | |
| 60 | void Fail(Napi::Value (*Throw)(Napi::Env, const char*), Napi::Env env, const char* message) { |
nothing calls this directly
no outgoing calls
no test coverage detected