Mathjs: Is there a Qml version of this code?

Created on 27 Mar 2019  路  12Comments  路  Source: josdejong/mathjs

I have tried to search for the usage of this JavaScript in QtQuick Qml JavaScript, which is not the same as the Web version, I can not figure out how to use BigInt, I get an undefined error, research led me to believe it is because of the "this" operator usage, but there are other isuse with this code as is, for example: to get rid of the warnings I could delete all the "use strict"; or just ignore the warnings, as well as the use new only for capitalized functions, still not sure if it is right to throw new Error, and change == to ===, and all like logic, which should be done anyway, this does not behave the way you think in any Engine, the only time you use == is when testing itmes that might be different in some ways, the original docs stated that and why they have == and === logic, the latter being used when you want to make sure they are the same in every way, where == may not fail === will, that means never use it, it is sloppy coding at best, if not used right, and there are times you have to use it, and Qml does not give a warning then, so life is good, Qt thought about that, but not the use of strict, grant you "use strict"; is required by the Web usage, and it is just a warning about assignment in Qml, so this is a Qt issues, they know about "use strict"; but their Qml JavaScript Engine does not like it, so it seems to me that someone should maintain a Qml verions of this code, to address all these issues, yet I could not find one, or anyone that was even using it in Qml, which I found odd, seeing how great it is, and for my needs, I need to deal with very large Numbers with very long Decimals, and the need for Accuracy is more important then speed, reference:

The lack of Qml references lead me to believe people are not using it, or not having problems using it, at least I could not find anything googling it, and the ones I did find where all about the above issues, so I know this is an issue, so if anyone is using it, and can tell me to just ignore all the warnings and errors, I would have to ask them how they got it to run, it does not really like errors at run time, which adding new to none capitalized functions using Qml's JavaScript Engine is, as is not adding to capitalized functions, easy fix, but it is a forced restriction on what some would think is not a requirement, but a coding standard, like all Global variables are Capitalized, when in fact Qml does not even like the use of Globals, and requires all its properties and vars to be lower case, as such I do not know what I can ignore, someone using it can, then at least, I know it should work without complications, or I just need to make the changes to fix all the errors and warnings and which ones I can safely ignore, like use strict, which I never understood the sync for putting it in quotes, why not just a comment, but it is what it is, STRICT=true makes more sense, but I like bash, JavaScript needs JavaScript Options; Engine.strict=true, make a prototype for it, then you only have one warning, instead of every time you use it, anyway you see my point, this code does not play well with Qml Engine, and that really is not your problem, but it is mine if I want to use it, so what I suggest is a qml version of the code, maybe name it QmlMath.js, since it likes all its Qml files capitalized, and the does not like caps at all, and there is no reason for a minimized version, that will only lead to problems with minimizing. When you come out with a new version, just post it to the new QmlMath, and let someone using Qml update it, I am not asking you to maintain the file, you have enough to do just making it, just allow others the option to use it and maintain it, as well as make improvements to it; this would apply to all such other libraries you also manage that could be used in Qml.

Qml Engine is not the same as others, and never will be, it is Qt, all I am asking is to make it easier for us Qt users, and at the same time you will gain more users and developers, so I think this would be good for the project.

I am working on cleaning up the errors, so I can try it, and got to thinking others have this same issue, but may have never reported it.

Thanks for the code and all the work that went into it.

question

All 12 comments

The mathjs library is ES5 compliant. Doesn't Qml support ES5?

That is debatable, for one thing there is a known bug with the use of "this", I cannot find that bug report, but it applies to all JavaScript functions that rely on "this", and if you try it, you will see what I mean, it mangles the name space, and functions cannot be found, besides messing up auto find when you hit ., that pulls up all the functions in a class in Qt Creator, it gives me run time errors, cannot find function.

Qml JavaScript is not the same as other engines.

So I guess there is some sort of port needed from JavaScript to "Qml JavaScript"? I don't know much about Qml. I've tested it a long time ago with mathjs and it worked at that time (except for a specific bug that we tried to pinpoint, see #505). If there are so many issues with loading math.js in Qml, I suppose you will have issues with a lot of JavaScript libaries?

Just to be sure: do you load the ES5 bundle of mathjs into your application? i.e. dist/math.js?

I used a

.import "math.js" as MathJs

I have tried many other libraries, and you are right, I have trouble with a lot of them, and that is just how the Engine works, it has a lot of the feature of a Normal JavaScript Engine, yet it is Qml, and does not support a lot of third party JavaScript code written for the web.

You can close this issue if no one know Qml, or wants this support, if I could get it to work, I would use it, but I do know a lot about the Qml JavaScript Engine, and my attempt at getting it to work, convinced me that I need to know the script and Qml limitations, and I have no seen any scripts work that are setup the way yours is, which is common for web usage, but most Qml Scripts that do run, are more or less just a function library, and I thought about cutting out the wrapper, which is what is causing it not to work, but got side tracked looking for a C++ alternative, which is not going along very well, and I do like this code, it is very well written, and seems to work fine for web use, but Qml is a different animal, and I cannot find really good documentation on how to write code for it, they push it off as if it is the same as the web, that is a mistake, because it is not.

In Qml JavaScript the .import is used just like it is in Qml, not a Web thing at all, nor is "use strict"; that is just a web thing, and I have written a lot of JavaScript, and find that I can not use Global var unless I set them up as a function with setter getter, so it is more like C, since very thing is dot oriented for example:

.import "math.js" as MathJs

var thisThing = MathJs.dosomething(withThis, andThis);

As such, you are actually just writing a C function class, and not a JavaScript, which I like, I do not like the way you structured the code, I know it is becoming the way that it is done, but it is not the only way that works, I call this a wrapper, it uses a lot of techniques that are hard to follow if you do not understand how they work, and I clearly do not, and never wrote any code like that because of that, in fact I learned how to write JavaScript by pretending it was C, so what do you expect, and that is why Qml works best with JavaScript structured like a C Function Library, and they run better in a Web Engine, do the bench marks, encapsulation has its performance enhancements, which is why you are using them, you understand them, and make them work, but from what I have seen of what Qml wants me to do to convert your script into what it needs, would require, would require making a function library out of it, and I have no idea how that code would preform compared to how you have it wrapped, so it is something to think about, you do not want to maintain to sets of Code, I would not, so the only way to make this work, would be to write your functions in a way they could be decoupled from the wrapper, to run as standalone functions, personally I believe that JavaScript Function Libraries are easier to maintain and debug, and you can run most Qml JavaScript's on web engines if you do not access libraries it does not have, a lot easier than you can get web engine scripts to run in Qml, meaning that if there were no performance issues with making a function library out of it, without the encapsulated wrapper, because I really do think that is the biggest problem in converting them, and in truth I never though that encapsulation in JavaScript was something I needed to learn, because it was very specific to the browser, regardless of Compliance of a Standard, we both know does not exist in the real world of JavaScript Engines, so what I am saying is that unless you want to use a wrapper they can understand, and just because I do not understand it, does not mean someone else might find a way to make this work the way it is, maybe I need to access it differently than just a dot operator, I never could get any code written like this to work, so it might be me, this needs more investigation, to be clear, but unless you are interested in Qml JavaScript compliance, which I would use, and I am sure others would as well, then no real reason you would be interested in making such a radical change to your code, or put it out there to ask someone if they could convert this to Qml JavaScript, and then just put it out there, and let the Qml JavaScript people maintain it, but I would not like to see two communities, this code needs to one Library, and one support system, if you branch it off, the two will drift apart into two projects, it is better to name all the functions the same and maintain how they work, arguments and that way, you fix a bug in one, you fix it in the other, otherwise you would have to bow down to how Qml wants their JavaScript, and Qt Creator is very fussy about that, it does more checking, in my opinion, less errors in the code, but not everyone like to use an IDE to write JavaScript, it is a different word to program in, and at first I wanted this Library to work so bad that I was trying to learn what I need to make this conversion, but at the end of the day, all I really wanted to do was finish my calculator, so I could get on with what is left of my life, and this is a project that would require more time than I have to put into it, and why I am forced to find a C++ solution, which is not really the Felgo way of doing things, and complicates the process of writing Qml apps, but I like C++, and have a working program that integrates C++ with Qml and JavaScript, so C++ is an option, but this Library would be a better option for me and most people who need it, so it would be worth the effort.

If you have the time, look at Qt Creator and Qml and Qml JavaScript, and try your code in it, just do
a dot import, and use the dot operator like you would for any Qml function, and if you cannot get it to work, try pasting in functions one at a time, till you get all you need to test them out, fix all the warnings and errors, so you have clean code, and get it to work, then take that code and test it in a web browser, and then you will know for sure if you have any interest in this project, I think you might like it, it gives you another platform to test your code on, then check out Felgo, and tell me you would not like to Sell your App on Google Play Store, if you are interested, I would help out on this project.

To be clear about what I would like to see this project do, for one, it has to run on all JavaScript Engines, and work good on all of them.

I am interested in the Web and Qml, and would use both, and for my effort, I would be willing to work on a Calculator that uses this code, it will be your Project and not mine, so I will do the project your way, for my part, I will write the program, test it, and once it works I will give it to you to do what you want with it, but I would like to see you sell it as a Felgo App on Google Play, and use that money to keep this project going, that way it is a win win, I can finish my Calculator, and use your code, so I can sell my App on Google Play Store, so there is a Darkside to my Plan, to make money and have Open Source at the Same time.

If you make a Qml JavaScript App that runs on any Browser, meaning I will also have to write a Web App, that looks like my Qml App, and to be clear, I am going to do this project anyway, it is part of my Galaxy Calculator, so it is not that much more work for me, if any, and as it is right now, I can not find a library that works the way I want it to, I need a float that I can change the number of decimal places, I do not really care about Precision, that term normally means the total amount of digits on the left and right side of a decimal place, but I do need to do math with a fixed Adjustable decimal place, and I do not know if your Library does that, since I never got it to work, so think about that, I also need it to return a fixed adjustable, meaning variable decimal place, so think about it and let me know.

Great to hear you like mathjs :)

I have tried many other libraries, and you are right, I have trouble with a lot of them, and that is just how the Engine works, it has a lot of the feature of a Normal JavaScript Engine, yet it is Qml, and does not support a lot of third party JavaScript code written for the web.

So if I understand it correctly, Qml has a JavaScript engine which is sort-of JavaScript but not ES5 compliant. I guess the only option to get mathjs running there is to write (and maintain) a port from ES5 to Qml-JavaScript. Please let me know if anyone is interested in that. If it works out, maybe we could create a link on the website to this Qml port.

To be clear about what I would like to see this project do, for one, it has to run on all JavaScript Engines, and work good on all of them.

It does. The problem though is that the JavaScript Engine of Qml is not standards compliant. It's not a problem of mathjs. I guess it would benefit Qml a lot to make their JavaScript engine ES5 compliant, so that people like you can "just" use any library there is on npm. Now, if there is only one tiny little thing that needs to be changed in mathjs to make it work on Qml I'm interested to hear about it and we can discuss it, but we can't add maintenance of a semi-JavaScript engine to the project itself.

Just a totally weird idea: there are compilers to compile JavaScript to C. Maybe you can get mathjs compiled into C and use that port in your application?

Doing more research into this issue:

https://wiki.qt.io/JavaScript

Read their short introduction:

Introduction

JavaScript is a minimalistic dynamically typed scripting language. It is truly object-oriented, although it lacks support for classes. Frequently associated with client-side web development, JavaScript is a language of its own. Originally developed at Netscape and nowadays standardized as ECMAScript-262 (3rd and 5th edition) , the language has found wide-spread use and circulates under various names. "JScript" is Microsoft's derivative of the language. "JavaScript" was the original name chosen by Netscape when the language was introduced with Netscape 2. Adobe's ActionScript was also based on ECMAScript-262 before version 3 was released.

Qt has been supporting a JavaScript engine compatible with ECMAScript-262 since Qt 4.3. This engine is called "QtScript" and was originally an independent implementation. Since Qt 4.5, QtScript has been based on JavaScriptCore from WebKit. Qt's new markup language(QML) makes intense use of QtScript. Property values in QML are JavaScript expressions and are evaluated using QtScript.

I got BigNumber.js to work, this is based on BigDecimal, I like to work with Decimal places instead of Precision, but for some reason, I just can not get this to work, after figuring out why I had issues with BigNumber working, I thought that it was the way I was importing the function, I tried multiple ways,
but nothing worked, I get an undefined error.

I get this error on import:

MathJs.js:11050: TypeError: Type error

That line is:

ArgumentsError.prototype.constructor = Error;

import QtQuick 2.0
// Math and math should not be the same
//import "math.js" as math; // I would think this steps on namespace, also it is still undefined
import "math.js" as MathJs;
Page {
    Component.onCompleted: {
        console.debug("test Started");
        // this does not work with or without MathJs, undefined error
        math.config( { number: 'BigNumber',   precision: 64 } );
        // let t = MathJs.math.eval('0.1 + 0.2');
        let t = math.eval('0.1 + 0.2');
        console.debug("t=" + t)
        console.debug("test Ended");
    }
}

I would really like to get this working, the only issue I have with BigNumber, is that I need a parser, or an eval that works with BigNumber, but for some reason, I can get BigNumber.js working, but not this Library, and it is a Qml JavaScript issue, or the way I am trying to use your Function in Qml, above is an example of how I am trying to do it.

Using BigNumber.js

import QtQuick 2.0
import "bignumber.js" as BigNumberJs;
Page {
    Component.onCompleted: {
        console.debug("test Started");
        BigNumber.config({ EXPONENTIAL_AT: 1e+9 });
        // this works with or without  BigNumberJs
        // or let t = new BigNumberJs.BigNumber("123.456");
        let t = new BigNumber("123.456");
        console.debug("t=" + t)
        console.debug("test Ended");
    }
}

If I could get your eval or parser to work with BigNumber, that would be great.

Thanks

math.js seems to work fine with QML as long as all the "use strict"; lines are commented-out.

import QtQuick 2.9
import QtQuick.Window 2.2
import "math.js" as Mathjs
// The `math` object is now available globally.

Window {
    visible: true
    width: 800
    height: 200

    Text {
        id: bigmathtext
        font.pointSize: 25
        anchors.centerIn: parent
    }

    function startup() {
        console.log(math.eval('0.1 + 0.2'));    // 0.30000000000000004

        const bigmath = math.create({
          number: 'BigNumber',
          precision: 32
        });

        const result = bigmath.eval('0.1 + 0.2');    // 0.3

        bigmathtext.text = result.toString();
    }

    Component.onCompleted: startup();
}

QMLmathjs.zip

It seems ridiculous that the Qt developers have not enabled their JavaScript engine to handle "use strict";.


Further investigation reveals that math.js also works if "use strict"; is replaced by ;"use strict";.


Further investigation reveals that only three of the 372 occurrences of "use strict"; need to be changed in math.js:

// Add a semicolon on lines 1962, 9004 and 11024.
;"use strict";

It seems like a bizarre parsing issue with the custom Errors.

I confirmed that it runs without the error in Qml, this solves my problem, the strange part to me is that BigNumber.js also has

'use strict';

Note the single quotes, compared to the double,
this is a separate issue, so I will close this issue, and report this issue.

I remember talk about this issue back when it first came out, mostly about the syntax,
why they did not go with STRICT=true is beyond me, but Qml has a lot more warnings in both projects,
and even some errors, I get the same warnings using JsLInt, or JsHint, so it is difficult to know if any of them are actually causing issues, till you try it.

Thanks, this really helped me.

wouw, thanks @MikeMcl for figuring this out, this solution is quite doable!

If this is not a known issue in the Qml community it may be good to open a topic there to get this addressed, it may solve issues not only with mathjs but also many other libraries.

In Qt Creator you get a lot of warnings, and use strict is one of them.

The way they implemented it came under fire way back when, there was talk about changing it to STRICT=true or false, that would have been the correct way of doing it, instead of this hack, also its scope is always defined as the root of the code, and calling functions means they must be included in them as well, why they implemented it this way is simple, it was added as a feature to JavaScript, by C programmers, who wanted to add this as a JavaScript Feature, but it only caused a lot of confusion, for example try this in your code:

var x = 'use strict';
x = x + ''; 

This was one way I have seen people swear works, if it does, the Engine is totally confused, and you might find it in some Qml apps that use the same code in but apps Web and Qml Engines, remember JScript, it had a few quarks with it also, having had to convert code from but to use in Qml, I find myself having to fix a lot of issues, but I do not like using a hack.

Another one I have seen is this:

function useStrict() {
    return 'use strict';
}

The concept was that it worked, how it worked is beyond my logic, just like the other hack,
but I will get jslint warnings, and JavaScript ignores // 'use strict', so that is not good solution, so out of all the hacks I have seen, this is the best on ;'use strict';

Qml JavaScript is not the latest Engine, it was one that was forked a long time ago, and they removed the use strict keyword, making it a default behavior, and most developers will comment them out, but this fix seems to be better, since it can still be used for other Engines, so most Qml JavaScript Developers know about this issue, but I did not know it would cause this error until now, for the most part I just ignored it, but now I know you can not ignore.

This is just one of many issues I have run into, but this one is one of the more annoying ones, because it is just a hack to begin with.

Instead of "use strict", I do like linters which warn you for anti-patterns in your code, for example eslint can warn you about using == instead of === and things like that. This way, you don't complicate the JS language itself, and can easily stay away from the bad parts of the language.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

skgadi picture skgadi  路  3Comments

gnobre picture gnobre  路  4Comments

nioate picture nioate  路  4Comments

lwirtz picture lwirtz  路  3Comments

kyoncy picture kyoncy  路  4Comments