ScriptCallStackFactory.cpp [plain text]
#include "config.h"
#include "ScriptCallStackFactory.h"
#include "InspectorInstrumentation.h"
#include "JSDOMBinding.h"
#include "JSMainThreadExecState.h"
#include "ScriptArguments.h"
#include "ScriptCallFrame.h"
#include "ScriptCallStack.h"
#include "ScriptValue.h"
#include <interpreter/CallFrame.h>
#include <interpreter/Interpreter.h>
#include <runtime/ArgList.h>
#include <runtime/JSCJSValue.h>
#include <runtime/JSFunction.h>
#include <runtime/VM.h>
#include <wtf/text/WTFString.h>
using namespace JSC;
namespace WebCore {
class ScriptExecutionContext;
PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyIsAllowed)
{
Vector<ScriptCallFrame> frames;
if (JSC::ExecState* exec = JSMainThreadExecState::currentState()) {
Vector<StackFrame> stackTrace;
Interpreter::getStackTrace(&exec->vm(), stackTrace, maxStackSize);
for (size_t i = 0; i < stackTrace.size(); i++) {
unsigned line;
unsigned column;
stackTrace[i].computeLineAndColumn(line, column);
frames.append(ScriptCallFrame(stackTrace[i].friendlyFunctionName(exec), stackTrace[i].friendlySourceURL(), line, column));
}
}
if (frames.isEmpty() && !emptyIsAllowed) {
frames.append(ScriptCallFrame("undefined", "undefined", 0, 0));
}
return ScriptCallStack::create(frames);
}
PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize)
{
Vector<ScriptCallFrame> frames;
Vector<StackFrame> stackTrace;
Interpreter::getStackTrace(&exec->vm(), stackTrace, maxStackSize + 1);
for (size_t i = stackTrace.size() == 1 ? 0 : 1; i < stackTrace.size(); i++) {
if (!stackTrace[i].callee && frames.size())
break;
String functionName = stackTrace[i].friendlyFunctionName(exec);
unsigned line;
unsigned column;
stackTrace[i].computeLineAndColumn(line, column);
frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, line, column));
}
return ScriptCallStack::create(frames);
}
PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState* exec, JSC::JSValue& exception, size_t maxStackSize)
{
Vector<ScriptCallFrame> frames;
RefCountedArray<StackFrame> stackTrace = exec->vm().exceptionStack();
for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) {
if (!stackTrace[i].callee && frames.size())
break;
String functionName = stackTrace[i].friendlyFunctionName(exec);
unsigned line;
unsigned column;
stackTrace[i].computeLineAndColumn(line, column);
frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, line, column));
}
if (frames.size() > 0) {
const ScriptCallFrame& firstCallFrame = frames.first();
JSObject* exceptionObject = exception.toObject(exec);
if (exception.isObject() && firstCallFrame.sourceURL().isEmpty()) {
JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line"));
int lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL"));
String exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined");
frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, 0);
}
}
return ScriptCallStack::create(frames);
}
PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState* exec)
{
size_t maxStackSize = 1;
if (InspectorInstrumentation::hasFrontends()) {
ScriptExecutionContext* scriptExecutionContext = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
if (InspectorInstrumentation::consoleAgentEnabled(scriptExecutionContext))
maxStackSize = ScriptCallStack::maxCallStackSizeToCapture;
}
return createScriptCallStack(exec, maxStackSize);
}
PassRefPtr<ScriptArguments> createScriptArguments(JSC::ExecState* exec, unsigned skipArgumentCount)
{
Vector<ScriptValue> arguments;
size_t argumentCount = exec->argumentCount();
for (size_t i = skipArgumentCount; i < argumentCount; ++i)
arguments.append(ScriptValue(exec->vm(), exec->argument(i)));
return ScriptArguments::create(exec, arguments);
}
}