Home | History | Annotate | Download | only in fxjs
      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