经过长时间的思考,我终于坐下来研究了一下这个问题。这是一个相对复杂的机制,用于在客户端收集诊断信息,包括能够将Javascript调用堆栈(包括函数名和Javascript文件)发送回服务器的功能。
请查看位于
%Program Files%\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\init.debug.js
的前250行代码,该文件定义了客户端上'ULS'实现的所有函数。
当然,您需要安装SharePoint 2010,才能在本地计算机上找到该文件。
更新--以下大致介绍了机制的运作方式。实际实现还要更多。
考虑以下具有几个js引用的HTML页面,每个引用都可以被其他引用调用。
<html>
<head>
<script type="text/javascript" src="ErrorHandling.js"></script>
<script type="text/javascript" src="File1.js"></script>
<script type="text/javascript" src="File2.js"></script>
</head>
<body>
<button onclick="DoStuff()">Do stuff</button>
</body>
</html>
我们有两个js包含文件,File1.js
function ULSabc() { var o = new Object; o.File = "File1.js"; return o; }
function DoStuff() {
ULSabc: ;
DoMoreStuff();
}
和 File2.js
function ULSdef() { var o = new Object; o.File = "File2.js"; return o; }
function DoMoreStuff() {
ULSdef: ;
DoEvenMoreStuff();
}
function DoEvenMoreStuff() {
ULSdef: ;
try {
throw "Testing";
} catch (e) {
DisplayCallStack(e);
}
}
现在,假设我们的ErrorHandling文件看起来像这样
function GetFunctionInfo(fn) {
var info = "";
if (fn) {
var fnTxt = fn.toString();
var fnName = fnTxt.substring(0, fnTxt.indexOf("(")).substring(8);
info += "Function: " + fnName;
var match = fnTxt.match(/ULS[^\s;]*:/);
if (match) {
var ULSLabel = match[0];
ULSLabel = ULSLabel.substring(0, ULSLabel.length - 1) + "()";
var fileInfo = eval(ULSLabel);
if (fileInfo && fileInfo.File) {
info += " => Script file: " + fileInfo.File;
}
}
}
return info;
}
function DisplayCallStack(e) {
var caller = DisplayCallStack.caller;
var stack = "Error! " + e + "\r\n";
while (caller) {
stack += GetFunctionInfo(caller) + "\r\n";
caller = caller.caller;
}
alert(stack);
}
当我们在页面上点击按钮时,我们的脚本文件将通过每个函数进行调用,并在DisplayCallStack结束,此时它将递归循环并收集堆栈跟踪
Error! Testing
Function: DoEvenMoreStuff => Script file: File2.js
Function: DoMoreStuff => Script file: File2.js
Function: DoStuff => Script file: File1.js
Function: onclick
toString
(这从未被标准化,并且在某些移动浏览器上不起作用),并且它依赖于该函数的字符串表示形式没有被优化删除无用标签。有趣,我想我会选择另一种方式。尽管如此,回答很好,+1。 - T.J. Crowder