script-file-name-utf8.js (6709B)
1 // |reftest| skip-if(!xulRuntime.shell) 2 3 // Retrieve the script file name through various functions and ensure it's 4 // always correctly decoded from UTF-8. 5 6 // Special value when filename cannot be retrieved. 7 const NOT_SUPPORTED = "*not supported*"; 8 9 // Return the file name from the Error#fileName property. 10 function errorFileName(fileName) { 11 return evaluate("new Error().fileName", {fileName}); 12 } 13 14 // Return the file name from the Parser by a SyntaxError. 15 function errorFileNameParser(fileName) { 16 try { 17 evaluate("###", {fileName}); 18 } catch (e) { 19 return e.fileName; 20 } 21 } 22 23 // Retrieve the file name through DescriptedCaller (1). 24 function descriptedCallerViaThisFileName(fileName) { 25 return evaluate("thisFilename()", {fileName}); 26 } 27 28 // Retrieve the file name through DescriptedCaller (2). 29 function descriptedCallerViaEvalInContext(fileName) { 30 return evaluate("evalcx('new Error().fileName')", {fileName}); 31 } 32 33 // Retrieve the file name through DescriptedCaller (3). 34 function descriptedCallerViaEval(fileName) { 35 var pattern = / line 1 > eval$/; 36 return evaluate("eval('new Error().fileName')", {fileName}).replace(pattern, ""); 37 } 38 39 // Retrieve the file name through DescriptedCaller (4). 40 function descriptedCallerViaFunction(fileName) { 41 var pattern = / line 1 > Function$/; 42 return evaluate("Function('return new Error().fileName')()", {fileName}).replace(pattern, ""); 43 } 44 45 // Retrieve the file name through DescriptedCaller (5). 46 function descriptedCallerViaEvalReturningScope(fileName) { 47 return evaluate("evalReturningScope('var a = new Error().fileName')", {fileName}).a; 48 } 49 50 // Retrieve the file name through DescriptedCaller (7). 51 var wasmModuleConstructorTemp; 52 function descriptedCallerViaWasm(fileName) { 53 if (!wasmIsSupported()) { 54 return fileName; 55 } 56 57 wasmModuleConstructorTemp = null; 58 evaluate(` 59 function wasmEvalText(str, imports) { 60 let binary = wasmTextToBinary(str); 61 assertEq(WebAssembly.validate(binary), true); 62 let m = new WebAssembly.Module(binary); 63 return new WebAssembly.Instance(m, imports); 64 } 65 wasmEvalText('(module (import "" "a" (func)) (func (call 0)) (export "bar" (func 1)))', 66 { 67 "": { 68 a() { 69 wasmModuleConstructorTemp = new Error().stack; 70 return 0; 71 } 72 } 73 }).exports.bar(); 74 `, {fileName}); 75 var pattern = /^@(.*) line \d+ >.*$/; 76 var index = 1; // Direct caller is the wasm function. 77 return wasmModuleConstructorTemp.split("\n")[index].replace(pattern, "$1"); 78 } 79 80 // Return the file name from Reflect.parse(). 81 function reflectParseSource(fileName) { 82 return Reflect.parse("", {source: fileName}).loc.source; 83 } 84 85 // Return the file name using the Error#stack property. 86 function fromErrorStack(fileName) { 87 var pattern = /^@(.*):\d+:\d+$/; 88 return evaluate("new Error().stack", {fileName}).split("\n")[0].replace(pattern, "$1"); 89 } 90 91 // Return the file name using the Error#stack property from an asm.js function. 92 function fromErrorStackAsmJS(fileName) { 93 var asm = evaluate(`(function asm(stdlib, foreign) { 94 "use asm"; 95 var f = foreign.f; 96 function g() { 97 return f() | 0; 98 } 99 return {g: g}; 100 })`, {fileName}); 101 102 var stackFileName; 103 var foreign = { 104 f() { 105 var pattern = /^g@(.*):\d+:\d+$/; 106 var index = 1; // Direct caller is the asm.js function. 107 var stack = new Error().stack; 108 stackFileName = stack.split("\n")[index].replace(pattern, "$1"); 109 return 0; 110 } 111 }; 112 113 asm(this, foreign).g(); 114 115 return stackFileName; 116 } 117 118 // Return the file name using the Error#stacl property when a streaming compiled WASM function. 119 function fromErrorStackStreamingWasm(fileName) { 120 if (!wasmIsSupported() || helperThreadCount() == 0) { 121 return fileName; 122 } 123 124 var source = new Uint8Array(wasmTextToBinary(` 125 (module (import "" "a" (func)) (func (call 0)) (export "bar" (func 1))) 126 `)); 127 source.url = fileName; 128 129 var stackFileName; 130 var imports = { 131 "": { 132 a() { 133 var pattern = /^@(.*):wasm-function.*$/; 134 var index = 1; // Direct caller is the asm.js function. 135 var stack = new Error().stack; 136 stackFileName = stack.split("\n")[index].replace(pattern, "$1"); 137 return 0; 138 } 139 } 140 }; 141 142 var result; 143 WebAssembly.instantiateStreaming(source, imports).then(r => result = r); 144 145 drainJobQueue(); 146 147 result.instance.exports.bar(); 148 149 return stackFileName; 150 } 151 152 // Return the file name using the embedded info in getBacktrace(). 153 function getBacktraceScriptName(fileName) { 154 var pattern = /^\d+ <TOP LEVEL> \["(.*)":\d+:\d\]$/; 155 return evaluate("getBacktrace()", {fileName}).split("\n")[0].replace(pattern, "$1"); 156 } 157 158 // Return the file name from the coverage report. 159 function getLcovInfoScriptName(fileName) { 160 var g = newGlobal(); 161 var scriptFiles = g.evaluate("getLcovInfo()", {fileName}) 162 .split("\n") 163 .filter(x => x.startsWith("SF:")); 164 assertEq(scriptFiles.length, 1); 165 return scriptFiles[0].substring(3); 166 } 167 168 // Return the file name from the error during module import. 169 function moduleResolutionError(fileName) { 170 const a = parseModule(`import { x } from "b";`, fileName); 171 const ma = registerModule("a", a); 172 const b = parseModule(`export var y = 10;`); 173 const mb = registerModule("b", b); 174 175 try { 176 moduleLink(ma); 177 } catch (e) { 178 return e.fileName; 179 } 180 } 181 182 // Return the file name from the profiler stack. 183 function geckoInterpProfilingStack(fileName) { 184 enableGeckoProfilingWithSlowAssertions(); 185 const stack = evaluate(`readGeckoInterpProfilingStack();`, { fileName }); 186 if (stack.length === 0) { 187 return NOT_SUPPORTED; 188 } 189 const result = stack[0].dynamicString; 190 disableGeckoProfiling(); 191 return result; 192 } 193 194 const testFunctions = [ 195 errorFileName, 196 errorFileNameParser, 197 descriptedCallerViaThisFileName, 198 descriptedCallerViaEvalInContext, 199 descriptedCallerViaEval, 200 descriptedCallerViaFunction, 201 descriptedCallerViaEvalReturningScope, 202 descriptedCallerViaWasm, 203 reflectParseSource, 204 fromErrorStack, 205 fromErrorStackAsmJS, 206 fromErrorStackStreamingWasm, 207 getBacktraceScriptName, 208 moduleResolutionError, 209 ]; 210 211 if (isLcovEnabled()) { 212 testFunctions.push(getLcovInfoScriptName); 213 } 214 215 const fileNames = [ 216 "", 217 "test", 218 "Ðëßþ", 219 "тест", 220 "テスト", 221 "\u{1F9EA}", 222 ]; 223 224 for (const fn of testFunctions) { 225 for (const fileName of fileNames) { 226 const result = fn(fileName); 227 if (result === NOT_SUPPORTED) { 228 continue; 229 } 230 assertEq(result, fileName, `Caller '${fn.name}'`); 231 } 232 } 233 234 if (typeof reportCompare === "function") 235 reportCompare(true, true);