#define NODE_ARGUMENTS const v8::FunctionCallbackInfo& #define NODE_ARGUMENTS_POINTER const v8::FunctionCallbackInfo* #define NODE_METHOD(name) static void name(NODE_ARGUMENTS info) #define NODE_GETTER(name) static void name(v8::Local _, const v8::PropertyCallbackInfo& info) #define INIT(name) static v8::Local name(v8::Isolate* isolate, v8::Local data) #define EasyIsolate v8::Isolate* isolate = v8::Isolate::GetCurrent() #define OnlyIsolate info.GetIsolate() #define OnlyContext isolate->GetCurrentContext() #define OnlyAddon static_cast(v8::Local::Cast(info.Data())->Value()) #define UseIsolate v8::Isolate* isolate = OnlyIsolate #define UseContext v8::Local ctx = OnlyContext #define UseAddon Addon* addon = OnlyAddon #define Unwrap node::ObjectWrap::Unwrap inline v8::Local StringFromUtf8(v8::Isolate* isolate, const char* data, int length) { return v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal, length).ToLocalChecked(); } inline v8::Local InternalizedFromUtf8(v8::Isolate* isolate, const char* data, int length) { return v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kInternalized, length).ToLocalChecked(); } inline v8::Local InternalizedFromUtf8OrNull(v8::Isolate* isolate, const char* data, int length) { if (data == NULL) return v8::Null(isolate); return InternalizedFromUtf8(isolate, data, length); } inline v8::Local InternalizedFromLatin1(v8::Isolate* isolate, const char* str) { return v8::String::NewFromOneByte(isolate, reinterpret_cast(str), v8::NewStringType::kInternalized).ToLocalChecked(); } #hdr template using CopyablePersistent = v8::Persistent>; #end inline void SetFrozen(v8::Isolate* isolate, v8::Local ctx, v8::Local obj, CopyablePersistent& key, v8::Local value) { obj->DefineOwnProperty(ctx, CS::Get(isolate, key), value, static_cast(v8::DontDelete | v8::ReadOnly)).FromJust(); } void ThrowError(const char* message) { EasyIsolate; isolate->ThrowException(v8::Exception::Error(StringFromUtf8(isolate, message, -1))); } void ThrowTypeError(const char* message) { EasyIsolate; isolate->ThrowException(v8::Exception::TypeError(StringFromUtf8(isolate, message, -1))); } void ThrowRangeError(const char* message) { EasyIsolate; isolate->ThrowException(v8::Exception::RangeError(StringFromUtf8(isolate, message, -1))); } #define REQUIRE_ARGUMENT_ANY(at, var) \ if (info.Length() <= (at())) \ return ThrowTypeError("Expected a "#at" argument"); \ var = info[at()] #define _REQUIRE_ARGUMENT(at, var, Type, message, ...) \ if (info.Length() <= (at()) || !info[at()]->Is##Type()) \ return ThrowTypeError("Expected "#at" argument to be "#message); \ var = v8::Local::Cast(info[at()])__VA_ARGS__ #define REQUIRE_ARGUMENT_INT32(at, var) \ _REQUIRE_ARGUMENT(at, var, Int32, a 32-bit signed integer, ->Value()) #define REQUIRE_ARGUMENT_BOOLEAN(at, var) \ _REQUIRE_ARGUMENT(at, var, Boolean, a boolean, ->Value()) #define REQUIRE_ARGUMENT_STRING(at, var) \ _REQUIRE_ARGUMENT(at, var, String, a string) #define REQUIRE_ARGUMENT_OBJECT(at, var) \ _REQUIRE_ARGUMENT(at, var, Object, an object) #define REQUIRE_ARGUMENT_FUNCTION(at, var) \ _REQUIRE_ARGUMENT(at, var, Function, a function) #define REQUIRE_DATABASE_OPEN(db) \ if (!db->open) \ return ThrowTypeError("The database connection is not open") #define REQUIRE_DATABASE_NOT_BUSY(db) \ if (db->busy) \ return ThrowTypeError("This database connection is busy executing a query") #define REQUIRE_DATABASE_NO_ITERATORS(db) \ if (db->iterators) \ return ThrowTypeError("This database connection is busy executing a query") #define REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db) \ if (!db->unsafe_mode) { \ REQUIRE_DATABASE_NO_ITERATORS(db); \ } ((void)0) #define REQUIRE_STATEMENT_NOT_LOCKED(stmt) \ if (stmt->locked) \ return ThrowTypeError("This statement is busy executing a query") #define first() 0 #define second() 1 #define third() 2 #define fourth() 3 #define fifth() 4 #define sixth() 5 #define seventh() 6 #define eighth() 7 #define ninth() 8 #define tenth() 9 // Returns a std:string of the concatenation of 3 well-formed C-strings. std::string CONCAT(const char* a, const char* b, const char* c) { std::string result(a); result += b; result += c; return result; } // Returns a copy of a well-formed C-string. const char* COPY(const char* source) { size_t bytes = strlen(source) + 1; char* dest = new char[bytes]; memcpy(dest, source, bytes); return dest; } // Determines whether to skip the given character at the start of an SQL string. inline bool IS_SKIPPED(char c) { return c == ' ' || c == ';' || (c >= '\t' && c <= '\r'); } // Allocates an empty array, without calling constructors/initializers. template inline T* ALLOC_ARRAY(size_t count) { return static_cast(::operator new[](count * sizeof(T))); } // Deallocates an array, without calling destructors. template inline void FREE_ARRAY(T* array_pointer) { ::operator delete[](array_pointer); } v8::Local NewConstructorTemplate( v8::Isolate* isolate, v8::Local data, v8::FunctionCallback func, const char* name ) { v8::Local t = v8::FunctionTemplate::New(isolate, func, data); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(InternalizedFromLatin1(isolate, name)); return t; } void SetPrototypeMethod( v8::Isolate* isolate, v8::Local data, v8::Local recv, const char* name, v8::FunctionCallback func ) { v8::HandleScope scope(isolate); recv->PrototypeTemplate()->Set( InternalizedFromLatin1(isolate, name), v8::FunctionTemplate::New(isolate, func, data, v8::Signature::New(isolate, recv)) ); } void SetPrototypeSymbolMethod( v8::Isolate* isolate, v8::Local data, v8::Local recv, v8::Local symbol, v8::FunctionCallback func ) { v8::HandleScope scope(isolate); recv->PrototypeTemplate()->Set( symbol, v8::FunctionTemplate::New(isolate, func, data, v8::Signature::New(isolate, recv)) ); } void SetPrototypeGetter( v8::Isolate* isolate, v8::Local data, v8::Local recv, const char* name, v8::AccessorGetterCallback func ) { v8::HandleScope scope(isolate); recv->InstanceTemplate()->SetAccessor( InternalizedFromLatin1(isolate, name), func, 0, data, v8::AccessControl::DEFAULT, v8::PropertyAttribute::None, v8::AccessorSignature::New(isolate, recv) ); }