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(); } inline void SetFrozen(v8::Isolate* isolate, v8::Local ctx, v8::Local obj, v8::Global& key, v8::Local value) { obj->DefineOwnProperty(ctx, key.Get(isolate), 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))); } // 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::AccessorNameGetterCallback func ) { v8::HandleScope scope(isolate); recv->InstanceTemplate()->SetNativeDataProperty( InternalizedFromLatin1(isolate, name), func, 0, data ); } #if defined(V8_ENABLE_SANDBOX) // When V8 Sandbox is enabled (in newer Electron versions), we need to use Buffer::Copy // instead of Buffer::New to ensure the ArrayBuffer backing store is allocated inside the sandbox static inline v8::MaybeLocal BufferSandboxNew(v8::Isolate* isolate, char* data, size_t length, void (*finalizeCallback)(char*, void*), void* finalizeHint) { v8::MaybeLocal buffer = node::Buffer::Copy(isolate, data, length); finalizeCallback(data, finalizeHint); return buffer; } #define SAFE_NEW_BUFFER(env, data, length, finalizeCallback, finalizeHint) BufferSandboxNew(env, data, length, finalizeCallback, finalizeHint) #else // When V8 Sandbox is not enabled, we can use the more efficient Buffer::New #define SAFE_NEW_BUFFER(env, data, length, finalizeCallback, finalizeHint) node::Buffer::New(env, data, length, finalizeCallback, finalizeHint) #endif