Problems with JS implementation

Posted on
  • I noticed that many functions are not implemented, and some uncommon behaviour is not supported (eg: [1,2,,,5]), but those are not common problems.

    You will find many inconsistencies by running the tests here, but I will list the most likely to affect users:

    • Unexpected if behaviour

      var asd = 1;
      if ( undefined )
      asd = 2;
      console.log('asd is:', asd); // 1 - is actually 2
      
    • Math.abs(-5) === 5, Math.log(Math.E*Math.E) === 2 and Math.log(1) === 0 should return true, but return false

    • no Date object

    • Number.POSITIVE_INFINITY === Infinity should be true but is actually false, same for NEGATIVE_INFINITY

    • (8.5).toString(16) should be 8.8 but found 8.5

    • (-8.5).toString(16) should be -8.8 but found -8.5

    • 09 should be 9 but found 0

    • 019 should be 19 but found 1

    • var i = -8; i >>>= 24 should be 255 but found 1099511627775

    • Math.PI should be 3.141592653589793 but found 3.141592653590000061569

    • Math.E should be 2.718281828459045 but found 2.718281828459999882596

    • Math.atan2(-1, Infinity) should be negative 0 (so -0) but found NaN

    • toFixed does not work although I remember @Gordon saying it was implemented

    • 'abc' ? 1 : 2 should be 1 but found 2

    • Trying to delete non-deletable properties eg: delete Array.prototype should return false but object is returned. delete always returns the value, so it's impossible to tell if the property was deleted or not from its return.

    • Redefining a var inside the same scope does not work

      var a = 'asd';
      console.log(a); // asd
      var a;
      console.log(a); // undefined - is actually asd
      
    • no unicode

      var u = "a\u1234c";
      console.log(u.charCodeAt(1)) // 4660 - is actually 117
      
    • the for (x in y) works differently with {}, for example the following code behaves differently if curly braces are used to wrap {propnames.push(i);}, view the comments.

      var arr = new Array('a','b','c');
      var propnames = [];
      for (var i in arr)
      propnames.push(i);
      
      console.log(propnames.length); // 3 - is actually 1
      console.log(propnames[0]); // 0 - is actually 2
      console.log(propnames[1]); // 1 - is actually undefined
      console.log(propnames[2]); // 2 - is actually undefined
      

    Other than not-yet-implemented functions and these examples, most tests in here run ok.

  • I have attached a file, if anyone wants to run the tests on their espruino. It contains a limited set of browser tests adapted to work on our devices.


    1 Attachment

  • For the octal part, 019 gets me an non-octal SyntaxError in Firefox, however, Espruino doesn't handle exceptions at the moment, so I guess either it should stay as-is or output NaN.

    As for the 2 constants, I guess this is a normal behaviour in the case of how floats are implemented on hardware. It can not be more precise than the hardware itself.

  • Hi. Thanks for the post. It'd actually be really handy if you could split some of the tests and issue a pull request for: https://github.com/espruino/Espruino/tree/master/tests (these rely on a variable called 'result' being set to either true or false). At least then we could quantify and work towards fixing some of these (there's a handy graph here: http://www.espruino.com/binaries/git/stats.html).

    You've spotted some interesting behaviour. One that is major but that I hadn't noticed is that === draws a distinction between int and float (which obviously it shouldn't as in JS everything is supposed to be a float). Hence I think a lot of your number-based tests will pass once 3.0===3 does!

    I'll try and sort some of those issues out - however I won't manage to get everything done... The hardware interface side of things needs a lot of work too but tends to get ignored because it's not as easy to test as just running JS language tests :)

  • Just to add: (8.5).toString(16) should be 8.8 but found 8.5 - this was fixed a few days ago and will be in 1v51.

  • Also, just wanted to say: some bits of JS are nasty and it pains me to implement them.

    >08
    =8
    >07
    =7
    

    But...

    >018
    =18
    >017
    =15
    >01A
    "Unexpected token ILLEGAL"
    >parseInt("01A")
    =1
    >17.
    =17
    >017.
    "Unexpected end of input"
    >parseInt("017.")
    =17
    
  • Ok, a bunch of these are now fixed. Your bug with for (i in foo) is actually to do with the way the Web IDE sends data to Espruino. We've got a bug open for it, and there's another one open in Espruino itself.

    If you write it in the console it's much more obvious what the problem is, because as you hit enter after the first line, Espruino executes it.

    if (false)
      console.log("No!");
    if (false)
    {
      console.log("No!");
    }
    

    Both print No!, but the following work:

    if (false) console.log("No!");
    if (false) {
      console.log("No!");
    }
    

    And the Web IDE does basically just paste code into the console, when it ought to do something a bit more interesting.

  • Allright I'll test against the latest dev version after work or tomorrow, and send proper pull requests if problems persist. Thanks for looking into this.

  • I saw that you mentioned exception are not supported right now. I am using the Adafruit CC3000 breakout and try to run a http post every 5 seconds to report some button states. I get a

    ERROR: Unable to locate host
    

    very often or the cc3000 dies altogether and making the espruino unresponsive and not run any code. Is there any way to recover from such an exception right now?

  • Could you start a new post for that please? I guess it's possible that the CC3000 has become disconnected from the internet.

    I guess it's possible that Espruino doesn't recover properly if the request fails at that point. The worst that should happen is that it hangs for 10 seconds, times out, and then reboots the CC3000.

  • I just thought I'd add another item I've just come across, rather than starting a new post (unless you have a preferred way of people reporting JS syntax issues?). In JS, it's common practice to namespace your code, which can be done in a number of ways, but the simplest way by far is

    var com = com || {};
    com.mynamespace = com.mynamespace || {};
    com.mynamespace.MyClass = function(){
        ...
    };
    

    This currently doesn't work however as rather than just reporting the variable as null and then falling back to the blank object, it actually errors with "Field or method does not already exist".

    Matt

  • Hi Matt,

    Probably the best place for this kind of thing is the Espruino github issue tracker. I've just made a bug for this: https://github.com/espruino/Espruino/issues/251

    The issue is that currently || (and &&) cast the values to booleans - rather than returning the value if it is true. Hopefully it's not a hard fix though.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Problems with JS implementation

Posted by Avatar for randunel @randunel

Actions