1 // Copyright 2016 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "fxjs/cfxjse_runtimedata.h" 8 9 #include <utility> 10 11 #include "fxjs/cfxjse_isolatetracker.h" 12 #include "fxjs/fxjs_v8.h" 13 14 namespace { 15 16 // Duplicates fpdfsdk's cjs_runtime.h, but keeps XFA from depending on it. 17 // TODO(tsepez): make a single version of this. 18 class FXJSE_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 19 void* Allocate(size_t length) override { return calloc(1, length); } 20 void* AllocateUninitialized(size_t length) override { return malloc(length); } 21 void Free(void* data, size_t length) override { free(data); } 22 }; 23 24 void Runtime_DisposeCallback(v8::Isolate* pIsolate, bool bOwned) { 25 if (FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate)) 26 delete pData; 27 if (bOwned) 28 pIsolate->Dispose(); 29 } 30 31 void KillV8() { 32 v8::V8::Dispose(); 33 } 34 35 } // namespace 36 37 void FXJSE_Initialize() { 38 if (!CFXJSE_IsolateTracker::g_pInstance) 39 CFXJSE_IsolateTracker::g_pInstance = new CFXJSE_IsolateTracker; 40 41 static bool bV8Initialized = false; 42 if (bV8Initialized) 43 return; 44 45 bV8Initialized = true; 46 atexit(KillV8); 47 } 48 49 void FXJSE_Finalize() { 50 if (!CFXJSE_IsolateTracker::g_pInstance) 51 return; 52 53 CFXJSE_IsolateTracker::g_pInstance->RemoveAll(Runtime_DisposeCallback); 54 delete CFXJSE_IsolateTracker::g_pInstance; 55 CFXJSE_IsolateTracker::g_pInstance = nullptr; 56 } 57 58 v8::Isolate* FXJSE_Runtime_Create_Own() { 59 std::unique_ptr<v8::ArrayBuffer::Allocator> allocator( 60 new FXJSE_ArrayBufferAllocator()); 61 v8::Isolate::CreateParams params; 62 params.array_buffer_allocator = allocator.get(); 63 v8::Isolate* pIsolate = v8::Isolate::New(params); 64 ASSERT(pIsolate && CFXJSE_IsolateTracker::g_pInstance); 65 CFXJSE_IsolateTracker::g_pInstance->Append(pIsolate, std::move(allocator)); 66 return pIsolate; 67 } 68 69 void FXJSE_Runtime_Release(v8::Isolate* pIsolate) { 70 if (!pIsolate) 71 return; 72 CFXJSE_IsolateTracker::g_pInstance->Remove(pIsolate, Runtime_DisposeCallback); 73 } 74 75 CFXJSE_RuntimeData::CFXJSE_RuntimeData(v8::Isolate* pIsolate) 76 : m_pIsolate(pIsolate) {} 77 78 CFXJSE_RuntimeData::~CFXJSE_RuntimeData() {} 79 80 std::unique_ptr<CFXJSE_RuntimeData> CFXJSE_RuntimeData::Create( 81 v8::Isolate* pIsolate) { 82 std::unique_ptr<CFXJSE_RuntimeData> pRuntimeData( 83 new CFXJSE_RuntimeData(pIsolate)); 84 CFXJSE_ScopeUtil_IsolateHandle scope(pIsolate); 85 v8::Local<v8::FunctionTemplate> hFuncTemplate = 86 v8::FunctionTemplate::New(pIsolate); 87 v8::Local<v8::ObjectTemplate> hGlobalTemplate = 88 hFuncTemplate->InstanceTemplate(); 89 hGlobalTemplate->Set( 90 v8::Symbol::GetToStringTag(pIsolate), 91 v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal) 92 .ToLocalChecked()); 93 v8::Local<v8::Context> hContext = 94 v8::Context::New(pIsolate, 0, hGlobalTemplate); 95 hContext->SetSecurityToken(v8::External::New(pIsolate, pIsolate)); 96 pRuntimeData->m_hRootContextGlobalTemplate.Reset(pIsolate, hFuncTemplate); 97 pRuntimeData->m_hRootContext.Reset(pIsolate, hContext); 98 return pRuntimeData; 99 } 100 101 CFXJSE_RuntimeData* CFXJSE_RuntimeData::Get(v8::Isolate* pIsolate) { 102 FXJS_PerIsolateData::SetUp(pIsolate); 103 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); 104 if (!pData->m_pFXJSERuntimeData) 105 pData->m_pFXJSERuntimeData = CFXJSE_RuntimeData::Create(pIsolate); 106 return pData->m_pFXJSERuntimeData.get(); 107 } 108 109 CFXJSE_IsolateTracker* CFXJSE_IsolateTracker::g_pInstance = nullptr; 110