//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2014-2016 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 //////////////////////////////////////////////////////////////////////////////// #include "v8-globals.h" #include "Basics/system-functions.h" TRI_v8_global_t::TRI_v8_global_t(v8::Isolate* isolate, size_t id) : AgencyTempl(), AgentTempl(), ClusterInfoTempl(), ServerStateTempl(), ClusterCommTempl(), ArangoErrorTempl(), VocbaseColTempl(), VocbaseViewTempl(), VocbaseTempl(), EnvTempl(), UsersTempl(), GeneralGraphModuleTempl(), GeneralGraphTempl(), #ifdef USE_ENTERPRISE SmartGraphTempl(), #endif BufferTempl(), StreamQueryCursorTempl(), BufferConstant(), DeleteConstant(), GetConstant(), HeadConstant(), OptionsConstant(), PatchConstant(), PostConstant(), PutConstant(), AddressKey(), AllowUseDatabaseKey(), AuthorizedKey(), BodyFromFileKey(), BodyKey(), ClientKey(), ClientTransactionIDKey(), CodeKey(), ContentTypeKey(), CoordTransactionIDKey(), DatabaseKey(), DomainKey(), EndpointKey(), ErrorKey(), ErrorMessageKey(), ErrorNumKey(), HeadersKey(), HttpOnlyKey(), IdKey(), InitTimeoutKey(), IsRestoreKey(), IsSystemKey(), KeepNullKey(), KeyOptionsKey(), LengthKey(), LifeTimeKey(), MergeObjectsKey(), NameKey(), OperationIDKey(), OverwriteKey(), ParametersKey(), PathKey(), PrefixKey(), PortKey(), PortTypeKey(), ProtocolKey(), RawSuffixKey(), RequestBodyKey(), RequestTypeKey(), ResponseCodeKey(), ReturnNewKey(), ReturnOldKey(), SecureKey(), ServerKey(), ShardIDKey(), SilentKey(), SingleRequestKey(), StatusKey(), SuffixKey(), TimeoutKey(), ToJsonKey(), TransformationsKey(), UrlKey(), UserKey(), ValueKey(), VersionKeyHidden(), WaitForSyncKey(), _DbCacheKey(), _DbNameKey(), _IdKey(), _KeyKey(), _RevKey(), _FromKey(), _ToKey(), _currentRequest(), _currentResponse(), _transactionContext(nullptr), _queryRegistry(nullptr), _query(nullptr), _vocbase(nullptr), _activeExternals(0), _canceled(false), _allowUseDatabase(true), _inForcedCollect(false), _id(id), _lastMaxTime(TRI_microtime()), _countOfTimes(0), _heapMax(0), _heapLow(0) { v8::HandleScope scope(isolate); BufferConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "Buffer")); DeleteConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "DELETE")); GetConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "GET")); HeadConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "HEAD")); OptionsConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "OPTIONS")); PatchConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "PATCH")); PostConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "POST")); PutConstant.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "PUT")); AddressKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "address")); AllowUseDatabaseKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "allowUseDatabase")); AuthorizedKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "authorized")); BodyFromFileKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "bodyFromFile")); BodyKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "body")); ClientKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "client")); ClientTransactionIDKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "clientTransactionID")); CodeKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "code")); ContentTypeKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "contentType")); CookiesKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "cookies")); CoordTransactionIDKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "coordTransactionID")); DatabaseKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "database")); DomainKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "domain")); EndpointKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "endpoint")); ErrorKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "error")); ErrorMessageKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "errorMessage")); ErrorNumKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "errorNum")); HeadersKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "headers")); HttpOnlyKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "httpOnly")); IdKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "id")); InitTimeoutKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "initTimeout")); IsRestoreKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "isRestore")); IsSynchronousReplicationKey.Reset( isolate, TRI_V8_ASCII_STRING(isolate, "isSynchronousReplication")); IsSystemKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "isSystem")); KeepNullKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "keepNull")); KeyOptionsKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "keyOptions")); LengthKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "length")); LifeTimeKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "lifeTime")); MergeObjectsKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "mergeObjects")); NameKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "name")); OperationIDKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "operationID")); OverwriteKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "overwrite")); ParametersKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "parameters")); PathKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "path")); PrefixKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "prefix")); PortKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "port")); PortTypeKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "portType")); ProtocolKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "protocol")); RawSuffixKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "rawSuffix")); RequestBodyKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "requestBody")); RequestTypeKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "requestType")); ResponseCodeKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "responseCode")); ReturnNewKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "returnNew")); ReturnOldKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "returnOld")); SecureKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "secure")); ServerKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "server")); ShardIDKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "shardID")); SilentKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "silent")); SingleRequestKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "singleRequest")); StatusKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "status")); SuffixKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "suffix")); TimeoutKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "timeout")); ToJsonKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "toJSON")); TransformationsKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "transformations")); UrlKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "url")); UserKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "user")); ValueKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "value")); VersionKeyHidden.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "*version")); WaitForSyncKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "waitForSync")); _DbCacheKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "__dbcache__")); _DbNameKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "_dbName")); _IdKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "_id")); _KeyKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "_key")); _RevKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "_rev")); _FromKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "_from")); _ToKey.Reset(isolate, TRI_V8_ASCII_STRING(isolate, "_to")); } TRI_v8_global_t::DataSourcePersistent::DataSourcePersistent( v8::Isolate* isolate, std::shared_ptr const& datasource, std::function&& cleanupCallback) : _cleanupCallback(std::move(cleanupCallback)), _datasource(datasource), _isolate(isolate) { TRI_GET_GLOBALS(); _persistent.Reset(isolate, v8::External::New(isolate, datasource.get())); _persistent.SetWeak(this, [](v8::WeakCallbackInfo const& data) -> void { auto isolate = data.GetIsolate(); auto* persistent = data.GetParameter(); persistent->_cleanupCallback(); TRI_GET_GLOBALS(); isolate = nullptr; auto* key = persistent->_datasource.get(); // same key as was used for v8g->JSDatasources.emplace(...) auto count = v8g->JSDatasources.erase(key); TRI_ASSERT(count); // zero indicates that v8g was probably deallocated before calling the v8::WeakCallbackInfo::Callback }, v8::WeakCallbackType::kFinalizer); v8g->increaseActiveExternals(); } TRI_v8_global_t::DataSourcePersistent::~DataSourcePersistent() { auto* isolate = _isolate; TRI_GET_GLOBALS(); v8g->decreaseActiveExternals(); _persistent.Reset(); // dispose and clear the persistent handle (SIGSEGV here may indicate that v8::Isolate was already deallocated) } TRI_v8_global_t::~TRI_v8_global_t() {} /// @brief creates a global context TRI_v8_global_t* TRI_CreateV8Globals(v8::Isolate* isolate, size_t id) { TRI_GET_GLOBALS(); TRI_ASSERT(v8g == nullptr); v8g = new TRI_v8_global_t(isolate, id); isolate->SetData(arangodb::V8PlatformFeature::V8_DATA_SLOT, v8g); return v8g; } /// @brief returns a global context TRI_v8_global_t* TRI_GetV8Globals(v8::Isolate* isolate) { TRI_GET_GLOBALS(); if (v8g == nullptr) { v8g = TRI_CreateV8Globals(isolate, 0); } TRI_ASSERT(v8g != nullptr); return v8g; } /// @brief adds a method to an object void TRI_AddMethodVocbase(v8::Isolate* isolate, v8::Handle tpl, v8::Handle name, void (*func)(v8::FunctionCallbackInfo const&), bool isHidden) { if (isHidden) { // hidden method tpl->Set(name, v8::FunctionTemplate::New(isolate, func), v8::DontEnum); } else { // normal method tpl->Set(name, v8::FunctionTemplate::New(isolate, func)); } } /// @brief adds a global function to the given context void TRI_AddGlobalFunctionVocbase(v8::Isolate* isolate, v8::Handle name, void (*func)(v8::FunctionCallbackInfo const&), bool isHidden) { // all global functions are read-only if (isHidden) { isolate->GetCurrentContext()->Global()->ForceSet( name, v8::FunctionTemplate::New(isolate, func)->GetFunction(), static_cast(v8::ReadOnly | v8::DontEnum)); } else { isolate->GetCurrentContext()->Global()->ForceSet( name, v8::FunctionTemplate::New(isolate, func)->GetFunction(), v8::ReadOnly); } } /// @brief adds a global function to the given context void TRI_AddGlobalFunctionVocbase(v8::Isolate* isolate, v8::Handle name, v8::Handle func, bool isHidden) { // all global functions are read-only if (isHidden) { isolate->GetCurrentContext()->Global()->ForceSet( name, func, static_cast(v8::ReadOnly | v8::DontEnum)); } else { isolate->GetCurrentContext()->Global()->ForceSet(name, func, v8::ReadOnly); } } /// @brief adds a global read-only variable to the given context void TRI_AddGlobalVariableVocbase(v8::Isolate* isolate, v8::Handle name, v8::Handle value) { // all global variables are read-only isolate->GetCurrentContext()->Global()->ForceSet(name, value, v8::ReadOnly); }