Merge pull request #1634 from ONLYOFFICE/fix/docbuilder-snapshots

Some small fixes in snapshot related code
This commit is contained in:
Oleg Korshul
2024-08-29 04:27:53 -07:00
committed by GitHub
7 changed files with 261 additions and 249 deletions

View File

@ -1086,7 +1086,7 @@ namespace NSDoctRenderer
void CDoctrenderer::CreateSnapshots()
{
#ifdef V8_VERSION_89_PLUS
#ifdef V8_SUPPORT_SNAPSHOTS
std::vector<NSDoctRenderer::DoctRendererEditorType> editors;
editors.push_back(NSDoctRenderer::DoctRendererEditorType::WORD);
editors.push_back(NSDoctRenderer::DoctRendererEditorType::SLIDE);

View File

@ -27,6 +27,7 @@ HEADERS += \
docbuilder.h
SOURCES += \
editors.cpp \
nativecontrol.cpp \
doctrenderer.cpp \
docbuilder.cpp \

View File

@ -0,0 +1,249 @@
#include "./editors.h"
#include "../common/StringBuilder.h"
namespace NSDoctRenderer
{
namespace
{
void AppendScript(NSStringUtils::CStringBuilderA* builder, const std::wstring& path)
{
NSFile::CFileBinary oFile;
if (!oFile.OpenFile(path))
return;
int size = (int)oFile.GetFileSize();
if (size < 3)
return;
BYTE* pData = new BYTE[size];
DWORD dwReadSize = 0;
oFile.ReadFile(pData, (DWORD)size, dwReadSize);
oFile.CloseFile();
int nOffset = 0;
if (pData[0] == 0xEF && pData[1] == 0xBB && pData[2] == 0xBF)
nOffset = 3;
builder->WriteString((char*)(pData + nOffset), size - nOffset);
builder->WriteString("\n\n");
RELEASEARRAYOBJECTS(pData);
}
bool RunScript(JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, const std::wstring& path)
{
NSFile::CFileBinary oFile;
if (!oFile.OpenFile(path))
return false;
int size = (int)oFile.GetFileSize();
if (size < 3)
return false;
BYTE* pData = new BYTE[size];
DWORD dwReadSize = 0;
oFile.ReadFile(pData, (DWORD)size, dwReadSize);
oFile.CloseFile();
int nOffset = 0;
if (pData[0] == 0xEF && pData[1] == 0xBB && pData[2] == 0xBF)
nOffset = 3;
context->runScript(std::string((char*)(pData + nOffset), size - nOffset), try_catch);
RELEASEARRAYOBJECTS(pData);
return !try_catch->Check();
}
std::wstring GetAllScript(NSStringUtils::CStringBuilderA* builder, const DoctRendererEditorType& type, CDoctRendererConfig* config, const bool& isSnapshot = false)
{
for (std::vector<std::wstring>::const_iterator i = config->m_arrFiles.cbegin(); i != config->m_arrFiles.cend(); i++)
AppendScript(builder, *i);
std::wstring sFontsPath = config->m_strSdkPath + L"/common/libfont/engine";
#ifdef SUPPORT_HARFBUZZ_SHAPER
sFontsPath += L"/fonts_native.js";
#else
sFontsPath += L"/fonts_ie.js";
#endif
std::wstring sCachePath = L"";
switch (type)
{
case DoctRendererEditorType::WORD:
{
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all.js");
sCachePath = config->m_strSdkPath + L"/word/sdk-all";
break;
}
case DoctRendererEditorType::SLIDE:
{
AppendScript(builder, config->m_strSdkPath + L"/slide/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/slide/sdk-all.js");
sCachePath = config->m_strSdkPath + L"/slide/sdk-all";
break;
}
case DoctRendererEditorType::CELL:
{
AppendScript(builder, config->m_strSdkPath + L"/cell/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/cell/sdk-all.js");
builder->WriteString("\n$.ready();", 11);
sCachePath = config->m_strSdkPath + L"/cell/sdk-all";
break;
}
case DoctRendererEditorType::VISIO:
{
if (!NSFile::CFileBinary::Exists(config->m_strSdkPath + L"/draw/sdk-all-min.js"))
return L"";
AppendScript(builder, config->m_strSdkPath + L"/draw/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/draw/sdk-all.js");
sCachePath = config->m_strSdkPath + L"/draw/sdk-all";
break;
}
case DoctRendererEditorType::PDF:
{
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all.js");
AppendScript(builder, config->m_strSdkPath + L"/pdf/src/engine/drawingfile_native.js");
sCachePath = config->m_strSdkPath + L"/pdf/sdk-all";
break;
}
default:
break;
}
if (!sCachePath.empty())
sCachePath += (isSnapshot ? L".bin" : L".cache");
return sCachePath;
}
std::wstring GetSnapshotPath(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
std::wstring sCachePath = L"";
switch (type)
{
case DoctRendererEditorType::WORD:
{
return config->m_strSdkPath + L"/word/sdk-all.bin";
}
case DoctRendererEditorType::SLIDE:
{
return config->m_strSdkPath + L"/slide/sdk-all.bin";
}
case DoctRendererEditorType::CELL:
{
return config->m_strSdkPath + L"/cell/sdk-all.bin";
}
case DoctRendererEditorType::VISIO:
{
return config->m_strSdkPath + L"/draw/sdk-all.bin";
}
case DoctRendererEditorType::PDF:
{
return config->m_strSdkPath + L"/pdf/sdk-all.bin";
}
default:
break;
}
return L"";
}
bool RunEditorFooter(JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, CDoctRendererConfig* config)
{
if (!RunScript(context, try_catch, config->m_strAllFonts))
return false;
std::string sFooter = "window.InitNativeEditors();";
if (context->isSnapshotUsed())
{
sFooter += "\
if (undefined === String.prototype.replaceAll)\
{\
String.prototype.replaceAll = function(str, newStr)\
{\
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]')\
return this.replace(str, newStr);\
return this.split(str).join(newStr);\
};\
}\n";
}
context->runScript(sFooter, try_catch);
return !try_catch->Check();
}
} // namespace
bool RunEditor(const DoctRendererEditorType& type, JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, CDoctRendererConfig* config)
{
if (context->isSnapshotUsed())
return RunEditorFooter(context, try_catch, config);
NSStringUtils::CStringBuilderA builder;
builder.AddSize(10 * 1024 * 1024);
std::wstring sCachePath = GetAllScript(&builder, type, config);
if (!sCachePath.empty())
{
context->runScript(builder.GetData(), try_catch, config->m_bIsUseCache ? sCachePath : L"");
RunEditorFooter(context, try_catch, config);
}
return !try_catch->Check();
}
bool GenerateEditorSnapshot(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
NSStringUtils::CStringBuilderA builder;
builder.AddSize(10 * 1024 * 1024);
std::wstring sCachePath = GetAllScript(&builder, type, config, true);
builder.WriteString("delete String.prototype.replaceAll;");
if (sCachePath.empty())
return false;
return NSJSBase::CJSContext::generateSnapshot(builder.GetData(), sCachePath);
}
namespace
{
JSSmart<NSJSBase::CJSContext> RunEditorWithSnapshot(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
#ifndef V8_SUPPORT_SNAPSHOTS
return NULL;
#endif
std::wstring sCachePath = GetSnapshotPath(type, config);
if (!NSFile::CFileBinary::Exists(sCachePath))
return NULL;
if (sCachePath.empty())
return NULL;
JSSmart<NSJSBase::CJSContext> context = new NSJSBase::CJSContext(false);
context->Initialize(sCachePath);
return context;
}
} // namespace
JSSmart<NSJSBase::CJSContext> CreateEditorContext(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
JSSmart<NSJSBase::CJSContext> context = RunEditorWithSnapshot(type, config);
if (context.is_init())
return context;
return new NSJSBase::CJSContext();
}
} // namespace NSDoctRenderer

View File

@ -34,7 +34,6 @@
#include "./config.h"
#include "../js_internal/js_base.h"
#include "../common/StringBuilder.h"
#ifdef CreateFile
#undef CreateFile
@ -53,246 +52,11 @@ namespace NSDoctRenderer
INVALID = 255
};
static void AppendScript(NSStringUtils::CStringBuilderA* builder, const std::wstring& path)
{
NSFile::CFileBinary oFile;
bool RunEditor(const DoctRendererEditorType& type, JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, CDoctRendererConfig* config);
if (!oFile.OpenFile(path))
return;
bool GenerateEditorSnapshot(const DoctRendererEditorType& type, CDoctRendererConfig* config);
int size = (int)oFile.GetFileSize();
if (size < 3)
return;
BYTE* pData = new BYTE[size];
DWORD dwReadSize = 0;
oFile.ReadFile(pData, (DWORD)size, dwReadSize);
oFile.CloseFile();
int nOffset = 0;
if (pData[0] == 0xEF && pData[1] == 0xBB && pData[2] == 0xBF)
nOffset = 3;
builder->WriteString((char*)(pData + nOffset), size - nOffset);
builder->WriteString("\n\n");
RELEASEARRAYOBJECTS(pData);
}
static bool RunScript(JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, const std::wstring& path)
{
NSFile::CFileBinary oFile;
if (!oFile.OpenFile(path))
return false;
int size = (int)oFile.GetFileSize();
if (size < 3)
return false;
BYTE* pData = new BYTE[size];
DWORD dwReadSize = 0;
oFile.ReadFile(pData, (DWORD)size, dwReadSize);
oFile.CloseFile();
int nOffset = 0;
if (pData[0] == 0xEF && pData[1] == 0xBB && pData[2] == 0xBF)
nOffset = 3;
context->runScript(std::string((char*)(pData + nOffset), size - nOffset), try_catch);
RELEASEARRAYOBJECTS(pData);
return !try_catch->Check();
}
static std::wstring GetAllScript(NSStringUtils::CStringBuilderA* builder, const DoctRendererEditorType& type, CDoctRendererConfig* config, const bool& isSnapshot = false)
{
for (std::vector<std::wstring>::const_iterator i = config->m_arrFiles.cbegin(); i != config->m_arrFiles.cend(); i++)
AppendScript(builder, *i);
std::wstring sFontsPath = config->m_strSdkPath + L"/common/libfont/engine";
#ifdef SUPPORT_HARFBUZZ_SHAPER
sFontsPath += L"/fonts_native.js";
#else
sFontsPath += L"/fonts_ie.js";
#endif
std::wstring sCachePath = L"";
switch (type)
{
case DoctRendererEditorType::WORD:
{
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all.js");
sCachePath = config->m_strSdkPath + L"/word/sdk-all";
break;
}
case DoctRendererEditorType::SLIDE:
{
AppendScript(builder, config->m_strSdkPath + L"/slide/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/slide/sdk-all.js");
sCachePath = config->m_strSdkPath + L"/slide/sdk-all";
break;
}
case DoctRendererEditorType::CELL:
{
AppendScript(builder, config->m_strSdkPath + L"/cell/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/cell/sdk-all.js");
builder->WriteString("\n$.ready();", 11);
sCachePath = config->m_strSdkPath + L"/cell/sdk-all";
break;
}
case DoctRendererEditorType::VISIO:
{
if (!NSFile::CFileBinary::Exists(config->m_strSdkPath + L"/draw/sdk-all-min.js"))
return L"";
AppendScript(builder, config->m_strSdkPath + L"/draw/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/draw/sdk-all.js");
sCachePath = config->m_strSdkPath + L"/draw/sdk-all";
break;
}
case DoctRendererEditorType::PDF:
{
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all-min.js");
AppendScript(builder, sFontsPath);
AppendScript(builder, config->m_strSdkPath + L"/word/sdk-all.js");
AppendScript(builder, config->m_strSdkPath + L"/pdf/src/engine/drawingfile_native.js");
sCachePath = config->m_strSdkPath + L"/pdf/sdk-all";
break;
}
default:
break;
}
if (!sCachePath.empty())
sCachePath += (isSnapshot ? L".bin" : L".cache");
return sCachePath;
}
static std::wstring GetSnapshotPath(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
std::wstring sCachePath = L"";
switch (type)
{
case DoctRendererEditorType::WORD:
{
return config->m_strSdkPath + L"/word/sdk-all.bin";
}
case DoctRendererEditorType::SLIDE:
{
return config->m_strSdkPath + L"/slide/sdk-all.bin";
}
case DoctRendererEditorType::CELL:
{
return config->m_strSdkPath + L"/cell/sdk-all.bin";
}
case DoctRendererEditorType::VISIO:
{
return config->m_strSdkPath + L"/draw/sdk-all.bin";
}
case DoctRendererEditorType::PDF:
{
return config->m_strSdkPath + L"/pdf/sdk-all.bin";
}
default:
break;
}
return L"";
}
static bool RunEditorFooter(JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, CDoctRendererConfig* config)
{
if (!RunScript(context, try_catch, config->m_strAllFonts))
return false;
std::string sFooter = "window.InitNativeEditors();";
if (context->isSnapshotUsed())
{
sFooter += "\
if (undefined === String.prototype.replaceAll)\
{\
String.prototype.replaceAll = function(str, newStr)\
{\
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]')\
return this.replace(str, newStr);\
return this.split(str).join(newStr);\
};\
}\n";
}
context->runScript(sFooter, try_catch);
return !try_catch->Check();
}
static bool RunEditor(const DoctRendererEditorType& type, JSSmart<NSJSBase::CJSContext>& context, JSSmart<NSJSBase::CJSTryCatch>& try_catch, CDoctRendererConfig* config)
{
if (context->isSnapshotUsed())
return RunEditorFooter(context, try_catch, config);
NSStringUtils::CStringBuilderA builder;
builder.AddSize(10 * 1024 * 1024);
std::wstring sCachePath = GetAllScript(&builder, type, config);
if (!sCachePath.empty())
{
context->runScript(builder.GetData(), try_catch, config->m_bIsUseCache ? sCachePath : L"");
RunEditorFooter(context, try_catch, config);
}
return !try_catch->Check();
}
static bool GenerateEditorSnapshot(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
NSStringUtils::CStringBuilderA builder;
builder.AddSize(10 * 1024 * 1024);
std::wstring sCachePath = GetAllScript(&builder, type, config, true);
builder.WriteString("delete String.prototype.replaceAll;");
if (sCachePath.empty())
return false;
return NSJSBase::CJSContext::generateSnapshot(builder.GetData(), sCachePath);
}
static JSSmart<NSJSBase::CJSContext> RunEditorWithSnapshot(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
#ifndef V8_VERSION_89_PLUS
return NULL;
#endif
#ifndef V8_SUPPORT_SNAPSHOTS
return NULL;
#endif
std::wstring sCachePath = GetSnapshotPath(type, config);
if (!NSFile::CFileBinary::Exists(sCachePath))
return NULL;
if (sCachePath.empty())
return NULL;
JSSmart<NSJSBase::CJSContext> context = new NSJSBase::CJSContext(false);
context->Initialize(sCachePath);
return context;
}
static JSSmart<NSJSBase::CJSContext> CreateEditorContext(const DoctRendererEditorType& type, CDoctRendererConfig* config)
{
JSSmart<NSJSBase::CJSContext> context = RunEditorWithSnapshot(type, config);
if (context.is_init())
return context;
return new NSJSBase::CJSContext();
}
JSSmart<NSJSBase::CJSContext> CreateEditorContext(const DoctRendererEditorType& type, CDoctRendererConfig* config);
}
#endif // DOC_BUILDER_EDITORS_CONFIG

View File

@ -490,7 +490,6 @@ namespace NSJSBase
/**
* Generate snapshot by script.
* @param script The script to be executed.
* @param exception The object for handling exceptions.
* @param snapshotPath The path to the snapshot
* @return Returns true whether a snapshot has been created.
*/

View File

@ -192,7 +192,7 @@ namespace NSJSBase
{
if (m_internal->m_isolate == NULL)
{
#ifdef V8_VERSION_89_PLUS
#ifdef V8_SUPPORT_SNAPSHOTS
if (!snapshotPath.empty())
{
BYTE* data = NULL;
@ -411,9 +411,9 @@ namespace NSJSBase
bool CJSContext::generateSnapshot(const std::string& script, const std::wstring& snapshotPath)
{
#ifdef V8_VERSION_89_PLUS
#ifdef V8_SUPPORT_SNAPSHOTS
bool result = false;
// snapshot creator should be in its own scope, because it handles entering, exiting and disposing the isolate
// Snapshot creator should be in its own scope, because it handles entering, exiting and disposing the isolate
v8::SnapshotCreator snapshotCreator;
v8::Isolate* isolate = snapshotCreator.GetIsolate();
{
@ -422,8 +422,7 @@ namespace NSJSBase
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
// Trying to handle compile & run errors:
// window
// Handle compile & run errors
v8::Local<v8::Object> global = context->Global();
global->Set(context, v8::String::NewFromUtf8Literal(isolate, "window"), global).Check();
global->Set(context, v8::String::NewFromUtf8Literal(isolate, "self"), global).Check();
@ -433,11 +432,11 @@ namespace NSJSBase
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, script.c_str()).ToLocalChecked();
v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
bool isEmpty = script->Run(context).IsEmpty();
script->Run(context).IsEmpty();
snapshotCreator.SetDefaultContext(context);
}
v8::StartupData data = snapshotCreator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
// Save snapshot to file
NSFile::CFileBinary snapshotFile;
if (data.data && snapshotFile.CreateFile(snapshotPath))
{

View File

@ -200,7 +200,7 @@ public:
nMaxVirtualMemory);
#endif
#ifdef V8_VERSION_89_PLUS
#ifdef V8_SUPPORT_SNAPSHOTS
create_params.snapshot_blob = startupData;
#endif