Runtime class extending

How does a one extend existing JS class in Cheerp? JS example:
class ExtendedClass extends ExampleLibrary.BaseClass { /* ... */ }
class ExtendedClass extends ExampleLibrary.BaseClass { /* ... */ }
11 Replies
Awesome
Awesome•4mo ago
As this approach seems to fail
namespace [[cheerp::client_layout]] client::ExampleLibrary {
struct BaseClass {};
}

struct [[cheerp::genericjs]] ExtendedClass: public client::ExampleLibrary::BaseClass {}

[[cheerp::genericjs]] void webMain() {
auto example = ExtendedClass();
}
namespace [[cheerp::client_layout]] client::ExampleLibrary {
struct BaseClass {};
}

struct [[cheerp::genericjs]] ExtendedClass: public client::ExampleLibrary::BaseClass {}

[[cheerp::genericjs]] void webMain() {
auto example = ExtendedClass();
}
- TypeError: g.BaseClass is not a function
- TypeError: g.BaseClass is not a function
apignotti
apignotti•4mo ago
There is no support for this feature in Cheerp, and it seems to fall outside of the scope of the project, since class extension is a JavaScript concept, while Cheerp is a C++ compiler. It's not something that seems to fix with JS interoperability either. Can yon try to elaborate on what you are trying to achieve? There might be better strategies more in line with the compiler architecture.
apignotti
apignotti•4mo ago
A possible solution, if you really need to use the extends syntax, is to do that from JavaScript and then call functions jsexport-ed from C++. See here for more information about this feature: https://labs.leaningtech.com/cheerp/reference/javascript-interop/JSExport-attribute
Leaning Technologies Developer
JSExport attribute - Cheerp Documentation
C/C++ compiler targeting WebAssembly and JavaScript.
Awesome
Awesome•4mo ago
Ohh, okay, just wanted to ensure that I didn't miss out anything, my goal was to actually provide an interface for a library and extend its class as an actual Cheerp's code - which is somewhat required in my case mostly because of how the library manages the provided objects, it seemed to be quite logical to me that it would work, as Cheerp appears to have mostly all the necessary information about the objects it works on. Ideally, I would avoid dealing with raw JS or its imports on the Cheerp side but I guess it's currently the only way for now. Couldn't it be still handled by the compiler? Like when it sees that the class has let's say an attribute [[cheerp::extendsjs]] attached to it, it could just put the ES6 extends AST part based on the parent's interface namespace path (like it's being resolved right now but with extends keyword), later on the ExtendedClass would let know that it should call parent's constructor aka super(...) based on the constructors chain, or when in case ES6 isn't possible to be used, provide an ES5 abstraction on top of it (setPrototypeOf() with apply()). In fact I feel like this could be implemented and would be in some cases useful considering it wouldn't be falling much outside of the scope of what really Cheerp tries to go towards to - "... expressive intefacing with JavaScript libraries and the DOM, without wrappers or any overhead". 😃
apignotti
apignotti•4mo ago
I see quite some problems, in particular the "layout" of the objects generated by Cheerp needs to be controlled by the compiler, while an extended class is "controlled" by the base. The compiler can add fields, but has no guarantee that they will be unique. @Chen please think about this functionality when you have the chance. As things stand right now it seems to me the additional technical complexities is excessive compared to the additional convenience
Awesome
Awesome•4mo ago
Hmmm, yeah, I get that, wouldn't it be quite alike to handling those objects as the other client::* native objects are being handled? I think it could be marked as something that is "off to the browser" and compiler shouldn't really care much about the base object other than checking the interface's typings
apignotti
apignotti•4mo ago
No, it would be quite different since client object are completely handled by the browser. But a class extended from C++ would necessarily have some additional "C++" fields within. So we would have a single object that is partly managed by the browser and partly by C++. This is not something that is currently supported at all
Awesome
Awesome•4mo ago
Ahh, okay, I see 😕
apignotti
apignotti•4mo ago
Anyway, @Chen is our engineer currently expanding the capabilities of jsexport. He wil evaluate if class extension can fit in the project and will let you know.
DutChen18
DutChen18•4mo ago
As Alessandro mentioned before, the structure of C++ objects and javascript objects declared in the client namespace is completely different and I see no way to make inheritance work in a way that makes sense. Supporting this type of inheritance for [[cheerp::jsexport]]-ed classes makes more sense. Currently, jsexport inheritance is not supported at all, but it is planned for the near future. When I get around to working on jsexport inheritance I will see if also supporting inheritance from client objects is feasible or not.
Awesome
Awesome•4mo ago
Alright, got it I'll probably gonna be better off with this for now then, it's a bit tedious to do it that way but it's better than nothing 😃