После долгих размышлений об этом я, наконец, сел и решил. Все это является частью относительно сложного механизма сбора диагностической информации на клиенте, который включает в себя возможность отправки стека вызовов javascript (включая имя функции и файл javascript) обратно на сервер.
Посмотрите на первые 250 строк файла init.debug.js , который находится в
% Программные файлы% \ Common Files \ Microsoft Shared \ Расширения веб-сервера \ 14 \ TEMPLATE \ LAYOUTS \ 1033 \ init.debug.js
Этот файл определяет все функции, которые реализует ULS на клиенте.
Конечно, вам нужно установить SharePoint 2010, чтобы файл существовал на вашем локальном компьютере.
ОБНОВЛЕНИЕ - Ниже приведено общее представление о том, как работает механизм. Реальная реализация делает больше, чем это
Рассмотрим следующую html-страницу с несколькими js-включениями, каждая из которых может вызывать друг друга.
<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 include, File1.js
function ULSabc() { var o = new Object; o.File = "File1.js"; return o; }
/* ULSabc is the unique label for this js file. Each function in
this file can be decorated with a label corresponding with the same name */
function DoStuff() {
ULSabc: ;
//label matches name of function above
DoMoreStuff();
}
и File2.js
function ULSdef() { var o = new Object; o.File = "File2.js"; return o; }
function DoMoreStuff() {
ULSdef: ;
DoEvenMoreStuff();
}
function DoEvenMoreStuff() {
ULSdef: ;
try {
//throw an error
throw "Testing";
} catch (e) {
//handle the error by displaying the callstack
DisplayCallStack(e);
}
}
Теперь, скажем, наш файл ErrorHandling выглядит следующим образом
function GetFunctionInfo(fn) {
var info = "";
if (fn) {
//if we have a function, convert it to a string
var fnTxt = fn.toString();
//find the name of the function by removing the 'function' and ()
var fnName = fnTxt.substring(0, fnTxt.indexOf("(")).substring(8);
info += "Function: " + fnName;
//next use a regular expression to find a match for 'ULS???:'
//which is the label within the function
var match = fnTxt.match(/ULS[^\s;]*:/);
if (match) {
var ULSLabel = match[0];
//if our function definition contains a label, strip off the
// : and add () to make it into a function we can call eval on
ULSLabel = ULSLabel.substring(0, ULSLabel.length - 1) + "()";
//eval our function that is defined at the top of our js file
var fileInfo = eval(ULSLabel);
if (fileInfo && fileInfo.File) {
//add the .File property of the returned object to the info
info += " => Script file: " + fileInfo.File;
}
}
}
return info;
}
function DisplayCallStack(e) {
//first get a reference to the function that call this
var caller = DisplayCallStack.caller;
var stack = "Error! " + e + "\r\n";
//recursively loop through the caller of each function,
//collecting the function name and script file as we go
while (caller) {
stack += GetFunctionInfo(caller) + "\r\n";
caller = caller.caller;
}
//alert the callstack, but we could alternately do something
//else like send the info to the server via XmlHttp.
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