Giter VIP home page Giter VIP logo

baristacore's People

Contributors

oceanswave avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

imgits lvyitian

baristacore's Issues

Implement Aggregating module loader

Allows multiple module loaders to be used. Scripts specify a particular module loader with a prefix, e.g. github!baristalabs/foo/bar.js. nuget!my.package.name/module

Future Module imports in dependent modules use the loader without needing a prefix

Add additional deep-type auto-conversions

There are some additional auto-conversions to consider:

  • Add support for indexed properties
  • Iterators/IEnumerable/IEnumerator
  • Compiler created iterators coming from functions using the yield statement
  • Unwrap nullable values
  • When projecting nullables to types, check HasValue to determine if the property should be set.
  • Enum values should auto convert
  • Generics (Maybe just testing. Concrete classes should just convert)
  • Arguments associated with an Event (BaristaTypeConversionStrategy.cs - invokeListener)
  • Types encountered in method/constructor/property parameters
  • DateTime <-> JsDate (when implemented)

Improve module evaluation by not requiring shim scripts in order to access namespace objects.

Thanks to chakra-core/ChakraCore#4707, it's now possible to programmatically get at namespace objects.

This allows the functionality in
https://github.com/BaristaLabs/BaristaCore/blob/master/src/BaristaLabs.BaristaCore.Common/BaristaContext.cs#L456
and
https://github.com/BaristaLabs/BaristaCore/blob/master/src/BaristaLabs.BaristaCore.Common/BaristaModuleRecord.cs#L260

to no longer rely on a 'shim' script in order to get at the variables exported by modules. This should improve execution speed, remove pollution of the global namespace, reduce the possibility of down-stream side effects, and allow the export of non-default values as well.

BaristaCore 1.0.2-beta03 does not work BaristaCore.ChakraCore 1.10.2

I initially had a hard time getting started b/c if an unhandled exception BaristaLabs.BaristaCore.JsScriptException: fetch import module failed. Here's the references used in a fresh console app:

<PackageReference Include="BaristaCore" Version="1.0.2-beta03" />
<PackageReference Include="BaristaLabs.BaristaCore.ChakraCore" Version="1.10.2" />

After pinning to 1.8.1, everything worked just fine. I then built from source and everything worked with the 1.10.2 version, so my best guess is BaristaCore/Extensions may need a newer publish to match ChakraCore, but I didn't look any further.

Besides this initial minor bump, I'm having a lot of fun experimenting with it this weekend; I'm really glad I stumbled across it. Thanks for sharing!

Provide .net object to JavaScript coersion

Implement an IConversionStrategy of which concrete implementations can shape how conversion happens

[x] Add the interface
[x] Utilize the interface in dynamic object overloads
[x] Allow for DI at the context level
[x] Perform primitive value conversion
[x] Perform various direct object conversions (Undefined, Task, etc)
[ ] Perform delegate to JsFunction conversion
[ ] Code Coverage
[ ] Implement non value complex object conversion using reflection.

Implement another strategy that allows for AttributeBasedConversion - uses something similar to jurassic's JsPropertyAttribute - to specify specific object members that will be part of the JsObject. This still requires the full gamut of complex object conversion already available, however.

Add ordered aggregate IModuleLoader

Similar to the AggregateModuleLoader except that

  • No Prefixes
  • Registered Module Loaders denote a priority, such that if a higher-priority module loader fails to find a module with a given specifier, it attempts to load from the lower-priority loader

e.g.
loader0 - webresource moduleloader
loader1 - github moduleloader
loader2 - assembly moduleloader

import foo from 'super-man'
  1. checks the webresource for a 'super-man.js' resource module
  2. checks the github module loader for a 'repository/super-man.js' resource module
  3. checks the assembly module loader for a 'super-man' module

Refactor factory methods to be true factory classes.

The current construction patterns have a lot to be desired -- RT classes should probably use factories that handle the pooling of resources rather than having that all gathered up in the rt/ctx/etc classes themselves

Goals here are to improve the ability to add additional dependencies via constructor easily.

Create AutoBuilder Module

The converter would

  • Create a new fn that when called, calls the type's constructor via Activator
  • Expose static members as fn properties
  • Set the prototype property to the shape of the class represented by the type.

Things to think about:
Generics?

Incorporate Span<T> and Memory<T> when marshaling large memory buffers

The intrinsic ChakraCore data types appear to support very large arrays > 2gb traditional .net limit, however, we've been limited to using byte[Int32.MaxValue] when marshaling them between ArrayBuffers, Strings and so forth.

We can probably leverage the new Memory object in C# 7.2 to get really big data sets in/out.

JsFunction set as property on JsObject is undefined when introspecting, but callable

I'm trying to get started with BaristaCore and it is a bumpy ride due to the lack of documentation. I could file a few issues, but I'm starting with this.

I created a new .NET Core 2.0 command line project, added the reference to the BaristaCore package (version 1.0.2-beta03) and used the following:

using System;
using BaristaLabs.BaristaCore;
using BaristaLabs.BaristaCore.Extensions;
using BaristaLabs.BaristaCore.ModuleLoaders;
using Microsoft.Extensions.DependencyInjection;

namespace TestBaristaRepro
{
    class Program
    {
        static void Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddBaristaCore();
            var moduleLoader = new InMemoryModuleLoader();
            moduleLoader.RegisterModule(new Test1Module());
            moduleLoader.RegisterModule(new Test2Module());
            serviceCollection.AddSingleton<IBaristaModuleLoader>(moduleLoader);

            var provider = serviceCollection.BuildServiceProvider();
            var baristaRuntimeFactory = provider.GetRequiredService<IBaristaRuntimeFactory>();

            using (var rt = baristaRuntimeFactory.CreateRuntime())
            using (var ctx = rt.CreateContext()) {
                var script = @"var objs = [{ name: 'm1', obj: m1 }, { name: 'm2', obj: m2 }];

var summary = """";
summary += ""result of manually running m1.test(1, 2): "" + m1.test(1, 2) + ""\n"";
//summary += ""result of manually running m2.test(1, 2): "" + m2.test(1, 2) + ""\n"";
for (let obj of objs) {
    var x = obj.obj;
    var name = obj.name;
    summary += ""#"" + name + ""#\n"" + ""= (toString: "" + (x === null ? ""NULL"" : (x === undefined ? ""UNDEFINED"" : ""'"" + x.toString() + ""'"")) + "" (JSON: "" + JSON.stringify(x) + "")\n"";
    for (var key in x) {
        summary += ""  "" + key + "": "" + global[key] + ""\n"";
    }
}
return summary;";

                using (ctx.Scope()) {
                    var moduleResult = ctx.EvaluateModule("import m1 from 'first-module'; import m2 from 'second-module'; export default function() {" + script + "}");
                    if (moduleResult is JsFunction fun) {
                        var resultOfCalling = fun.Call();
                        if (resultOfCalling is JsString str) {
                            var res = str.ToString();
                            Console.WriteLine("result is: ");
                            Console.WriteLine(res);
                        }
                    }
                }
            }

        }

        [BaristaModule("first-module", "Module one")]
        public class Test1Module : IBaristaModule
        {
            public JsValue ExportDefault(BaristaContext context, BaristaModuleRecord referencingModule) {
                var obj = context.CreateObject();
                var fnAdd = context.CreateFunction(new Func<JsObject, int, int, int>((thisObj, a, b) =>
                {
                    return a + b;
                }));
                obj.SetProperty("test", fnAdd);
                return obj;
            }
        }

        [BaristaModule("second-module", "Module two")]
        public class Test2Module : IBaristaModule
        {
            public JsValue ExportDefault(BaristaContext context, BaristaModuleRecord referencingModule) {
                return context.CreateExternalObject(new Test2());
            }
        }

        [BaristaObject("test2")]
        public class Test2 {
            [BaristaProperty("test", Configurable = false, Enumerable = true)]
            public int Test(int a, int b) {
                return a + b;
            }
        }
    }
}

This uses two different modules to make two different functions available. The code outputs the following:

result is:
result of manually running m1.test(1, 2): 3
#m1#
= (toString: '[object Object]' (JSON: {})
  test: undefined
#m2#
= (toString: '[object Object]' (JSON: {})

In other words, on the first module, test is callable, and it is visible as a property (so enumerable), but its value is undefined instead of a function. On the second module, test is neither callable nor visible.

So the question being: is there a way for the real value to be visible in case of the first module, and what do I need to do to make the second module work?

(Additionally, outside the scope of this issue, some background: I am trying to use BaristaCore to provide Javascript execution to make a small piece of business logic an interchangeable script. It would have a number of either modules or objects available that would return domain-specific information or allow it to perform the purpose of the script.

I try to follow along as well as I can in how to put this together, but the documentation is slim and differs from the code (in the documentation, the IBaristaModule interface is asynchronous and in the code it's not, and I don't even know which behavior is the outdated one and will be going away). I have been working with Jurassic previously and am weighing BaristaCore and using the C# wrappers for ChakraCore directly.

I don't quite understand how you're meant to just evaluate code without wrapping it inside a module which exports a default function that you then call. That you had to use Scope() took a while to figure out as well.)

Implement complex object conversion

Reflect over properties/methods and expose to runtime.

  • Expose constructors
  • Expose Properties
  • Expose Methods
  • Expose Events
  • Add attributes to configure how the above are projected on the prototype.

Consider parallel or full switch of CI to VSTS

VSTS now has Linux and macOS build agents in preview. Consider switching over to VSTS. And advantage will be that the Windows test harness can start auto-reporting code coverage again as the enterprise bits required to do so are on VSTS

Use Blazor + ChakraCore to dynamically compile and execute C#/Razor via WASM

This is a bit theoretical, but with Blazor, it should be possible to have BaristaCore compile C# code to WASM and then execute the result using the ChakraCore runtime. This would go towards one of the BaristaCore goals of having multiple languages (not just JavaScript) participate in the serverless execution environment that it provides.

Doing so would be an interesting foray to having a completely sandboxed C# runtime/serverless execution environment with BaristaCore (Remember VS for Applications?...)

Given the current goals of Blazor, and it's seeming desire to be a WASM web framework rather than a generic C# WASM generator, it may require stripping out the pertinent bits.

Add more built-in types

Add the following built-in types to make it easier when creating/providing these types to/from .net

Objects

  • Date
  • Math
  • ...

Functions:

  • encodeURIComponent()
  • parseInt()
  • ...

Note these are built-in methods/types intrinsic to the JavaScript engine, not new objects that need to be created, such as Blob.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.