Some people are better at applying Murphy's Law than others. It's a valuable skill.
On 2013-09-20, at 11:06 AM, André Bargull <andrebarg...@googlemail.com> wrote: > Yeah, I start to feel nervous reporting all these issues en masse. Especially > since you like handguns according to your twitter profile! Maybe I should > consider wearing a bullet-resistant vest in public. :-D > > I've possibly already spend too much time on the ECMAScript specification, so > I just know where to look for when reviewing the source code. That really > sounds like a poor explanation. Basically for ECMAScript you need to apply > Murphy's law ("Whatever can go wrong will go wrong.") all the time. But I bet > this is no news for you! > > > - André > > > On 9/20/2013 3:15 PM, Marcus Lagergren wrote: >> Wow! How do you find all these! This is extremely helpful, even though I'm >> not sure if I should hug you or beat you up ;-) >> >> /M >> >> On Sep 20, 2013, at 3:03 PM, André Bargull <andrebarg...@googlemail.com> >> wrote: >> >>> Some more compliance issues... :( >>> >>> - André >>> >>> >>> jjs> JSON.parse('{"a":0,"b":1}', function(p,v){print("p:"+p+"-"+v); >>> if(p=="a"){this.b = Object.create({c:0})} return v}) >>> >>> Expected: property "c" not visited >>> Actual: property "c" visited >>> >>> jjs> JSON.parse('{"a":0,"b":1}', function(p,v){print("p:"+p+"-"+v); >>> if(p=="a"){var arr=[123]; arr.x = 456; this.b=arr} return v}) >>> >>> Expected: property "x" not visited >>> Actual: property "x" visited >>> >>> jjs> JSON.parse('{"a":0,"b":1}', function(p,v){print("p:"+p+"-"+v); >>> if(p=="a"){ this.b = {get x(){print("456"); return null}, set >>> x(_){print("whoa")}} } return v}) >>> >>> Expected: "whoa" not printed >>> Actual: "whoa" printed >>> >>> jjs> JSON.parse('{"a":0,"b":1}', function(p,v){print("p:"+p+"-"+v); >>> if(p=="a"){ this.b=Object.defineProperty({},"0",{value:123,enumerable:1}) } >>> return (p!="0"?v:456) }).b[0] >>> >>> Expected: returns 123 >>> Actual: returns 456 >>> >>> jjs> JSON.stringify({get x(){print("getter called")}}, ["x", "x"]) >>> >>> Expected: "getter called" appears once >>> Actual: "getter called" appears twice >>> >>> jjs> JSON.parse('[0,]') >>> >>> Expected: JSON SyntaxError >>> Actual: No SyntaxError >>> >>> jjs> JSON.parse('{"a":0,}') >>> >>> Expected: JSON SyntaxError >>> Actual: No SyntaxError >>> >>> jjs> JSON.stringify({},[],new Number(Infinity)) >>> >>> Expected: no ClassCastException >>> Actual: ClassCastException thrown >>> >>> jjs> JSON.stringify({},[],(n = new Number(0), n.valueOf = function(){throw >>> "blubb"}, n)) >>> >>> Expected: "blubb" is thrown >>> Actual: no exception >>> >>> jjs> JSON.stringify({},[],(n = new String(""), n.toString = >>> function(){throw "blubb"}, n)) >>> >>> Expected: "blubb" is thrown >>> Actual: no exception >>> >>> jjs> (function f(a){ Object.defineProperty(arguments,"0",{get >>> value(){print("arrrgh")}}) })(0) >>> >>> Expected: "arrrgh" printed once >>> Actual: "arrrgh" printed twice >>> >>> jjs> new >>> RegExp({toString:function(){print("str1")}},{toString:function(){print("str2")}}) >>> >>> Expected: "str1" and then "str2" >>> Actual: "str2" and then "str1" >>> >>> jjs> new RegExp(/asdf/, {toString:function(){throw "blubb"}}) >>> >>> Expected: throw TypError instead of "blubb" >>> Actual: "blubb" is thrown >>> >>> jjs> "use strict"; >>> Object.defineProperty(Object.defineProperty(/a/.exec("a"),"0",{configurable:0}), >>> "length", {value:0}).length >>> >>> Expected: throws TypeError >>> Actual: returns 0 >>> >>> jjs> try{Object.defineProperty(a=[],"length",{writable:false, >>> value:-1})}catch(e){} >>> >>> Expected(?): a can still perform bulk ops >>> Actual: IS_LENGTH_NOT_WRITABLE flag is set for a >>> >>> jjs> (function(a){ Object.defineProperty(arguments,"0",{get >>> configurable(){a=3; return true}, get:function(){return 2}}); return >>> [a,arguments[0]] })(0) >>> >>> Expected: returns array [3,2] >>> Actual: returns array [0, 3] >>> >>> jjs> >>> Object.defineProperties(Object.defineProperty({},"a",{configurable:false}),{get >>> a(){print("a");return{get value(){return 0}}},get >>> b(){print("b");return{}}}) >>> >>> Expected: prints "a" and "b" then throws TypeError >>> Actual: prints "a" then throws TypeError >>> >>> jjs> Object.defineProperty({},"foo",{get configurable(){print("get >>> configurable")}, get value(){print("get value")}, get get(){print("get >>> get")}}) >>> >>> Expected: prints "get configurable", "get value", "get get" and then >>> TypeError >>> Actual: immediately throws TypeError >>> >>> jjs> [1,2,3].splice(0) >>> >>> Expected: returns [1,2,3] for web compat >>> Actual: returns [] >>> >>> jjs> "0" in Array.prototype.slice.call(Object.create({length: 1}), 0, 1) >>> >>> Expected: returns false >>> Actual: returns true >>> >>> jjs> [0].map(function(){ return this === (1,eval)("this") }, null) >>> >>> Expected: returns [true] >>> Actual: returns [false] >>> >>> jjs> Object.defineProperty(Boolean.prototype, "length", {configurable:true, >>> get:function(){obj=this; return 1}})[0] = "blubb" >>> jjs> Array.prototype.reduce.call(false, >>> function(a,b,i,o){print("same:"+(obj===o))}, 0) >>> >>> Expected: prints "same:true" >>> Actual: prints "same:false" >>> >>> jjs> Object.defineProperty({},"",{get writable(){print("w")}, get >>> enumerable(){print("e")}, get configurable(){print("c")}, get >>> value(){print("v")}}) >>> >>> Expected: order is "e c v w" >>> Actual: order is "c e w v" >>> >>> jjs> Object.defineProperty({},"",{get enumerable(){print("e")}, get >>> configurable(){print("c")}}) >>> >>> Expected: order is "e c" >>> Actual: order is "c e" >>> >>> jjs> Object.defineProperty({},"",{get enumerable(){print("e")}, get >>> configurable(){print("c")}, get get(){print("g")}, get set(){print("s")}}) >>> >>> Expected: order is "e c g s" >>> Actual: order is "c e g s" >>> >>> jjs> Object.defineProperty([], "length", >>> {value:{valueOf:function(){Object.prototype.get = 0; return 0}}}) >>> >>> Expected: no TypeError >>> Actual: throws TypeError >>> >>> jjs> Object.defineProperty(a=[1,2,3], "length", >>> {value:{valueOf:function(){a[5] = 0; Object.seal(a); return 3}}}) >>> >>> Expected: TypeError is thrown >>> Actual: no TypeError >>> >>> jjs> Object.defineProperty(a=[0], "length", >>> {value:{valueOf:function(){Object.defineProperty(a,1,{get:function(){return >>> -1}}); return 1}}})[1] >>> >>> Expected: throw TypeError >>> Actual: returns -1 and array invariant violation >>> >>> jjs> Object.prototype.get = 0; Object.defineProperty([],0,{__proto__: null, >>> value:1}) >>> >>> Expected: returns array [1] >>> Actual: TypeError is thrown >>> >>> jjs> >>> Object.defineProperty([],"length",{value:{valueOf:function(){print("asdf"); >>> return 0}}}).length >>> >>> Expected: print "asdf" twice >>> Actual: "asdf" is printed only once >>> >>> jjs> def = function(o,i){return >>> Object.defineProperty(o,i,{configurable:true, >>> get:function(){print("getter:"+i); o.length=0; return void 0}})} >>> jjs> def(def([1,2,3],0),1).concat([]) >>> >>> Expected: don't print "getter:1" >>> Actual: "getter:1" is printed >>> >>> jjs> def = function(o,i){return >>> Object.defineProperty(o,i,{configurable:true, get:function(){o.length=0; >>> return void 0}})} >>> jjs> "1" in def(def([1,2,3],0),1).concat([]) >>> >>> Expected: returns false >>> Acual: returns true >>> >>> jjs> >>> Array.prototype.pop.call(Object.defineProperty({},"length",{get:function(){java.util.Objects.requireNonNull(null)}})) >>> >>> Expected(?): don't swallow ClassCastExceptions and NullPointerExceptions in >>> Array.prototype.pop et al. >>> Actual: throws a TypeError >>> >>> jjs> [].shift.call(o={length:2, 0:0}); "0" in o >>> >>> Expected: returns false >>> Actual: returns true >>> >>> jjs> "0" in [].slice.call({length:1}) >>> >>> Expected: returns false >>> Actual: returns true >>> >>> jjs> Object.defineProperty([],0,{get:function(){print("ggett")}}).unshift(1) >>> >>> Expected: "ggett" printed and then TypeError thrown >>> Actual: returns 2 >>> >>> jjs> [].indexOf(null, {valueOf:function(){throw "not reached"}}) >>> >>> Expected: returns -1 >>> Actual: throws "not reached" >>> >>> jjs> String.prototype.charAt.call({toString:function(){print("toStr")}}, >>> {valueOf:function(){print("valueOf")}}) >>> >>> Expected: first "toStr" and then "valueOf" printed >>> Actual: "valueOf" and then "toStr" printed >>> >>> jjs> >>> String.prototype.charCodeAt.call({toString:function(){print("toStr")}}, >>> {valueOf:function(){print("valueOf")}}) >>> >>> Expected: first "toStr" and then "valueOf" printed >>> Actual: "valueOf" and then "toStr" printed >>> >>> jjs> "aa aa".match(/\b/g).length >>> >>> Expected: returns 4 >>> Actual: returns 6 >>> (Note: spec bug https://bugs.ecmascript.org/show_bug.cgi?id=1467) >>> >>> jjs> "aa aa".replace(/\b/g, "c") >>> >>> Expected: returns "caac caac" >>> Actual: returns "caacc caacc" >>> (Note: spec bug https://bugs.ecmascript.org/show_bug.cgi?id=1467) >>> >>> NativeString#splitString(), line 884: Why LinkedList instead of ArrayList? >>> >>> jjs> "ababab".replace(/b/g, function(){return RegExp.leftContext}) >>> >>> Expected: returns "aaaabaaababa" (web compat) >>> Actual: returns "aaa" >>> >>> jjs> (r = /a/g, r.lastIndex = 0x100000000, r).test("a") >>> >>> Expected: returns false >>> Actual: returns true >>> >>> jjs> parseFloat("2e2.") >>> >>> Expected: returns 200 >>> Actual: returns NaN >>> >>> jjs> parseInt("", {valueOf:function(){throw "blubb"}}) >>> >>> Expected: throws "blubb" >>> Actual: returns NaN >>> >>> jjs> parseInt("12345678901234567890", 10)+"" >>> >>> Expected: 12345678901234567000 >>> Actual: 12345678901234570000 >>> >>> jjs> (function f(){return eval("arguments"); var arguments})(); (function >>> f(){return eval("arguments"); function arguments(){}})(); >>> jjs> (function (){return eval("arguments"); var arguments})(); (function >>> (){return eval("arguments"); function arguments(){}})(); >>> java.lang.ClassCastException: Cannot cast >>> jdk.nashorn.internal.scripts.JO1P0 to jdk.nashorn.internal.scripts.JO2P0 >>> >>> (Execute both lines after each other in a fresh shell) >>> >>> Expected: return `function arguments(){}` for both lines >>> Actual: first lines returns undefined and then ClassCastException >> >