function.name.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  6. function testGetPropertyNames(foo,checkForName)
  7. {
  8. var properties = Object.getOwnPropertyNames(foo);
  9. var len = properties.length;
  10. var check = 0;
  11. for(var i = 0; i < len; i++)
  12. {
  13. var prop = properties[i].toString();
  14. if(prop == "prototype" || (checkForName && prop == "name") ||
  15. prop == "arguments" || prop == "caller" || prop == "length")
  16. {
  17. check++;
  18. }
  19. if (!checkForName && prop == "name")
  20. {
  21. return false;
  22. }
  23. }
  24. return check == len;
  25. }
  26. var tests = [
  27. {
  28. name: "function.name",
  29. body: function ()
  30. {
  31. function foo(){} //function declaration
  32. assert.areEqual("foo",foo.name,"name should be foo");
  33. foo.name = "bar";
  34. assert.areEqual("foo",foo.name, "function names are read only");
  35. assert.areEqual("funcExpr",(function funcExpr(){}).name,"function expression case should still print a name");
  36. assignment = function(){}; // "assignment"
  37. assert.areEqual("assignment",assignment.name,"Assignment functions should print the assigned name");
  38. var lambdaDecl = () => {}; // "lambda assignment"
  39. assert.areEqual("lambdaDecl",lambdaDecl.name,"lambda assignment should print the assigned name");
  40. var a = function bar() {}
  41. var b = foo;
  42. assert.areEqual("bar",a.name,"Assignment functions should inherit the declaration name in this case bar");
  43. assert.areEqual("foo",b.name,"Assignment functions should inherit the declaration name in this case foo");
  44. }
  45. },
  46. {
  47. name: "anonymous function",
  48. body: function ()
  49. {
  50. var f = function() { };
  51. assert.areEqual("f", f.name, "function name is determined on assignment");
  52. f.name = "foo";
  53. assert.areEqual("f", f.name, "function names are read only");
  54. assert.areEqual(undefined, (function (){}).prototype.name, "function.prototype.name is undefined");
  55. assert.isFalse(Object.hasOwnProperty.call((function(){}), 'name'), "[hasPropertyCheck]: anonymous function does not have a name property");
  56. assert.areEqual("", (function(){}).name);
  57. assert.areEqual("", (function(){})["name"]);
  58. //lambdas () => {}
  59. assert.isFalse(Object.hasOwnProperty.call((() => {}), 'name'), "[hasPropertyCheck]: anonymous lambda function does not have a name property");
  60. assert.areEqual("", (() => {}).name);
  61. assert.areEqual("", (() => {})["name"]);
  62. //generators
  63. assert.isFalse(Object.hasOwnProperty.call((function*(){}), 'name'), "[hasPropertyCheck]: anonymous generator function does not have name property");
  64. assert.areEqual("", (function*(){}).name);
  65. assert.areEqual("", (function*(){})["name"]);
  66. //classes
  67. assert.isFalse(Object.hasOwnProperty.call(class {}, 'name'), "[hasPropertyCheck]: anonymous class does not have a name property");
  68. assert.areEqual("", class {}.name);
  69. assert.areEqual("", class {}['name']);
  70. }
  71. },
  72. {
  73. name: "function.name for external functions",
  74. body: function ()
  75. {
  76. assert.areEqual("LoadScriptFile",WScript.LoadScriptFile.name,"check to make sure external functions are supported");
  77. assert.areEqual("Quit",WScript.Quit.name,"check to make sure external functions are supported");
  78. assert.areEqual("LoadScript",WScript.LoadScript.name,"check to make sure external functions are supported");
  79. assert.areEqual("SetTimeout",WScript.SetTimeout.name,"check to make sure external functions are supported");
  80. assert.areEqual("ClearTimeout",WScript.ClearTimeout.name,"check to make sure external functions are supported");
  81. assert.areEqual("prototype,name,caller,arguments",Object.getOwnPropertyNames(WScript.Quit).toString(),"Check to make sure name is exposed");
  82. //Bug 639652
  83. var a = WScript.Echo.toString();
  84. var b = WScript.Echo.name;
  85. assert.areEqual("Echo",b,"b should be the name of function echo not toString of Echo function body");
  86. }
  87. },
  88. {
  89. name: "static name method overrides the creation of a name string.",
  90. body: function ()
  91. {
  92. //default constructor case
  93. var qux = class { static name() {} };
  94. assert.areEqual("function", typeof qux.name,
  95. "14.5.15 Runtime Semantics: If the class definition included a 'name' static method then that method is not over-written");
  96. assert.areEqual("name",qux.name.name,"confirm we get the name 'name'");
  97. assert.areEqual(qux.name , qux.prototype.constructor.name,
  98. "confirm qux.prototype.constructor.name is the same function as qux.name");
  99. assert.areEqual("Function",qux.constructor.name,"The function constructor should still have the name Function");
  100. var qux = class { constructor(a,b) {} static name() {} };
  101. var quxobj = new qux(1,2);
  102. assert.areEqual("function", typeof qux.name,
  103. "14.5.15 Runtime Semantics: If the class definition included a \"name\" static method then that method is not over-written");
  104. assert.areEqual("name",qux.name.name,"confirm we get the name \"name\"");
  105. assert.areEqual(qux.name , qux.prototype.constructor.name,
  106. "confirm qux.prototype.constructor.name is the same function as qux.name");
  107. assert.areEqual("Function",qux.constructor.name,"The function constructor should still have the name Function");
  108. }
  109. },
  110. {
  111. name: "function.name's that match IsConstantFunctionName",
  112. body: function ()
  113. {
  114. var o = {
  115. "" : function() {},
  116. "Anonymous function" : function() {},
  117. "Function code" : function() {}
  118. }
  119. assert.areEqual("", o[""].name);
  120. assert.areEqual("Anonymous function", o["Anonymous function"].name, "should not get converted to empty string");
  121. assert.areEqual("Function code", o["Function code"].name, "should not get converted to Anonymous");
  122. },
  123. },
  124. {
  125. name: "function.name for built in constructors",
  126. body: function ()
  127. {
  128. function* gf() { }
  129. assert.areEqual("GeneratorFunction", gf.constructor.name);
  130. assert.areEqual("Array", Array.name);
  131. assert.areEqual("ArrayBuffer", ArrayBuffer.name);
  132. assert.areEqual("DataView", DataView.name);
  133. assert.areEqual("Error", Error.name);
  134. assert.areEqual("SyntaxError", SyntaxError.name);
  135. assert.areEqual("EvalError", EvalError.name);
  136. assert.areEqual("RangeError", RangeError.name);
  137. assert.areEqual("ReferenceError", ReferenceError.name);
  138. assert.areEqual("Boolean", Boolean.name);
  139. assert.areEqual("Symbol", Symbol.name);
  140. assert.areEqual("Promise", Promise.name);
  141. assert.areEqual("Proxy", Proxy.name);
  142. assert.areEqual("Date", Date.name);
  143. assert.areEqual("Function", Function.name);
  144. assert.areEqual("Number", Number.name);
  145. assert.areEqual("Object", Object.name);
  146. assert.areEqual("RegExp", RegExp.name);
  147. assert.areEqual("String", String.name);
  148. assert.areEqual("Map", Map.name);
  149. assert.areEqual("Set", Set.name);
  150. assert.areEqual("WeakMap", WeakMap.name);
  151. assert.areEqual("WeakSet", WeakSet.name);
  152. }
  153. },
  154. {
  155. name: "Numeric value test cases",
  156. body: function ()
  157. {
  158. var a = [];
  159. var b = 1;
  160. var c = 2;
  161. a[4] = function() {};
  162. a[1.2] = function() {};
  163. function foo()
  164. {
  165. return a;
  166. }
  167. foo()[5] = function() {};
  168. a[4+3] = function() {};
  169. a[b] = function() {};
  170. a[c] = function() {};
  171. a[b+c] = function() {};
  172. var index1 = 4;
  173. var index2 = 4+8;
  174. var o = { index1 : function() {}, index2 : function() {}, [index1+1] : function() {}}
  175. assert.areEqual("index1", o.index1.name);
  176. assert.areEqual("index2",o.index2.name);
  177. assert.areEqual("5", o[5].name, "when our name has brackets return the computed name")
  178. assert.areEqual("b",a[1].name,"expressions are not evaluated, default to expression name");
  179. assert.areEqual("c",a[2].name,"expressions are not evaluated, default to expression name");
  180. assert.areEqual("1.2",a[1.2].name,"constants are the given numeric literal");
  181. var o = { 1.4 : function() {} };
  182. assert.areEqual("1.4",o[1.4].name,"constants are the given numeric literal");
  183. assert.areEqual("",a[3].name,"expressions are not evaluated, default to empty string since it lacks a variable name");
  184. assert.areEqual("4",a[4].name,"constants are the given numeric literal");
  185. assert.areEqual("5",a[5].name,"constants are the given numeric literal");
  186. assert.areEqual("",a[7].name,"expressions are not evaluated, default to empty string since it lacks a variable name");
  187. }
  188. },
  189. {
  190. name: "Strings With Brackets or Periods in them",
  191. body: function ()
  192. {
  193. var o = { "hello.friend" : function() {},
  194. "[a" : function() {},
  195. "]" : function() {},
  196. "]a" : function() {}};
  197. assert.areEqual("hello.friend",o["hello.friend"].name,"the period is included in the name don't shorten");
  198. assert.areEqual("[a",o["[a"].name,"the bracket is included in the name don't shorten");
  199. assert.areEqual("]",o["]"].name,"the bracket is included in the name don't shorten");
  200. assert.areEqual("]a",o["]a"].name,"the bracket is included in the name don't shorten");
  201. var o = { "a[" : function() {} };
  202. assert.areEqual("a[",o["a["].name,"the bracket is included in the name don't shorten");
  203. var o = { ["a["] : function() {} };
  204. assert.areEqual("a[",o["a["].name,"computed property names use a different code path");
  205. var a = [];
  206. a["["] = function() {};
  207. a["]"] = function() {};
  208. assert.areEqual("",a["["].name);
  209. assert.areEqual("",a["]"].name);
  210. a["hello.buddy"] = function() {};
  211. assert.areEqual("",a["hello.buddy"].name);
  212. class ClassTest
  213. {
  214. static [".f"]() {}
  215. static ["f."]() {}
  216. static ["f["]() {}
  217. static ["f]"]() {}
  218. static ["]]f]]"]() {}
  219. static ["[f"]() {}
  220. static ["[[[[[f"]() {}
  221. static ["]f"]() {}
  222. }
  223. assert.areEqual("f.", ClassTest["f."].name);
  224. assert.areEqual(".f", ClassTest[".f"].name);
  225. assert.areEqual("f[", ClassTest["f["].name);
  226. assert.areEqual("f]", ClassTest["f]"].name);
  227. assert.areEqual("]]f]]", ClassTest["]]f]]"].name);
  228. assert.areEqual("[f", ClassTest["[f"].name);
  229. assert.areEqual("[[[[[f", ClassTest["[[[[[f"].name);
  230. assert.areEqual("]f", ClassTest["]f"].name);
  231. var a = {"\0" : { f : function() {}, c : class {} }}
  232. assert.areEqual("f", a["\0"].f.name);
  233. assert.areEqual("c", a["\0"].c.name);
  234. }
  235. },
  236. {
  237. name: "Class.name",
  238. body: function ()
  239. {
  240. var a = class foo {}
  241. assert.areEqual("foo",a.name,"should pick the class name not the assignment name");
  242. class ClassDecl {} // constructor is "ClassDecl"
  243. var c = class { method(){}}
  244. var b = new c();
  245. assert.areEqual("ClassDecl",ClassDecl.name,"name should be ClassDecl");
  246. assert.areEqual("c",c.name,"class name should be c");
  247. assert.areEqual("method",b.method.name,"c is a constructor, b is an instance so method is accessible on b");
  248. ClassDecl.name = "foo";
  249. assert.areEqual("ClassDecl",ClassDecl.name, "function names are read only");
  250. assert.areEqual("ClassExpr",(class ClassExpr {}).name,"class expression case should still print a name");
  251. var classFoo = class
  252. {
  253. constructor(){} // "classFoo "
  254. static func(){} // "func"
  255. method(){} // "method"
  256. get getter(){} // "get getter"
  257. set setter(v){} // "set setter"
  258. };
  259. class classFoo2
  260. {
  261. constructor(){}
  262. }
  263. assert.areEqual("Function",classFoo2.constructor.name, "classFoo2.constructor.name === 'Function'");
  264. assert.areEqual("classFoo2",classFoo2.prototype.constructor.name, "confirm that the prototype constructors name is the class name");
  265. var oGet = Object.getOwnPropertyDescriptor(classFoo.prototype,"getter");
  266. var oSet = Object.getOwnPropertyDescriptor(classFoo.prototype,"setter");
  267. assert.areEqual("Function",classFoo.constructor.name, "classFoo.constructor.name === 'Function'");
  268. assert.areEqual("classFoo",classFoo.name, "Name of the class should be classFoo");
  269. assert.areEqual("classFoo",classFoo.prototype.constructor.name, "Name of the constructor should be the class name");
  270. assert.areEqual("func",classFoo.func.name, "Name should just be func");
  271. assert.areEqual("method",classFoo.prototype.method.name, "Name should be method");
  272. assert.areEqual("get getter",oGet.get.name,"Accessors getter should be prefixed with get");
  273. assert.areEqual("set setter",oSet.set.name, "Accessors setter should be prefixed with set");
  274. var instanceFoo = new classFoo();
  275. var instanceFoo2 = new classFoo2();
  276. assert.areEqual("classFoo2",instanceFoo2.constructor.name, "instance constructor should be class name");
  277. assert.areEqual("classFoo",instanceFoo.constructor.name, "instance constructor should be class name");
  278. assert.areEqual("method",instanceFoo.method.name, "instance should have function name method");
  279. }
  280. },
  281. {
  282. name: "Generator functions",
  283. body: function ()
  284. {
  285. function* gf() { }
  286. var gfe = function* () { }
  287. var obj = { gfm : function* () { } }
  288. assert.areEqual("gf",gf.name, "Generator Declaration");
  289. assert.areEqual("gfe",gfe.name, "Generator Expression");
  290. assert.areEqual("gfm",obj.gfm.name, "Generator Method");
  291. var GeneratorFunction = Object.getPrototypeOf(gf).constructor;
  292. assert.areEqual("anonymous",(new GeneratorFunction ).name,"Should be anonymous");
  293. }
  294. },
  295. {
  296. name: "function inside objects",
  297. body: function ()
  298. {
  299. let obj =
  300. {
  301. prop: () => {},
  302. noOverride: function named(){},
  303. "literal": function(){},
  304. 5: () => {}
  305. };
  306. assert.areEqual("prop",obj.prop.name,"lambda function name is assigned to prop");
  307. assert.areEqual("named",obj.noOverride.name, "noOverride inherits name from function named");
  308. assert.areEqual("literal",obj.literal.name, "string function definitions are valid");
  309. assert.areEqual("5",obj["5"].name, "numeral function definitions are valid");
  310. var obj2 =
  311. {
  312. method(){}
  313. }
  314. obj2.property = function(){};
  315. assert.areEqual("method",obj2.method.name, "tests functions without the function reserved word");
  316. assert.areEqual("",obj2.property.name, "test to make sure defining a property outside of a function is empty string");
  317. }
  318. },
  319. {
  320. name: "function.name's are read only",
  321. body: function ()
  322. {
  323. var object =
  324. {
  325. f: function() {}
  326. };
  327. assert.areEqual("f",object.f.name, "function name is f");
  328. object.f.name = "foo";
  329. assert.areEqual("f",object.f.name, "function names are read only");
  330. }
  331. },
  332. {
  333. name: "function.name test functions named get\set don't get confused for accessors",
  334. body: function ()
  335. {
  336. var foo = {
  337. value : 0,
  338. get : function() { return value;},
  339. set : function (val) {value = val}
  340. }
  341. assert.areEqual("get", foo.get.name, "name should be get");
  342. assert.areEqual("set", foo.set.name, "name should be set");
  343. var obj3 = { get : function foo () { },
  344. set : function bar (v) { }};
  345. //like the var a = function foo() {} case a inherits foo's name
  346. assert.areEqual("foo",obj3.get.name, "should inherited name foo");
  347. assert.areEqual("bar",obj3.set.name, "should inherited name bar");
  348. }
  349. },
  350. {
  351. name: "function.name accessor test",
  352. body: function ()
  353. {
  354. var oRuntime = Object.getOwnPropertyDescriptor(Map.prototype,"size");
  355. assert.areEqual("get size",oRuntime.get.name, "Map.prototype.size is a getter");
  356. assert.areEqual(undefined,oRuntime.set, "Map.prototype.size does not have a setter");
  357. // Single Property descriptor
  358. var o = { get foo(){}, set foo(x){} };
  359. var descriptor = Object.getOwnPropertyDescriptor(o, "foo");
  360. assert.areEqual("get foo", descriptor.get.name, "get accessors on function foo are prefixed with get");
  361. assert.areEqual("set foo", descriptor.set.name, "set accessors on function foo are prefixed with set");
  362. let obj =
  363. {
  364. get getter(){ return 0;},
  365. set setter(v){}
  366. };
  367. // Multiple property descriptors
  368. var oGet = Object.getOwnPropertyDescriptor(obj,"getter")
  369. var oSet = Object.getOwnPropertyDescriptor(obj,"setter");
  370. assert.areEqual("get getter",oGet.get.name, "get accessors functions are prefixed with get");
  371. assert.areEqual("set setter",oSet.set.name, "set accessors functions are prefixed with set");
  372. }
  373. },
  374. {
  375. name: "function.name Property existence test",
  376. body: function ()
  377. {
  378. function foo(){}
  379. assert.areEqual(true,testGetPropertyNames(foo,true),"Properties on foo");
  380. assert.areEqual(0,Object.keys(foo).length,"no enumerable properties in function instance foo");
  381. Object.defineProperty(foo,"name",{writable: false,enumerable: true,configurable: true});
  382. var o = Object.getOwnPropertyDescriptor(foo,"name");
  383. assert.areEqual(true, o.enumerable, "Name is redefined to enumerable");
  384. for (i in foo)
  385. {
  386. assert.areEqual("name",i,"Name should be the only enumerable property");
  387. }
  388. assert.areEqual(1,Object.keys(foo).length,"name is now an enumerated property");
  389. assert.areEqual("name",Object.keys(foo).toString(),"Name should be the only enumerable property");
  390. }
  391. },
  392. {
  393. name: "function.name delete test",
  394. body: function ()
  395. {
  396. function foo(){}
  397. assert.areEqual(true,testGetPropertyNames(foo,true), "Properties on foo");
  398. delete foo.name;
  399. assert.areEqual(true,testGetPropertyNames(foo,false),"Properties on foo");
  400. }
  401. },
  402. {
  403. name: "built-in function.name",
  404. body: function ()
  405. {
  406. assert.areEqual("slice",[].slice.name,"name should be slice");
  407. [].slice.name = "bar";
  408. assert.areEqual("slice",[].slice.name, "function names are read only");
  409. }
  410. },
  411. {
  412. name: "built-in function.name delete test",
  413. body: function ()
  414. {
  415. assert.areEqual(true,testGetPropertyNames([].splice,true),"Properties on foo");
  416. delete [].splice.name;
  417. assert.areEqual(true,testGetPropertyNames([].splice,false),"Properties on foo");
  418. }
  419. },
  420. {
  421. name: "anonymous function special cases",
  422. body: function ()
  423. {
  424. assert.areEqual("anonymous",(new Function).name,"Should be anonymous");
  425. assert.areEqual("",Function.prototype.name,"19.2.3 The value of the name property of the Function prototype object is the empty String.");
  426. }
  427. },
  428. {
  429. name: "nested function assignment names",
  430. body: function ()
  431. {
  432. var obj =
  433. {
  434. x : function(){},
  435. y : () => {},
  436. z : class {}
  437. };
  438. assert.areEqual("x",obj.x.name,"x defined in obj Should be x");
  439. assert.areEqual("y",obj.y.name,"y defined in obj Should be y");
  440. assert.areEqual("z",obj.z.name,"z defined in obj Should be z");
  441. var obj =
  442. {
  443. innerObj :
  444. {
  445. x : function(){},
  446. y : () => {},
  447. z : class {}
  448. }
  449. };
  450. assert.areEqual("x",obj.innerObj.x.name,"Should be x");
  451. assert.areEqual("y",obj.innerObj.y.name,"Should be y");
  452. assert.areEqual("z",obj.innerObj.z.name,"Should be z");
  453. var obj = {};
  454. obj.x = function(){};
  455. obj.y = () => {};
  456. obj.z = class {};
  457. assert.areEqual("",obj.x.name,"Should be ''");
  458. assert.areEqual("",obj.y.name,"Should be ''");
  459. assert.areEqual("",obj.z.name,"Should be ''");
  460. var obj = {innerObj : {}};
  461. obj.innerObj.x = function(){};
  462. obj.innerObj.y = () => {};
  463. obj.innerObj.z = class {};
  464. assert.areEqual("",obj.innerObj.x.name,"Should be ''");
  465. assert.areEqual("",obj.innerObj.y.name,"Should be ''");
  466. assert.areEqual("",obj.innerObj.z.name,"Should be ''");
  467. }
  468. },
  469. {
  470. name: "Check the Class of an Object",
  471. body: function ()
  472. {
  473. function foo(){}
  474. var f = new foo();
  475. assert.areEqual("foo",f.constructor.name,"The constructor is foo");
  476. assert.areEqual(undefined,f.name,"f is an instance of the function foo, the name exists only on the constructor");
  477. }
  478. },
  479. {
  480. name: "Attributes test",
  481. body: function ()
  482. {
  483. function foo(){}
  484. assert.areEqual(true, foo.hasOwnProperty("name"), "foo should have a name property");
  485. var o = Object.getOwnPropertyDescriptor(foo,"name");
  486. assert.areEqual(false, o.writable, "Name is not writable");
  487. assert.areEqual(false, o.enumerable, "Name is not enumerable");
  488. assert.areEqual(true, o.configurable, "Name is configurable");
  489. assert.areEqual("foo", o.value, "Names value should be foo");
  490. }
  491. },
  492. {
  493. name: "Symbol names",
  494. body: function ()
  495. {
  496. var sym1 = Symbol("foo");
  497. var sym2 = Symbol("bar");
  498. var sym3 = Symbol("baz");
  499. var sym4 = Symbol();
  500. var o = {[Symbol.toPrimitive]: function() {},
  501. [sym1] : function() {},
  502. [sym3] : function bear() {},
  503. [sym4] : function() {},
  504. }
  505. o[Symbol.unscopables] = function(){}
  506. o[sym2] = function() {}
  507. 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 \"]\"");
  508. assert.areEqual("[Symbol.toPrimitive]",o[Symbol.toPrimitive].name,
  509. "9.2.11.4 SetFunctionName: If Type(name) is Symbol, then let name be the concatenation of \"[\", description, and \"]\"");
  510. 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");
  511. assert.areEqual("sym2", o[sym2].name, "computed property names are not bound to index yet");
  512. assert.areEqual("bear", o[sym3].name, "if the function already has a name don't overwrite it");
  513. assert.areEqual("", o[sym4].name, "empty symbols have empty string as a name");
  514. }
  515. },
  516. {
  517. name: "Redefine Attributes test",
  518. body: function ()
  519. {
  520. function foo(){}
  521. Object.defineProperty(foo,"name",{writable: true,enumerable: true,configurable: false});
  522. foo.name = "bar";
  523. var o = Object.getOwnPropertyDescriptor(foo,"name");
  524. assert.areEqual(true, o.writable, "Name is redefined to writable");
  525. assert.areEqual(true, o.enumerable, "Name is redefined to enumerable");
  526. assert.areEqual(false, o.configurable, "Name redefined not configurable");
  527. assert.areEqual("bar", o.value, "Names value should be bar");
  528. assert.areEqual("bar",foo.name,"foo renamed to bar");
  529. }
  530. },
  531. {
  532. name: "strings with null terminators sprinkled in",
  533. body: function()
  534. {
  535. var str = "hello\0 foo";
  536. var a = [];
  537. a["hello\0 foo"] = function() {};
  538. var o = {[str] : function() {}, ["h\0h"] : function() {}}
  539. var b = {}
  540. b["hello\0 foo"] = function() {}
  541. var c = { "hello\0 foo" : function() {} }
  542. assert.areEqual(str, o[str].name);
  543. assert.areEqual("h\0h", o["h\0h"].name);
  544. assert.areEqual("hello\0 foo", a["hello\0 foo"].name);
  545. assert.areEqual("hello\0 foo", b["hello\0 foo"].name);
  546. assert.areEqual("hello\0 foo", c["hello\0 foo"].name);
  547. var d = { "goo.\0d" : function() {} }
  548. var e = { "g\0oo\0.d" : function() {} }
  549. var f = { "fo\0o" : class {} }
  550. assert.areEqual("goo.\0d", d["goo.\0d"].name);
  551. assert.areEqual("g\0oo\0.d", e["g\0oo\0.d"].name);
  552. assert.areEqual("fo\0o", f["fo\0o"].name);
  553. }
  554. },
  555. {
  556. name: "Function Bind",
  557. body: function()
  558. {
  559. function add(x, y)
  560. {
  561. return x+y;
  562. }
  563. var AddZer0 = add.bind(null,0 /* x */);
  564. var Add2Nums = add.bind();
  565. assert.areEqual("bound add",AddZer0.name, "AddZer0 needs a bound prefix on add");
  566. assert.areEqual("bound add",Add2Nums.name,"Add2Nums needs a bound prefix on add");
  567. }
  568. },
  569. {
  570. name: "Bug 1642987 & 1242667",
  571. body: function()
  572. {
  573. e = ''['u3 = undefined'] = function () {}
  574. assert.areEqual('', e.name, "Bug 1642987: we should not AV if we can't shorten the name") ;
  575. f = ''['[f]o'] = function () {};
  576. assert.areEqual('', f.name, "Bug 1242667: We need to wrap strings in Brackets") ;
  577. }
  578. },
  579. {
  580. name: "Bug 2302197",
  581. body: function()
  582. {
  583. var b = {};
  584. var c = b.x = function Ctor() {}
  585. var a = new c();
  586. assert.areEqual('Ctor', b.x.name, "confirm IsNameIdentifierRef does not override IsNamedFunctionExpression");
  587. assert.areEqual('Ctor', c.name, "confirm IsNameIdentifierRef does not override IsNamedFunctionExpression");
  588. assert.areEqual('Ctor', a.constructor.name, "confirm IsNameIdentifierRef does not override IsNamedFunctionExpression");
  589. }
  590. },
  591. {
  592. name: "Bug 3941893 & Bug 4153027",
  593. body: function()
  594. {
  595. class B {
  596. static ["n"+"a"+"me"]() {}
  597. }
  598. assert.areEqual("function", typeof B.name, "Function 'name' attribute should not be inferred in presence of static computed 'name' method");
  599. assert.areEqual("name", B.name.name, "Make sure the name is correct");
  600. var o = {
  601. ['A'+'B'] : class extends B {},
  602. ['C'+'B'] : class {},
  603. ['a'+'b'] : class extends B {foo_ab(){}},
  604. ['c'+'b'] : class {foo_cb(){}},
  605. ['d'+'f'] : class extends B {static foo_df(){}},
  606. ['f'+'d'] : class {static foo_fd(){}}
  607. }
  608. assert.areEqual("AB", o.AB.name, "confirm empty super class is properly assigned to a computed property");
  609. assert.areEqual("CB", o.CB.name, "confirm empty base class is properly assigned to a computed property");
  610. assert.areEqual("ab", o.ab.name, "confirm filled super class is properly assigned to a computed property");
  611. assert.areEqual("cb", o.cb.name, "confirm filled base class is properly assigned to a computed property");
  612. assert.areEqual("df", o.df.name, "confirm static filled super class is properly assigned to a computed property");
  613. assert.areEqual("fd", o.fd.name, "confirm static filled base class is properly assigned to a computed property");
  614. }
  615. },
  616. {
  617. name: "Bug 3713125",
  618. body: function()
  619. {
  620. var target = Object.defineProperty(function() {}, 'name', { value: 'target' });
  621. assert.areEqual('bound bound target', target.bind().bind().name, "confirm bound is appended to the front twice");
  622. d = Object.getOwnPropertyDescriptor(target.bind().bind(), 'name')
  623. assert.areEqual(false, d.writable);
  624. assert.areEqual(false, d.enumerable);
  625. assert.areEqual(true, d.configurable);
  626. }
  627. },
  628. {
  629. name: "Bug 3713014",
  630. body: function()
  631. {
  632. var namedSym = Symbol('test');
  633. var anonSym = Symbol();
  634. class A {
  635. set [namedSym](_) {}
  636. get [namedSym]() {}
  637. }
  638. var classASymbolSet = Object.getOwnPropertyDescriptor(A.prototype, namedSym).set;
  639. var classASymbolGet = Object.getOwnPropertyDescriptor(A.prototype, namedSym).get;
  640. assert.areEqual("get [test]",classASymbolGet.name, " should not throw because of toString call on symbol");
  641. assert.areEqual("set [test]",classASymbolSet.name, " should not throw because of toString call on symbol");
  642. class B {
  643. set [anonSym](_) {}
  644. get [anonSym]() {}
  645. }
  646. var classBSymbolSet = Object.getOwnPropertyDescriptor(B.prototype, anonSym).set;
  647. var classBSymbolGet = Object.getOwnPropertyDescriptor(B.prototype, anonSym).get;
  648. assert.areEqual("get ",classBSymbolGet.name, " should not throw because of toString call on symbol");
  649. assert.areEqual("set ",classBSymbolSet.name, " should not throw because of toString call on symbol");
  650. }
  651. },
  652. {
  653. name: "OS Bug 3933663 Classes Should not un-defer a class constructor before we store the computed property",
  654. body: function()
  655. {
  656. var first = 'a';
  657. var second = 'b';
  658. var third = Symbol('c');
  659. var fourth = Symbol();
  660. var o;
  661. o = {
  662. [first]: class {},
  663. [second]: class {},
  664. [third]: class {},
  665. [fourth]: class {}
  666. };
  667. assert.areEqual("a", o[first].name , "confirm class constructor names are the computed property value a");
  668. assert.areEqual("b", o[second].name, "confirm class constructor names are the computed property value b");
  669. assert.areEqual("[c]", o[third].name , "confirm class constructor names are the computed property value [c]");
  670. assert.areEqual("", o[fourth].name, "confirm class constructor names are the computed property value empty string");
  671. }
  672. },
  673. {
  674. name: "fix for toString override",
  675. body: function()
  676. {
  677. var b="barzee";
  678. class foo {
  679. [b] () {}
  680. };
  681. var inst=new foo();
  682. inst[b].toString();
  683. assert.areEqual("barzee",inst[b].name);
  684. }
  685. },
  686. {
  687. name: "Issue 539 Fix: preserve the shortNameOffset per append",
  688. body: function()
  689. {
  690. class C { foo(){} };
  691. assert.areEqual("foo",(new C).foo.name);
  692. }
  693. },
  694. {
  695. name: "Getter and setter have correct name in defineProperty",
  696. body: function()
  697. {
  698. var obj = {};
  699. Object.defineProperty(obj, 'test', {get : function () {}, set : function () {} });
  700. var desc = Object.getOwnPropertyDescriptor(obj, 'test');
  701. assert.areEqual("get", desc.get.name);
  702. assert.areEqual("set", desc.set.name);
  703. }
  704. },
  705. {
  706. name: "Function name will be set only when LHS is identifier reference.",
  707. body: function()
  708. {
  709. var obj = {};
  710. obj.foo = function() {
  711. assert.areEqual(obj.foo.name, "");
  712. }
  713. obj.foo();
  714. }
  715. }
  716. ];
  717. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });