Merge to XFA: Fix V8 array buffer allocator.
[pdfium.git] / xfa / src / fxjse / src / runtime.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../foxitlib.h"\r
8 #include "fxv8.h"\r
9 #include "runtime.h"\r
10 #include "scope_inline.h"\r
11 \r
12 // Duplicates fpdfsdk's JS_Runtime.h, but keeps XFA from depending on it.\r
13 // TODO(tsepez): make a single version of this.\r
14 class FXJSE_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {\r
15     void* Allocate(size_t length) override {\r
16         return calloc(1, length);\r
17     }\r
18     void* AllocateUninitialized(size_t length) override {\r
19         return malloc(length);\r
20     }\r
21     void Free(void* data, size_t length) override {\r
22         free(data);\r
23     }\r
24 };\r
25 \r
26 static void FXJSE_KillV8()\r
27 {\r
28     v8::V8::Dispose();\r
29 }\r
30 void FXJSE_Initialize()\r
31 {\r
32     if(!CFXJSE_RuntimeData::g_RuntimeList) {\r
33         CFXJSE_RuntimeData::g_RuntimeList = FX_NEW CFXJSE_RuntimeList;\r
34     }\r
35     static FX_BOOL bV8Initialized = FALSE;\r
36     if (bV8Initialized) {\r
37         return;\r
38     }\r
39     bV8Initialized = TRUE;\r
40     atexit(FXJSE_KillV8);\r
41     FX_LPCSTR szCmdFlags =\r
42         "--harmony_proxies "\r
43         "--block_concurrent_recompilation "\r
44         ;\r
45     v8::V8::SetFlagsFromString(szCmdFlags, FXSYS_strlen(szCmdFlags));\r
46 }\r
47 static void FXJSE_Runtime_DisposeCallback(v8::Isolate* pIsolate)\r
48 {\r
49     {\r
50         v8::Locker locker(pIsolate);\r
51         CFXJSE_RuntimeData *pRuntimeData = reinterpret_cast<CFXJSE_RuntimeData*>(pIsolate->GetData(0));\r
52         if(pRuntimeData) {\r
53             pIsolate->SetData(0, NULL);\r
54             delete pRuntimeData;\r
55         }\r
56     }\r
57     pIsolate->Dispose();\r
58 }\r
59 void FXJSE_Finalize()\r
60 {\r
61     if(CFXJSE_RuntimeData::g_RuntimeList) {\r
62         CFXJSE_RuntimeData::g_RuntimeList->RemoveAllRuntimes(FXJSE_Runtime_DisposeCallback);\r
63         delete CFXJSE_RuntimeData::g_RuntimeList;\r
64         CFXJSE_RuntimeData::g_RuntimeList = NULL;\r
65     }\r
66 }\r
67 FXJSE_HRUNTIME  FXJSE_Runtime_Create()\r
68 {\r
69     v8::Isolate::CreateParams params;\r
70     params.array_buffer_allocator = new FXJSE_ArrayBufferAllocator();\r
71     v8::Isolate* pIsolate = v8::Isolate::New(params);\r
72     ASSERT(pIsolate && CFXJSE_RuntimeData::g_RuntimeList);\r
73     CFXJSE_RuntimeData::g_RuntimeList->AppendRuntime(pIsolate);\r
74     return reinterpret_cast<FXJSE_HRUNTIME>(pIsolate);\r
75 }\r
76 void FXJSE_Runtime_Release(FXJSE_HRUNTIME hRuntime)\r
77 {\r
78     v8::Isolate* pIsolate = reinterpret_cast<v8::Isolate*>(hRuntime);\r
79     if(pIsolate) {\r
80         ASSERT(CFXJSE_RuntimeData::g_RuntimeList);\r
81         CFXJSE_RuntimeData::g_RuntimeList->RemoveRuntime(pIsolate, FXJSE_Runtime_DisposeCallback);\r
82     }\r
83 }\r
84 CFXJSE_RuntimeData* CFXJSE_RuntimeData::Create(v8::Isolate* pIsolate)\r
85 {\r
86     CFXJSE_RuntimeData* pRuntimeData = FX_NEW CFXJSE_RuntimeData(pIsolate);\r
87     ASSERT(pRuntimeData);\r
88     CFXJSE_ScopeUtil_IsolateHandle scope(pIsolate);\r
89     v8::Local<v8::FunctionTemplate> hFuncTemplate = v8::FunctionTemplate::New(pIsolate);\r
90     v8::Local<v8::Context> hContext = v8::Context::New(pIsolate, 0, hFuncTemplate->InstanceTemplate());\r
91     hContext->SetSecurityToken(v8::External::New(pIsolate, pIsolate));\r
92     pRuntimeData->m_hRootContextGlobalTemplate.Reset(pIsolate, hFuncTemplate);\r
93     pRuntimeData->m_hRootContext.Reset(pIsolate, hContext);\r
94     return pRuntimeData;\r
95 }\r
96 CFXJSE_RuntimeData* CFXJSE_RuntimeData::Get(v8::Isolate* pIsolate)\r
97 {\r
98     ASSERT(pIsolate);\r
99     CFXJSE_RuntimeData* pRuntimeData = static_cast<CFXJSE_RuntimeData*>(pIsolate->GetData(0));\r
100     if(!pRuntimeData) {\r
101         pRuntimeData = CFXJSE_RuntimeData::Create(pIsolate);\r
102         ASSERT(pRuntimeData);\r
103         pIsolate->SetData(0, pRuntimeData);\r
104     }\r
105     return pRuntimeData;\r
106 }\r
107 CFXJSE_RuntimeList * CFXJSE_RuntimeData::g_RuntimeList = NULL;\r
108 void CFXJSE_RuntimeList::AppendRuntime(v8::Isolate* pIsolate)\r
109 {\r
110     m_RuntimeList.Add(pIsolate);\r
111 }\r
112 void CFXJSE_RuntimeList::RemoveRuntime(v8::Isolate* pIsolate, CFXJSE_RuntimeList::RuntimeDisposeCallback lpfnDisposeCallback)\r
113 {\r
114     FX_INT32 iIdx = m_RuntimeList.Find(pIsolate, 0);\r
115     if(iIdx >= 0) {\r
116         m_RuntimeList.RemoveAt(iIdx, 1);\r
117     }\r
118     if(lpfnDisposeCallback) {\r
119         lpfnDisposeCallback(pIsolate);\r
120     }\r
121 }\r
122 void CFXJSE_RuntimeList::RemoveAllRuntimes(CFXJSE_RuntimeList::RuntimeDisposeCallback lpfnDisposeCallback)\r
123 {\r
124     FX_INT32 iSize = m_RuntimeList.GetSize();\r
125     if(lpfnDisposeCallback) {\r
126         for(FX_INT32 iIdx = 0; iIdx < iSize; iIdx++) {\r
127             lpfnDisposeCallback(m_RuntimeList[iIdx]);\r
128         }\r
129     }\r
130     m_RuntimeList.RemoveAll();\r
131 }\r