Skip to content

Issues with LambdaS5

Marek Materzok edited this page Dec 16, 2015 · 56 revisions

Semantics problems

  • Setting fields syntax form obj[name=value] is parsed as let (v=value) {obj[name=v, {[] "0": {#value: v, #writable: true}}]} - this is very strange!

  • Setter functions for obj[name=value,arg] only receive name and arg, value is not passed

  • Trying to create a new field on an unextensible object returns undefined - it would be more consistent with the rest of semantics to throw some exception

  • What should be the default value of obj<#code> - null or undefined? Paper suggests undefined, code suggests null.

  • Should obj<#code> be allowed to be anything other than a closure if defined?

  • obj<#primval> is "unset" by default in the code (the paper specifies undefined), but it seems there is no value in that, this complicates semantics.

  • try e1 finally e2 returns the value of e1 in the semantics, and value of e2 in the interpreter.

  • Interpreter does not check the object's 'extensible' property when shadowing a field -- the check is in the semantics.

  • Undefined getters/setters are not handled - the following program crashes:

      var o = { set x(v) {} }; o.x
    

    ES5: 8.12.3 1, 8.12.4 2.a.i 7.a; ES6: 9.1.8 7, 9.1.9 8

    New test created: get-getter-undefined.js

  • The following program returns 1 instead of 2:

      var x = {set y(v) { return 1 }};
      x.y = 2
    

    ES5: 11.13.1 6, ES6: 12.14.4 11

Desugaring bugs

  • The following program returns 3 instead of 2 in S5:

      var o = {x: 0};
      function f() { o.x++; return o };
      (f()).x += 1
    

    ES5: 11.13.2 2, ES6: 12.14.4 2

  • The following program prints just A instead of A B:

      switch(1) {default: print("A"); case 2: print("B")}
    

    ES5: ???, ES6: 13.12.9 12

  • This program returns 1:

      "use strict"; var x = {get a() { var y = 1; return y; }}; x.a
    

    This program throws an exception in S5:

      "use strict"; if (false) y = 0; var x = {get a() { var y = 1; return y; }}; x.a
    

    Implementation-related bug.

  • This program returns 1 in S5, should return 5:

      a: for (var x = 1; x < 5; x+=1) { continue a }; x
    

    Labeled continue was not implemented; it worked like break.

  • This program returns 1 in S5, should return undefined:

      var x = 1
    

    ES5: 12.2, ES6: 13.3.2.4

    New test created: var-empty-completion.js

  • This program returns 1 in S5, should return 0:

      function f(x) {x = 0; return arguments[0] }; f(1)
    

    This is fine for strict mode, but wrong for sloppy mode.

  • This program returns 1 in S5, should return 2:

      var x = 1; try { throw 1 } catch (e) { (function() { e = 2 })(); x = e }; x
    
  • This program returns 120 in S5, should throw an exception:

      var x = function f (a) { var f; if (a == 0) return 1; else return a * f(a-1) }; x(5)
    

    ES5 10.4.3 5, 10.5

  • This program returns "null" instead of "object":

      typeof null
    

    ES5 11.4.3, ES6 12.5.6

    Tested by: 11.4.3_A3.2 (null.js)

  • This program fails in S5 instead of returning true:

      function x() {}
      x == x
    

    ES5 11.9.3 1.f, ES6 7.2.12 3.a

  • This program gives "numbernumber", should give "numberobject":

      "use strict";
      Number.prototype.f = function () { return typeof this };
      var x = 1;
      var y = new Number(2);
      x.f() + y.f()
    

    ES5 10.4.3 1, ES6 9.2.1.2 5

    Tested by: 10.4.3-1-1-s

  • The arguments object is often not the real arguments object, as defined by the spec. For example, this program returns undefined instead of 0:

      var obj = {get f() { return arguments.length }};
      obj.f
    
  • The new operator does not check if the constructor argument is an object. This program fails instead of throwing TypeError:

      new 1
    

    ES5 11.2.2 3, ES6 7.2.4 & 12.3.3.1.1 8

    Tested by: S11.2.2_A3_T1

  • The delete operator only works on objects. The following program crashes instead of returning true:

      var x = 1; delete x.a
    

    ES5 11.4.1 4.a, ES6 12.5.4.2 5.b

    New test created: delete-primitive-field.js

  • Deleting an nonexistent property returns false instead of true:

      var x = {}; delete x.a
    

    ES5 8.12.7 2, ES6 9.1.10 4

    Tested by: S8.12.7_A2_T1, S8.12.7_A2_T2

  • Deleting a nonconfigurable property fails instead of returning false:

      var x = {a:1}; Object.seal(x); delete x.a
    

    ES5 8.12.7 5, ES6 9.1.10 6

    Tested by: 11.4.1-4.a-3

  • Deleting a nonconfigurable property in strict mode fails instead of throwing TypeError:

      "use strict"; var x = {a:1}; Object.seal(x); delete x.a
    

    ES5 8.12.7 4, ES6 12.5.4.2 5.e

    Tested by: 11.4.1-4.a-3-s

  • Deleting a non-reference expression does not evaluate it - the following program does not throw:

      delete ((function f() { throw 1 })())
    

    ES5 11.4.1 1, ES6 12.5.4.2 1

    New test created: delete-expr-evaluated.js

  • Adding new fields to a binding object in the with statement does not make new variables visible:

      var x = {};
      with (x) { x.b=1; b }
    
  • Getters and setters created using object literals are unconfigurable in S5, but they should be configurable.

      var x = {get f(){}};
      Object.getOwnPropertyDescriptor(x,"f").configurable
    

    ES5 11.1.5, ES6 14.3.9

  • S5 improperly distinguishes calling/constructing. The following program returns a string object instead of a string:

      var obj = {f:String}
      obj.f(1)
    
  • Number.toString does not throw the right exception when called with a wrong radix:

      1..toString(-1)
    

    ES5 15.7.4.2, ES6 20.1.3.6 7

  • Object.hasOwnProperty does not call ToString on its argument. Following program fails:

      Object.hasOwnProperty(1)
    

    ES5 15.2.4.5 1, ES6 19.1.3.2 1

  • Elisions in array literals do not result in the respective indexes being undefined. The following program gives "true,true,true,false" instead of "true,false,true,false":

      var x = [1,,3,]
      print(x.hasOwnProperty("0"));
      print(x.hasOwnProperty("1"));
      print(x.hasOwnProperty("2"));
      print(x.hasOwnProperty("3"))
    
  • Recursive function definition does not get an immutable binding. The following program gives 0 instead of a function:

      f = function f() { f = 0; return f };
      print(f())
    
  • The same problem is also in strict mode, if one uses eval. This program should throw TypeError, but returns 0 in S5:

      "use strict";
      var f = function f() { eval("f = 0"); return f };
      print(f())
    
  • Eval in non-strict mode does not handle the variable environment correctly in S5. The following program should return 2, it throws in S5:

      try { throw 1 } catch (x) { eval("var y = 2") }; y
    
  • Function redefinition is handled incorrectly. The following program does not crash, it should throw TypeError:

      Object.defineProperty(this, 'f', {
        value: 42,
        writable: true,
        enumerable: false,
        configurable: false
      });
      eval("function f(){}")
    
  • Array length change works incorrectly when the array has unconfigurable fields. The following program crashes the interpreter (it should give 2):

      x=[1,2,3];
      Object.defineProperty(x,1,{configurable:false});
      x.length=0;
      x.length
    
  • Array length change does not work using defineProperty (this should give undefined, it gives 3):

      x=[1,2,3];
      Object.defineProperty(x,"length",{value:1});
      x[2]
    
  • The bind objects do not realize isinstanceof properly. The following program throws instead of returning true:

      function f(){};
      var o = new f();
      var fb = f.bind();
      o instanceof fb
    

Environment bugs

  • These programs returns 9 instead of 6:

      (new Array(3, 2, 1, 0)).reduceRight(function(a, b) { return a + b; });
    
      (new Array(0, 1, 2, 3)).reduceRight(function(a, b) { return a + b; });
    
  • This program returns 6 instead of 3:

      (new Array(0, 0, 0, 0)).reduceRight(function(a, b, i) { return a + b + i; });
    
  • Prototypes for native errors did not have the correct class and message fields.

  • Invalid prototypes for error constructors: error prototypes instead of function prototypes were used. The following program should give true, in S5 it gives false.

      TypeError.constructor === Function.constructor
    
  • Undefined length property for many built-in function objects.