Closed ZverGuy closed 2 years ago
https://github.com/ZverGuy/yantra/commits/main if you want test - check my repo
I really hope that you can help, because I do not know why this is happening
You can use,
context.RegisterModule("test", ClrType.From(typeof(YourClrClass));
You can make module builder as follow,
public class ModuleBuilder {
private List<(string name,Type type)> exportedTypes = new ();
public ModuleBuilder Export<T>(string name = null) {
exportedTypes.Add((name ?? typeof(T).Name, typeof(T)));
return this;
}
public JSModuleContext Builder(JSModuleContext context) {
foreach(var (name,type) in exportedTypes) {
var exports = new JSObject();
// currently YantraJS does not support synthetic default imports
// so we should add "default" property in exports
exports[KeyStrings.@default] = ClrType.From(type);
context.RegisterModule(name, exports);
}
}
}
public static class ModuleBuilderExtensions {
public static JSModuleContext Build(this JSModuleContext context, Action<ModuleBuilder> builder) {
var mb = new ModuleBuilder();
builder(mb);
return mb.Build(context);
}
}
Big thanks
expect my pull request soon
Check my pull request
You forgot to set default
. Please note, we haven't added support for synthetic default modules like node, so as per ES6 we need to set default
on exports to support "import test from .... " syntax. We are working on synthetic default module support.
Instead of JSFunction
, use JSFunctionDelegate
as JSFunction needs to be created per JSContext instance. I have added following code, which works correclty.
public class ModuleBuilder {
private List<(string name,object value)> exportedObjects = new ();
public ModuleBuilder ExportType<T>(string name = null) {
exportedObjects .Add((name ?? typeof(T).Name, typeof(T)));
return this;
}
public ModuleBuilder Export(string name, object value) {
exportedObjects .Add((name , value));
return this;
}
public ModuleBuilder ExportFunction(string name, JSFunctionDelegate @delegate) {
exportedObjects .Add((name , @delegate));
return this;
}
public JSModuleContext Builder(JSModuleContext context) {
foreach(var (name,value) in exportedTypes) {
var exports = new JSObject();
var r = JSUndefined.Value;
switch(value) {
case Type type:
r = ClrType.From(type);
break;
case JSFunctionDelegate @delegate:
r = new JSFunction(name, @delegate);
break;
case JSValue jv:
r = jv;
break;
default:
r = ClrProxy.Marshal(value);
break;
}
// currently YantraJS does not support synthetic default imports
// so we should add "default" property in exports
exports[KeyStrings.@default] = r;
context.RegisterModule(name, exports);
}
}
}
public static class ModuleBuilderExtensions {
public static JSModuleContext Build(this JSModuleContext context, Action<ModuleBuilder> builder) {
var mb = new ModuleBuilder();
builder(mb);
return mb.Build(context);
}
}
but there is a flaw in your method. each exported object has its own module. I want to do for example
import {TestClass, testFunc} from 'test'
But with your method i cant do that Only
import TestClass from 'TestClass'
import testFunc from 'testFunc'
public class ModuleBuilder {
private readonly string moduleName;
public ModuleBuilder(string moduleName) {
this.moduleName = moduleName;
}
private List<(KeyString name,object value)> exportedObjects = new ();
public ModuleBuilder ExportType<T>(string name = null) {
exportedObjects .Add((name ?? typeof(T).Name, typeof(T)));
return this;
}
public ModuleBuilder Export(string name, object value) {
exportedObjects .Add((name , value));
return this;
}
public ModuleBuilder ExportFunction(string name, JSFunctionDelegate @delegate) {
exportedObjects .Add((name , @delegate));
return this;
}
public JSModuleContext Builder(JSModuleContext context) {
var exports = new JSObject();
foreach(var (name,value) in exportedTypes) {
var r = JSUndefined.Value;
switch(value) {
case Type type:
r = ClrType.From(type);
break;
case JSFunctionDelegate @delegate:
r = new JSFunction(name, @delegate);
break;
case JSValue jv:
r = jv;
break;
default:
r = ClrProxy.Marshal(value);
break;
}
exports[name] = r;
}
context.RegisterModule(moduleName, exports);
}
}
public static class ModuleBuilderExtensions {
public static JSModuleContext Build(this JSModuleContext context string moduleName, Action<ModuleBuilder> builder) {
var mb = new ModuleBuilder(moduleName);
builder(mb);
return mb.Build(context);
}
}
Usage
context.Build("moduleName", (mb) => {
mb.ExportType<SomeClrType>();
mb.ExportFunction("SomeFunction", (in Arguments a) => JSUndefined.Value);
});
import { SomeClrType, SomeFunction } from "moduleName";
i made simillar Its ok? Can be merged? (Not used boolean and commented code i delete before merge)
public class ModuleBuilder
{
private List<(string name,object value)> exportedObjects = new ();
private string _moduleName;
private readonly bool _enableSyntheticDefaultModules;
public ModuleBuilder ExportType<T>()
{
exportedObjects.Add((typeof(T).Name, typeof(T)));
return this;
}
public ModuleBuilder(string moduleName, bool enableSyntheticDefaultModules = false)
{
_moduleName = moduleName;
_enableSyntheticDefaultModules = enableSyntheticDefaultModules;
}
public ModuleBuilder ExportType(Type type, string name = null)
{
exportedObjects.Add((type.Name, type));
return this;
}
public ModuleBuilder ExportValue(string name, object value)
{
exportedObjects.Add((name, value.Marshal()));
return this;
}
public ModuleBuilder ExportFunction(string name, JSFunctionDelegate func)
{
exportedObjects.Add((name, new JSFunction(func)));
return this;
}
public void AddModuleToContext(JSModuleContext context)
{
JSObject globalExport = new JSObject();
foreach ((string name, object value) in exportedObjects)
{
// if (_enableSyntheticDefaultModules)
// {
// //Used for make Sythetic default import work around
// JSObject localexport = new JSObject();
// localexport[KeyStrings.@default] = value switch
// {
// Type type => ClrType.From(type),
// JSFunctionDelegate @delegate => new JSFunction(@delegate),
// JSValue jsValue => globalExport[name] = jsValue,
// _ => ClrProxy.Marshal(value)
// };
// context.RegisterModule(name, localexport);
// }
globalExport[name] = value switch
{
Type type => ClrType.From(type),
JSFunctionDelegate @delegate => new JSFunction(@delegate),
JSValue jsValue => globalExport[name] = jsValue,
_ => ClrProxy.Marshal(value)
};
}
context.RegisterModule(_moduleName, globalExport);
}
}
In JSModuleContext
public void CreateModule(string moduleName,bool enableSyntheticDefaultImport, Action<ModuleBuilder> builder)
{
var mb = new ModuleBuilder(moduleName, enableSyntheticDefaultImport);
builder(mb);
mb.AddModuleToContext(this);
}
Why can't you use ModuleBuilder
in your own code? Since we haven't finalized api for synthetic defaults, we don't want to add ModuleBuilder now.
Okay But curently i fix stuff with "synthetic default import" and its works (if i understand your issue)
@ZverGuy Your code will only work inside ModuleBuilder
where else we are planning to support CSX
modules and may be some other languages as well, so I need to understand the formal specification of ES6 and I want to implement it correct way.
@ZverGuy Your code will only work inside
ModuleBuilder
where else we are planning to supportCSX
modules and may be some other languages as well, so I need to understand the formal specification of ES6 and I want to implement it correct way.
I move ModuleBuilder to extension methods and other package
I go to test modulebuilder with csx module loader for check if something is broken or not
@ZverGuy Your code will only work inside
ModuleBuilder
where else we are planning to supportCSX
modules and may be some other languages as well, so I need to understand the formal specification of ES6 and I want to implement it correct way.
Hmm Maybe i implement "ExportCSXModule" Method?
Hello again i am trying to implement "moduleBuilder" like jint
And when i try to create TestClass instance
I am get exception
TestClass implementation
ModuleBuilder implementation
Maybe you can help what i do wrong?
upd some intresting information
ClrType return function() { [clr-native]}
On runing this return a VoidValueTask
When i call testFunc() this is called but dont return value