//////////////////////////////////////////////////////////////////////////////// /// @brief Aql, v8 context executor /// /// @file /// /// DISCLAIMER /// /// Copyright 2014 ArangoDB GmbH, Cologne, Germany /// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Jan Steemann /// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany /// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// #include "Aql/V8Executor.h" #include "Aql/AstNode.h" #include "Basics/StringBuffer.h" #include "Utils/Exception.h" #include "V8/v8-conv.h" #include "V8/v8-globals.h" using namespace triagens::aql; // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief creates an executor //////////////////////////////////////////////////////////////////////////////// V8Executor::V8Executor () : _buffer(nullptr) { } //////////////////////////////////////////////////////////////////////////////// /// @brief destroys an executor //////////////////////////////////////////////////////////////////////////////// V8Executor::~V8Executor () { if (_buffer != nullptr) { delete _buffer; _buffer = nullptr; } } // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief executes a comparison operation using V8 //////////////////////////////////////////////////////////////////////////////// TRI_json_t* V8Executor::executeComparison (std::string const& func, AstNode const* lhs, AstNode const* rhs) { triagens::basics::StringBuffer* buffer = getBuffer(); TRI_ASSERT(buffer != nullptr); _buffer->appendText("(function(){ var aql = require(\"org/arangodb/ahuacatl\"); return aql.RELATIONAL_"); _buffer->appendText(func); _buffer->appendText("("); lhs->append(buffer); _buffer->appendText(", "); rhs->append(buffer); _buffer->appendText("); })"); return execute(); } // ----------------------------------------------------------------------------- // --SECTION-- private methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief create the string buffer //////////////////////////////////////////////////////////////////////////////// triagens::basics::StringBuffer* V8Executor::getBuffer () { if (_buffer == nullptr) { _buffer = new triagens::basics::StringBuffer(TRI_UNKNOWN_MEM_ZONE); if (_buffer == nullptr) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } _buffer->reserve(256); } else { _buffer->clear(); } return _buffer; } //////////////////////////////////////////////////////////////////////////////// /// @brief executes the contents of the string buffer //////////////////////////////////////////////////////////////////////////////// TRI_json_t* V8Executor::execute () { TRI_ASSERT(_buffer != nullptr); v8::Handle compiled = v8::Script::Compile(v8::String::New(_buffer->c_str(), (int) _buffer->length()), v8::String::New("--script--")); if (compiled.IsEmpty()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } v8::TryCatch tryCatch; v8::Handle func = compiled->Run(); if (tryCatch.HasCaught()) { if (tryCatch.CanContinue()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } else { TRI_v8_global_t* v8g = static_cast(v8::Isolate::GetCurrent()->GetData()); v8g->_canceled = true; THROW_ARANGO_EXCEPTION(TRI_ERROR_REQUEST_CANCELED); } } if (func.IsEmpty() || ! func->IsFunction()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } // execute the function v8::Handle args[] = { }; v8::Handle result = v8::Handle::Cast(func)->Call(v8::Object::New(), 0, args); if (tryCatch.HasCaught()) { if (tryCatch.CanContinue()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } else { TRI_v8_global_t* v8g = static_cast(v8::Isolate::GetCurrent()->GetData()); v8g->_canceled = true; THROW_ARANGO_EXCEPTION(TRI_ERROR_REQUEST_CANCELED); } } if (result.IsEmpty()) { THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); } return TRI_ObjectToJson(result); } // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE // ----------------------------------------------------------------------------- // Local Variables: // mode: outline-minor // outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" // End: