diff --git a/DesktopEditor/doctrenderer/js_internal/js_base.cpp b/DesktopEditor/doctrenderer/js_internal/js_base.cpp index 3382574845..e25d025e23 100644 --- a/DesktopEditor/doctrenderer/js_internal/js_base.cpp +++ b/DesktopEditor/doctrenderer/js_internal/js_base.cpp @@ -56,10 +56,10 @@ namespace NSJSBase { void CJSContext::AddEmbedCreator(const std::string& name, EmbedObjectCreator creator, - const IsolateAdditionalDataType& type) + const bool& isAllowedInJS) { CEmbedObjectRegistrator& oRegistrator = CEmbedObjectRegistrator::getInstance(); - oRegistrator.Register(name, creator, type); + oRegistrator.Register(name, creator, isAllowedInJS); } CJSObject::CJSObject() @@ -149,6 +149,12 @@ namespace NSJSBase { JSSmart CJSContext::createEmbedObject(const std::string& name) { + // Allow creation for embedded class in JS while in current scope + CEmbedObjectRegistrator& oRegistrator = CEmbedObjectRegistrator::getInstance(); + JSSmart oCreationScope = oRegistrator.AllowCreationInScope(name); + if (!oCreationScope.IsInit()) + return nullptr; + // Call CreateEmbedObject() from JS JSSmart context = CJSContext::GetCurrent(); JSSmart args[1]; args[0] = CJSContext::createString(name); diff --git a/DesktopEditor/doctrenderer/js_internal/js_base.h b/DesktopEditor/doctrenderer/js_internal/js_base.h index 765ede92e9..b5764aaa5c 100644 --- a/DesktopEditor/doctrenderer/js_internal/js_base.h +++ b/DesktopEditor/doctrenderer/js_internal/js_base.h @@ -423,16 +423,6 @@ namespace NSJSBase using EmbedObjectCreator = CJSEmbedObject* (*)(); - /** - * Used to specify creation mode for an embedded object. - * By default the creation mode is iadtUndefined. - */ - enum IsolateAdditionalDataType { - iadtSingletonNative = 0, - iadtUndefined = 1, - iadtNone = 2 - }; - /** * The class for getting JS context instance for working with it. */ @@ -480,12 +470,13 @@ namespace NSJSBase /** * Embeds specified class in JS contexts. * @tparam T Embedded class name. - * @param type Specifies how an object of the embedded class will be created. + * @param isAllowedInJS If true, user can create the embedded object instance from JS code using CreateEmbedObject(). + * If this parameter is false, then user can do so only using JSContext::createEmbedObject(). */ template - static void Embed(const IsolateAdditionalDataType& type = iadtUndefined) + static void Embed(const bool& isAllowedInJS = true) { - AddEmbedCreator(T::getName(), T::getCreator, type); + AddEmbedCreator(T::getName(), T::getCreator, isAllowedInJS); } /** @@ -515,9 +506,9 @@ namespace NSJSBase * Adds a creator object for corresponding embedded class name. * @param name The name of an embedded class. * @param creator The creator function for an embedded class. - * @param type The type of an embedded object being created. + * @param isAllowedInJS Specifies whether user can create the embedded object from JS code or not. */ - static void AddEmbedCreator(const std::string& name, EmbedObjectCreator creator, const IsolateAdditionalDataType& type = iadtUndefined); + static void AddEmbedCreator(const std::string& name, EmbedObjectCreator creator, const bool& isAllowedInJS = true); public: /** diff --git a/DesktopEditor/doctrenderer/js_internal/js_base_p.h b/DesktopEditor/doctrenderer/js_internal/js_base_p.h index d0244d6d32..fc7e64deed 100644 --- a/DesktopEditor/doctrenderer/js_internal/js_base_p.h +++ b/DesktopEditor/doctrenderer/js_internal/js_base_p.h @@ -11,18 +11,37 @@ public: { public: NSJSBase::EmbedObjectCreator m_creator; - NSJSBase::IsolateAdditionalDataType m_type; + bool m_bIsCreationAllowed; - CEmdedClassInfo(NSJSBase::EmbedObjectCreator creator, const NSJSBase::IsolateAdditionalDataType& type = NSJSBase::iadtUndefined) + CEmdedClassInfo(NSJSBase::EmbedObjectCreator creator, const bool& bIsCreationAllowed = true) { m_creator = creator; - m_type = type; + m_bIsCreationAllowed = bIsCreationAllowed; + } + }; + + using store_t = std::map; + + class CAllowedCreationScope + { + private: + store_t::iterator m_oIter; + bool m_bPrev; + + public: + CAllowedCreationScope(const store_t::iterator& iter) : m_oIter(iter) + { + m_bPrev = m_oIter->second.m_bIsCreationAllowed; + m_oIter->second.m_bIsCreationAllowed = true; + } + + ~CAllowedCreationScope() + { + m_oIter->second.m_bIsCreationAllowed = m_bPrev; } }; public: - using store_t = std::map; - store_t m_infos; private: @@ -31,9 +50,17 @@ private: public: void Register(const std::string& name, NSJSBase::EmbedObjectCreator creator, - const NSJSBase::IsolateAdditionalDataType& type = NSJSBase::iadtUndefined) + const bool& bIsCreationAllowed = true) { - m_infos.insert(std::pair(name, CEmdedClassInfo(creator, type))); + m_infos.insert(std::pair(name, CEmdedClassInfo(creator, bIsCreationAllowed))); + } + + CAllowedCreationScope* AllowCreationInScope(const std::string& name) + { + store_t::iterator iter = m_infos.find(name); + if (iter == m_infos.end()) + return nullptr; + return new CAllowedCreationScope(iter); } static CEmbedObjectRegistrator& getInstance() diff --git a/DesktopEditor/doctrenderer/js_internal/v8/v8_base.cpp b/DesktopEditor/doctrenderer/js_internal/v8/v8_base.cpp index ad2b5447cb..1666f426a0 100644 --- a/DesktopEditor/doctrenderer/js_internal/v8/v8_base.cpp +++ b/DesktopEditor/doctrenderer/js_internal/v8/v8_base.cpp @@ -531,11 +531,11 @@ namespace NSJSBase CEmbedObjectRegistrator::CEmdedClassInfo& oInfo = itFound->second; - if (oInfo.m_type == NSJSBase::iadtNone) + if (oInfo.m_bIsCreationAllowed == false) + { + args.GetReturnValue().Set(v8::Undefined(isolate)); return; - - if (oInfo.m_type == NSJSBase::iadtSingletonNative) - oInfo.m_type = NSJSBase::iadtNone; + } CJSEmbedObject* pNativeObj = oInfo.m_creator(); v8::Local oCurTemplate; diff --git a/DesktopEditor/doctrenderer/test/internal/main.cpp b/DesktopEditor/doctrenderer/test/internal/main.cpp index cc8848d99e..bf1d7156ba 100644 --- a/DesktopEditor/doctrenderer/test/internal/main.cpp +++ b/DesktopEditor/doctrenderer/test/internal/main.cpp @@ -214,19 +214,32 @@ int main(int argc, char *argv[]) // External CTestEmbed CJSContextScope scope(oContext1); - CJSContext::Embed(); + CJSContext::Embed(false); JSSmart oResTestEmbed1 = oContext1->runScript("(function() { var value = CreateEmbedObject('CTestEmbed'); return value.FunctionSum(10, 5); })();"); - std::cout << "FunctionSum(10, 5) = " << oResTestEmbed1->toInt32() << std::endl; + if (oResTestEmbed1->isNumber()) + std::cout << "FunctionSum(10, 5) = " << oResTestEmbed1->toInt32() << std::endl; - JSSmart oResTestEmbed2 = oContext1->runScript("(function() { var value = CreateEmbedObject('CTestEmbed'); return value.FunctionSquare(4); })();"); - std::cout << "FunctionSquare(4) = " << oResTestEmbed2->toInt32() << std::endl; + JSSmart oTestEmbed = CJSContext::createEmbedObject("CTestEmbed"); - JSSmart oResTestEmbed3 = oContext1->runScript("(function() { var value = CreateEmbedObject('CTestEmbed'); return value.FunctionDel(30, 3); })();"); - std::cout << "FunctionDel(30, 3) = " << oResTestEmbed3->toInt32() << std::endl; +// JSSmart oResTestEmbed2 = oContext1->runScript("(function() { var value = CreateEmbedObject('CTestEmbed'); return value.FunctionSquare(4); })();"); + JSSmart args2[1]; + args2[0] = CJSContext::createInt(4); + JSSmart oResTestEmbed2 = oTestEmbed->call_func("FunctionSquare", 1, args2); + if (oResTestEmbed2->isNumber()) + std::cout << "FunctionSquare(4) = " << oResTestEmbed2->toInt32() << std::endl; + +// JSSmart oResTestEmbed3 = oContext1->runScript("(function() { var value = CreateEmbedObject('CTestEmbed'); return value.FunctionDel(30, 3); })();"); + JSSmart args3[2]; + args3[0] = CJSContext::createInt(30); + args3[1] = CJSContext::createInt(3); + JSSmart oResTestEmbed3 = oTestEmbed->call_func("FunctionDel", 2, args3); + if (oResTestEmbed3->isNumber()) + std::cout << "FunctionDel(30, 3) = " << oResTestEmbed3->toInt32() << std::endl; JSSmart oResTestEmbed4 = oContext1->runScript("(function() { var value = CreateEmbedObject('CTestEmbed'); return value.FunctionGet(); })();"); - std::cout << "FunctionGet() = " << oResTestEmbed4->toInt32() << std::endl; + if (oResTestEmbed4->isNumber()) + std::cout << "FunctionGet() = " << oResTestEmbed4->toInt32() << std::endl; // Internal CHashEmbed CreateDefaults();