From 06f935f844ac319b6fbcf9ae699f37c2b69041b7 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Mon, 4 May 2015 11:51:34 +0200 Subject: [PATCH 01/11] Speed up exception checking The IsException() method was complicated, so receival of large tables were really slow. --- src/Common.h | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/src/Common.h b/src/Common.h index 9d4cdaf..232cfc8 100644 --- a/src/Common.h +++ b/src/Common.h @@ -1,4 +1,4 @@ -/* +/* ----------------------------------------------------------------------------- Copyright (c) 2011 Joachim Dorner @@ -46,7 +46,7 @@ static std::string convertToString(v8::Handle const &str) if (s != nullptr) { return std::string(s, utf8String.length()); } - + return emptyString; } @@ -54,7 +54,7 @@ static std::string convertToString(const SAP_UC *str) { v8::HandleScope scope; v8::Local utf16String = v8::String::New((const uint16_t*)(str)); - + return convertToString(utf16String); } @@ -80,9 +80,9 @@ static SAP_UC* convertToSAPUC(v8::Handle const &str) { static v8::Handle RfcError(const RFC_ERROR_INFO &info) { v8::HandleScope scope; - + v8::Local e = v8::Exception::Error(v8::String::New((const uint16_t*)(info.message))); - + v8::Local obj = e->ToObject(); obj->Set(v8::String::New("code"), v8::Integer::New(info.code)); obj->Set(v8::String::New("group"), v8::Integer::New(info.group)); @@ -94,36 +94,19 @@ static v8::Handle RfcError(const RFC_ERROR_INFO &info) obj->Set(v8::String::New("msgv2"), v8::String::New((const uint16_t*)(info.abapMsgV2))); obj->Set(v8::String::New("msgv3"), v8::String::New((const uint16_t*)(info.abapMsgV3))); obj->Set(v8::String::New("msgv4"), v8::String::New((const uint16_t*)(info.abapMsgV4))); - + return scope.Close(obj); } static v8::Handle RfcError(const char* message, v8::Handle value) { - v8::HandleScope scope; - v8::Local exceptionString = v8::String::Concat(v8::String::New(message), value->ToString()); - v8::Local e = v8::Exception::Error(exceptionString); - - return scope.Close(e->ToObject()); + return v8::ThrowException(exceptionString); } static bool IsException(v8::Handle value) { - v8::HandleScope scope; - const v8::Local sample = v8::Exception::Error(v8::String::New("")); - const v8::Local protoSample = sample->ToObject()->ObjectProtoToString(); - - if (!value->IsObject()) { - return false; - } - v8::Local protoReal = value->ToObject()->ObjectProtoToString(); - if (protoReal->Equals(protoSample)) { - return true; - } - scope.Close(v8::Undefined()); - - return false; + return value->IsNativeError(); } #endif /* COMMON_H_ */ From 8fba57742c4597cec670a0413c2fafdfa97b7fa2 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Mon, 4 May 2015 17:39:06 +0200 Subject: [PATCH 02/11] Code cleanup --- src/Function.cc | 88 ++++++++++++++++++++++++------------------------- src/Function.h | 8 ++--- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index a20ebde..552adff 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -1,4 +1,4 @@ -/* +/* ----------------------------------------------------------------------------- Copyright (c) 2011 Joachim Dorner @@ -37,7 +37,7 @@ Function::~Function() void Function::Init(v8::Handle target) { v8::HandleScope scope; - + ctorTemplate = v8::Persistent::New(v8::FunctionTemplate::New(New)); ctorTemplate->InstanceTemplate()->SetInternalFieldCount(1); ctorTemplate->SetClassName(v8::String::NewSymbol("Function")); @@ -53,7 +53,7 @@ v8::Handle Function::NewInstance(Connection &connection, const v8::Ar unsigned int parmCount; RFC_RC rc = RFC_OK; RFC_ERROR_INFO errorInfo; - + v8::Local func = ctorTemplate->GetFunction()->NewInstance(); Function *self = node::ObjectWrap::Unwrap(func); @@ -73,7 +73,7 @@ v8::Handle Function::NewInstance(Connection &connection, const v8::Ar if (self->functionDescHandle == nullptr) { return RFC_ERROR(errorInfo); } - + rc = RfcGetParameterCount(self->functionDescHandle, &parmCount, &errorInfo); if (rc != RFC_OK) { return RFC_ERROR(errorInfo); @@ -82,7 +82,7 @@ v8::Handle Function::NewInstance(Connection &connection, const v8::Ar // Dynamically add parameters to JS object for (unsigned int i = 0; i < parmCount; i++) { RFC_PARAMETER_DESC parmDesc; - + rc = RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &errorInfo); if (rc != RFC_OK) { return RFC_ERROR(errorInfo); @@ -113,7 +113,7 @@ v8::Handle Function::Invoke(const v8::Arguments &args) RFC_RC rc = RFC_OK; unsigned int parmCount; RFC_ERROR_INFO errorInfo; - + Function *self = node::ObjectWrap::Unwrap(args.This()); assert(self != nullptr); @@ -134,7 +134,7 @@ v8::Handle Function::Invoke(const v8::Arguments &args) // Store callback baton->cbInvoke = v8::Persistent::New(v8::Local::Cast(args[1])); - + baton->functionHandle = RfcCreateFunction(self->functionDescHandle, &errorInfo); if (baton->functionHandle == nullptr) { delete baton; @@ -151,7 +151,7 @@ v8::Handle Function::Invoke(const v8::Arguments &args) for (unsigned int i = 0; i < parmCount; i++) { RFC_PARAMETER_DESC parmDesc; - + rc = RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &errorInfo); if (rc != RFC_OK) { delete baton; @@ -210,7 +210,7 @@ void Function::EIO_Invoke(uv_work_t *req) { RFC_RC rc = RFC_OK; int isValid; - + InvocationBaton *baton = static_cast(req->data); assert(baton != nullptr); @@ -225,7 +225,7 @@ void Function::EIO_Invoke(uv_work_t *req) if (baton->errorInfo.code == RFC_INVALID_HANDLE) { rc = RfcIsConnectionHandleValid(baton->connection->GetConnectionHandle(), &isValid, &baton->errorInfo); } - + baton->connection->UnlockMutex(); } @@ -233,14 +233,14 @@ void Function::EIO_AfterInvoke(uv_work_t *req) { v8::HandleScope scope; RFC_ERROR_INFO errorInfo; - + InvocationBaton *baton = static_cast(req->data); assert(baton != nullptr); - + v8::Local argv[2]; argv[0] = v8::Local::New(v8::Null()); argv[1] = v8::Local::New(v8::Null()); - + if (baton->errorInfo.code != RFC_OK) { argv[0] = v8::Local::New(RfcError(baton->errorInfo)); } else { @@ -276,7 +276,7 @@ v8::Handle Function::DoReceive(const CHND container) RFC_RC rc = RFC_OK; RFC_ERROR_INFO errorInfo; unsigned int parmCount; - + v8::Local result = v8::Object::New(); // Get resulting values for exporting/changing/table parameters @@ -288,7 +288,7 @@ v8::Handle Function::DoReceive(const CHND container) for (unsigned int i = 0; i < parmCount; i++) { RFC_PARAMETER_DESC parmDesc; v8::Handle parmValue; - + rc = RfcGetParameterDescByIndex(this->functionDescHandle, i, &parmDesc, &errorInfo); if (rc != RFC_OK) { return RFC_ERROR(errorInfo); @@ -387,7 +387,7 @@ v8::Handle Function::SetValue(const CHND container, RFCTYPE type, con return scope.Close(result); } - return scope.Close(v8::Null()); + return scope.Close(v8::Null()); } v8::Handle Function::StructureToExternal(const CHND container, const SAP_UC *name, v8::Handle value) @@ -473,7 +473,7 @@ v8::Handle Function::TableToExternal(const CHND container, const SAP_ for (uint32_t i = 0; i < rowCount; i++){ strucHandle = RfcAppendNewRow(tableHandle, nullptr); - + v8::Handle line = this->StructureToExternal(container, strucHandle, source->CloneElementAt(i)); // Bail out on exception if (IsException(line)) { @@ -536,7 +536,7 @@ v8::Handle Function::NumToExternal(const CHND container, const SAP_UC if (valueU16.length() > len) { return RFC_ERROR("Argument exceeds maximum length: ", v8::String::New((const uint16_t*)(name))); } - + rc = RfcSetNum(container, name, (const RFC_NUM*)*valueU16, valueU16.length(), &errorInfo); if (rc != RFC_OK) { return RFC_ERROR(errorInfo); @@ -564,7 +564,7 @@ v8::Handle Function::CharToExternal(const CHND container, const SAP_U if (rc != RFC_OK) { return RFC_ERROR(errorInfo); } - + return scope.Close(v8::Null()); } @@ -582,12 +582,12 @@ v8::Handle Function::ByteToExternal(const CHND container, const SAP_U if (valueAscii.length() > len) { return RFC_ERROR("Argument exceeds maximum length: ", v8::String::New((const uint16_t*)(name))); } - + rc = RfcSetBytes(container, name, reinterpret_cast(*valueAscii), len, &errorInfo); if (rc != RFC_OK) { return RFC_ERROR(errorInfo); } - + return scope.Close(v8::Null()); } @@ -690,7 +690,7 @@ v8::Handle Function::DateToExternal(const CHND container, const SAP_U if (str->Length() != 8) { return RFC_ERROR("Invalid date format: ", v8::String::New((const uint16_t*)(name))); } - + v8::String::Value rfcValue(str); assert(*rfcValue); RFC_RC rc = RfcSetDate(container, name, (const RFC_CHAR*)*rfcValue, &errorInfo); @@ -736,12 +736,12 @@ v8::Handle Function::BCDToExternal(const CHND container, const SAP_UC } v8::String::Value valueU16(value->ToString()); - + rc = RfcSetString(container, name, (const SAP_UC*)*valueU16, valueU16.length(), &errorInfo); if (rc != RFC_OK) { return RFC_ERROR(errorInfo); } - + return scope.Close(v8::Null()); } @@ -890,7 +890,7 @@ v8::Handle Function::TableToInternal(const CHND container, const SAP_ // Create array holding table lines v8::Local obj = v8::Array::New(); - + for (unsigned int i = 0; i < rowCount; i++){ RfcMoveTo(tableHandle, i, nullptr); strucHandle = RfcGetCurrentRow(tableHandle, nullptr); @@ -925,17 +925,17 @@ v8::Handle Function::StringToInternal(const CHND container, const SAP SAP_UC *buffer = static_cast(malloc((strLen + 1) * sizeof(SAP_UC))); assert(buffer); memset(buffer, 0, (strLen + 1) * sizeof(SAP_UC)); - + rc = RfcGetString(container, name, buffer, strLen + 1, &retStrLen, &errorInfo); if (rc != RFC_OK) { free(buffer); return RFC_ERROR(errorInfo); } - + v8::Local value = v8::String::New((const uint16_t*)(buffer)); free(buffer); - + return scope.Close(value); } @@ -958,17 +958,17 @@ v8::Handle Function::XStringToInternal(const CHND container, const SA SAP_RAW *buffer = static_cast(malloc(strLen * sizeof(SAP_RAW))); assert(buffer); memset(buffer, 0, strLen * sizeof(SAP_RAW)); - + rc = RfcGetXString(container, name, buffer, strLen, &retStrLen, &errorInfo); if (rc != RFC_OK) { free(buffer); return RFC_ERROR(errorInfo); } - + v8::Local value = v8::String::New(reinterpret_cast(buffer), strLen); free(buffer); - + return scope.Close(value); } @@ -980,17 +980,17 @@ v8::Handle Function::NumToInternal(const CHND container, const SAP_UC RFC_NUM *buffer = static_cast(malloc((len + 1) * sizeof(RFC_NUM))); assert(buffer); memset(buffer, 0, (len + 1) * sizeof(RFC_NUM)); - + RFC_RC rc = RfcGetNum(container, name, buffer, len, &errorInfo); if (rc != RFC_OK) { free(buffer); return RFC_ERROR(errorInfo); } - + v8::Local value = v8::String::New((const uint16_t*)(buffer)); free(buffer); - + return scope.Close(value); } @@ -1002,17 +1002,17 @@ v8::Handle Function::CharToInternal(const CHND container, const SAP_U RFC_CHAR *buffer = static_cast(malloc((len + 1) * sizeof(RFC_CHAR))); assert(buffer); memset(buffer, 0, (len + 1) * sizeof(RFC_CHAR)); - + RFC_RC rc = RfcGetChars(container, name, buffer, len, &errorInfo); if (rc != RFC_OK) { free(buffer); return RFC_ERROR(errorInfo); } - + v8::Local value = v8::String::New((const uint16_t*)(buffer)); free(buffer); - + return scope.Close(value); } @@ -1024,17 +1024,17 @@ v8::Handle Function::ByteToInternal(const CHND container, const SAP_U RFC_BYTE *buffer = static_cast(malloc(len * sizeof(RFC_BYTE))); assert(buffer); memset(buffer, 0, len * sizeof(RFC_BYTE)); - + RFC_RC rc = RfcGetBytes(container, name, buffer, len, &errorInfo); if (rc != RFC_OK) { free(buffer); return RFC_ERROR(errorInfo); } - + v8::Local value = v8::String::New(reinterpret_cast(buffer)); free(buffer); - + return scope.Close(value); } @@ -1124,7 +1124,7 @@ v8::Handle Function::TimeToInternal(const CHND container, const SAP_U assert(sizeof(RFC_CHAR) > 0); // Shouldn't occur except in case of a compiler glitch v8::Local value = v8::String::New((const uint16_t*)(time), sizeof(RFC_TIME) / sizeof(RFC_CHAR)); - + return scope.Close(value); } @@ -1141,7 +1141,7 @@ v8::Handle Function::BCDToInternal(const CHND container, const SAP_UC buffer = static_cast(malloc((strLen + 1) * sizeof(SAP_UC))); assert(buffer); memset(buffer, 0, (strLen + 1) * sizeof(SAP_UC)); - + rc = RfcGetString(container, name, buffer, strLen + 1, &retStrLen, &errorInfo); if (rc == RFC_BUFFER_TOO_SMALL) { @@ -1152,10 +1152,10 @@ v8::Handle Function::BCDToInternal(const CHND container, const SAP_UC return RFC_ERROR(errorInfo); } } while (rc == RFC_BUFFER_TOO_SMALL); - + v8::Local value = v8::String::New((const uint16_t*)(buffer), retStrLen); free(buffer); - + return scope.Close(value->ToNumber()); } diff --git a/src/Function.h b/src/Function.h index 1d009ef..9d3c866 100644 --- a/src/Function.h +++ b/src/Function.h @@ -1,4 +1,4 @@ -/* +/* ----------------------------------------------------------------------------- Copyright (c) 2011 Joachim Dorner @@ -43,7 +43,7 @@ class Function : public node::ObjectWrap protected: Function(); ~Function(); - + static v8::Handle New(const v8::Arguments &args); static v8::Handle Invoke(const v8::Arguments &args); @@ -96,7 +96,7 @@ class Function : public node::ObjectWrap InvocationBaton() : function(nullptr), functionHandle(nullptr) { }; ~InvocationBaton() { RFC_ERROR_INFO errorInfo; - + if (this->functionHandle) { RfcDestroyFunction(this->functionHandle, &errorInfo); this->functionHandle = nullptr; @@ -116,7 +116,7 @@ class Function : public node::ObjectWrap }; static v8::Persistent ctorTemplate; - + //RFC_CONNECTION_HANDLE connectionHandle; Connection *connection; RFC_FUNCTION_DESC_HANDLE functionDescHandle; From 1879dfc3f6ac6fd9984ee1dc22b6559d50d035ef Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Tue, 5 May 2015 21:45:21 +0200 Subject: [PATCH 03/11] Function: handle is now disposed by garbage collector The SAP function handle is managed by the garbage collector, so structures and large arrays will be able to hold reference to it. --- src/Function.cc | 9 +++++---- src/Function.h | 15 ++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index 552adff..478f9bc 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -236,6 +236,9 @@ void Function::EIO_AfterInvoke(uv_work_t *req) InvocationBaton *baton = static_cast(req->data); assert(baton != nullptr); + assert(baton->functionHandle != nullptr); + + v8::Persistent wrappedFunctionHandle = v8::Persistent::New(v8::External::New(baton->functionHandle)); v8::Local argv[2]; argv[0] = v8::Local::New(v8::Null()); @@ -252,10 +255,8 @@ void Function::EIO_AfterInvoke(uv_work_t *req) } } - if (baton->functionHandle) { - RfcDestroyFunction(baton->functionHandle, &errorInfo); - baton->functionHandle = nullptr; - } + wrappedFunctionHandle.MakeWeak(nullptr, InvocationBaton::DestroyFunctionHandle); + baton->functionHandle = nullptr; v8::TryCatch try_catch; diff --git a/src/Function.h b/src/Function.h index 9d3c866..2068515 100644 --- a/src/Function.h +++ b/src/Function.h @@ -95,19 +95,20 @@ class Function : public node::ObjectWrap public: InvocationBaton() : function(nullptr), functionHandle(nullptr) { }; ~InvocationBaton() { - RFC_ERROR_INFO errorInfo; - - if (this->functionHandle) { - RfcDestroyFunction(this->functionHandle, &errorInfo); - this->functionHandle = nullptr; - } - if (!this->cbInvoke.IsEmpty()) { this->cbInvoke.Dispose(); this->cbInvoke.Clear(); } }; + static void DestroyFunctionHandle(v8::Persistent value, void *parameters) { + printf("Destructed\n"); + v8::Handle wrappedFunctionHandle = v8::Handle::Cast(value); + RFC_FUNCTION_HANDLE functionHandle = static_cast(wrappedFunctionHandle->Value()); + RFC_ERROR_INFO errorInfo; + RfcDestroyFunction(functionHandle, &errorInfo); + }; + Function *function; Connection *connection; RFC_FUNCTION_HANDLE functionHandle; From 1be77d3d539e6080f43d8f560b02bebbbbf3c144 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Tue, 5 May 2015 21:54:21 +0200 Subject: [PATCH 04/11] Function: pass the v8 persistent function handle to structure and table --- src/Function.cc | 32 ++++++++++++++++---------------- src/Function.h | 14 +++++++------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index 478f9bc..64ae0e8 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -247,7 +247,7 @@ void Function::EIO_AfterInvoke(uv_work_t *req) if (baton->errorInfo.code != RFC_OK) { argv[0] = v8::Local::New(RfcError(baton->errorInfo)); } else { - v8::Local result = v8::Local::New(baton->function->DoReceive(baton->functionHandle)); + v8::Local result = v8::Local::New(baton->function->DoReceive(baton->functionHandle, wrappedFunctionHandle)); if (IsException(result)) { argv[0] = result; } else { @@ -271,7 +271,7 @@ void Function::EIO_AfterInvoke(uv_work_t *req) } } -v8::Handle Function::DoReceive(const CHND container) +v8::Handle Function::DoReceive(const CHND container, v8::Persistent functionHandle) { v8::HandleScope scope; RFC_RC rc = RFC_OK; @@ -301,7 +301,7 @@ v8::Handle Function::DoReceive(const CHND container) case RFC_CHANGING: case RFC_TABLES: case RFC_EXPORT: - parmValue = this->GetParameter(container, parmDesc); + parmValue = this->GetParameter(container, parmDesc, functionHandle); if (IsException(parmValue)) { return ThrowException(parmValue); } @@ -746,19 +746,19 @@ v8::Handle Function::BCDToExternal(const CHND container, const SAP_UC return scope.Close(v8::Null()); } -v8::Handle Function::GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc) +v8::Handle Function::GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc, v8::Persistent functionHandle) { v8::HandleScope scope; - return scope.Close(this->GetValue(container, desc.type, desc.name, desc.nucLength)); + return scope.Close(this->GetValue(container, desc.type, desc.name, desc.nucLength, functionHandle)); } -v8::Handle Function::GetField(const CHND container, const RFC_FIELD_DESC &desc) +v8::Handle Function::GetField(const CHND container, const RFC_FIELD_DESC &desc, v8::Persistent functionHandle) { v8::HandleScope scope; - return scope.Close(this->GetValue(container, desc.type, desc.name, desc.nucLength)); + return scope.Close(this->GetValue(container, desc.type, desc.name, desc.nucLength, functionHandle)); } -v8::Handle Function::GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len) +v8::Handle Function::GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len, v8::Persistent functionHandle) { v8::HandleScope scope; v8::Handle value = v8::Null(); @@ -795,10 +795,10 @@ v8::Handle Function::GetValue(const CHND container, RFCTYPE type, con value = this->Int2ToInternal(container, name); break; case RFCTYPE_STRUCTURE: - value = this->StructureToInternal(container, name); + value = this->StructureToInternal(container, name, functionHandle); break; case RFCTYPE_TABLE: - value = this->TableToInternal(container, name); + value = this->TableToInternal(container, name, functionHandle); break; case RFCTYPE_STRING: value = this->StringToInternal(container, name); @@ -816,7 +816,7 @@ v8::Handle Function::GetValue(const CHND container, RFCTYPE type, con return scope.Close(value); } -v8::Handle Function::StructureToInternal(const CHND container, const SAP_UC *name) +v8::Handle Function::StructureToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle) { v8::HandleScope scope; RFC_ERROR_INFO errorInfo; @@ -828,10 +828,10 @@ v8::Handle Function::StructureToInternal(const CHND container, const return RFC_ERROR(errorInfo); } - return scope.Close(this->StructureToInternal(container, strucHandle)); + return scope.Close(this->StructureToInternal(container, strucHandle, functionHandle)); } -v8::Handle Function::StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc) +v8::Handle Function::StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Persistent functionHandle) { v8::HandleScope scope; RFC_ERROR_INFO errorInfo; @@ -859,7 +859,7 @@ v8::Handle Function::StructureToInternal(const CHND container, const return RFC_ERROR(errorInfo); } - v8::Handle value = this->GetField(struc, fieldDesc); + v8::Handle value = this->GetField(struc, fieldDesc, functionHandle); // Bail out on exception if (IsException(value)) { return scope.Close(value); @@ -870,7 +870,7 @@ v8::Handle Function::StructureToInternal(const CHND container, const return scope.Close(obj); } -v8::Handle Function::TableToInternal(const CHND container, const SAP_UC *name) +v8::Handle Function::TableToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle) { v8::HandleScope scope; RFC_ERROR_INFO errorInfo; @@ -896,7 +896,7 @@ v8::Handle Function::TableToInternal(const CHND container, const SAP_ RfcMoveTo(tableHandle, i, nullptr); strucHandle = RfcGetCurrentRow(tableHandle, nullptr); - v8::Handle line = this->StructureToInternal(container, strucHandle); + v8::Handle line = this->StructureToInternal(container, strucHandle, functionHandle); // Bail out on exception if (IsException(line)) { return scope.Close(line); diff --git a/src/Function.h b/src/Function.h index 2068515..2e8b9b7 100644 --- a/src/Function.h +++ b/src/Function.h @@ -50,7 +50,7 @@ class Function : public node::ObjectWrap static void EIO_Invoke(uv_work_t *req); static void EIO_AfterInvoke(uv_work_t *req); - v8::Handle DoReceive(const CHND container); + v8::Handle DoReceive(const CHND container, v8::Persistent functionHandle); v8::Handle SetParameter(const CHND container, RFC_PARAMETER_DESC &desc, v8::Handle value); v8::Handle SetField(const CHND container, RFC_FIELD_DESC &desc, v8::Handle value); @@ -71,12 +71,12 @@ class Function : public node::ObjectWrap v8::Handle DateToExternal(const CHND container, const SAP_UC *name, v8::Handle value); v8::Handle BCDToExternal(const CHND container, const SAP_UC *name, v8::Handle value); - v8::Handle GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc); - v8::Handle GetField(const CHND container, const RFC_FIELD_DESC &desc); - v8::Handle GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len); - v8::Handle StructureToInternal(const CHND container, const SAP_UC *name); - v8::Handle StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc); - v8::Handle TableToInternal(const CHND container, const SAP_UC *name); + v8::Handle GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc, v8::Persistent functionHandle); + v8::Handle GetField(const CHND container, const RFC_FIELD_DESC &desc, v8::Persistent functionHandle); + v8::Handle GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len, v8::Persistent functionHandle); + v8::Handle StructureToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle); + v8::Handle StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Persistent functionHandle); + v8::Handle TableToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle); v8::Handle StringToInternal(const CHND container, const SAP_UC *name); v8::Handle XStringToInternal(const CHND container, const SAP_UC *name); v8::Handle NumToInternal(const CHND container, const SAP_UC *name, unsigned len); From 89ca14813ad146fe8e950afad27445bd566d5ee0 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Tue, 5 May 2015 23:56:13 +0200 Subject: [PATCH 05/11] Code cleanup Removed debug message. --- src/Function.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Function.h b/src/Function.h index 2e8b9b7..c4b6f0e 100644 --- a/src/Function.h +++ b/src/Function.h @@ -102,7 +102,6 @@ class Function : public node::ObjectWrap }; static void DestroyFunctionHandle(v8::Persistent value, void *parameters) { - printf("Destructed\n"); v8::Handle wrappedFunctionHandle = v8::Handle::Cast(value); RFC_FUNCTION_HANDLE functionHandle = static_cast(wrappedFunctionHandle->Value()); RFC_ERROR_INFO errorInfo; From 068e21cb03703c0c01b5fbf47c7215be55c09a42 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Wed, 6 May 2015 22:58:11 +0200 Subject: [PATCH 06/11] Function: use less memory when receiving large tables and structs The structures are not stored in plain objects anymore. ObjectTemplate is utilized to convert SAP data to JS only when it is read. --- src/Function.cc | 81 +++++++++++++++++++++++++++++++------------------ src/Function.h | 45 ++++++++++++++++++++++----- 2 files changed, 90 insertions(+), 36 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index 64ae0e8..2debdb5 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -25,6 +25,7 @@ SOFTWARE. #include "Function.h" v8::Persistent Function::ctorTemplate; +v8::Persistent Function::structureTemplate; Function::Function(): connection(nullptr), functionDescHandle(nullptr) { @@ -45,6 +46,10 @@ void Function::Init(v8::Handle target) NODE_SET_PROTOTYPE_METHOD(ctorTemplate, "Invoke", Function::Invoke); target->Set(v8::String::NewSymbol("Function"), ctorTemplate->GetFunction()); + + Function::structureTemplate = v8::Persistent::New(v8::ObjectTemplate::New()); + Function::structureTemplate->SetInternalFieldCount(4); + Function::structureTemplate->SetNamedPropertyHandler(Function::StructureGetter); } v8::Handle Function::NewInstance(Connection &connection, const v8::Arguments &args) @@ -271,7 +276,7 @@ void Function::EIO_AfterInvoke(uv_work_t *req) } } -v8::Handle Function::DoReceive(const CHND container, v8::Persistent functionHandle) +v8::Handle Function::DoReceive(const CHND container, v8::Handle functionHandle) { v8::HandleScope scope; RFC_RC rc = RFC_OK; @@ -746,19 +751,19 @@ v8::Handle Function::BCDToExternal(const CHND container, const SAP_UC return scope.Close(v8::Null()); } -v8::Handle Function::GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc, v8::Persistent functionHandle) +v8::Handle Function::GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc, v8::Handle functionHandle) { v8::HandleScope scope; return scope.Close(this->GetValue(container, desc.type, desc.name, desc.nucLength, functionHandle)); } -v8::Handle Function::GetField(const CHND container, const RFC_FIELD_DESC &desc, v8::Persistent functionHandle) +v8::Handle Function::GetField(const CHND container, const RFC_FIELD_DESC &desc, v8::Handle functionHandle) { v8::HandleScope scope; return scope.Close(this->GetValue(container, desc.type, desc.name, desc.nucLength, functionHandle)); } -v8::Handle Function::GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len, v8::Persistent functionHandle) +v8::Handle Function::GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len, v8::Handle functionHandle) { v8::HandleScope scope; v8::Handle value = v8::Null(); @@ -816,7 +821,7 @@ v8::Handle Function::GetValue(const CHND container, RFCTYPE type, con return scope.Close(value); } -v8::Handle Function::StructureToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle) +v8::Handle Function::StructureToInternal(const CHND container, const SAP_UC *name, v8::Handle functionHandle) { v8::HandleScope scope; RFC_ERROR_INFO errorInfo; @@ -831,52 +836,71 @@ v8::Handle Function::StructureToInternal(const CHND container, const return scope.Close(this->StructureToInternal(container, strucHandle, functionHandle)); } -v8::Handle Function::StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Persistent functionHandle) +v8::Handle Function::StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Handle functionHandle) { v8::HandleScope scope; + v8::Handle fieldDescriptions = this->BuildFieldDescriptionMap(struc, functionHandle); + if (IsException(fieldDescriptions)) { + scope.Close(fieldDescriptions); + } + return scope.Close(this->StructureToObject(struc, functionHandle, fieldDescriptions)); +} + +v8::Handle Function::StructureToObject(const RFC_STRUCTURE_HANDLE struc, v8::Handle functionHandle, v8::Handle fieldDescriptions) +{ + v8::Local result = structureTemplate->NewInstance(); + result->SetPointerInInternalField(0, this); + result->SetPointerInInternalField(1, struc); + result->SetInternalField(2, functionHandle); + result->SetInternalField(3, fieldDescriptions); + + return result; +} + +v8::Handle Function::BuildFieldDescriptionMap(const RFC_STRUCTURE_HANDLE struc, v8::Handle functionHandle) +{ RFC_ERROR_INFO errorInfo; RFC_RC rc = RFC_OK; RFC_TYPE_DESC_HANDLE typeHandle; - RFC_FIELD_DESC fieldDesc; + RFC_FIELD_DESC *fieldDesc; unsigned fieldCount; typeHandle = RfcDescribeType(struc, &errorInfo); assert(typeHandle); if (typeHandle == nullptr) { - return RFC_ERROR(errorInfo); + return RfcError(errorInfo); } rc = RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); if (rc != RFC_OK) { - return RFC_ERROR(errorInfo); + return RfcError(errorInfo); } - v8::Local obj = v8::Object::New(); + v8::Local result = v8::Object::New(); + // Keep a reference to functionHandle (so SAP function result is not freed) + result->SetHiddenValue(v8::String::NewSymbol("__fhr__"), functionHandle); for (unsigned int i = 0; i < fieldCount; i++) { - rc = RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); + fieldDesc = new RFC_FIELD_DESC; + rc = RfcGetFieldDescByIndex(typeHandle, i, fieldDesc, &errorInfo); if (rc != RFC_OK) { - return RFC_ERROR(errorInfo); + return RfcError(errorInfo); } - v8::Handle value = this->GetField(struc, fieldDesc, functionHandle); - // Bail out on exception - if (IsException(value)) { - return scope.Close(value); - } - obj->Set(v8::String::New((const uint16_t*)(fieldDesc.name)), value); + v8::Persistent value = v8::Persistent::New(v8::External::New(fieldDesc)); + result->Set(v8::String::New((const uint16_t*)(fieldDesc->name)), value); + value.MakeWeak(nullptr, Function::DestroyFieldDesc); } - return scope.Close(obj); + return result; } -v8::Handle Function::TableToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle) +v8::Handle Function::TableToInternal(const CHND container, const SAP_UC *name, v8::Handle functionHandle) { v8::HandleScope scope; RFC_ERROR_INFO errorInfo; RFC_RC rc = RFC_OK; RFC_TABLE_HANDLE tableHandle; - RFC_STRUCTURE_HANDLE strucHandle; unsigned rowCount; rc = RfcGetTable(container, name, &tableHandle, &errorInfo); @@ -892,16 +916,15 @@ v8::Handle Function::TableToInternal(const CHND container, const SAP_ // Create array holding table lines v8::Local obj = v8::Array::New(); + RfcMoveToFirstRow(tableHandle, nullptr); + v8::Handle fieldDescs = this->BuildFieldDescriptionMap(RfcGetCurrentRow(tableHandle, nullptr), functionHandle); + if (IsException(fieldDescs)) { + return scope.Close(fieldDescs); + } + for (unsigned int i = 0; i < rowCount; i++){ RfcMoveTo(tableHandle, i, nullptr); - strucHandle = RfcGetCurrentRow(tableHandle, nullptr); - - v8::Handle line = this->StructureToInternal(container, strucHandle, functionHandle); - // Bail out on exception - if (IsException(line)) { - return scope.Close(line); - } - obj->Set(v8::Integer::New(i), line); + obj->Set(v8::Integer::New(i), this->StructureToObject(RfcGetCurrentRow(tableHandle, nullptr), functionHandle, fieldDescs)); } return scope.Close(obj); diff --git a/src/Function.h b/src/Function.h index c4b6f0e..31af2f8 100644 --- a/src/Function.h +++ b/src/Function.h @@ -50,7 +50,7 @@ class Function : public node::ObjectWrap static void EIO_Invoke(uv_work_t *req); static void EIO_AfterInvoke(uv_work_t *req); - v8::Handle DoReceive(const CHND container, v8::Persistent functionHandle); + v8::Handle DoReceive(const CHND container, v8::Handle functionHandle); v8::Handle SetParameter(const CHND container, RFC_PARAMETER_DESC &desc, v8::Handle value); v8::Handle SetField(const CHND container, RFC_FIELD_DESC &desc, v8::Handle value); @@ -71,12 +71,14 @@ class Function : public node::ObjectWrap v8::Handle DateToExternal(const CHND container, const SAP_UC *name, v8::Handle value); v8::Handle BCDToExternal(const CHND container, const SAP_UC *name, v8::Handle value); - v8::Handle GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc, v8::Persistent functionHandle); - v8::Handle GetField(const CHND container, const RFC_FIELD_DESC &desc, v8::Persistent functionHandle); - v8::Handle GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len, v8::Persistent functionHandle); - v8::Handle StructureToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle); - v8::Handle StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Persistent functionHandle); - v8::Handle TableToInternal(const CHND container, const SAP_UC *name, v8::Persistent functionHandle); + v8::Handle GetParameter(const CHND container, const RFC_PARAMETER_DESC &desc, v8::Handle functionHandle); + v8::Handle GetField(const CHND container, const RFC_FIELD_DESC &desc, v8::Handle functionHandle); + v8::Handle GetValue(const CHND container, RFCTYPE type, const SAP_UC *name, unsigned len, v8::Handle functionHandle); + v8::Handle StructureToInternal(const CHND container, const SAP_UC *name, v8::Handle functionHandle); + v8::Handle StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Handle functionHandle); + v8::Handle StructureToObject(const RFC_STRUCTURE_HANDLE struc, v8::Handle functionHandle, v8::Handle fieldDescriptions); + v8::Handle BuildFieldDescriptionMap(const RFC_STRUCTURE_HANDLE struc, v8::Handle functionHandle); + v8::Handle TableToInternal(const CHND container, const SAP_UC *name, v8::Handle functionHandle); v8::Handle StringToInternal(const CHND container, const SAP_UC *name); v8::Handle XStringToInternal(const CHND container, const SAP_UC *name); v8::Handle NumToInternal(const CHND container, const SAP_UC *name, unsigned len); @@ -106,6 +108,7 @@ class Function : public node::ObjectWrap RFC_FUNCTION_HANDLE functionHandle = static_cast(wrappedFunctionHandle->Value()); RFC_ERROR_INFO errorInfo; RfcDestroyFunction(functionHandle, &errorInfo); + value.Dispose(); }; Function *function; @@ -116,6 +119,34 @@ class Function : public node::ObjectWrap }; static v8::Persistent ctorTemplate; + static v8::Persistent structureTemplate; + + static v8::Handle StructureGetter(v8::Local property, const v8::AccessorInfo &info) { + v8::HandleScope scope; + Function *function = static_cast(info.This()->GetPointerFromInternalField(0)); + RFC_STRUCTURE_HANDLE struc = static_cast(info.This()->GetPointerFromInternalField(1)); + v8::Handle functionHandle = v8::Handle::Cast(info.This()->GetInternalField(2)); + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + + if (!fieldDescriptions->Has(property)) { + v8::Handle result; + return result; + } + + v8::Handle wrappedFieldDesc = v8::Handle::Cast(fieldDescriptions->Get(property)); + RFC_FIELD_DESC *fieldDesc = static_cast(wrappedFieldDesc->Value()); + + return scope.Close(function->GetField(struc, *fieldDesc, functionHandle)); + }; + + static void DestroyFieldDesc(v8::Persistent value, void *parameters) { + v8::Handle wrappedFieldDesc = v8::Handle::Cast(value); + RFC_FIELD_DESC *fieldDesc = static_cast(wrappedFieldDesc->Value()); + if (fieldDesc) { + delete fieldDesc; + } + value.Dispose(); + }; //RFC_CONNECTION_HANDLE connectionHandle; Connection *connection; From 44f95868ffe8d58d464b51169446620346c86589 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Thu, 7 May 2015 11:18:04 +0200 Subject: [PATCH 07/11] Function: Do not build fied descriptions when the result table is empty --- src/Function.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Function.cc b/src/Function.cc index 2debdb5..c02837c 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -916,6 +916,10 @@ v8::Handle Function::TableToInternal(const CHND container, const SAP_ // Create array holding table lines v8::Local obj = v8::Array::New(); + if (rowCount == 0) { + return scope.Close(obj); + } + RfcMoveToFirstRow(tableHandle, nullptr); v8::Handle fieldDescs = this->BuildFieldDescriptionMap(RfcGetCurrentRow(tableHandle, nullptr), functionHandle); if (IsException(fieldDescs)) { From 8ab5dc5dbb34e7f6bc6201529715a8d52d51d542 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Thu, 7 May 2015 11:18:43 +0200 Subject: [PATCH 08/11] Function: Added query and enumerator callbacks to structure --- src/Function.cc | 8 +++++++- src/Function.h | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Function.cc b/src/Function.cc index c02837c..f50f8ed 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -49,7 +49,13 @@ void Function::Init(v8::Handle target) Function::structureTemplate = v8::Persistent::New(v8::ObjectTemplate::New()); Function::structureTemplate->SetInternalFieldCount(4); - Function::structureTemplate->SetNamedPropertyHandler(Function::StructureGetter); + Function::structureTemplate->SetNamedPropertyHandler( + Function::StructureGetter, + nullptr, + Function::StructureQuery, + nullptr, + Function::StructureEnumerate + ); } v8::Handle Function::NewInstance(Connection &connection, const v8::Arguments &args) diff --git a/src/Function.h b/src/Function.h index 31af2f8..c48230f 100644 --- a/src/Function.h +++ b/src/Function.h @@ -139,6 +139,25 @@ class Function : public node::ObjectWrap return scope.Close(function->GetField(struc, *fieldDesc, functionHandle)); }; + static v8::Handle StructureQuery(v8::Local property, const v8::AccessorInfo &info) { + v8::HandleScope scope; + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + + if (!fieldDescriptions->Has(property)) { + v8::Handle result; + return result; + } + + v8::Handle result(v8::Integer::New(v8::ReadOnly)); + return scope.Close(result); + }; + + static v8::Handle StructureEnumerate(const v8::AccessorInfo &info) { + v8::HandleScope scope; + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + return scope.Close(fieldDescriptions->GetOwnPropertyNames()); + }; + static void DestroyFieldDesc(v8::Persistent value, void *parameters) { v8::Handle wrappedFieldDesc = v8::Handle::Cast(value); RFC_FIELD_DESC *fieldDesc = static_cast(wrappedFieldDesc->Value()); From 598438bd819adba76101fc7a8a12b25d38e7e420 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Thu, 7 May 2015 11:41:59 +0200 Subject: [PATCH 09/11] Function: Fixed compile warnings --- src/Function.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index f50f8ed..7ae8775 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -545,7 +545,7 @@ v8::Handle Function::NumToExternal(const CHND container, const SAP_UC } v8::String::Value valueU16(value->ToString()); - if (valueU16.length() > len) { + if (valueU16.length() < 0 || (static_cast(valueU16.length()) > len)) { return RFC_ERROR("Argument exceeds maximum length: ", v8::String::New((const uint16_t*)(name))); } @@ -568,7 +568,7 @@ v8::Handle Function::CharToExternal(const CHND container, const SAP_U } v8::String::Value valueU16(value->ToString()); - if (valueU16.length() > len) { + if (valueU16.length() < 0 || (static_cast(valueU16.length()) > len)) { return RFC_ERROR("Argument exceeds maximum length: ", v8::String::New((const uint16_t*)(name))); } @@ -591,7 +591,7 @@ v8::Handle Function::ByteToExternal(const CHND container, const SAP_U } v8::String::AsciiValue valueAscii(value->ToString()); - if (valueAscii.length() > len) { + if (valueAscii.length() < 0 || (static_cast(valueAscii.length()) > len)) { return RFC_ERROR("Argument exceeds maximum length: ", v8::String::New((const uint16_t*)(name))); } From 9f3bcbcc7f4f62cd8601a2bb86c0d0280d68c8fc Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Thu, 7 May 2015 11:59:13 +0200 Subject: [PATCH 10/11] Code cleanup --- src/Function.cc | 37 +++++++++++++++++++++++++++++++++++++ src/Function.h | 41 ++++------------------------------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index 7ae8775..c1baa99 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -1193,3 +1193,40 @@ v8::Handle Function::BCDToInternal(const CHND container, const SAP_UC return scope.Close(value->ToNumber()); } + +v8::Handle Function::StructureGetter(v8::Local property, const v8::AccessorInfo &info) { + v8::HandleScope scope; + Function *function = static_cast(info.This()->GetPointerFromInternalField(0)); + RFC_STRUCTURE_HANDLE struc = static_cast(info.This()->GetPointerFromInternalField(1)); + v8::Handle functionHandle = v8::Handle::Cast(info.This()->GetInternalField(2)); + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + + if (!fieldDescriptions->Has(property)) { + v8::Handle result; + return result; + } + + v8::Handle wrappedFieldDesc = v8::Handle::Cast(fieldDescriptions->Get(property)); + RFC_FIELD_DESC *fieldDesc = static_cast(wrappedFieldDesc->Value()); + + return scope.Close(function->GetField(struc, *fieldDesc, functionHandle)); +}; + +v8::Handle Function::StructureQuery(v8::Local property, const v8::AccessorInfo &info) { + v8::HandleScope scope; + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + + if (!fieldDescriptions->Has(property)) { + v8::Handle result; + return result; + } + + v8::Handle result(v8::Integer::New(v8::ReadOnly)); + return scope.Close(result); +}; + +v8::Handle Function::StructureEnumerate(const v8::AccessorInfo &info) { + v8::HandleScope scope; + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + return scope.Close(fieldDescriptions->GetOwnPropertyNames()); +}; diff --git a/src/Function.h b/src/Function.h index c48230f..f298852 100644 --- a/src/Function.h +++ b/src/Function.h @@ -92,6 +92,10 @@ class Function : public node::ObjectWrap v8::Handle TimeToInternal(const CHND container, const SAP_UC *name); v8::Handle BCDToInternal(const CHND container, const SAP_UC *name); + static v8::Handle StructureGetter(v8::Local property, const v8::AccessorInfo &info); + static v8::Handle StructureQuery(v8::Local property, const v8::AccessorInfo &info); + static v8::Handle StructureEnumerate(const v8::AccessorInfo &info); + class InvocationBaton { public: @@ -121,43 +125,6 @@ class Function : public node::ObjectWrap static v8::Persistent ctorTemplate; static v8::Persistent structureTemplate; - static v8::Handle StructureGetter(v8::Local property, const v8::AccessorInfo &info) { - v8::HandleScope scope; - Function *function = static_cast(info.This()->GetPointerFromInternalField(0)); - RFC_STRUCTURE_HANDLE struc = static_cast(info.This()->GetPointerFromInternalField(1)); - v8::Handle functionHandle = v8::Handle::Cast(info.This()->GetInternalField(2)); - v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); - - if (!fieldDescriptions->Has(property)) { - v8::Handle result; - return result; - } - - v8::Handle wrappedFieldDesc = v8::Handle::Cast(fieldDescriptions->Get(property)); - RFC_FIELD_DESC *fieldDesc = static_cast(wrappedFieldDesc->Value()); - - return scope.Close(function->GetField(struc, *fieldDesc, functionHandle)); - }; - - static v8::Handle StructureQuery(v8::Local property, const v8::AccessorInfo &info) { - v8::HandleScope scope; - v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); - - if (!fieldDescriptions->Has(property)) { - v8::Handle result; - return result; - } - - v8::Handle result(v8::Integer::New(v8::ReadOnly)); - return scope.Close(result); - }; - - static v8::Handle StructureEnumerate(const v8::AccessorInfo &info) { - v8::HandleScope scope; - v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); - return scope.Close(fieldDescriptions->GetOwnPropertyNames()); - }; - static void DestroyFieldDesc(v8::Persistent value, void *parameters) { v8::Handle wrappedFieldDesc = v8::Handle::Cast(value); RFC_FIELD_DESC *fieldDesc = static_cast(wrappedFieldDesc->Value()); From f5509317922148197cb4f1f1c35c80e77f208d61 Mon Sep 17 00:00:00 2001 From: Szilard Novaki Date: Fri, 8 May 2015 15:28:19 +0200 Subject: [PATCH 11/11] Function: added setter and deleter interceptor for structures --- src/Function.cc | 39 ++++++++++++++++++++++++++++++++++----- src/Function.h | 2 ++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/Function.cc b/src/Function.cc index c1baa99..b611aa7 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -51,9 +51,9 @@ void Function::Init(v8::Handle target) Function::structureTemplate->SetInternalFieldCount(4); Function::structureTemplate->SetNamedPropertyHandler( Function::StructureGetter, - nullptr, + Function::StructureSetter, Function::StructureQuery, - nullptr, + Function::StructureDeleter, Function::StructureEnumerate ); } @@ -1194,7 +1194,8 @@ v8::Handle Function::BCDToInternal(const CHND container, const SAP_UC return scope.Close(value->ToNumber()); } -v8::Handle Function::StructureGetter(v8::Local property, const v8::AccessorInfo &info) { +v8::Handle Function::StructureGetter(v8::Local property, const v8::AccessorInfo &info) +{ v8::HandleScope scope; Function *function = static_cast(info.This()->GetPointerFromInternalField(0)); RFC_STRUCTURE_HANDLE struc = static_cast(info.This()->GetPointerFromInternalField(1)); @@ -1212,7 +1213,21 @@ v8::Handle Function::StructureGetter(v8::Local property, return scope.Close(function->GetField(struc, *fieldDesc, functionHandle)); }; -v8::Handle Function::StructureQuery(v8::Local property, const v8::AccessorInfo &info) { +v8::Handle Function::StructureSetter(v8::Local property, v8::Local value, const v8::AccessorInfo &info) +{ + v8::HandleScope scope; + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + + if (fieldDescriptions->Has(property)) { + return scope.Close(v8::ThrowException(v8::String::New("Cannot modify properties of SAP structures"))); + } + + v8::Local result; + return scope.Close(result); +}; + +v8::Handle Function::StructureQuery(v8::Local property, const v8::AccessorInfo &info) +{ v8::HandleScope scope; v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); @@ -1225,8 +1240,22 @@ v8::Handle Function::StructureQuery(v8::Local property, return scope.Close(result); }; -v8::Handle Function::StructureEnumerate(const v8::AccessorInfo &info) { +v8::Handle Function::StructureEnumerate(const v8::AccessorInfo &info) +{ v8::HandleScope scope; v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); return scope.Close(fieldDescriptions->GetOwnPropertyNames()); }; + +v8::Handle Function::StructureDeleter(v8::Local property, const v8::AccessorInfo &info) +{ + v8::HandleScope scope; + v8::Local fieldDescriptions = v8::Local::Cast(info.This()->GetInternalField(3)); + + if (fieldDescriptions->Has(property)) { + return scope.Close(v8::Boolean::New(false)); + } + + v8::Local result; + return scope.Close(result); +}; diff --git a/src/Function.h b/src/Function.h index f298852..56bdace 100644 --- a/src/Function.h +++ b/src/Function.h @@ -93,7 +93,9 @@ class Function : public node::ObjectWrap v8::Handle BCDToInternal(const CHND container, const SAP_UC *name); static v8::Handle StructureGetter(v8::Local property, const v8::AccessorInfo &info); + static v8::Handle StructureSetter(v8::Local property, v8::Local value, const v8::AccessorInfo &info); static v8::Handle StructureQuery(v8::Local property, const v8::AccessorInfo &info); + static v8::Handle StructureDeleter(v8::Local property, const v8::AccessorInfo &info); static v8::Handle StructureEnumerate(const v8::AccessorInfo &info); class InvocationBaton