[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/ambelovsky/node-sqlanywhere/master/src/utils.cpp [Back]  [Original]

// ***************************************************************************
// Copyright (c) 2018 SAP SE or an SAP affiliate company. All rights reserved.
// ***************************************************************************
#include "nodever_cover.h"
#include "sqlany_utils.h"
#include "nan.h"

#if !v010

using namespace v8;
using namespace node;

void getErrorMsg( int code, std::string &str )
/********************************************/
{
    std::ostringstream message;
    message ThrowException( 
		Exception::Error( String::NewFromUtf8( isolate, str->c_str() ) ) );
	}
    }
}

static bool getWideBindParameters( std::vector		&execData,
				   Handle			arg,
				   std::vector &	params,
				   unsigned				&num_rows )
/*********************************************************************************/
{
    Handle	rows = Handle::Cast( arg );
    num_rows = rows->Length();

    Handle	row0 = Handle::Cast( rows->Get(0) );
    unsigned		num_cols = row0->Length();
    unsigned		c;

    if( num_cols == 0 ) {
	// if an empty array was passed in, we still need ExecuteData
	ExecuteData *ex = new ExecuteData;
	execData.push_back( ex );
	return true;
    }

    // Make sure that each array in the list has the same number and types
    // of values
    for( unsigned int r = 1; r < num_rows; r++ ) {
	Handle	row = Handle::Cast( rows->Get(r) );
	for( c = 0; c < num_cols; c++ ) {
	    Handle val0 = row0->Get(c);
	    Handle val = row->Get(c);

	    if( ( val0->IsInt32() || val0->IsNumber() ) &&
		( !val->IsInt32() && !val->IsNumber() && !val->IsNull() ) ) {
		return false;
	    }
	    if( val0->IsString() &&
		!val->IsString() && !val->IsNull() ) {
		return false;
	    }
	    if( Buffer::HasInstance( val0 ) &&
		!Buffer::HasInstance( val ) && !val->IsNull() ) {
		return false;
	    }
	}
    }

    for( c = 0; c < num_cols; c++ ) {
	a_sqlany_bind_param 	param;
	memset( ¶m, 0, sizeof( param ) );

	ExecuteData *ex = new ExecuteData;
	execData.push_back( ex );

	double *	param_double = new double[num_rows];
	ex->addNum( param_double );
	char **		char_arr = new char *[num_rows];
	size_t *	len = new size_t[num_rows];
	ex->addStrings( char_arr, len );
	sacapi_bool *	is_null = new sacapi_bool[num_rows];
	ex->addNull( is_null );
	param.value.is_null	= is_null;
	param.value.is_address	= false;

	if( row0->Get(c)->IsInt32() || row0->Get(c)->IsNumber() ) {
	    param.value.type	= A_DOUBLE;
	    param.value.buffer	= (char *)( param_double );

	} else if( row0->Get(c)->IsString() ) {
	    param.value.type	= A_STRING;
	    param.value.buffer	= (char *)char_arr;
	    param.value.length	= len;
	    param.value.is_address = true;

	} else if( Buffer::HasInstance( row0->Get(c) ) ) {
	    param.value.type	= A_BINARY;
	    param.value.buffer	= (char *)char_arr;
	    param.value.length	= len;
	    param.value.is_address = true;
	    
	} else if( row0->Get(c)->IsNull() ) {

	} else{
	    return false;
	}

	for( unsigned int r = 0; r < num_rows; r++ ) {
	    Handle	bind_params = Handle::Cast( rows->Get(r) );
	
	    is_null[r] = false;
	    if( bind_params->Get(c)->IsInt32() || bind_params->Get(c)->IsNumber() ) {
		param_double[r] = bind_params->Get(c)->NumberValue();
	
	    } else if( bind_params->Get(c)->IsString() ) {
		String::Utf8Value paramValue( bind_params->Get(c)->ToString() );
		const char* param_string = (*paramValue);
		len[r] = (size_t)paramValue.length();
		char *param_char = new char[len[r] + 1];
		char_arr[r] = param_char;
		memcpy( param_char, param_string, len[r] + 1 );
		
	    } else if( Buffer::HasInstance( bind_params->Get(c) ) ) {
		len[r] = Buffer::Length( bind_params->Get(c) );
		char *param_char = new char[len[r]];
		char_arr[r] = param_char;
		memcpy( param_char, Buffer::Data( bind_params->Get(c) ), len[r] );

	    } else if( bind_params->Get(c)->IsNull() ) {
		is_null[r] = true;
	    }
	}
    
	params.push_back( param );
    }

    return true;	   
}

bool getBindParameters( std::vector		&execData,
			Handle 				arg,
			std::vector &	params,
			unsigned				&num_rows )
/*************************************************************************/
{
    Handle		bind_params = Handle::Cast( arg );

    if( bind_params->Length() == 0 ) {
	// if an empty array was passed in, we still need ExecuteData
	ExecuteData *ex = new ExecuteData;
	execData.push_back( ex );
	return true;
    }

    if( bind_params->Get(0)->IsArray() ) {
	return getWideBindParameters( execData, arg, params, num_rows );
    }
    num_rows = 1;

    ExecuteData *ex = new ExecuteData;
    execData.push_back( ex );

    for( unsigned int i = 0; i < bind_params->Length(); i++ ) {
	a_sqlany_bind_param 	param;
	memset( ¶m, 0, sizeof( param ) );

	if( bind_params->Get(i)->IsInt32() ) {
	    int *param_int = new int;
	    *param_int = bind_params->Get(i)->Int32Value();
	    ex->addInt( param_int );
	    param.value.buffer = (char *)( param_int );
	    param.value.type   = A_VAL32;
	    
	} else if( bind_params->Get(i)->IsNumber() ) {
	    double *param_double = new double;
	    *param_double = bind_params->Get(i)->NumberValue(); // Remove Round off Error
	    ex->addNum( param_double );
	    param.value.buffer = (char *)( param_double );
	    param.value.type   = A_DOUBLE;
	
	} else if( bind_params->Get(i)->IsString() ) {
	    String::Utf8Value paramValue( bind_params->Get(i)->ToString() );
	    const char* param_string = (*paramValue);
	    size_t *len = new size_t;
	    *len = (size_t)paramValue.length();
	    
	    char **char_arr = new char *;
	    char *param_char = new char[*len + 1];
	    *char_arr = param_char;

	    memcpy( param_char, param_string, ( *len ) + 1 );
	    ex->addStrings( char_arr, len );
	    
	    param.value.type = A_STRING;
	    param.value.buffer = param_char;
	    param.value.length = len;
	    param.value.buffer_size = *len + 1;
	    
	} else if( Buffer::HasInstance( bind_params->Get(i) ) ) {
	    size_t *len = new size_t;
	    *len = Buffer::Length( bind_params->Get(i) );
	    char **char_arr = new char *;
	    char *param_char = new char[*len];
	    *char_arr = param_char;
	    
	    memcpy( param_char, Buffer::Data( bind_params->Get(i) ), *len );
	    ex->addStrings( char_arr, len );
	    
	    param.value.type = A_BINARY;
	    param.value.buffer = param_char;
	    param.value.length = len;
	    param.value.buffer_size = sizeof( param_char );
	    
	} else if( bind_params->Get(i)->IsNull() ) {
	    param.value.type = A_STRING;
	    sacapi_bool *is_null = new sacapi_bool;
	    param.value.is_null = is_null;
	    ex->addNull( is_null );
	    is_null[0] = true;
	    
	} else{
	    return false;
	}
	    
	params.push_back( param );
    }

    return true;	   
}

bool getResultSet( Persistent &			Result,
		   int &				rows_affected,
		   std::vector &		colNames,
		   ExecuteData *			execData,
		   std::vector &	col_types )
/*****************************************************************/
{
    Isolate *isolate = Isolate::GetCurrent();
    HandleScope scope( isolate );
    int 	num_rows = 0;
    size_t	num_cols = colNames.size();

    if( rows_affected >= 0 ) {
	Result.Reset( isolate, Integer::New( isolate, rows_affected ) );
	return true;
    }
    
    if( num_cols > 0 ) {
	size_t count = 0;
	size_t count_int = 0, count_num = 0, count_string = 0;
	Local ResultSet = Array::New( isolate );
	while( count_int < execData->intSize() ||
	       count_num < execData->numSize() ||
	       count_string < execData->stringSize() ) {
	    Local curr_row = Object::New( isolate );
	    num_rows++;
	    for( size_t i = 0; i < num_cols; i++ ) {
		switch( col_types[count] ) {
		    case A_INVALID_TYPE:
			curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
				       Null( isolate ) );
			break;

		    case A_VAL32:
		    case A_VAL16:
		    case A_UVAL16:
		    case A_VAL8:
		    case A_UVAL8:
			if( execData->intIsNull( count_int ) ) {
			    curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
					   Null( isolate ) );
			} else {
			    curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
					   Integer::New( isolate, execData->getInt( count_int ) ) );
			}
			count_int++;
			break;
			
		    case A_UVAL32:
		    case A_UVAL64:
		    case A_VAL64:
		    case A_DOUBLE:
			if( execData->numIsNull( count_num ) ) {
			    curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
					   Null( isolate ) );
			} else {
			    curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
					   Number::New( isolate, execData->getNum( count_num ) ) );
			}
			count_num++;
			break;
			
		    case A_BINARY:
			if( execData->stringIsNull( count_string ) ) {
			    curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
					   Null( isolate ) );
			} else {
#if v012
			    Local buf = node::Buffer::New( 
				isolate, execData->getString( count_string ),
				execData->getLen( count_string ) ); 
			    curr_row->Set( String::NewFromUtf8( isolate,
								colNames[i] ),
					   buf );
#else
			    MaybeLocal mbuf = node::Buffer::Copy( 
				isolate, execData->getString( count_string ),
				execData->getLen( count_string ) ); 
			    Local buf = mbuf.ToLocalChecked();
#endif
			    curr_row->Set( String::NewFromUtf8( isolate,
								colNames[i] ),
					   buf );
			}
			count_string++;
			break;
			
		    case A_STRING:		    
			if( execData->stringIsNull( count_string ) ) {
			    curr_row->Set( String::NewFromUtf8( isolate, colNames[i] ),
					   Null( isolate ) );
			} else {
			    curr_row->Set( String::NewFromUtf8( isolate,
								colNames[i] ),
#if v012
					   String::NewFromUtf8( isolate,
								execData->getString( count_string ),
								String::NewStringType::kNormalString,
								(int)execData->getLen( count_string ) )
#else
					   String::NewFromUtf8( isolate,
								execData->getString( count_string ),
								NewStringType::kNormal,
								(int)execData->getLen( count_string ) ).ToLocalChecked()
#endif
				);
			}
			count_string++;
			break;
		
		    default:
			return false;
		}
		count++;
	    }
	    ResultSet->Set( num_rows - 1, curr_row );
	}
	Result.Reset( isolate, ResultSet );
    } else {
	Result.Reset( isolate, Local::New( isolate, 
						  Undefined( isolate ) ) );
    }
    
    return true;
}

bool fetchResultSet( a_sqlany_stmt *			sqlany_stmt,
		     int &				rows_affected,
		     std::vector &		colNames,
		     ExecuteData *			execData,
		     std::vector &	col_types )
/*****************************************************************/
{
    
    a_sqlany_data_value		value;
    int				num_cols = 0;
    
    rows_affected = api.sqlany_affected_rows( sqlany_stmt );
    num_cols = api.sqlany_num_cols( sqlany_stmt );
    
    
    if( rows_affected > 0 && num_cols < 1 ) {
        return true;
    }
    
    rows_affected = -1;
    if( num_cols > 0 ) {
	
	for( int i = 0; i < num_cols; i++ ) {
	    a_sqlany_column_info info;
	    api.sqlany_get_column_info( sqlany_stmt, i, &info );
	    size_t size = strlen( info.name ) + 1;
	    char *name = new char[ size ];
	    memcpy( name, info.name, size );
	    colNames.push_back( name );
	}
	
	int count_string = 0, count_num = 0, count_int = 0;
	while( api.sqlany_fetch_next( sqlany_stmt ) ) {

	    for( int i = 0; i < num_cols; i++ ) {

		if( !api.sqlany_get_column( sqlany_stmt, i, &value ) ) {
		    return false;
		    break;
		}
	
		if( *(value.is_null) ) {
		    col_types.push_back( A_INVALID_TYPE );
		    continue;
		}
		
		switch( value.type ) {
		    case A_BINARY:
		    {
			size_t *size = new size_t;
			*size = *(value.length);
			char *val = new char[ *size ];
			memcpy( val, value.buffer, *size );
			execData->addString( val, size );
			count_string++;
			break;
		    }
		    
		    case A_STRING:
		    {
			size_t *size = new size_t;
			*size = (size_t)( (int)*(value.length) );
			char *val = new char[ *size ];
			memcpy( val, (char *)value.buffer, *size );
			execData->addString( val, size );
			count_string++;
			break;
		    }
			
		    case A_VAL64:
		    {
			double *val = new double;
			*val = (double)*(long long *)value.buffer;
			execData->addNum( val );
			count_num++;
			break;
		    }
			
		    case A_UVAL64:
		    {
			double *val = new double;
			*val = (double)*(unsigned long long *)value.buffer;
			execData->addNum( val );
			count_num++;
			break;
		    }
			
		    case A_VAL32:
		    {
			int *val = new int;
			*val = *(int*)value.buffer;
			execData->addInt( val );
			count_int++;
			break;
		    }

		    case A_UVAL32:
		    {
			double *val = new double;
			*val = (double)*(unsigned int*)value.buffer;
			execData->addNum( val );
			count_num++;
			break;
		    }
			
		    case A_VAL16:
		    {
			int *val = new int;
			*val = (int)*(short*)value.buffer;
			execData->addInt( val );
			count_int++;
			break;
		    }

		    case A_UVAL16:
		    {
			int *val = new int;
			*val = (int)*(unsigned short*)value.buffer;
			execData->addInt( val );
			count_int++;
			break;
		    }
			
		    case A_VAL8:
		    {
			int *val = new int;
			*val = (int)*(char *)value.buffer;
			execData->addInt( val );
			count_int++;
			break;
		    }
			
		    case A_UVAL8:
		    {
			int *val = new int;
			*val = (int)*(unsigned char *)value.buffer;
			execData->addInt( val );
			count_int++;
			break;
		    }
			
		    case A_DOUBLE:
		    {
			double *val = new double;
			*val = (double)*(double *)value.buffer;
			execData->addNum( val );
			count_num++;
			break;
		    }
			
                    default:
			return false;
		}
		col_types.push_back( value.type );
	    }
	}
    }
    
    return true;
}

bool cleanAPI()
/*************/
{
    if( openConnections == 0 ) {
	if( api.initialized ) {
	    api.sqlany_fini();
	    sqlany_finalize_interface( &api );
	    return true;
	}
    }
    return false;
}

// Generic Baton and Callback (After) Function
// Use this if the function does not have any return values and
// Does not take any parameters. 
// Create custom Baton and Callback (After) functions otherwise

void Connection::noParamAfter( uv_work_t *req )
/*********************************************/
{
    Isolate *isolate = Isolate::GetCurrent();
    HandleScope	scope(isolate);
    noParamBaton *baton = static_cast(req->data);
    Local undef = Local::New( isolate, Undefined( isolate ) );

    if( baton->err ) {
	callBack( &( baton->error_msg ), baton->callback, undef,
		  baton->callback_required );
	return;
    }
    
    callBack( NULL, baton->callback, undef, baton->callback_required );
    
    delete baton;
    delete req;
}


// Stmt Object Functions
StmtObject::StmtObject()
/**********************/
{
    connection = NULL;
    sqlany_stmt = NULL;
}

StmtObject::~StmtObject()
/***********************/
{
    uv_mutex_t *mutex = NULL;
    if( connection != NULL ) {
	mutex = &connection->conn_mutex;
	uv_mutex_lock( mutex );
    }

    cleanup();
    removeConnection();

    if( mutex != NULL ) {
	uv_mutex_unlock( mutex );
    }
}

Persistent StmtObject::constructor;

void StmtObject::Init( Isolate *isolate )
/***************************************/
{
    HandleScope	scope(isolate);
    // Prepare constructor template
    Local tpl = FunctionTemplate::New( isolate, New );
    tpl->SetClassName( String::NewFromUtf8( isolate, "StmtObject" ) );
    tpl->InstanceTemplate()->SetInternalFieldCount( 1 );

    // Prototype
    NODE_SET_PROTOTYPE_METHOD( tpl, "exec", exec );
    NODE_SET_PROTOTYPE_METHOD( tpl, "drop", drop );
    NODE_SET_PROTOTYPE_METHOD( tpl, "getMoreResults", getMoreResults );
    constructor.Reset( isolate, tpl->GetFunction() );
}

void StmtObject::New( const FunctionCallbackInfo &args )
/*************************************************************/
{
    StmtObject* obj = new StmtObject();

    obj->Wrap( args.This() );
    args.GetReturnValue().Set( args.This() );
}

void StmtObject::NewInstance( const FunctionCallbackInfo &args )
/*********************************************************************/
{
    Persistent obj;
    CreateNewInstance( args, obj );
    args.GetReturnValue().Set( obj );
}

void StmtObject::CreateNewInstance( const FunctionCallbackInfo &	args,
				    Persistent &		obj )
/***************************************************************************/
{
    Isolate *isolate = args.GetIsolate();
    HandleScope	scope(isolate);
    const unsigned argc = 1;
    Handle argv[argc] = { args[0] };
    Localcons = Local::New( isolate, constructor );
#if NODE_MAJOR_VERSION >= 10
    Local env = isolate->GetCurrentContext();
    MaybeLocal mlObj = cons->NewInstance( env, argc, argv );
    Local instance = mlObj.ToLocalChecked();

    obj.Reset( isolate, instance );
#else
    obj.Reset( isolate, cons->NewInstance( argc, argv ) );
#endif
}

void StmtObject::cleanup( void )
/******************************/
{
    if( sqlany_stmt != NULL ) {
	api.sqlany_free_stmt( sqlany_stmt );
	sqlany_stmt = NULL;
    }
}

void StmtObject::removeConnection( void )
/***************************************/
{
    if( connection != NULL ) {
	connection->removeStmt( this );
    	connection = NULL;
    }
}

// Connection Functions

void HashToString( Local obj, Persistent &ret )
/*************************************************************/
{
    Isolate *isolate = Isolate::GetCurrent();
    HandleScope	scope(isolate);
    Local props = obj->GetOwnPropertyNames();
    int length = props->Length();
    std::string params = "";
    bool	first = true;
    for( int i = 0; i < length; i++ ) {
	Local key = props->Get(i).As();
	Local val = obj->Get(key).As();
	String::Utf8Value key_utf8( key );
	String::Utf8Value val_utf8( val );
	if( !first ) {
	    params += ";";
	}
	first = false;
	params += std::string(*key_utf8);
	params += "=";
	params += std::string(*val_utf8);
    }
    ret.Reset( isolate, String::NewFromUtf8( isolate, params.c_str() ) );
}

#if 0
// Handy function for determining what type an object is.
static void CheckArgType( Local &obj )
/*******************************************/
{
    static const char *type = NULL;
    if( obj->IsArray() ) {
	type = "Array";
    } else if( obj->IsBoolean() ) {
	type = "Boolean";
    } else if( obj->IsBooleanObject() ) {
	type = "BooleanObject";
    } else if( obj->IsDate() ) {
	type = "Date";
    } else if( obj->IsExternal() ) {
	type = "External";
    } else if( obj->IsFunction() ) {
	type = "Function";
    } else if( obj->IsInt32() ) {
	type = "Int32";
    } else if( obj->IsNativeError() ) {
	type = "NativeError";
    } else if( obj->IsNull() ) {
	type = "Null";
    } else if( obj->IsNumber() ) {
	type = "Number";
    } else if( obj->IsNumberObject() ) {
	type = "NumberObject";
    } else if( obj->IsObject() ) {
	type = "Object";
    } else if( obj->IsRegExp() ) {
	type = "RegExp";
    } else if( obj->IsString() ) {
	type = "String";
    } else if( obj->IsStringObject() ) {
	type = "StringObject";
    } else if( obj->IsUint32() ) {
	type = "Uint32";
    } else if( obj->IsUndefined() ) {
	type = "Undefined";
    } else {
	type = "Unknown";
    }
}
#endif

Connection::Connection( const FunctionCallbackInfo &args )
/***************************************************************/
{
    Isolate *isolate = args.GetIsolate();
    HandleScope scope( isolate );
    uv_mutex_init(&conn_mutex);
    conn = NULL;

    if( args.Length() > 1 ) {
	throwError( JS_ERR_INVALID_ARGUMENTS );
	return;
    }

    if( args.Length() == 1 ) {
	//CheckArgType( args[0] );
	if( args[0]->IsString() ) {
	    Local str = args[0]->ToString();
	    int string_len = str->Utf8Length();
	    char *buf = new char[string_len+1];
	    str->WriteUtf8( buf );
	    _arg.Reset( isolate, String::NewFromUtf8( isolate, buf ) );
	    delete [] buf;
	} else if( args[0]->IsObject() ) {
	    HashToString( args[0]->ToObject(), _arg );
	} else if( !args[0]->IsUndefined() && !args[0]->IsNull() ) {
	    throwError( JS_ERR_INVALID_ARGUMENTS );
	} else {
	    _arg.Reset( isolate, String::NewFromUtf8( isolate, "" ) );
	}
    } else {
	_arg.Reset( isolate, String::NewFromUtf8( isolate, "" ) );
    }
}


Connection::~Connection()
/***********************/
{
    scoped_lock api_lock( api_mutex );
    scoped_lock lock( conn_mutex );

    _arg.Reset();
    cleanupStmts();
    if( conn != NULL ) {
	api.sqlany_disconnect( conn );
	api.sqlany_free_connection( conn );
	conn = NULL;
	openConnections--;
    }
    
    cleanAPI();
};

void Connection::cleanupStmts( void )
/***********************************/
{
    std::vector::iterator findit;
    for( findit = statements.begin(); findit != statements.end(); findit++ ) {
	StmtObject *s = reinterpret_cast(*findit);
	s->cleanup();
    }
}

void Connection::removeStmt( class StmtObject *stmt )
/***************************************************/
{
    // caller must get mutex
    std::vector::iterator findit;
    for( findit = statements.begin(); findit != statements.end(); findit++ ) {
	if( *findit == reinterpret_cast(stmt) ) {
	    statements.erase( findit );
	    return;
	}
    }
}

Persistent Connection::constructor;

void Connection::Init( Isolate *isolate )
/***************************************/
{
    HandleScope scope( isolate );
    // Prepare constructor template
    Local tpl = FunctionTemplate::New( isolate, New );
    tpl->SetClassName( String::NewFromUtf8( isolate, "Connection" ) );
    tpl->InstanceTemplate()->SetInternalFieldCount( 1 );
    
    // Prototype
    NODE_SET_PROTOTYPE_METHOD( tpl, "exec", exec );
    NODE_SET_PROTOTYPE_METHOD( tpl, "prepare", prepare );
    NODE_SET_PROTOTYPE_METHOD( tpl, "connect", connect );
    NODE_SET_PROTOTYPE_METHOD( tpl, "disconnect", disconnect );
    NODE_SET_PROTOTYPE_METHOD( tpl, "close", disconnect );
    NODE_SET_PROTOTYPE_METHOD( tpl, "commit", commit );
    NODE_SET_PROTOTYPE_METHOD( tpl, "rollback", rollback );
    NODE_SET_PROTOTYPE_METHOD( tpl, "connected", connected );

    constructor.Reset( isolate, tpl->GetFunction() );
}

void Connection::New( const FunctionCallbackInfo &args )
/*************************************************************/
{
    Isolate *isolate = args.GetIsolate();
    HandleScope scope( isolate );

    if( args.IsConstructCall() ) {
	Connection *obj = new Connection( args );
	obj->Wrap( args.This() );
	args.GetReturnValue().Set( args.This() );
    } else {
	const int argc = 1;
	Local argv[argc] = { args[0] };
	Local cons = Local::New( isolate, constructor );
#if NODE_MAJOR_VERSION >= 10
        Local env = isolate->GetCurrentContext();
        MaybeLocal mlObj = cons->NewInstance( env, argc, argv );
        const Local obj = mlObj.ToLocalChecked();
	args.GetReturnValue().Set( obj );
#else
	args.GetReturnValue().Set( cons->NewInstance( argc, argv ) );
#endif
    }
}

void Connection::NewInstance( const FunctionCallbackInfo &args )
/*********************************************************************/
{
    Isolate *isolate = args.GetIsolate();
    HandleScope scope( isolate );
    const unsigned argc = 1;
    Handle argv[argc] = { args[0] };
    Local cons = Local::New( isolate, constructor );
#if NODE_MAJOR_VERSION >= 10
    Local env = isolate->GetCurrentContext();
    MaybeLocal mlObj = cons->NewInstance( env, argc, argv );
    Local instance = mlObj.ToLocalChecked();
#else
    Local instance = cons->NewInstance( argc, argv );
#endif
    args.GetReturnValue().Set( instance );
}

#endif // !v010

Web Proxy Viewer  |  New URL  |  Original Page