function-toString-discard-source-name.js (5491B)
1 // Repeats the test from 'function/function-toString-discard-source.js' and 2 // additionally verifies the name matches the expected value. 3 // 4 // This behaviour is not required by the ECMAScript standard. 5 6 // The Function.prototype.toString() representation of sourceless functions 7 // must match the NativeFunction syntax. 8 9 function test() { 10 // Greatly (!) simplified patterns for the PropertyName production. 11 var propertyName = [ 12 // PropertyName :: LiteralPropertyName :: IdentifierName 13 "\\w+", 14 15 // PropertyName :: LiteralPropertyName :: StringLiteral 16 "(?:'[^']*')", 17 "(?:\"[^\"]*\")", 18 19 // PropertyName :: LiteralPropertyName :: NumericLiteral 20 "\\d+", 21 22 // PropertyName :: ComputedPropertyName 23 "(?:\\[[^\\]]+\\])", 24 ].join("|") 25 26 var nativeCode = RegExp([ 27 "^", "function", ("(" + propertyName + ")?"), "\\(", "\\)", "\\{", "\\[native code\\]", "\\}", "$" 28 ].join("\\s*")); 29 30 function assertFunctionName(fun, expected) { 31 var match = nativeCode.exec(fun.toString()); 32 assertEq(match[1], expected); 33 } 34 35 36 // Function declarations. 37 38 eval(` 39 function funDecl() {} 40 function* genDecl() {} 41 async function asyncFunDecl() {} 42 async function* asyncGenDecl() {} 43 `); 44 45 assertFunctionName(funDecl, "funDecl"); 46 assertFunctionName(genDecl, "genDecl"); 47 assertFunctionName(asyncFunDecl, "asyncFunDecl"); 48 assertFunctionName(asyncGenDecl, "asyncGenDecl"); 49 50 51 // Named function expressions. 52 53 eval(` 54 var funExpr = function fn() {}; 55 var genExpr = function* fn() {}; 56 var asyncFunExpr = async function fn() {}; 57 var asyncGenExpr = async function* fn() {}; 58 `); 59 60 assertFunctionName(funExpr, "fn"); 61 assertFunctionName(genExpr, "fn"); 62 assertFunctionName(asyncFunExpr, "fn"); 63 assertFunctionName(asyncGenExpr, "fn"); 64 65 66 // Anonymous function expressions. 67 68 eval(` 69 var funExprAnon = function() {}; 70 var genExprAnon = function*() {}; 71 var asyncFunExprAnon = async function() {}; 72 var asyncGenExprAnon = async function*() {}; 73 `); 74 75 assertFunctionName(funExprAnon, undefined); 76 assertFunctionName(genExprAnon, undefined); 77 assertFunctionName(asyncFunExprAnon, undefined); 78 assertFunctionName(asyncGenExprAnon, undefined); 79 80 81 // Class declarations and expressions (implicit constructor). 82 eval(` 83 class classDecl {} 84 var classExpr = class C {}; 85 var classExprAnon = class {}; 86 var classExprAnonField = class {x = 1}; 87 88 this.classDecl = classDecl; 89 `); 90 91 assertFunctionName(classDecl, "classDecl"); 92 assertFunctionName(classExpr, "C"); 93 assertFunctionName(classExprAnon, undefined); 94 assertFunctionName(classExprAnonField, undefined); 95 96 97 // Class declarations and expressions (explicit constructor). 98 eval(` 99 class classDecl { constructor() {} } 100 var classExpr = class C { constructor() {} }; 101 var classExprAnon = class { constructor() {} }; 102 103 this.classDecl = classDecl; 104 `); 105 106 assertFunctionName(classDecl, "classDecl"); 107 assertFunctionName(classExpr, "C"); 108 assertFunctionName(classExprAnon, undefined); 109 110 111 // Method definitions (identifier names). 112 eval(` 113 var obj = { 114 m() {}, 115 *gm() {}, 116 async am() {}, 117 async* agm() {}, 118 get x() {}, 119 set x(_) {}, 120 }; 121 `); 122 123 assertFunctionName(obj.m, undefined); 124 assertFunctionName(obj.gm, undefined); 125 assertFunctionName(obj.am, undefined); 126 assertFunctionName(obj.agm, undefined); 127 assertFunctionName(Object.getOwnPropertyDescriptor(obj, "x").get, undefined); 128 assertFunctionName(Object.getOwnPropertyDescriptor(obj, "x").set, undefined); 129 130 131 // Method definitions (string names). 132 eval(` 133 var obj = { 134 "foo m"() {}, 135 * "foo gm"() {}, 136 async "foo am"() {}, 137 async* "foo agm"() {}, 138 get "foo x"() {}, 139 set "foo x"(_) {}, 140 }; 141 `); 142 143 assertFunctionName(obj["foo m"], undefined); 144 assertFunctionName(obj["foo gm"], undefined); 145 assertFunctionName(obj["foo am"], undefined); 146 assertFunctionName(obj["foo agm"], undefined); 147 assertFunctionName(Object.getOwnPropertyDescriptor(obj, "foo x").get, undefined); 148 assertFunctionName(Object.getOwnPropertyDescriptor(obj, "foo x").set, undefined); 149 150 151 // Method definitions (number names). 152 eval(` 153 var obj = { 154 100() {}, 155 *200() {}, 156 async 300() {}, 157 async* 400() {}, 158 get 500() {}, 159 set 500(_) {}, 160 }; 161 `); 162 163 assertFunctionName(obj[100], undefined); 164 assertFunctionName(obj[200], undefined); 165 assertFunctionName(obj[300], undefined); 166 assertFunctionName(obj[400], undefined); 167 assertFunctionName(Object.getOwnPropertyDescriptor(obj, 500).get, undefined); 168 assertFunctionName(Object.getOwnPropertyDescriptor(obj, 500).set, undefined); 169 170 171 // Method definitions (computed property names). 172 173 var sym1 = Symbol(); 174 var sym2 = Symbol("desc"); 175 var sym3 = Symbol.for("reg-sym"); 176 var sym4 = Symbol.match; 177 var sym5 = Symbol(); 178 179 eval(` 180 var obj = { 181 [sym1]() {}, 182 *[sym2]() {}, 183 async [sym3]() {}, 184 async* [sym4]() {}, 185 get [sym5]() {}, 186 set [sym5](_) {}, 187 }; 188 `); 189 190 assertFunctionName(obj[sym1], undefined); 191 assertFunctionName(obj[sym2], undefined); 192 assertFunctionName(obj[sym3], undefined); 193 assertFunctionName(obj[sym4], undefined); 194 assertFunctionName(Object.getOwnPropertyDescriptor(obj, sym5).get, undefined); 195 assertFunctionName(Object.getOwnPropertyDescriptor(obj, sym5).set, undefined); 196 197 198 // Arrow functions. 199 eval(` 200 var arrowFn = () => {}; 201 var asyncArrowFn = () => {}; 202 `); 203 204 assertFunctionName(arrowFn, undefined); 205 assertFunctionName(asyncArrowFn, undefined); 206 207 208 // asm.js functions. 209 eval(` 210 function asm() { 211 "use asm"; 212 function f(){ return 0|0; } 213 return {f: f}; 214 } 215 `); 216 217 assertFunctionName(asm, "asm"); 218 assertFunctionName(asm().f, "f"); 219 } 220 221 var g = newGlobal({ discardSource: true }); 222 g.evaluate(test.toString() + "test()");