आपको जावास्क्रिप्ट इंजन स्विचर 3.0 के बारे में क्या पता होना चाहिए

डीलक्स इंजन स्विचर के तीसरे संस्करण के लोगो के लिए


जावास्क्रिप्ट इंजन स्विचर मूल रूप से एक सहायक पुस्तकालय के रूप में बनाया गया था और इसका विकास काफी हद तक पुस्तकालयों की जरूरतों से निर्धारित होता था जो इसका उपयोग करते थे। वास्तव में, इसके प्रत्येक प्रमुख संस्करण ने अन्य पुस्तकालयों के आगे विकास के लिए आवश्यक एक या कई प्रमुख कार्यों को हल किया:


  1. पहले संस्करण में, यह कार्य लोकप्रिय जेएस इंजनों के लिए अधिक से अधिक एडेप्टर मॉड्यूल जोड़ना था जो .NET प्लेटफ़ॉर्म का यथासंभव समर्थन करते हैं। और इसने बंडल ट्रांसफ़ॉर्मर उपयोगकर्ताओं को कुछ लचीलापन दिया: डेवलपर के कंप्यूटर पर, वे MSIE मॉड्यूल का उपयोग कर सकते हैं जो विज़ुअल स्टूडियो का उपयोग करके जेएस कोड के डिबगिंग का समर्थन करता है, और उन सर्वरों पर जिनके पास इंटरनेट एक्सप्लोरर का आधुनिक संस्करण नहीं था या यह बिल्कुल भी स्थापित नहीं था, वे उपयोग कर सकते थे V8 मॉड्यूल। कुछ ने भी जुरासिक और जिंट मॉड्यूल का उपयोग करके मोनो और लिनक्स पर मोनो में बंडल ट्रांसफार्मर को चलाने में कामयाब रहे।
  2. दूसरे संस्करण का मुख्य कार्य .NET कोर समर्थन का कार्यान्वयन था, जिसे ReactJS.NET पुस्तकालय के नए संस्करण के लिए आवश्यक था। एक अन्य महत्वपूर्ण कार्य एक क्रॉस-प्लेटफ़ॉर्म मॉड्यूल का निर्माण था जो बड़ी मात्रा में जेएस कोड को संसाधित कर सकता है (जुरासिक और जिंट मॉड्यूल इसके लिए उपयुक्त नहीं थे), और कई सुधारों के बाद चक्रकोर मॉड्यूल एक ऐसा मॉड्यूल बन गया।
  3. तीसरे संस्करण में, मुख्य फोकस ReactJS.NET पुस्तकालय के साथ एकीकरण में सुधार और उत्पादकता में सुधार पर था।

इस लेख में, हम तीसरे संस्करण के कुछ नवाचारों पर विचार करेंगे, जिनमें से कई रिलीज़ टेक्स्ट और डॉक्यूमेंटेशन खंड "एप्लिकेशन को संस्करण 3.X में अपग्रेड कैसे करें" को पढ़ने के बाद भी JsEngineSwitcher : JsEngineSwitcher वर्ग में परिवर्तन, अपवादों का पुनर्गठन, अधिक जानकारीपूर्ण त्रुटि संदेश, रुकावट। और लिपियों का प्रारंभिक संकलन, चक्रकोर और MSIE मॉड्यूल में अधिकतम स्टैक आकार को बदलने की क्षमता, साथ ही NiL.JS पर आधारित एक नया मॉड्यूल।


JsEngineSwitcher वर्ग में परिवर्तन


नए संस्करण में, JsEngineSwitcher वर्ग IJsEngineSwitcher इंटरफ़ेस लागू करता है और अब एक सिंगलटन नहीं है (आप new ऑपरेटर का उपयोग करके इसे तुरंत कर सकते हैं)। एक वैश्विक उदाहरण प्राप्त करने के लिए, Instance संपत्ति के बजाय, Current संपत्ति का उपयोग करें। Current संपत्ति, IJsEngineSwitcher गए Instance गुण के विपरीत, वापसी प्रकार IJsEngineSwitcher । इसके अलावा, Current संपत्ति में एक सेटर है, जिसके साथ आप मानक कार्यान्वयन को अपने स्वयं के साथ बदल सकते हैं:


 JsEngineSwitcher.Current = new MyJsEngineSwitcher(); 

ASP.NET कोर वेब अनुप्रयोगों में जहां JavaScriptEngineSwitcher.Extensions.MsD AddJsEngineSwitcher स्थापित है, इसे AddJsEngineSwitcher एक्सटेंशन AddJsEngineSwitcher का उपयोग करके प्रतिस्थापित किया जाता है:


 using JavaScriptEngineSwitcher.Extensions.MsDependencyInjection; … public class Startup { … public void ConfigureServices(IServiceCollection services) { … services.AddJsEngineSwitcher(new MyJsEngineSwitcher(), options => … ) … ; … } … } … 

ये लगभग हमेशा "ब्रेक" अनुप्रयोगों या पुस्तकालयों में परिवर्तन करते हैं जो जावास्क्रिप्ट इंजन स्विचर के पिछले संस्करण का उपयोग करते हैं। इसलिए, आपको अपने कोड में निम्नलिखित बदलाव करने होंगे:


  1. JsEngineSwitcher से JsEngineSwitcher के प्रकार, पैरामीटर या गुण IJsEngineSwitcher
  2. Instance प्रॉपर्टी के बजाय, हर जगह Current प्रॉपर्टी का इस्तेमाल करें।

यह भी ध्यान देने योग्य है कि अधिकांश डेवलपर्स के लिए, इन परिवर्तनों का विशेष लाभ नहीं होगा, क्योंकि उनका मुख्य लक्ष्य यूनिट परीक्षणों को सरल बनाना था (उदाहरण के लिए, पहले, ReactJS.NET पुस्तकालय के यूनिट परीक्षणों में, ताले का उपयोग किया जाता था , लेकिन अब आप उनके बिना कर सकते हैं )।


अपवादों का पुनर्गठन


तीसरे संस्करण से पहले, अधिकांश JS इंजन त्रुटियां JsRuntimeException में बदल JsRuntimeException , और इंजन आरंभीकरण प्रक्रिया के दौरान हुई केवल त्रुटियाँ JsEngineLoadException में बदल JsEngineLoadException । एक बेस क्लास JsException भी थी, जिसमें से उपरोक्त दो प्रकार के अपवाद विरासत में मिले थे, जिसने JS इंजनों के संचालन के दौरान होने वाली बिल्कुल सभी त्रुटियों को रोकना संभव बना दिया था। स्पष्ट कमियों के बावजूद, अपवादों का यह संगठन जेएस इंजनों की बुनियादी क्षमताओं तक पहुंचने के लिए एकीकृत इंटरफ़ेस की अवधारणा के साथ अच्छी तरह से फिट बैठता है।


लेकिन लिपियों के रुकावट और पूर्व-संकलन के कार्यान्वयन के साथ (मैं निम्नलिखित वर्गों में उनकी चर्चा करूंगा), अपवादों को व्यवस्थित करने के लिए एक नए दृष्टिकोण के लिए एक आवश्यकता उत्पन्न हुई। सबसे पहले एक नए प्रकार के अपवाद को जोड़ना था - JsInterruptedException , जो उपयोगकर्ता को स्क्रिप्ट निष्पादन के रुकावट के बारे में सूचित करने के लिए आवश्यक था। तब स्क्रिप्ट के प्रसंस्करण के दौरान हुई सभी त्रुटियों को स्पष्ट रूप से दो समूहों में विभाजित करना आवश्यक था: संकलन त्रुटियां (पार्सिंग) और रनटाइम त्रुटियां। चक्र और वी 8 की सभी प्रकार की विशिष्ट त्रुटियों को अलग करना भी आवश्यक था, जो लिपियों के प्रसंस्करण से संबंधित नहीं थे। जिंट इंजन में एक अपवाद की उपस्थिति को भी ध्यान में रखना आवश्यक था जो तब होता है जब किसी स्क्रिप्ट को निष्पादित करने की समय-अवधि समाप्त हो जाती है (टाइमआउट) समाप्त हो गया है। परिणामस्वरूप, अपवादों के संगठन के लिए एक नया दृष्टिकोण बनाया गया था, जिसे निम्नलिखित पदानुक्रमित संरचना के रूप में दर्शाया जा सकता है:


  • JsException
    • JsEngineException
      • JsEngineLoadException
    • JsFatalException
    • JsScriptException
      • JsCompilationException
      • JsRuntimeException
        • JsInterruptedException
        • JsTimeoutException
    • JsUsageException
  • JsEngineNotFoundException *

* - यह अपवाद जेएस इंजन के स्तर पर नहीं होता है, लेकिन जावास्क्रिप्ट इंजन स्विचर के स्तर पर होता है।


मुझे लगता है कि ऊपर दिए गए अपवादों के पदानुक्रम को टिप्पणियों की आवश्यकता नहीं है, क्योंकि अपवादों के नाम खुद के लिए बोलते हैं। इस दृष्टिकोण के साथ, हम न केवल त्रुटि के कारणों के बारे में अधिक जानकारी प्राप्त करते हैं, बल्कि कुछ प्रकार के अपवादों को अधिक लचीले ढंग से संभाल सकते हैं।


एकीकृत त्रुटि संदेश स्वरूप


जावास्क्रिप्ट इंजन स्विचर के पिछले संस्करणों के साथ एक और समस्या यह थी कि स्क्रिप्ट को संसाधित करते समय होने वाली त्रुटियों का पता लगाने में कठिनाई हुई। Message अपवाद संपत्ति से, यह समझना मुश्किल था कि कोड में त्रुटि कहां हुई, इसलिए मुझे अन्य अपवाद गुणों का विश्लेषण करना पड़ा, जो हमेशा सुविधाजनक नहीं था। इसके अलावा, मौजूदा संपत्तियों का सेट भी पर्याप्त नहीं था।


इसलिए, JsScriptException वर्ग में 2 नए गुण जोड़े गए:


  1. प्रकार - जावास्क्रिप्ट त्रुटि का प्रकार (उदाहरण के लिए, SyntaxError या TypeError );
  2. डॉक्यूमेंटनाम - दस्तावेज़ का नाम (आमतौर पर निम्नलिखित मापदंडों के मूल्यों से निकाला जाता है: documentName का नाम ExecuteFile और ExecuteFile , ExecuteFile मेथड path , ExecuteFile का ExecuteFile , ExecuteResource विधि, आदि);

JsRuntimeException class - CallStack में एक नई प्रॉपर्टी भी जोड़ी गई है, जिसमें कॉल स्टैक का एक स्ट्रिंग प्रतिनिधित्व है।


पहले, मूल .NET अपवाद या जावास्क्रिप्ट त्रुटि के एक स्ट्रिंग प्रतिनिधित्व की एक समान संपत्ति से एक मूल्य बस Message संपत्ति में कॉपी किया गया था। अक्सर, विभिन्न JS इंजनों में त्रुटि संदेश न केवल प्रारूप में, बल्कि उनमें प्रस्तुत उपयोगी जानकारी की मात्रा में भी भिन्न होते हैं। उदाहरण के लिए, कुछ त्रुटि संदेशों में पंक्ति और स्तंभ संख्या जानकारी की कमी के कारण, ReactJS.NET पुस्तकालय के डेवलपर्स को जावास्क्रिप्ट इंजन स्विचर से प्राप्त अपवादों को फिर से फेंकने के लिए मजबूर किया गया था।


इसलिए, मैंने एडॉप्टर मॉड्यूल स्तर पर अपने स्वयं के त्रुटि संदेश उत्पन्न करने का निर्णय लिया, जिसमें एक एकल (एकीकृत) प्रारूप होगा। यह प्रारूप सभी उपलब्ध त्रुटि जानकारी का उपयोग करता है: प्रकार, विवरण, दस्तावेज का नाम, लाइन नंबर, कॉलम नंबर, कोड टुकड़ा और कॉल स्टैक। नए प्रारूप के लिए एक आधार के रूप में, मैंने Microsoft ClearScript लाइब्रेरी से त्रुटि प्रारूप लिया।


नीचे एक ही संकलन त्रुटि के बारे में संदेश दिए गए हैं जो विभिन्न एडाप्टर मॉड्यूल द्वारा उत्पन्न किए गए थे:


 ChakraCore ========== SyntaxError: Unexpected identifier after numeric literal at declinationOfSeconds.js:12:23 -> caseIndex = number % 1O < 5 ? number % 10 : 5; Jint ==== SyntaxError: Unexpected token ILLEGAL at declinationOfSeconds.js:12:25 Jurassic ======== SyntaxError: Expected operator but found 'O' at declinationOfSeconds.js:12 MSIE   Classic ===================== SyntaxError: Expected ';' at declinationOfSeconds.js:12:25 -> caseIndex = number % 1O < 5 ? number % 10 : 5; MSIE   Chakra ActiveScript ================================= SyntaxError: Expected ';' at declinationOfSeconds.js:12:25 -> caseIndex = number % 1O < 5 ? number % 10 : 5; MSIE   Chakra IE JsRT ============================ SyntaxError: Expected ';' at 12:25 -> caseIndex = number % 1O < 5 ? number % 10 : 5; MSIE   Chakra Edge JsRT ============================== SyntaxError: Unexpected identifier after numeric literal at declinationOfSeconds.js:12:23 -> caseIndex = number % 1O < 5 ? number % 10 : 5; NiL === SyntaxError: Unexpected token 'O' at 12:25 V8 == SyntaxError: Invalid or unexpected token at declinationOfSeconds.js:12:24 -> caseIndex = number % 1O < 5 ? number % 10 : 5; Vroom ===== SyntaxError: Unexpected token ILLEGAL at declinationOfSeconds.js:12:24 

रनटाइम त्रुटि के लिए एक समान उदाहरण:


 ChakraCore ========== TypeError: Unable to get property '' of undefined or null reference at transliterate (russian-translit.js:929:4) -> newCharValue = typeof charMapping[charValue] !== 'undefined' ? at Global code (Script Document:1:1) Jint ==== TypeError: charMapping is undefined at russian-translit.js:929:26 Jurassic ======== TypeError: undefined cannot be converted to an object at transliterate (russian-translit.js:929) at Global code (Script Document:1) MSIE   Classic ===================== TypeError: 'undefined' is null or not an object at russian-translit.js:929:4 MSIE   Chakra ActiveScript ================================= TypeError: Unable to get property '' of undefined or null reference at russian-translit.js:929:4 MSIE   Chakra IE JsRT ============================ TypeError: Unable to get property '' of undefined or null reference at transliterate (russian-translit.js:929:4) at Global code (Script Document:1:1) MSIE   Chakra Edge JsRT ============================== TypeError: Unable to get property '' of undefined or null reference at transliterate (russian-translit.js:929:4) at Global code (Script Document:1:1) NiL === TypeError: Can't get property "" of "undefined" V8 == TypeError: Cannot read property '' of undefined at transliterate (russian-translit.js:929:37) -> newCharValue = typeof charMapping[charValue] !== 'undefined' ? at Script Document:1:1 Vroom ===== TypeError: Cannot read property '' of undefined at russian-translit.js:929:37 

यह उदाहरणों से देखा जा सकता है कि कुछ JS इंजन हमें पूरी तरह से अलग-अलग त्रुटि विवरण और कॉलम नंबर देते हैं, और हमें हमेशा त्रुटि डेटा का एक पूरा सेट नहीं मिल सकता है, लेकिन इन कमियों के बावजूद, एकीकृत प्रारूप हमें त्रुटि स्थान के बारे में अधिक जानकारी देता है। मूल त्रुटि संदेश।


मूल निवासी विधानसभा तैनाती युक्तियाँ


जावास्क्रिप्ट इंजन स्विचर के दूसरे संस्करण के साथ काम करते समय त्रुटियों का मुख्य कारण यह था कि कई डेवलपर्स चक्रगोर और वी 8 मॉड्यूल के लिए देशी असेंबली वाले नुगेट पैकेज स्थापित करना भूल गए थे। एक समय, ReactJS.NET बगट्रैकर में एक पोस्ट भी इस समस्या के लिए समर्पित था ( रूसी अनुवाद भी उपलब्ध है)। अब, ऐसी गलती मुख्य रूप से शुरुआती लोगों द्वारा ही सामना की जाती है, जिन्होंने किसी कारण से, प्रलेखन को नहीं पढ़ा।


ReactJS.NET के लेखकों ने त्रुटि संदेशों के अंदर संकेत का उपयोग करके ऐसी त्रुटियों की संख्या को कम करने की कोशिश की, लेकिन इस दृष्टिकोण के बहुत सफल कार्यान्वयन ने और भी भ्रम की स्थिति पैदा नहीं की । संकेत का विचार अच्छा था, लेकिन जेएस इंजनों के एडेप्टर मॉड्यूल के स्तर पर इसे मौलिक रूप से अलग कार्यान्वयन की आवश्यकता थी। जावास्क्रिप्ट इंजन स्विचर के नए संस्करण में, DllNotFoundException और TypeLoadException अपवादों JsEngineLoadException समय त्रुटि संदेश में ऐसे संकेत जोड़ दिए जाते हैं ( चक्र , V8 और Vroom मॉड्यूल के लिए कार्यान्वयन उदाहरण देखें)। इसके अलावा, इन युक्तियों बुद्धिमान हैं, क्योंकि उनकी पीढ़ी कई कारकों को ध्यान में रखती है: ऑपरेटिंग सिस्टम का प्रकार, प्रोसेसर आर्किटेक्चर, और रनटाइम (.NET फ्रेमवर्क, .NET कोर या मोनो)।


उदाहरण के लिए, विंडोज ऑपरेटिंग सिस्टम पर 64-बिट प्रक्रिया में मूल असेंबली के बिना चक्रकोर मॉड्यूल का उपयोग करते समय, त्रुटि संदेश इस पर दिखेगा:


ChakraCoreJsEngine का उदाहरण बनाने में विफल। सबसे अधिक संभावना है कि यह हुआ, क्योंकि 'चक्रकॉर। डीएल' विधानसभा या इसकी एक निर्भरता नहीं मिली थी। NuGet के माध्यम से JavaScriptEngineSwitcher.ChakraCore.Native.win-x64 पैकेज स्थापित करने का प्रयास करें। इसके अलावा, आपको अभी भी Visual Studio 2017 ( https://www.visualstudio.com/downloads/#microsoft-visual-c-redistributable-for-visual-studio-2017 ) के लिए Microsoft Visual C ++ Redistributable इंस्टॉल करना होगा।

त्रुटि संदेश एक संकेत देता है कि आपको जावास्क्रिप्ट NuGet packageEngineSwitcher.ChakraCore.Native.win-x64 को स्थापित करने की आवश्यकता है, और यह भी उल्लेख करता है कि Windows के लिए चक्रचोर को Visual Studio 2017 के लिए Microsoft Visual C ++ सारिणी घटक की आवश्यकता है। यदि यह त्रुटि है। यदि यह 32-बिट प्रक्रिया में होता है, तो उपयोगकर्ता को JavaScriptEngineSwitcher.ChakraCore.Native.win-x86 पैकेज स्थापित करने के लिए कहा जाएगा।


.NET कोर में लिनक्स पर एक समान त्रुटि संदेश इस तरह दिखेगा:


ChakraCoreJsEngine का उदाहरण बनाने में विफल। सबसे अधिक संभावना है कि ऐसा हुआ, क्योंकि 'libChakraCore.so' विधानसभा या इसकी एक निर्भरता नहीं मिली थी। जावास्क्रिप्ट के माध्यम से JavaScriptEngineSwitcher.ChakraCore.Native.linux-x64 पैकेज स्थापित करने का प्रयास करें।

इस स्थिति में, इसे JavaScriptEngineSwitcher.ChakraCore.Native.linux-x64 पैकेज स्थापित करने का सुझाव दिया जाएगा।


मोनो में लॉन्च होने पर, एक और संकेत प्रदर्शित किया जाएगा:


... JavaScriptEngineSwitcher.ChakraCore.Native.linux- * पैकेज मोनो के तहत स्थापना का समर्थन नहीं करते हैं, लेकिन आप मूल असेंबली को मैन्युअल रूप से स्थापित करने के लिए कर सकते हैं ( https://github.com/Taritsyn/JavaScriptEngine.witcher/wiki/ChakraCore#linux )।

चूंकि JavaScriptEngineSwitcher.ChakraCore.Native.linux-x64 पैकेज केवल .NET कोर के साथ संगत है, इसलिए टूलटिप लिनक्स पर मूल असेंबली को मैन्युअल रूप से तैनात करने के निर्देश के लिए एक लिंक प्रदान करेगा।


कई और उदाहरण दिए जा सकते हैं, लेकिन इसका कोई मतलब नहीं है।


गर्भपात स्क्रिप्ट निष्पादन


जब हम उपयोगकर्ताओं को सर्वर पर मनमाने ढंग से जेएस-कोड निष्पादित करने का अवसर देते हैं, तो हमें एक बहुत गंभीर समस्या का सामना करना पड़ता है - हमें नहीं पता कि इस कोड को निष्पादित करने में कितना समय लगेगा। यह एक बड़ी मात्रा में गैर-इष्टतम कोड या कोड हो सकता है जो एक अनंत लूप चलाता है। किसी भी स्थिति में, यह अनियंत्रित कोड होगा जो हमारे सर्वर के संसाधनों को अनिश्चित काल तक उपभोग करेगा। किसी तरह इस प्रक्रिया को नियंत्रित करने के लिए, हमें स्क्रिप्ट के निष्पादन को बाधित करने की क्षमता की आवश्यकता होती है। शुद्ध .NET (उदाहरण के लिए, जिंट, जुरासिक या NiL.JS) में लिखे गए इंजनों का उपयोग करते समय, हम हमेशा जेएस कोड को रद्द करने की क्षमता के साथ एक कार्य के रूप में निष्पादित करना शुरू कर सकते हैं, लेकिन यह दृष्टिकोण अन्य इंजनों के लिए काम नहीं करेगा। सौभाग्य से हमारे लिए, C ++ इंजन में स्क्रिप्ट को बाधित करने के लिए अंतर्निहित तंत्र हैं।


इन तंत्रों तक पहुंच प्रदान करने के लिए, IJsEngine इंटरफ़ेस में IJsEngine प्रॉपर्टी और Interrupt विधि को जोड़ा गया था। चूंकि सभी इंजन इस सुविधा का समर्थन नहीं करते हैं, इसलिए आपको हमेशा Interrupt विधि को कॉल करने से पहले SupportsScriptInterruption प्रॉपर्टी के मूल्य की जांच करनी चाहिए (यदि जावास्क्रिप्ट इंजन स्विचर के पिछले संस्करणों में आपको कचरा कलेक्टर को मैन्युअल रूप से चलाना था, तो आप तुरंत समझ जाएंगे कि आप किस बारे में बात कर रहे हैं):


 if (engine.SupportsScriptInterruption) { engine.Interrupt(); } 

और आपको इस विधि को उस थ्रेड से अलग थ्रेड में कॉल करने की आवश्यकता है जिसमें स्क्रिप्ट निष्पादित की जाती हैं। Interrupt विधि को कॉल करने के बाद, पहले से चल रहे सभी Evaluate , Execute* और CallFunction को JsInterruptedException साथ समाप्त हो जाएगा।


चूंकि यह API निम्न-स्तर का है, इसलिए खंड के आरंभ में वर्णित कार्यों के लिए विस्तार विधियों का उपयोग करने की अनुशंसा की जाती है:


 using System; #if !NET40 using System.Runtime.ExceptionServices; #endif using System.Threading; using System.Threading.Tasks; using JavaScriptEngineSwitcher.Core; #if NET40 using JavaScriptEngineSwitcher.Core.Extensions; #endif using JavaScriptEngineSwitcher.Core.Resources; … /// <summary> /// Extension methods for <see cref="IJsEngine"/> /// </summary> public static class JsEngineExtensions { /// <summary> /// Evaluates an expression within a specified time interval /// </summary> /// <typeparam name="T">Type of result</typeparam> /// <param name="engine">JS engine</param> /// <param name="expression">JS expression</param> /// <param name="timeoutInterval">Interval to wait before the /// script execution times out</param> /// <param name="documentName">Document name</param> /// <returns>Result of the expression</returns> /// <exception cref="ObjectDisposedException"/> /// <exception cref="ArgumentNullException"/> /// <exception cref="ArgumentException"/> /// <exception cref="JsCompilationException"/> /// <exception cref="JsTimeoutException"/> /// <exception cref="JsRuntimeException"/> /// <exception cref="JsException"/> public static T Evaluate<T>(this IJsEngine engine, string expression, TimeSpan timeoutInterval, string documentName) { if (engine == null) { throw new ArgumentNullException(nameof(engine)); } if (engine.SupportsScriptInterruption) { using (var timer = new Timer(state => engine.Interrupt(), null, timeoutInterval, #if NET40 new TimeSpan(0, 0, 0, 0, -1))) #else Timeout.InfiniteTimeSpan)) #endif { try { return engine.Evaluate<T>(expression, documentName); } catch (JsInterruptedException e) { throw new JsTimeoutException( Strings.Runtime_ScriptTimeoutExceeded, e.EngineName, e.EngineVersion, e ); } } } else { #if NET40 Task<T> task = Task.Factory.StartNew(() => #else Task<T> task = Task.Run(() => #endif { return engine.Evaluate<T>(expression, documentName); }); bool isCompletedSuccessfully = false; try { isCompletedSuccessfully = task.Wait(timeoutInterval); } catch (AggregateException e) { Exception innerException = e.InnerException; if (innerException != null) { #if NET40 innerException.PreserveStackTrace(); throw innerException; #else ExceptionDispatchInfo.Capture(innerException).Throw(); #endif } else { throw; } } if (isCompletedSuccessfully) { return task.Result; } else { throw new JsTimeoutException( Strings.Runtime_ScriptTimeoutExceeded, engine.Name, engine.Version ); } } } … } … 

यह विधि इंजन विधि पर एक ऐड-ऑन है Evaluate<T> , जो timeoutInterval पैरामीटर का उपयोग करके स्क्रिप्ट को निष्पादित करने के लिए प्रतीक्षा करने के लिए टाइमआउट सेट timeoutInterval अनुमति देता है। इस विस्तार विधि के संचालन का सिद्धांत बहुत सरल है। सबसे पहले, हम जांचते हैं कि हमारा इंजन अंतर्निहित अंतर्क्रिया तंत्र का समर्थन करता है या नहीं। यदि ऐसा timeoutInterval , तो हम Timer क्लास का एक उदाहरण बनाते हैं, जो timeoutInterval पैरामीटर में निर्दिष्ट timeoutInterval अंतराल के बाद, Interrupt विधि को शुरू करता है, फिर हम Evaluate<T> इंजन विधि, और त्रुटि के मामले में, JsInterruptedException को JsInterruptedException और इसे JsTimeoutException में JsTimeoutException । यदि इंजन इंटरप्ट का समर्थन नहीं करता है, तो Task क्लास का एक उदाहरण बनाएं, जो इंजन के Evaluate<T> का Evaluate<T> विधि, तो timeoutInterval पैरामीटर से मान के बराबर कार्य के लिए प्रतीक्षा अंतराल सेट करें, और यदि कार्य टाइमआउट से पूरा होता है, तो एक JsTimeoutException प्रकार JsTimeoutException । निम्नलिखित इस विस्तार विधि का उपयोग करने का एक उदाहरण है:


 using System; … using JavaScriptEngineSwitcher.Core; using JavaScriptEngineSwitcher.Core.Helpers; … class Program { … static void Main(string[] args) { const string expression = @"function getRandomInt(minValue, maxValue) { minValue = Math.ceil(minValue); maxValue = Math.floor(maxValue); return Math.floor(Math.random() * (maxValue - minValue + 1)) + minValue; } function sleep(millisecondsTimeout) { var totalMilliseconds = new Date().getTime() + millisecondsTimeout; while (new Date().getTime() < totalMilliseconds) { } } var randomNumber = getRandomInt(1, 10); sleep(randomNumber * 1000); randomNumber;"; using (IJsEngine engine = JsEngineSwitcher.Current.CreateDefaultEngine()) { try { int result = engine.Evaluate<int>(expression, TimeSpan.FromSeconds(3), "randomNumber.js"); Console.WriteLine(" = {0}", result); } catch (JsTimeoutException) { Console.WriteLine("    JavaScript " + "   !"); } catch (JsException e) { Console.WriteLine("   JavaScript-  " + "!"); Console.WriteLine(); Console.WriteLine(JsErrorHelpers.GenerateErrorDetails(e)); } } } … } … 

विस्तार विधि का उपयोग करते हुए, हम जेएस अभिव्यक्ति के परिणाम की गणना करते हैं। अभिव्यक्ति का परिणाम एक यादृच्छिक पूर्णांक है, और यह संख्या भी सेकंड की संख्या है जिसके द्वारा इस अभिव्यक्ति में देरी हो रही है। इसके अलावा, एक्सटेंशन विधि को कॉल करते समय, हम 3 सेकंड की प्रतीक्षा अंतराल निर्दिष्ट करते हैं। चूंकि अभिव्यक्ति की गणना करने का समय 1 से 10 सेकंड तक भिन्न होता है, एक मामले में अभिव्यक्ति का परिणाम कंसोल पर प्रदर्शित किया जाएगा, और दूसरे में, टाइमआउट के बारे में एक संदेश।


अन्य इंजन विधियों (उदाहरण के लिए, Execute* , CallFunction या Evaluate पद्धति के अन्य अतिभारित संस्करणों) को कॉल करने के लिए इस विस्तार विधि का रीमेक बनाना आपके लिए मुश्किल नहीं होना चाहिए। अभी तक मैंने यह तय नहीं किया है कि मैं पुस्तकालय में इस तरह के विस्तार के तरीकों को जोड़ूंगा या नहीं, क्योंकि यह अभी तक स्पष्ट नहीं है कि उनकी मांग कितनी होगी।


स्क्रिप्ट प्रीकंप्लिमेंटेशन


मुझे 2015 में वापस स्क्रिप्ट के प्रारंभिक संकलन के लिए समर्थन जोड़ने के लिए कहा गया था। उस समय, यह स्पष्ट नहीं था कि इस तरह के फ़ंक्शन को एकीकृत इंटरफ़ेस की अवधारणा में कैसे फिट किया जा सकता है। लेकिन समय बीतने के साथ, कचरा संग्रह और स्क्रिप्ट रुकावट जैसी पहुंच सुविधाओं के लिए समर्थन धीरे-धीरे जावास्क्रिप्ट इंजन स्विचर में दिखाई देने लगा। तीसरे संस्करण पर काम के अंतिम चरणों में, बारी प्रारंभिक संकलन के लिए आई।


Precompilation का उपयोग करते हुए, आप एक बार एक स्क्रिप्ट संकलित कर सकते हैं और फिर JS इंजन को इनिशियलाइज़ करने के लिए कई बार इसका उपयोग कर सकते हैं। इस तथ्य के कारण कि पूर्व-संकलित स्क्रिप्ट को पार्सिंग की आवश्यकता नहीं है, इंजनों का आरंभीकरण तेजी से होगा।


वर्तमान में, पूर्व-संकलन 5 एडाप्टर मॉड्यूल द्वारा समर्थित है: चक्रकोर, जिंट, जुरासिक, एमएसआईई (केवल जेएसआरटी मोड में) और वी 8। संबंधित इंजन तंत्रों तक पहुँच प्रदान करने के लिए, SupportsScriptPrecompilation प्रॉपर्टी और 3 नए तरीकों को IJsEngine इंटरफ़ेस में जोड़ा गया: Precompile , PrecompileFile और PrecompileResourcePrecompile* विधियाँ किसी ऑब्जेक्ट की आवृत्ति IPrecompiledScript जो IPrecompiledScript इंटरफ़ेस को लागू IPrecompiledScript है। यह ऑब्जेक्ट एक पूर्व-संकलित स्क्रिप्ट है जिसका उपयोग इंजन के विभिन्न उदाहरणों द्वारा किया जा सकता है (इस उद्देश्य के लिए Execute विधि का एक अधिभार संस्करण)। इस API का उपयोग करने के एक सरल उदाहरण पर विचार करें:


 using System; … using JavaScriptEngineSwitcher.Core; using JavaScriptEngineSwitcher.Core.Helpers; … class Program { … static void Main(string[] args) { const string sourceCode = @"function declinationOfSeconds(number) { var result, titles = ['', '', ''], titleIndex, cases = [2, 0, 1, 1, 1, 2], caseIndex ; if (number % 100 > 4 && number % 100 < 20) { titleIndex = 2; } else { caseIndex = number % 10 < 5 ? number % 10 : 5; titleIndex = cases[caseIndex]; } result = number + ' ' + titles[titleIndex]; return result; }"; const string functionName = "declinationOfSeconds"; const int itemCount = 4; int[] inputSeconds = new int[itemCount] { 0, 1, 42, 600 }; string[] outputStrings = new string[itemCount]; IJsEngineSwitcher engineSwitcher = JsEngineSwitcher.Current; IPrecompiledScript precompiledCode = null; using (var engine = engineSwitcher.CreateDefaultEngine()) { if (!engine.SupportsScriptPrecompilation) { Console.WriteLine("{0}  {1}   " + "  !", engine.Name, engine.Version); return; } try { precompiledCode = engine.Precompile(sourceCode, "declinationOfSeconds.js"); engine.Execute(precompiledCode); outputStrings[0] = engine.CallFunction<string>(functionName, inputSeconds[0]); } catch (JsCompilationException e) { Console.WriteLine("     " + " !"); Console.WriteLine(); Console.WriteLine(JsErrorHelpers.GenerateErrorDetails(e)); return; } catch (JsException e) { Console.WriteLine("   JavaScript-  " + "!"); Console.WriteLine(); Console.WriteLine(JsErrorHelpers.GenerateErrorDetails(e)); return; } } for (int itemIndex = 1; itemIndex < itemCount; itemIndex++) { using (var engine = engineSwitcher.CreateDefaultEngine()) { try { engine.Execute(precompiledCode); outputStrings[itemIndex] = engine.CallFunction<string>( functionName, inputSeconds[itemIndex]); } catch (JsException e) { Console.WriteLine("   JavaScript- " + " !"); Console.WriteLine(); Console.WriteLine(JsErrorHelpers.GenerateErrorDetails(e)); return; } } } for (int itemIndex = 0; itemIndex < itemCount; itemIndex++) { Console.WriteLine(outputStrings[itemIndex]); } } … } … 

, . SupportsScriptPrecompilation , , , . Precompile , , JsCompilationException . C Execute , .. . CallFunction declinationOfSeconds . . , , . 3 . , , . , , .


, , . , , . ReactJS.NET. JSPool , ( System.Runtime.Caching.MemoryCache .NET Framework 4.X, System.Web.Caching.Cache ASP.NET 4.X Microsoft.Extensions.Caching.Memory.IMemoryCache ASP.NET Core). , ( ). , ReactJS.NET.


ReactJS.NET . . AllowJavaScriptPrecompilation true .


ASP.NET 4.X App_Start/ReactConfig.cs :


 public static class ReactConfig { public static void Configure() { ReactSiteConfiguration.Configuration … .SetAllowJavaScriptPrecompilation(true) … ; … } } … 

ASP.NET Core Startup.cs :


 public class Startup { … public void Configure(IApplicationBuilder app, IHostingEnvironment env) { … app.UseReact(config => { config … .SetAllowJavaScriptPrecompilation(true) … ; }); app.UseStaticFiles(); … } } … 

, . JsExecutionBenchmark , BenchmarkDotNet . JS- . 14,9 , , . JavaScript Engine Switcher ( 3.0.4).


, .NET Framework 4.7.2:


..Gen 0 . .Gen 1 . .Gen 2 . ..
ChakraCore41,72---74,46
35,07---91,79
Jint27,192 812,501 343,75-16 374,58
15,541 296,88640,6331,257 521,49
Jurassic455,702 000,001 000,00-15 575,28
78,701 000,00--7 892,94
MSIE Chakra IE JsRT30,97---77,75
24,40---90,58
MSIE Chakra Edge JsRT33,14---78,40
32,86---95,48
V841,10---79,33
39,25---96,17

, .NET — Jurassic 5,79 , Jint 1,75 a. 2 , 2 . . Jurassic, : Jurassic JS- IL- Reflection.Emit, . , , . Jint .NET-, . Jint , . , Jint , , . Jint Jurassic .


, C++, MSIE Chakra IE JsRT — 26,93%. ChakraCore (18,96%), V8 (4,71%) MSIE Chakra Edge JsRT (0,85%). Internet Explorer Edge. . ( ) . , - 12-17 ( ). . . .


.NET Core 2.0 ( V8 , Microsoft ClearScript, , .NET Core):


..Gen 0 . .Gen 1 . .Gen 2 . ..
ChakraCore43,65---18,07
36,37---16,59
Jint24,872 750,001 375,00-16 300,25
15,251 281,25593,7562,507 447,44
Jurassic469,972 000,001 000,00-15 511,70
80,721 000,00--7 845,98
MSIE Chakra IE JsRT31,50---20,28
24,52---18,78
MSIE Chakra Edge JsRT35,54---20,45
31,44---18,99

. , — MSIE Chakra Edge JsRT (7,69%). Chakra .


ChakraCore MSIE


, Microsoft, , . IIS (256 32- 512 64-), ASP.NET JS- (, TypeScript) . JavaScript Engine Switcher . , Node.js (492 32- 984 64-). , , - . ChakraCore MSIE MaxStackSize , . Node.js. , .


NiL.JS


- NiL , NiL.JS . NiL.JS — JS-, .NET. 2014 , Jurassic Jint. — . , .


.NET Framework 4.7.2 :


.Gen 0 . .Gen 1 . .Gen 2 . ..
Jint27,192 812,501 343,75-16 374,58
Jurassic455,702 000,001 000,00-15 575,28
NiL17,801 000,00--4 424,09

.NET Core 2.0 :


.Gen 0 . .Gen 1 . .Gen 2 . ..
Jint24,872 750,001 375,00-16 300,25
Jurassic469,972 000,001 000,00-15 511,70
NiL19,671 000,00--4 419,95

. , ( ). , Jint 2016 , . 3.0.0 Beta 1353 , Jint 2,4 , NiL.JS 2.5.1200, .


NiL.JS . - , - , . Bundle Transformer, JavaScript Engine Switcher, Hogan Handlebars, ReactJS.NET. NiL.JS.


संदर्भ


  1. JavaScript Engine Switcher GitHub
  2. JavaScript Engine Switcher
  3. « JavaScript Engine Switcher 2.X»
  4. JSPool GitHub
  5. ReactJS.NET
  6. ReactJS.NET GitHub

Source: https://habr.com/ru/post/hi439446/


All Articles