Merge to XFA: PDFium embeddertests.
authorTom Sepez <tsepez@chromium.org>
Fri, 16 Jan 2015 22:59:26 +0000 (14:59 -0800)
committerTom Sepez <tsepez@chromium.org>
Fri, 16 Jan 2015 22:59:26 +0000 (14:59 -0800)
This consists of two origin/master CLs:
Review URL: https://codereview.chromium.org/857483005
Review URL: https://codereview.chromium.org/827733006

It also fixes a couple of segv's in XFA when the library is initialized and destroyed multiple times in the same process.

R=jam@chromium.org
TBR=jam@chromium.org

Review URL: https://codereview.chromium.org/856623004

fpdfsdk/src/fpdfview_embeddertest.cpp [new file with mode: 0644]
pdfium.gyp
testing/embedder_test.cpp [new file with mode: 0644]
testing/embedder_test.h [new file with mode: 0644]
testing/resources/about_blank.pdf [new file with mode: 0644]
xfa/src/fwl/src/core/fwl_appimp.cpp
xfa/src/fwl/src/core/fwl_noteimp.cpp
xfa/src/fwl/src/core/include/fwl_noteimp.h
xfa/src/fxjse/src/runtime.cpp

diff --git a/fpdfsdk/src/fpdfview_embeddertest.cpp b/fpdfsdk/src/fpdfview_embeddertest.cpp
new file mode 100644 (file)
index 0000000..94a5109
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2015 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "../../testing/embedder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class FPDFViewEmbeddertest : public EmbedderTest {
+};
+
+TEST_F(FPDFViewEmbeddertest, Document) {
+  EXPECT_TRUE(OpenDocument("testing/resources/about_blank.pdf"));
+  EXPECT_EQ(1, GetPageCount());
+  EXPECT_EQ(0, GetFirstPageNum());
+
+  int version;
+  EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
+  EXPECT_EQ(14, version);
+
+  EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocPermissions(document()));
+  EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document()));
+}
+
+TEST_F(FPDFViewEmbeddertest, Page) {
+  EXPECT_TRUE(OpenDocument("testing/resources/about_blank.pdf"));
+  FPDF_FORMHANDLE form_handle = SetFormFillEnvironment();
+  FPDF_PAGE page = LoadPage(0, form_handle);
+  EXPECT_NE(nullptr, page);
+  EXPECT_EQ(612.0, FPDF_GetPageWidth(page));
+  EXPECT_EQ(792.0, FPDF_GetPageHeight(page));
+  UnloadPage(page, form_handle);
+  EXPECT_EQ(nullptr, LoadPage(1, form_handle));
+  ClearFormFillEnvironment(form_handle);
+}
+
+TEST_F(FPDFViewEmbeddertest, ViewerRef) {
+  EXPECT_TRUE(OpenDocument("testing/resources/about_blank.pdf"));
+  EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
+  EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document()));
+  EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
+}
+
index f52fd2d..6b8214e 100644 (file)
         'xfa/src/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp',
       ],
     },
+    {
+      'target_name': 'pdfium_embeddertests',
+      'type': 'executable',
+      'dependencies': [
+        '<(DEPTH)/testing/gtest.gyp:gtest_main',
+        '<(DEPTH)/testing/gtest.gyp:gtest',
+        'pdfium',
+      ],
+      'include_dirs': [
+        '<(DEPTH)'
+      ],
+      'sources': [
+        'fpdfsdk/src/fpdfview_embeddertest.cpp',
+        'testing/embedder_test.cpp',
+        'testing/embedder_test.h',
+        'testing/fx_string_testhelpers.cpp',
+        'testing/fx_string_testhelpers.h',
+      ],
+    },
   ],
 }
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
new file mode 100644 (file)
index 0000000..539f48c
--- /dev/null
@@ -0,0 +1,309 @@
+// Copyright (c) 2015 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "embedder_test.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <list>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "../fpdfsdk/include/fpdf_ext.h"
+#include "../fpdfsdk/include/fpdftext.h"
+#include "../fpdfsdk/include/fpdfview.h"
+#include "../core/include/fxcrt/fx_system.h"
+#include "v8/include/v8.h"
+
+#ifdef _WIN32
+#define snprintf _snprintf
+#define PATH_SEPARATOR '\\'
+#else
+#define PATH_SEPARATOR '/'
+#endif
+
+namespace {
+
+// Reads the entire contents of a file into a newly malloc'd buffer.
+static char* GetFileContents(const char* filename, size_t* retlen) {
+  FILE* file = fopen(filename, "rb");
+  if (!file) {
+    fprintf(stderr, "Failed to open: %s\n", filename);
+    return NULL;
+  }
+  (void) fseek(file, 0, SEEK_END);
+  size_t file_length = ftell(file);
+  if (!file_length) {
+    return NULL;
+  }
+  (void) fseek(file, 0, SEEK_SET);
+  char* buffer = (char*) malloc(file_length);
+  if (!buffer) {
+    return NULL;
+  }
+  size_t bytes_read = fread(buffer, 1, file_length, file);
+  (void) fclose(file);
+  if (bytes_read != file_length) {
+    fprintf(stderr, "Failed to read: %s\n", filename);
+    free(buffer);
+    return NULL;
+  }
+  *retlen = bytes_read;
+  return buffer;
+}
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+// Returns the full path for an external V8 data file based on either
+// the currect exectuable path or an explicit override.
+static std::string GetFullPathForSnapshotFile(const Options& options,
+                                              const std::string& filename) {
+  std::string result;
+  if (!options.bin_directory.empty()) {
+    result = options.bin_directory;
+    if (*options.bin_directory.rbegin() != PATH_SEPARATOR) {
+      result += PATH_SEPARATOR;
+    }
+  } else if (!options.exe_path.empty()) {
+    size_t last_separator = options.exe_path.rfind(PATH_SEPARATOR);
+    if (last_separator != std::string::npos)  {
+      result = options.exe_path.substr(0, last_separator + 1);
+    }
+  }
+  result += filename;
+  return result;
+}
+
+// Reads an extenal V8 data file from the |options|-indicated location,
+// returing true on success and false on error.
+static bool GetExternalData(const Options& options,
+                            const std::string& bin_filename,
+                            v8::StartupData* result_data) {
+  std::string full_path = GetFullPathForSnapshotFile(options, bin_filename);
+  size_t data_length = 0;
+  char* data_buffer = GetFileContents(full_path.c_str(), &data_length);
+  if (!data_buffer) {
+    return false;
+  }
+  result_data->data = const_cast<const char*>(data_buffer);
+  result_data->raw_size = data_length;
+  return true;
+}
+#endif  // V8_USE_EXTERNAL_STARTUP_DATA
+
+}  // namespace
+
+int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {
+  printf("Form_Alert called.\n");
+  return 0;
+}
+
+void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
+  std::string feature = "Unknown";
+  switch (type) {
+    case FPDF_UNSP_DOC_XFAFORM:
+      feature = "XFA";
+      break;
+    case FPDF_UNSP_DOC_PORTABLECOLLECTION:
+      feature = "Portfolios_Packages";
+      break;
+    case FPDF_UNSP_DOC_ATTACHMENT:
+    case FPDF_UNSP_ANNOT_ATTACHMENT:
+      feature = "Attachment";
+      break;
+    case FPDF_UNSP_DOC_SECURITY:
+      feature = "Rights_Management";
+      break;
+    case FPDF_UNSP_DOC_SHAREDREVIEW:
+      feature = "Shared_Review";
+      break;
+    case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
+    case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
+    case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
+      feature = "Shared_Form";
+      break;
+    case FPDF_UNSP_ANNOT_3DANNOT:
+      feature = "3D";
+      break;
+    case FPDF_UNSP_ANNOT_MOVIE:
+      feature = "Movie";
+      break;
+    case FPDF_UNSP_ANNOT_SOUND:
+      feature = "Sound";
+      break;
+    case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
+    case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
+      feature = "Screen";
+      break;
+    case FPDF_UNSP_ANNOT_SIG:
+      feature = "Digital_Signature";
+      break;
+  }
+  printf("Unsupported feature: %s.\n", feature.c_str());
+}
+
+class TestLoader {
+ public:
+  TestLoader(const char* pBuf, size_t len);
+
+  const char* m_pBuf;
+  size_t m_Len;
+};
+
+TestLoader::TestLoader(const char* pBuf, size_t len)
+    : m_pBuf(pBuf), m_Len(len) {
+}
+
+int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
+              unsigned long size) {
+  TestLoader* pLoader = (TestLoader*) param;
+  if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
+  memcpy(pBuf, pLoader->m_pBuf + pos, size);
+  return 1;
+}
+
+bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
+  return true;
+}
+
+void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
+}
+
+void EmbedderTest::SetUp() {
+    v8::V8::InitializeICU();
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+    ASSERT_TRUE(GetExternalData(options, "natives_blob.bin", &natives_));
+    ASSERT_TRUE(GetExternalData(options, "snapshot_blob.bin", &snapshot_));
+    v8::V8::SetNativesDataBlob(&natives);
+    v8::V8::SetSnapshotDataBlob(&snapshot);
+#endif  // V8_USE_EXTERNAL_STARTUP_DATA
+
+    FPDF_InitLibrary();
+
+    UNSUPPORT_INFO unsuppored_info;
+    memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
+    unsuppored_info.version = 1;
+    unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;
+    FSDK_SetUnSpObjProcessHandler(&unsuppored_info);
+  }
+
+void EmbedderTest::TearDown() {
+  FPDF_CloseDocument(document_);
+  FPDFAvail_Destroy(avail_);
+  FPDF_DestroyLibrary();
+  if (loader_) {
+    delete loader_;
+  }
+  if (file_contents_) {
+    free(file_contents_);
+  }
+}
+
+bool EmbedderTest::OpenDocument(const std::string& filename) {
+  file_contents_ = GetFileContents(filename.c_str(), &file_length_);
+  if (!file_contents_) {
+    return false;
+  }
+
+  loader_ = new TestLoader(file_contents_, file_length_);
+  file_access_.m_FileLen = static_cast<unsigned long>(file_length_);
+  file_access_.m_GetBlock = Get_Block;
+  file_access_.m_Param = loader_;
+
+  file_avail_.version = 1;
+  file_avail_.IsDataAvail = Is_Data_Avail;
+
+  hints_.version = 1;
+  hints_.AddSegment = Add_Segment;
+
+  avail_ = FPDFAvail_Create(&file_avail_, &file_access_);
+  (void) FPDFAvail_IsDocAvail(avail_, &hints_);
+
+  if (!FPDFAvail_IsLinearized(avail_)) {
+    document_ = FPDF_LoadCustomDocument(&file_access_, NULL);
+  } else {
+    document_ = FPDFAvail_GetDocument(avail_, NULL);
+  }
+  if (!document_) {
+    return false;
+  }
+  (void) FPDF_LoadXFA(document_);
+  (void) FPDF_GetDocPermissions(document_);
+  (void) FPDFAvail_IsFormAvail(avail_, &hints_);
+  return true;
+}
+
+FPDF_FORMHANDLE EmbedderTest::SetFormFillEnvironment() {
+  IPDF_JSPLATFORM platform_callbacks;
+  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
+  platform_callbacks.version = 1;
+  platform_callbacks.app_alert = Form_Alert;
+
+  FPDF_FORMFILLINFO form_callbacks;
+  memset(&form_callbacks, '\0', sizeof(form_callbacks));
+  form_callbacks.version = 1;
+  form_callbacks.m_pJsPlatform = &platform_callbacks;
+
+  FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnvironment(document_,
+                                                         &form_callbacks);
+  FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD);
+  FPDF_SetFormFieldHighlightAlpha(form, 100);
+  return form;
+}
+
+void EmbedderTest::ClearFormFillEnvironment(FPDF_FORMHANDLE form) {
+  FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC);
+  FPDFDOC_ExitFormFillEnvironment(form);
+}
+
+void EmbedderTest::DoOpenActions(FPDF_FORMHANDLE form) {
+  FORM_DoDocumentJSAction(form);
+  FORM_DoDocumentOpenAction(form);
+}
+
+int EmbedderTest::GetFirstPageNum() {
+  int first_page = FPDFAvail_GetFirstPageNum(document_);
+  (void) FPDFAvail_IsPageAvail(avail_, first_page, &hints_);
+  return first_page;
+}
+
+int EmbedderTest::GetPageCount() {
+  int page_count = FPDF_GetPageCount(document_);
+  for (int i = 0; i < page_count; ++i) {
+    (void) FPDFAvail_IsPageAvail(avail_, i, &hints_);
+  }
+  return page_count;
+}
+
+FPDF_PAGE EmbedderTest::LoadPage(int page_number,
+                                 FPDF_FORMHANDLE form) {
+  FPDF_PAGE page = FPDF_LoadPage(document_, page_number);
+  if (!page) {
+    return nullptr;
+  }
+  FORM_OnAfterLoadPage(page, form);
+  FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN);
+  return page;
+}
+
+FPDF_BITMAP EmbedderTest::RenderPage(FPDF_PAGE page,
+                                     FPDF_FORMHANDLE form) {
+  int width = static_cast<int>(FPDF_GetPageWidth(page));
+  int height = static_cast<int>(FPDF_GetPageHeight(page));
+  FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
+  FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
+  FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
+  FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0);
+  return bitmap;
+}
+
+void EmbedderTest::UnloadPage(FPDF_PAGE page, FPDF_FORMHANDLE form) {
+  FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
+  FORM_OnBeforeClosePage(page, form);
+  FPDF_ClosePage(page);
+}
diff --git a/testing/embedder_test.h b/testing/embedder_test.h
new file mode 100644 (file)
index 0000000..48ea415
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (c) 2015 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_EMBEDDER_TEST_H_
+#define TESTING_EMBEDDER_TEST_H_
+
+#include <string>
+
+#include "../core/include/fxcrt/fx_system.h"
+#include "../fpdfsdk/include/fpdf_dataavail.h"
+#include "../fpdfsdk/include/fpdfformfill.h"
+#include "../fpdfsdk/include/fpdfview.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "v8/include/v8.h"
+
+class TestLoader;
+
+// This class is used to load a PDF document, and then run programatic
+// API tests against it.
+class EmbedderTest : public ::testing::Test {
+ public:
+  EmbedderTest() :
+      document_(nullptr),
+      avail_(nullptr),
+      loader_(nullptr),
+      file_length_(0),
+      file_contents_(nullptr) {
+    memset(&hints_, 0, sizeof(hints_));
+    memset(&file_access_, 0, sizeof(file_access_));
+    memset(&file_avail_, 0, sizeof(file_avail_));
+  }
+
+  virtual ~EmbedderTest() { }
+
+  void SetUp() override;
+  void TearDown() override;
+
+  FPDF_DOCUMENT document() { return document_; }
+
+  // Open the document specified by |filename|, or return false on failure.
+  virtual bool OpenDocument(const std::string& filename);
+
+  // Create and return a handle to the form fill module for use with the
+  // FORM_ family of functions from fpdfformfill.h, or return NULL on failure.
+  virtual FPDF_FORMHANDLE SetFormFillEnvironment();
+
+  // Release the resources obtained from SetFormFillEnvironment().
+  virtual void ClearFormFillEnvironment(FPDF_FORMHANDLE form);
+
+  // Perform JavaScript actions that are to run at document open time.
+  virtual void DoOpenActions(FPDF_FORMHANDLE form);
+
+  // Determine the page numbers present in the document.
+  virtual int GetFirstPageNum();
+  virtual int GetPageCount();
+
+  // Load a specific page of the open document.
+  virtual FPDF_PAGE LoadPage(int page_number, FPDF_FORMHANDLE form);
+
+  // Convert a loaded page into a bitmap.
+  virtual FPDF_BITMAP RenderPage(FPDF_PAGE page, FPDF_FORMHANDLE form);
+
+  // Relese the resources obtained from LoadPage(). Further use of |page|
+  // is prohibited after this call is made.
+  virtual void UnloadPage(FPDF_PAGE page, FPDF_FORMHANDLE form);
+
+ private:
+  FPDF_DOCUMENT document_;
+  FPDF_AVAIL avail_;
+  FX_DOWNLOADHINTS hints_;
+  FPDF_FILEACCESS file_access_;
+  FX_FILEAVAIL file_avail_;
+  v8::StartupData natives_;
+  v8::StartupData snapshot_;
+  TestLoader* loader_;
+  size_t file_length_;
+  char* file_contents_;
+};
+
+#endif  // TESTING_EMBEDDER_TEST_H_
+
diff --git a/testing/resources/about_blank.pdf b/testing/resources/about_blank.pdf
new file mode 100644 (file)
index 0000000..d640582
Binary files /dev/null and b/testing/resources/about_blank.pdf differ
index 70e46e6..e70d3f6 100644 (file)
@@ -28,7 +28,7 @@ CFWL_AppImp::CFWL_AppImp(IFWL_AdapterNative *pAdapter)
 }\r
 CFWL_AppImp::~CFWL_AppImp()\r
 {\r
-    delete CFWL_ToolTipContainer::getInstance();\r
+    CFWL_ToolTipContainer::DeleteInstance();\r
     if (m_bFuelAdapter) {\r
         FWL_ReleaseFuelAdapterNative(m_pAdapterNative);\r
         m_pAdapterNative = NULL;\r
index 40f0c11..417020a 100644 (file)
@@ -938,6 +938,9 @@ FX_BOOL CFWL_EventTarget::IsFilterEvent(CFWL_Event *pEvent, FX_DWORD dwFilter)
     }\r
     return bRet;\r
 }\r
+\r
+CFWL_ToolTipContainer* CFWL_ToolTipContainer::s_pInstance = NULL;\r
+\r
 CFWL_ToolTipContainer::CFWL_ToolTipContainer()\r
     : pCurTarget(NULL)\r
     , m_pToolTipImp(NULL)\r
@@ -959,13 +962,21 @@ CFWL_ToolTipContainer::~CFWL_ToolTipContainer()
         m_ToolTipDp = NULL;\r
     }\r
 }\r
+// static\r
 CFWL_ToolTipContainer* CFWL_ToolTipContainer::getInstance()\r
 {\r
-    static CFWL_ToolTipContainer * _toolTipContainer = NULL;\r
-    if (!_toolTipContainer) {\r
-        _toolTipContainer = FX_NEW CFWL_ToolTipContainer;\r
+    if (!s_pInstance) {\r
+        s_pInstance = FX_NEW CFWL_ToolTipContainer;\r
+    }\r
+    return s_pInstance;\r
+}\r
+// static\r
+void CFWL_ToolTipContainer::DeleteInstance()\r
+{\r
+    if (s_pInstance) {\r
+        delete s_pInstance;\r
+        s_pInstance = NULL;\r
     }\r
-    return _toolTipContainer;\r
 }\r
 FX_ERR CFWL_ToolTipContainer::AddToolTipTarget(IFWL_ToolTipTarget *pTarget)\r
 {\r
index 1e72392..aeed0b3 100644 (file)
@@ -127,8 +127,8 @@ protected:
 class CFWL_ToolTipContainer: public CFX_Object\r
 {\r
 public:\r
-    virtual ~CFWL_ToolTipContainer();\r
     static CFWL_ToolTipContainer* getInstance();\r
+    static void DeleteInstance();\r
 \r
     FX_ERR             AddToolTipTarget(IFWL_ToolTipTarget *pTarget);\r
     FX_ERR             RemoveToolTipTarget(IFWL_ToolTipTarget *pTarget);\r
@@ -140,13 +140,18 @@ public:
     FX_BOOL ProcessLeave(CFWL_EvtMouse *pEvt);\r
 \r
     FX_ERR  SetToolTipInitialDelay(FX_INT32 iDelayTime);\r
-    FX_ERR     SetToolTipAutoPopDelay(FX_INT32 iDelayTime);\r
+    FX_ERR  SetToolTipAutoPopDelay(FX_INT32 iDelayTime);\r
+\r
 protected:\r
     CFWL_ToolTipContainer();\r
+    virtual ~CFWL_ToolTipContainer();\r
 \r
     IFWL_ToolTipTarget         *pCurTarget;\r
     CFWL_ToolTipImp                    *m_pToolTipImp;\r
     CFWL_CoreToopTipDP         *m_ToolTipDp;\r
     CFX_PtrArray                       m_arrWidget;\r
+\r
+private:\r
+    static CFWL_ToolTipContainer* s_pInstance;\r
 };\r
 #endif\r
index e406f6a..0a1b0db 100644 (file)
@@ -14,6 +14,9 @@ static void FXJSE_KillV8()
 }\r
 void FXJSE_Initialize()\r
 {\r
+    if(!CFXJSE_RuntimeData::g_RuntimeList) {\r
+        CFXJSE_RuntimeData::g_RuntimeList = FX_NEW CFXJSE_RuntimeList;\r
+    }\r
     static FX_BOOL bV8Initialized = FALSE;\r
     if (bV8Initialized) {\r
         return;\r
@@ -26,12 +29,9 @@ void FXJSE_Initialize()
         ;\r
     v8::V8::SetFlagsFromString(szCmdFlags, FXSYS_strlen(szCmdFlags));\r
     v8::V8::InitializeICU();\r
-       v8::Platform* platform = v8::platform::CreateDefaultPlatform();\r
-       v8::V8::InitializePlatform(platform);\r
+    v8::Platform* platform = v8::platform::CreateDefaultPlatform();\r
+    v8::V8::InitializePlatform(platform);\r
     v8::V8::Initialize();\r
-    if(!CFXJSE_RuntimeData::g_RuntimeList) {\r
-        CFXJSE_RuntimeData::g_RuntimeList = FX_NEW CFXJSE_RuntimeList;\r
-    }\r
 }\r
 static void FXJSE_Runtime_DisposeCallback(v8::Isolate* pIsolate)\r
 {\r