Re: [Development] Question about QtDeclarative Internals

2021-04-25 Thread Alex Shaw
Hi Ulf,

Thanks for the advice. I think I got it working.
Patch submitted on Gerrit:
https://codereview.qt-project.org/c/qt/qtdeclarative/+/345339
It includes documentation and a test, and it works with named imports (i.e.
import { version } from "info")

Mostly it was just storing the QJSValues as PersistentValues, then
converting them to StaticValues when needed.
There were some other things, like telling the engine to skip calling
loadModule in the ExecutionUnit if it's already been registered in
nativeModules.

It works for any QJSValue, but one thing that might make this feature more
useful in the future is exposing functions or methods as a QJSValue.
One way might just be to have a std::function constructor (for a lambda)
Another might be to have QJSValue act as an intermediary between an
imported function in JavaScript and a slot in a QObject. That might require
some internal changes though.
But that's a whole different discussion. For now, I hope this works.

Thanks for your advice,
Alex


On Thu, Apr 22, 2021 at 1:55 AM Ulf Hermann  wrote:

> Hi Alex,
>
> the simplest way I can see here would not be a compilation unit. The
> compilation unit is only needed if you want to run JavaScript. The place
> where the imports of a script are saved is
> QV4::CompiledData::CompilationUnitBase::imports of the _importing_ unit.
> That's an array QV4::StaticValue*. Imports are always resolved
> statically when loading the script that does the import.
>
> You need a way to tell the engine "Hey, here is my implementation of
> foobar, use that when importing foobar in JavaScript". Then you can just
> provide a QV4::Value (that has been protected against garbage collection
> in some way) as that will fit the bill for the imports array.
>
> You might store those values as a hash of QUrl to QV4::PersistentValue
> in QV4::ExecutionEngine. Then you can query them in addition to the
> compilation units whenever something is imported. In a second step, the
> original modules hash may be changed to store some abstraction over both
> variations.
>
> This of course does involve some changes in the QML engine itself.
> However, better integration of C++ into JavaScript (as opposed to QML)
> has been on my list for a long time. This would be a welcome addition.
> Don't hesitate to ask me if you have further questions. You can also
> find me on freenode IRC in the #qt-v4vm channel.
>
> best regards,
> Ulf
>
> ___
> Development mailing list
> Development@qt-project.org
> https://lists.qt-project.org/listinfo/development
>
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Question about QtDeclarative Internals

2021-04-21 Thread Ulf Hermann

Hi Alex,

the simplest way I can see here would not be a compilation unit. The 
compilation unit is only needed if you want to run JavaScript. The place 
where the imports of a script are saved is 
QV4::CompiledData::CompilationUnitBase::imports of the _importing_ unit. 
That's an array QV4::StaticValue*. Imports are always resolved 
statically when loading the script that does the import.


You need a way to tell the engine "Hey, here is my implementation of 
foobar, use that when importing foobar in JavaScript". Then you can just 
provide a QV4::Value (that has been protected against garbage collection 
in some way) as that will fit the bill for the imports array.


You might store those values as a hash of QUrl to QV4::PersistentValue 
in QV4::ExecutionEngine. Then you can query them in addition to the 
compilation units whenever something is imported. In a second step, the 
original modules hash may be changed to store some abstraction over both 
variations.


This of course does involve some changes in the QML engine itself. 
However, better integration of C++ into JavaScript (as opposed to QML) 
has been on my list for a long time. This would be a welcome addition. 
Don't hesitate to ask me if you have further questions. You can also 
find me on freenode IRC in the #qt-v4vm channel.


best regards,
Ulf

___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Question about QtDeclarative Internals

2021-04-21 Thread Alex Shaw
Hello Fabian,

Thanks for replying.

The QJSValue represents any basic JS type that could be exported from a
regular module.
For example:
export const MAGIC = 6;
export default {
  name: "Qt6",
  version: "6.1.3"
}

In C++:
QJSValue magic(6);
QJSValue name("Qt6");
QJSValue version("6.1.3");
QJSValue obj = myEngine.newObject();
obj.setProperty("name", name);
obj.setProperty("version", version);
myEngine.registerModule("magic", magic);
myEngine.registerModule("qt_info", obj);

Then in JS:
import MAGIC from "magic";
import { version } from "qt_info";

Basically, it's like CreateSyntheticModule from V8.
I think something like this could be useful for applications using JS as a
scripting language.

There might be other ways to do what I need than converting QJSValue to an
ExecutableCompilationUnit;
I just thought this might be the most straightforward.

Thanks,
Alex
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Question about QtDeclarative Internals

2021-04-21 Thread Fabian Kosmale
Hi,

there is certainly no straightforward way from QV4::Value to 
ExecutableCompilationUnit, especially considering that the Value can be 
anything, from a primitive like bool or undefined to basically arbitrary 
objects managed on the engine's heap.

Could you expand a bit more how exactly you envision registerModule to work? 
What is your QJSValue supposed to contain:
- A string with the JS code of the module?
- An URL?
- A C++ object which ought to provide methods that can then be used in the JS 
engine?

Regards,
Fabian
--
Fabian Kosmale
Software Engineer

The Qt Company GmbH
Erich-Thilo-Str. 10
D-12489 Berlin
fabian.kosm...@qt.io
+49 1638686070
http://qt.io


Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen
Sitz der Gesellschaft: Berlin
Registergericht: Amtsgericht Charlottenburg, HRB 144331 B

--


Von: Development  im Auftrag von Alex Shaw 

Gesendet: Mittwoch, 21. April 2021 16:18
An: development@qt-project.org
Betreff: [Development] Question about QtDeclarative Internals

Hello,

In QtDeclarative, can a QV4::ReturnedValue or a QV4::Value be converted into an 
ExecutableCompilationUnit?

I'm trying to work on a patch for QJSEngine to allow importing modules from C++ 
(similar to Node.js: import fs from "fs")
The planned method is something along the lines of:
void QJSEngine::registerModule(const QString , const QJSValue )

I can see that behind the scenes, loadModule compiles a URL to an 
ExecutableCompilationUnit, then saves it to a list of modules for future lookup.
I thought the easiest way to do what I need is to convert a QJSValue to an 
internal QV4::Value, and from there into an ExecutableCompilationUnit.
Is there any way of doing that?

Thanks.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] Question about QtDeclarative Internals

2021-04-21 Thread Jason H

> Hello,
>  
> In QtDeclarative, can a QV4::ReturnedValue or a QV4::Value be converted into 
> an ExecutableCompilationUnit?
> 
> I'm trying to work on a patch for QJSEngine to allow importing modules from 
> C++ (similar to Node.js: import fs from "fs")
> The planned method is something along the lines of:
> void QJSEngine::registerModule(const QString , const QJSValue 
> )
>  
> I can see that behind the scenes, loadModule compiles a URL to an 
> ExecutableCompilationUnit, then saves it to a list of modules for future 
> lookup.
> I thought the easiest way to do what I need is to convert a QJSValue to an 
> internal QV4::Value, and from there into an ExecutableCompilationUnit.
> Is there any way of doing that?

This may not be what you asked for, but having done NodeJS, I would probably 
just recommend importing a Qt QObject as a Singleton to expose the functions 
under the fa import.
See qmlRegisterSingletonType().

import org.mine.fs 1.0

...
var file = fs.openFileSync(...);
...


___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


[Development] Question about QtDeclarative Internals

2021-04-21 Thread Alex Shaw
Hello,

In QtDeclarative, can a QV4::ReturnedValue or a QV4::Value be converted
into an ExecutableCompilationUnit?

I'm trying to work on a patch for QJSEngine to allow importing modules from
C++ (similar to Node.js: import fs from "fs")
The planned method is something along the lines of:
void QJSEngine::registerModule(const QString , const QJSValue
)

I can see that behind the scenes, loadModule compiles a URL to an
ExecutableCompilationUnit, then saves it to a list of modules for future
lookup.
I thought the easiest way to do what I need is to convert a QJSValue to an
internal QV4::Value, and from there into an ExecutableCompilationUnit.
Is there any way of doing that?

Thanks.
___
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development