/// <summary>
        /// Constructs an instance of adapter for the Node JS engine
        /// </summary>
        /// <param name="service">Node JS service</param>
        /// <param name="settings">Settings of the Node JS engine</param>
        public NodeJsEngine(INodeJSService service, NodeSettings settings)
        {
            if (service == null)
            {
                throw new ArgumentNullException(nameof(service));
            }

            _jsService = service;

            try
            {
                Task <string> versionTask = _jsService.InvokeFromStringAsync <string>(
                    @"module.exports = (callback) => {
	var version = process.versions.node;
	callback(null , version);
};"
                    );
                _engineVersion = versionTask.ConfigureAwait(false).GetAwaiter().GetResult();
            }
            catch (Exception e)
            {
                throw JsErrorHelpers.WrapEngineLoadException(e, EngineName, _engineVersion, true);
            }

            NodeSettings nodeSettings = settings ?? new NodeSettings();

            _executionTimeout = (int)nodeSettings.TimeoutInterval.TotalMilliseconds;
            _engineId         = JsEngineIdGenerator.GetNextId();

            InvokeEngineHelper("addContext", new object[] { _engineId, nodeSettings.UseBuiltinLibrary });
        }
Example #2
0
        static void Main()
        {
            IServiceCollection services = new ServiceCollection();

            services.AddNodeJS();
            ServiceProvider serviceProvider = services.BuildServiceProvider();
            INodeJSService  nodeJSService   = serviceProvider.GetRequiredService <INodeJSService>();

            int result = nodeJSService.InvokeFromStringAsync <int>("module.exports = (callback) => callback(null, 1)").GetAwaiter().GetResult();

            Console.WriteLine(result);
        }
        public void INodeJSService_InvokeFromCache_Setup()
        {
            var services = new ServiceCollection();

            services.AddNodeJS();
            _serviceProvider = services.BuildServiceProvider();
            _nodeJSService   = _serviceProvider.GetRequiredService <INodeJSService>(); // Default INodeJSService is HttpNodeJSService
            _counter         = 0;

            // Cache module
            DummyResult _ = _nodeJSService.InvokeFromStringAsync <DummyResult>("module.exports = (callback, resultString) => callback(null, { result: resultString });", DUMMY_MODULE_IDENTIFIER, args: new object[] { $"success {_counter++}" }).Result;
        }
Example #4
0
        public void INodeJSService_Latency_InvokeFromCache_Setup()
        {
            var services = new ServiceCollection();

            services.AddNodeJS();
            _serviceProvider = services.BuildServiceProvider();
            _nodeJSService   = _serviceProvider.GetRequiredService <INodeJSService>();
            _counter         = 0;

            // Warmup/cache.
            _nodeJSService.InvokeFromStringAsync <DummyResult>(DummyModuleFactory, DUMMY_MODULE_IDENTIFIER, args: new object[] { _counter++ }).GetAwaiter().GetResult();
        }
Example #5
0
        public void INodeJSService_Concurrency_None_Setup()
        {
            var services = new ServiceCollection();

            services.AddNodeJS();
            services.Configure <NodeJSProcessOptions>(options => options.ProjectPath = _projectPath);
            _serviceProvider = services.BuildServiceProvider();
            _nodeJSService   = _serviceProvider.GetRequiredService <INodeJSService>();

            // Warmup. First run starts a Node.js processes.
            _nodeJSService.InvokeFromStringAsync(DUMMY_WARMUP_MODULE).GetAwaiter().GetResult();
        }
Example #6
0
        public void INodeJSService_Latency_InvokeFromFile_GracefulShutdownEnabled_Setup()
        {
            var services = new ServiceCollection();

            services.AddNodeJS();
            services.Configure <NodeJSProcessOptions>(options => options.ProjectPath = _projectPath);
            services.Configure <OutOfProcessNodeJSServiceOptions>(options => options.EnableFileWatching = true);
            _serviceProvider = services.BuildServiceProvider();
            _nodeJSService   = _serviceProvider.GetRequiredService <INodeJSService>();
            _counter         = 0;

            // Warmup. First run starts a Node.js process.
            _nodeJSService.InvokeFromStringAsync(DUMMY_WARMUP_MODULE).GetAwaiter().GetResult();
        }
Example #7
0
        public void INodeJSService_Concurrency_MultiProcess_Setup()
        {
            var services = new ServiceCollection();

            services.AddNodeJS();
            services.Configure <NodeJSProcessOptions>(options => options.ProjectPath             = _projectPath);
            services.Configure <OutOfProcessNodeJSServiceOptions>(options => options.Concurrency = Concurrency.MultiProcess);
            _serviceProvider = services.BuildServiceProvider();
            _nodeJSService   = _serviceProvider.GetRequiredService <INodeJSService>();

            // Warmup. First few runs start Node.js processes, so they take longer. If we don't manually warm up, BenchmarkDotNet erroneously complains
            // about iteration time being too low
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                _nodeJSService.InvokeFromStringAsync(DUMMY_WARMUP_MODULE).GetAwaiter().GetResult();
            }
        }
        public void INodeJSService_RealWorkload_Setup()
        {
            var services = new ServiceCollection();

            services.AddNodeJS();
            services.Configure <NodeJSProcessOptions>(options => options.ProjectPath             = _projectPath); // Module loads prismjs from node_modules
            services.Configure <OutOfProcessNodeJSServiceOptions>(options => options.Concurrency = Concurrency.MultiProcess);
            _serviceProvider = services.BuildServiceProvider();
            _nodeJSService   = _serviceProvider.GetRequiredService <INodeJSService>();
            _counter         = 0;

            // Warmup/cache. First few runs start Node.js processes, so they take longer. If we don't manually warm up, BenchmarkDotNet erroneously complains
            // about iteration time being too low
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                _nodeJSService.InvokeFromStringAsync(DummyModuleFactory, DUMMY_CACHE_IDENTIFIER, args: new object[] { string.Format(DUMMY_CODE_FORMAT, _counter++) }).GetAwaiter().GetResult();
            }
        }
Example #9
0
        static void Main()
        {
            string javascriptModule = @"
module.exports = (callback, x, y) => {  // Module must export a function that takes a callback as its first parameter
    var result = x + y; // Your javascript logic
    callback(null /* If an error occurred, provide an error object or message */, result); // Call the callback when you're done.
}";

            // Create INodeJSService instance
            var services = new ServiceCollection();

            services.AddNodeJS();
            ServiceProvider serviceProvider = services.BuildServiceProvider();
            INodeJSService  nodeJSService   = serviceProvider.GetRequiredService <INodeJSService>();

            // Invoke javascript
            int result = nodeJSService.InvokeFromStringAsync <int>(javascriptModule, args: new object[] { 3, 5 }).Result;

            Console.WriteLine(result);
        }
Example #10
0
 /// <summary>
 /// Performs server-side prerendering by invoking code in Node.js.
 /// </summary>
 /// <param name="applicationBasePath">The root path to your application. This is used when resolving project-relative paths.</param>
 /// <param name="nodeServices">The instance of <see cref="INodeServices"/> that will be used to invoke JavaScript code.</param>
 /// <param name="applicationStoppingToken">A token that indicates when the host application is stopping.</param>
 /// <param name="bootModule">The path to the JavaScript file containing the prerendering logic.</param>
 /// <param name="requestAbsoluteUrl">The URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
 /// <param name="requestPathAndQuery">The path and query part of the URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
 /// <param name="customDataParameter">An optional JSON-serializable parameter to be supplied to the prerendering code.</param>
 /// <param name="timeoutMilliseconds">The maximum duration to wait for prerendering to complete.</param>
 /// <param name="requestPathBase">The PathBase for the currently-executing HTTP request.</param>
 /// <returns></returns>
 public static Task <RenderToStringResult> RenderToString(
     string applicationBasePath,
     INodeJSService nodeServices,
     CancellationToken applicationStoppingToken,
     JavaScriptModuleExport bootModule,
     string requestAbsoluteUrl,
     string requestPathAndQuery,
     object customDataParameter,
     int timeoutMilliseconds,
     string requestPathBase)
 {
     return(nodeServices.InvokeFromStringAsync <RenderToStringResult>(
                GetNodeScript(applicationStoppingToken), //Embedded JS file
                args: new object[] {                     //Actual request args
         applicationBasePath,
         bootModule,
         requestAbsoluteUrl,
         requestPathAndQuery,
         customDataParameter,
         timeoutMilliseconds,
         requestPathBase
     }
                ));
 }