| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| |
| WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js"); |
| |
| function testGetPropertyNames(foo,checkForName) |
| { |
| var properties = Object.getOwnPropertyNames(foo); |
| var len = properties.length; |
| var check = 0; |
| for(var i = 0; i < len; i++) |
| { |
| var prop = properties[i].toString(); |
| if(prop == "prototype" || (checkForName && prop == "name") || |
| prop == "arguments" || prop == "caller" || prop == "length") |
| { |
| check++; |
| } |
| if (!checkForName && prop == "name") |
| { |
| return false; |
| } |
| } |
| return check == len; |
| } |
| |
| var tests = [ |
| { |
| name: "function.name", |
| body: function () |
| { |
| function foo(){} //function declaration |
| assert.areEqual("foo",foo.name,"name should be foo"); |
| foo.name = "bar"; |
| assert.areEqual("foo",foo.name, "function names are read only"); |
| assert.areEqual("funcExpr",(function funcExpr(){}).name,"function expression case should still print a name"); |
| assignment = function(){}; // "assignment" |
| assert.areEqual("assignment",assignment.name,"Assignment functions should print the assigned name"); |
| var lambdaDecl = () => {}; // "lambda assignment" |
| assert.areEqual("lambdaDecl",lambdaDecl.name,"lambda assignment should print the assigned name"); |
| var a = function bar() {} |
| var b = foo; |
| assert.areEqual("bar",a.name,"Assignment functions should inherit the declaration name in this case bar"); |
| assert.areEqual("foo",b.name,"Assignment functions should inherit the declaration name in this case foo"); |
| } |
| }, |
| { |
| name: "anonymous function", |
| body: function () |
| { |
| var f = function() { }; |
| assert.areEqual("f", f.name, "function name is determined on assignment"); |
| f.name = "foo"; |
| assert.areEqual("f", f.name, "function names are read only"); |
| assert.areEqual(undefined, (function (){}).prototype.name, "function.prototype.name is undefined"); |
| assert.isFalse(Object.hasOwnProperty.call((function(){}), 'name'), "[hasPropertyCheck]: anonymous function does not have a name property"); |
| assert.areEqual("", (function(){}).name); |
| assert.areEqual("", (function(){})["name"]); |
| |
| //lambdas () => {} |
| assert.isFalse(Object.hasOwnProperty.call((() => {}), 'name'), "[hasPropertyCheck]: anonymous lambda function does not have a name property"); |
| assert.areEqual("", (() => {}).name); |
| assert.areEqual("", (() => {})["name"]); |
| |
| //generators |
| assert.isFalse(Object.hasOwnProperty.call((function*(){}), 'name'), "[hasPropertyCheck]: anonymous generator function does not have name property"); |
| assert.areEqual("", (function*(){}).name); |
| assert.areEqual("", (function*(){})["name"]); |
| |
| //classes |
| assert.isFalse(Object.hasOwnProperty.call(class {}, 'name'), "[hasPropertyCheck]: anonymous class does not have a name property"); |
| assert.areEqual("", class {}.name); |
| assert.areEqual("", class {}['name']); |
| |
| } |
| }, |
| { |
| name: "function.name for external functions", |
| body: function () |
| { |
| assert.areEqual("LoadScriptFile",WScript.LoadScriptFile.name,"check to make sure external functions are supported"); |
| assert.areEqual("Quit",WScript.Quit.name,"check to make sure external functions are supported"); |
| assert.areEqual("LoadScript",WScript.LoadScript.name,"check to make sure external functions are supported"); |
| assert.areEqual("SetTimeout",WScript.SetTimeout.name,"check to make sure external functions are supported"); |
| assert.areEqual("ClearTimeout",WScript.ClearTimeout.name,"check to make sure external functions are supported"); |
| |
| assert.areEqual("prototype,name,caller,arguments",Object.getOwnPropertyNames(WScript.Quit).toString(),"Check to make sure name is exposed"); |
| |
| //Bug 639652 |
| var a = WScript.Echo.toString(); |
| var b = WScript.Echo.name; |
| assert.areEqual("Echo",b,"b should be the name of function echo not toString of Echo function body"); |
| |
| } |
| }, |
| { |
| name: "static name method overrides the creation of a name string.", |
| body: function () |
| { |
| //default constructor case |
| var qux = class { static name() {} }; |
| assert.areEqual("function", typeof qux.name, |
| "14.5.15 Runtime Semantics: If the class definition included a 'name' static method then that method is not over-written"); |
| assert.areEqual("name",qux.name.name,"confirm we get the name 'name'"); |
| assert.areEqual(qux.name , qux.prototype.constructor.name, |
| "confirm qux.prototype.constructor.name is the same function as qux.name"); |
| assert.areEqual("Function",qux.constructor.name,"The function constructor should still have the name Function"); |
| |
| var qux = class { constructor(a,b) {} static name() {} }; |
| var quxobj = new qux(1,2); |
| assert.areEqual("function", typeof qux.name, |
| "14.5.15 Runtime Semantics: If the class definition included a \"name\" static method then that method is not over-written"); |
| assert.areEqual("name",qux.name.name,"confirm we get the name \"name\""); |
| assert.areEqual(qux.name , qux.prototype.constructor.name, |
| "confirm qux.prototype.constructor.name is the same function as qux.name"); |
| assert.areEqual("Function",qux.constructor.name,"The function constructor should still have the name Function"); |
| } |
| }, |
| { |
| name: "function.name's that match IsConstantFunctionName", |
| body: function () |
| { |
| var o = { |
| "" : function() {}, |
| "Anonymous function" : function() {}, |
| "Function code" : function() {} |
| } |
| assert.areEqual("", o[""].name); |
| assert.areEqual("Anonymous function", o["Anonymous function"].name, "should not get converted to empty string"); |
| assert.areEqual("Function code", o["Function code"].name, "should not get converted to Anonymous"); |
| }, |
| }, |
| { |
| name: "function.name for built in constructors", |
| body: function () |
| { |
| function* gf() { } |
| assert.areEqual("GeneratorFunction", gf.constructor.name); |
| assert.areEqual("Array", Array.name); |
| assert.areEqual("ArrayBuffer", ArrayBuffer.name); |
| assert.areEqual("DataView", DataView.name); |
| assert.areEqual("Error", Error.name); |
| assert.areEqual("SyntaxError", SyntaxError.name); |
| assert.areEqual("EvalError", EvalError.name); |
| assert.areEqual("RangeError", RangeError.name); |
| assert.areEqual("ReferenceError", ReferenceError.name); |
| assert.areEqual("Boolean", Boolean.name); |
| assert.areEqual("Symbol", Symbol.name); |
| assert.areEqual("Promise", Promise.name); |
| assert.areEqual("Proxy", Proxy.name); |
| assert.areEqual("Date", Date.name); |
| assert.areEqual("Function", Function.name); |
| assert.areEqual("Number", Number.name); |
| assert.areEqual("Object", Object.name); |
| assert.areEqual("RegExp", RegExp.name); |
| assert.areEqual("String", String.name); |
| assert.areEqual("Map", Map.name); |
| assert.areEqual("Set", Set.name); |
| assert.areEqual("WeakMap", WeakMap.name); |
| assert.areEqual("WeakSet", WeakSet.name); |
| } |
| }, |
| { |
| name: "Numeric value test cases", |
| body: function () |
| { |
| var a = []; |
| var b = 1; |
| var c = 2; |
| a[4] = function() {}; |
| a[1.2] = function() {}; |
| function foo() |
| { |
| return a; |
| } |
| foo()[5] = function() {}; |
| a[4+3] = function() {}; |
| a[b] = function() {}; |
| a[c] = function() {}; |
| a[b+c] = function() {}; |
| var index1 = 4; |
| var index2 = 4+8; |
| var o = { index1 : function() {}, index2 : function() {}, [index1+1] : function() {}} |
| assert.areEqual("index1", o.index1.name); |
| assert.areEqual("index2",o.index2.name); |
| assert.areEqual("5", o[5].name, "when our name has brackets return the computed name") |
| assert.areEqual("b",a[1].name,"expressions are not evaluated, default to expression name"); |
| assert.areEqual("c",a[2].name,"expressions are not evaluated, default to expression name"); |
| assert.areEqual("1.2",a[1.2].name,"constants are the given numeric literal"); |
| var o = { 1.4 : function() {} }; |
| assert.areEqual("1.4",o[1.4].name,"constants are the given numeric literal"); |
| assert.areEqual("",a[3].name,"expressions are not evaluated, default to empty string since it lacks a variable name"); |
| assert.areEqual("4",a[4].name,"constants are the given numeric literal"); |
| assert.areEqual("5",a[5].name,"constants are the given numeric literal"); |
| assert.areEqual("",a[7].name,"expressions are not evaluated, default to empty string since it lacks a variable name"); |
| } |
| }, |
| { |
| name: "Strings With Brackets or Periods in them", |
| body: function () |
| { |
| var o = { "hello.friend" : function() {}, |
| "[a" : function() {}, |
| "]" : function() {}, |
| "]a" : function() {}}; |
| assert.areEqual("hello.friend",o["hello.friend"].name,"the period is included in the name don't shorten"); |
| assert.areEqual("[a",o["[a"].name,"the bracket is included in the name don't shorten"); |
| assert.areEqual("]",o["]"].name,"the bracket is included in the name don't shorten"); |
| assert.areEqual("]a",o["]a"].name,"the bracket is included in the name don't shorten"); |
| |
| var o = { "a[" : function() {} }; |
| assert.areEqual("a[",o["a["].name,"the bracket is included in the name don't shorten"); |
| var o = { ["a["] : function() {} }; |
| assert.areEqual("a[",o["a["].name,"computed property names use a different code path"); |
| var a = []; |
| a["["] = function() {}; |
| a["]"] = function() {}; |
| assert.areEqual("",a["["].name); |
| assert.areEqual("",a["]"].name); |
| a["hello.buddy"] = function() {}; |
| assert.areEqual("",a["hello.buddy"].name); |
| |
| class ClassTest |
| { |
| static [".f"]() {} |
| static ["f."]() {} |
| static ["f["]() {} |
| static ["f]"]() {} |
| static ["]]f]]"]() {} |
| static ["[f"]() {} |
| static ["[[[[[f"]() {} |
| static ["]f"]() {} |
| } |
| assert.areEqual("f.", ClassTest["f."].name); |
| assert.areEqual(".f", ClassTest[".f"].name); |
| assert.areEqual("f[", ClassTest["f["].name); |
| assert.areEqual("f]", ClassTest["f]"].name); |
| assert.areEqual("]]f]]", ClassTest["]]f]]"].name); |
| assert.areEqual("[f", ClassTest["[f"].name); |
| assert.areEqual("[[[[[f", ClassTest["[[[[[f"].name); |
| assert.areEqual("]f", ClassTest["]f"].name); |
| |
| var a = {"\0" : { f : function() {}, c : class {} }} |
| assert.areEqual("f", a["\0"].f.name); |
| assert.areEqual("c", a["\0"].c.name); |
| } |
| }, |
| { |
| name: "Class.name", |
| body: function () |
| { |
| var a = class foo {} |
| assert.areEqual("foo",a.name,"should pick the class name not the assignment name"); |
| class ClassDecl {} // constructor is "ClassDecl" |
| var c = class { method(){}} |
| var b = new c(); |
| assert.areEqual("ClassDecl",ClassDecl.name,"name should be ClassDecl"); |
| assert.areEqual("c",c.name,"class name should be c"); |
| assert.areEqual("method",b.method.name,"c is a constructor, b is an instance so method is accessible on b"); |
| ClassDecl.name = "foo"; |
| assert.areEqual("ClassDecl",ClassDecl.name, "function names are read only"); |
| assert.areEqual("ClassExpr",(class ClassExpr {}).name,"class expression case should still print a name"); |
| |
| var classFoo = class |
| { |
| constructor(){} // "classFoo " |
| static func(){} // "func" |
| method(){} // "method" |
| get getter(){} // "get getter" |
| set setter(v){} // "set setter" |
| }; |
| |
| class classFoo2 |
| { |
| constructor(){} |
| } |
| assert.areEqual("Function",classFoo2.constructor.name, "classFoo2.constructor.name === 'Function'"); |
| assert.areEqual("classFoo2",classFoo2.prototype.constructor.name, "confirm that the prototype constructors name is the class name"); |
| |
| var oGet = Object.getOwnPropertyDescriptor(classFoo.prototype,"getter"); |
| var oSet = Object.getOwnPropertyDescriptor(classFoo.prototype,"setter"); |
| assert.areEqual("Function",classFoo.constructor.name, "classFoo.constructor.name === 'Function'"); |
| assert.areEqual("classFoo",classFoo.name, "Name of the class should be classFoo"); |
| assert.areEqual("classFoo",classFoo.prototype.constructor.name, "Name of the constructor should be the class name"); |
| assert.areEqual("func",classFoo.func.name, "Name should just be func"); |
| assert.areEqual("method",classFoo.prototype.method.name, "Name should be method"); |
| assert.areEqual("get getter",oGet.get.name,"Accessors getter should be prefixed with get"); |
| assert.areEqual("set setter",oSet.set.name, "Accessors setter should be prefixed with set"); |
| |
| var instanceFoo = new classFoo(); |
| var instanceFoo2 = new classFoo2(); |
| assert.areEqual("classFoo2",instanceFoo2.constructor.name, "instance constructor should be class name"); |
| assert.areEqual("classFoo",instanceFoo.constructor.name, "instance constructor should be class name"); |
| assert.areEqual("method",instanceFoo.method.name, "instance should have function name method"); |
| } |
| }, |
| { |
| name: "Generator functions", |
| body: function () |
| { |
| function* gf() { } |
| var gfe = function* () { } |
| var obj = { gfm : function* () { } } |
| assert.areEqual("gf",gf.name, "Generator Declaration"); |
| assert.areEqual("gfe",gfe.name, "Generator Expression"); |
| assert.areEqual("gfm",obj.gfm.name, "Generator Method"); |
| var GeneratorFunction = Object.getPrototypeOf(gf).constructor; |
| assert.areEqual("anonymous",(new GeneratorFunction ).name,"Should be anonymous"); |
| } |
| }, |
| { |
| name: "function inside objects", |
| body: function () |
| { |
| let obj = |
| { |
| prop: () => {}, |
| noOverride: function named(){}, |
| "literal": function(){}, |
| 5: () => {} |
| }; |
| |
| assert.areEqual("prop",obj.prop.name,"lambda function name is assigned to prop"); |
| assert.areEqual("named",obj.noOverride.name, "noOverride inherits name from function named"); |
| |
| assert.areEqual("literal",obj.literal.name, "string function definitions are valid"); |
| assert.areEqual("5",obj["5"].name, "numeral function definitions are valid"); |
| |
| var obj2 = |
| { |
| method(){} |
| } |
| obj2.property = function(){}; |
| |
| assert.areEqual("method",obj2.method.name, "tests functions without the function reserved word"); |
| assert.areEqual("",obj2.property.name, "test to make sure defining a property outside of a function is empty string"); |
| } |
| }, |
| { |
| name: "function.name's are read only", |
| body: function () |
| { |
| var object = |
| { |
| f: function() {} |
| }; |
| assert.areEqual("f",object.f.name, "function name is f"); |
| object.f.name = "foo"; |
| assert.areEqual("f",object.f.name, "function names are read only"); |
| |
| } |
| }, |
| { |
| name: "function.name test functions named get\set don't get confused for accessors", |
| body: function () |
| { |
| var foo = { |
| value : 0, |
| get : function() { return value;}, |
| set : function (val) {value = val} |
| } |
| assert.areEqual("get", foo.get.name, "name should be get"); |
| assert.areEqual("set", foo.set.name, "name should be set"); |
| |
| var obj3 = { get : function foo () { }, |
| set : function bar (v) { }}; |
| //like the var a = function foo() {} case a inherits foo's name |
| assert.areEqual("foo",obj3.get.name, "should inherited name foo"); |
| assert.areEqual("bar",obj3.set.name, "should inherited name bar"); |
| } |
| }, |
| { |
| name: "function.name accessor test", |
| body: function () |
| { |
| var oRuntime = Object.getOwnPropertyDescriptor(Map.prototype,"size"); |
| assert.areEqual("get size",oRuntime.get.name, "Map.prototype.size is a getter"); |
| assert.areEqual(undefined,oRuntime.set, "Map.prototype.size does not have a setter"); |
| // Single Property descriptor |
| var o = { get foo(){}, set foo(x){} }; |
| var descriptor = Object.getOwnPropertyDescriptor(o, "foo"); |
| assert.areEqual("get foo", descriptor.get.name, "get accessors on function foo are prefixed with get"); |
| assert.areEqual("set foo", descriptor.set.name, "set accessors on function foo are prefixed with set"); |
| |
| let obj = |
| { |
| get getter(){ return 0;}, |
| set setter(v){} |
| }; |
| |
| // Multiple property descriptors |
| var oGet = Object.getOwnPropertyDescriptor(obj,"getter") |
| var oSet = Object.getOwnPropertyDescriptor(obj,"setter"); |
| assert.areEqual("get getter",oGet.get.name, "get accessors functions are prefixed with get"); |
| assert.areEqual("set setter",oSet.set.name, "set accessors functions are prefixed with set"); |
| } |
| }, |
| |
| { |
| name: "function.name Property existence test", |
| body: function () |
| { |
| function foo(){} |
| |
| assert.areEqual(true,testGetPropertyNames(foo,true),"Properties on foo"); |
| assert.areEqual(0,Object.keys(foo).length,"no enumerable properties in function instance foo"); |
| Object.defineProperty(foo,"name",{writable: false,enumerable: true,configurable: true}); |
| var o = Object.getOwnPropertyDescriptor(foo,"name"); |
| assert.areEqual(true, o.enumerable, "Name is redefined to enumerable"); |
| for (i in foo) |
| { |
| assert.areEqual("name",i,"Name should be the only enumerable property"); |
| } |
| assert.areEqual(1,Object.keys(foo).length,"name is now an enumerated property"); |
| assert.areEqual("name",Object.keys(foo).toString(),"Name should be the only enumerable property"); |
| } |
| }, |
| |
| { |
| name: "function.name delete test", |
| body: function () |
| { |
| function foo(){} |
| |
| assert.areEqual(true,testGetPropertyNames(foo,true), "Properties on foo"); |
| delete foo.name; |
| assert.areEqual(true,testGetPropertyNames(foo,false),"Properties on foo"); |
| } |
| }, |
| |
| { |
| name: "built-in function.name", |
| body: function () |
| { |
| assert.areEqual("slice",[].slice.name,"name should be slice"); |
| [].slice.name = "bar"; |
| assert.areEqual("slice",[].slice.name, "function names are read only"); |
| } |
| }, |
| |
| { |
| name: "built-in function.name delete test", |
| body: function () |
| { |
| assert.areEqual(true,testGetPropertyNames([].splice,true),"Properties on foo"); |
| delete [].splice.name; |
| assert.areEqual(true,testGetPropertyNames([].splice,false),"Properties on foo"); |
| } |
| }, |
| { |
| name: "anonymous function special cases", |
| body: function () |
| { |
| assert.areEqual("anonymous",(new Function).name,"Should be anonymous"); |
| assert.areEqual("",Function.prototype.name,"19.2.3 The value of the name property of the Function prototype object is the empty String."); |
| |
| } |
| }, |
| { |
| name: "nested function assignment names", |
| body: function () |
| { |
| var obj = |
| { |
| x : function(){}, |
| y : () => {}, |
| z : class {} |
| }; |
| |
| assert.areEqual("x",obj.x.name,"x defined in obj Should be x"); |
| assert.areEqual("y",obj.y.name,"y defined in obj Should be y"); |
| assert.areEqual("z",obj.z.name,"z defined in obj Should be z"); |
| |
| var obj = |
| { |
| innerObj : |
| { |
| x : function(){}, |
| y : () => {}, |
| z : class {} |
| } |
| }; |
| |
| assert.areEqual("x",obj.innerObj.x.name,"Should be x"); |
| assert.areEqual("y",obj.innerObj.y.name,"Should be y"); |
| assert.areEqual("z",obj.innerObj.z.name,"Should be z"); |
| |
| var obj = {}; |
| obj.x = function(){}; |
| obj.y = () => {}; |
| obj.z = class {}; |
| |
| assert.areEqual("",obj.x.name,"Should be ''"); |
| assert.areEqual("",obj.y.name,"Should be ''"); |
| assert.areEqual("",obj.z.name,"Should be ''"); |
| |
| var obj = {innerObj : {}}; |
| |
| obj.innerObj.x = function(){}; |
| obj.innerObj.y = () => {}; |
| obj.innerObj.z = class {}; |
| |
| assert.areEqual("",obj.innerObj.x.name,"Should be ''"); |
| assert.areEqual("",obj.innerObj.y.name,"Should be ''"); |
| assert.areEqual("",obj.innerObj.z.name,"Should be ''"); |
| |
| } |
| }, |
| { |
| name: "Check the Class of an Object", |
| body: function () |
| { |
| function foo(){} |
| var f = new foo(); |
| |
| assert.areEqual("foo",f.constructor.name,"The constructor is foo"); |
| assert.areEqual(undefined,f.name,"f is an instance of the function foo, the name exists only on the constructor"); |
| |
| } |
| }, |
| { |
| name: "Attributes test", |
| body: function () |
| { |
| function foo(){} |
| assert.areEqual(true, foo.hasOwnProperty("name"), "foo should have a name property"); |
| var o = Object.getOwnPropertyDescriptor(foo,"name"); |
| |
| assert.areEqual(false, o.writable, "Name is not writable"); |
| assert.areEqual(false, o.enumerable, "Name is not enumerable"); |
| assert.areEqual(true, o.configurable, "Name is configurable"); |
| assert.areEqual("foo", o.value, "Names value should be foo"); |
| |
| } |
| }, |
| { |
| name: "Symbol names", |
| body: function () |
| { |
| var sym1 = Symbol("foo"); |
| var sym2 = Symbol("bar"); |
| var sym3 = Symbol("baz"); |
| var sym4 = Symbol(); |
| var o = {[Symbol.toPrimitive]: function() {}, |
| [sym1] : function() {}, |
| [sym3] : function bear() {}, |
| [sym4] : function() {}, |
| } |
| o[Symbol.unscopables] = function(){} |
| o[sym2] = function() {} |
| assert.areEqual("[foo]", o[sym1].name, "9.2.11.4 SetFunctionName: If Type(name) is Symbol, then let name be the concatenation of \"[\", description, and \"]\""); |
| assert.areEqual("[Symbol.toPrimitive]",o[Symbol.toPrimitive].name, |
| "9.2.11.4 SetFunctionName: If Type(name) is Symbol, then let name be the concatenation of \"[\", description, and \"]\""); |
| assert.areEqual("", o[Symbol.unscopables].name, "computed property names are not bound to index yet and builtin symbols are not bound to a name so they are empty strings"); |
| assert.areEqual("sym2", o[sym2].name, "computed property names are not bound to index yet"); |
| assert.areEqual("bear", o[sym3].name, "if the function already has a name don't overwrite it"); |
| assert.areEqual("", o[sym4].name, "empty symbols have empty string as a name"); |
| } |
| }, |
| { |
| name: "Redefine Attributes test", |
| body: function () |
| { |
| function foo(){} |
| |
| Object.defineProperty(foo,"name",{writable: true,enumerable: true,configurable: false}); |
| foo.name = "bar"; |
| var o = Object.getOwnPropertyDescriptor(foo,"name"); |
| |
| assert.areEqual(true, o.writable, "Name is redefined to writable"); |
| assert.areEqual(true, o.enumerable, "Name is redefined to enumerable"); |
| assert.areEqual(false, o.configurable, "Name redefined not configurable"); |
| assert.areEqual("bar", o.value, "Names value should be bar"); |
| assert.areEqual("bar",foo.name,"foo renamed to bar"); |
| |
| } |
| }, |
| { |
| name: "strings with null terminators sprinkled in", |
| body: function() |
| { |
| var str = "hello\0 foo"; |
| var a = []; |
| a["hello\0 foo"] = function() {}; |
| var o = {[str] : function() {}, ["h\0h"] : function() {}} |
| var b = {} |
| b["hello\0 foo"] = function() {} |
| var c = { "hello\0 foo" : function() {} } |
| assert.areEqual(str, o[str].name); |
| assert.areEqual("h\0h", o["h\0h"].name); |
| assert.areEqual("hello\0 foo", a["hello\0 foo"].name); |
| assert.areEqual("hello\0 foo", b["hello\0 foo"].name); |
| assert.areEqual("hello\0 foo", c["hello\0 foo"].name); |
| var d = { "goo.\0d" : function() {} } |
| var e = { "g\0oo\0.d" : function() {} } |
| var f = { "fo\0o" : class {} } |
| assert.areEqual("goo.\0d", d["goo.\0d"].name); |
| assert.areEqual("g\0oo\0.d", e["g\0oo\0.d"].name); |
| assert.areEqual("fo\0o", f["fo\0o"].name); |
| |
| } |
| }, |
| { |
| name: "Function Bind", |
| body: function() |
| { |
| function add(x, y) |
| { |
| return x+y; |
| } |
| var AddZer0 = add.bind(null,0 /* x */); |
| var Add2Nums = add.bind(); |
| |
| assert.areEqual("bound add",AddZer0.name, "AddZer0 needs a bound prefix on add"); |
| assert.areEqual("bound add",Add2Nums.name,"Add2Nums needs a bound prefix on add"); |
| } |
| }, |
| { |
| name: "Bug 1642987 & 1242667", |
| body: function() |
| { |
| e = ''['u3 = undefined'] = function () {} |
| assert.areEqual('', e.name, "Bug 1642987: we should not AV if we can't shorten the name") ; |
| f = ''['[f]o'] = function () {}; |
| assert.areEqual('', f.name, "Bug 1242667: We need to wrap strings in Brackets") ; |
| } |
| }, |
| { |
| name: "Bug 2302197", |
| body: function() |
| { |
| var b = {}; |
| var c = b.x = function Ctor() {} |
| var a = new c(); |
| assert.areEqual('Ctor', b.x.name, "confirm IsNameIdentifierRef does not override IsNamedFunctionExpression"); |
| assert.areEqual('Ctor', c.name, "confirm IsNameIdentifierRef does not override IsNamedFunctionExpression"); |
| assert.areEqual('Ctor', a.constructor.name, "confirm IsNameIdentifierRef does not override IsNamedFunctionExpression"); |
| } |
| }, |
| { |
| name: "Bug 3941893 & Bug 4153027", |
| body: function() |
| { |
| class B { |
| static ["n"+"a"+"me"]() {} |
| } |
| assert.areEqual("function", typeof B.name, "Function 'name' attribute should not be inferred in presence of static computed 'name' method"); |
| assert.areEqual("name", B.name.name, "Make sure the name is correct"); |
| var o = { |
| ['A'+'B'] : class extends B {}, |
| ['C'+'B'] : class {}, |
| |
| ['a'+'b'] : class extends B {foo_ab(){}}, |
| ['c'+'b'] : class {foo_cb(){}}, |
| |
| ['d'+'f'] : class extends B {static foo_df(){}}, |
| ['f'+'d'] : class {static foo_fd(){}} |
| } |
| |
| assert.areEqual("AB", o.AB.name, "confirm empty super class is properly assigned to a computed property"); |
| assert.areEqual("CB", o.CB.name, "confirm empty base class is properly assigned to a computed property"); |
| |
| assert.areEqual("ab", o.ab.name, "confirm filled super class is properly assigned to a computed property"); |
| assert.areEqual("cb", o.cb.name, "confirm filled base class is properly assigned to a computed property"); |
| |
| assert.areEqual("df", o.df.name, "confirm static filled super class is properly assigned to a computed property"); |
| assert.areEqual("fd", o.fd.name, "confirm static filled base class is properly assigned to a computed property"); |
| } |
| }, |
| { |
| name: "Bug 3713125", |
| body: function() |
| { |
| var target = Object.defineProperty(function() {}, 'name', { value: 'target' }); |
| assert.areEqual('bound bound target', target.bind().bind().name, "confirm bound is appended to the front twice"); |
| d = Object.getOwnPropertyDescriptor(target.bind().bind(), 'name') |
| assert.areEqual(false, d.writable); |
| assert.areEqual(false, d.enumerable); |
| assert.areEqual(true, d.configurable); |
| } |
| }, |
| { |
| name: "Bug 3713014", |
| body: function() |
| { |
| var namedSym = Symbol('test'); |
| var anonSym = Symbol(); |
| class A { |
| set [namedSym](_) {} |
| get [namedSym]() {} |
| } |
| var classASymbolSet = Object.getOwnPropertyDescriptor(A.prototype, namedSym).set; |
| var classASymbolGet = Object.getOwnPropertyDescriptor(A.prototype, namedSym).get; |
| |
| assert.areEqual("get [test]",classASymbolGet.name, " should not throw because of toString call on symbol"); |
| assert.areEqual("set [test]",classASymbolSet.name, " should not throw because of toString call on symbol"); |
| |
| class B { |
| set [anonSym](_) {} |
| get [anonSym]() {} |
| } |
| var classBSymbolSet = Object.getOwnPropertyDescriptor(B.prototype, anonSym).set; |
| var classBSymbolGet = Object.getOwnPropertyDescriptor(B.prototype, anonSym).get; |
| |
| assert.areEqual("get ",classBSymbolGet.name, " should not throw because of toString call on symbol"); |
| assert.areEqual("set ",classBSymbolSet.name, " should not throw because of toString call on symbol"); |
| |
| } |
| }, |
| { |
| name: "OS Bug 3933663 Classes Should not un-defer a class constructor before we store the computed property", |
| body: function() |
| { |
| var first = 'a'; |
| var second = 'b'; |
| var third = Symbol('c'); |
| var fourth = Symbol(); |
| var o; |
| o = { |
| [first]: class {}, |
| [second]: class {}, |
| [third]: class {}, |
| [fourth]: class {} |
| }; |
| assert.areEqual("a", o[first].name , "confirm class constructor names are the computed property value a"); |
| assert.areEqual("b", o[second].name, "confirm class constructor names are the computed property value b"); |
| assert.areEqual("[c]", o[third].name , "confirm class constructor names are the computed property value [c]"); |
| assert.areEqual("", o[fourth].name, "confirm class constructor names are the computed property value empty string"); |
| } |
| }, |
| { |
| name: "fix for toString override", |
| body: function() |
| { |
| var b="barzee"; |
| class foo { |
| [b] () {} |
| }; |
| var inst=new foo(); |
| inst[b].toString(); |
| assert.areEqual("barzee",inst[b].name); |
| } |
| }, |
| { |
| name: "Issue 539 Fix: preserve the shortNameOffset per append", |
| body: function() |
| { |
| class C { foo(){} }; |
| assert.areEqual("foo",(new C).foo.name); |
| } |
| }, |
| { |
| name: "Getter and setter have correct name in defineProperty", |
| body: function() |
| { |
| var obj = {}; |
| Object.defineProperty(obj, 'test', {get : function () {}, set : function () {} }); |
| var desc = Object.getOwnPropertyDescriptor(obj, 'test'); |
| assert.areEqual("get", desc.get.name); |
| assert.areEqual("set", desc.set.name); |
| } |
| }, |
| { |
| name: "Function name will be set only when LHS is identifier reference.", |
| body: function() |
| { |
| var obj = {}; |
| obj.foo = function() { |
| assert.areEqual(obj.foo.name, ""); |
| } |
| obj.foo(); |
| } |
| } |
| |
| ]; |
| |
| testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); |