Ignore:
Timestamp:
Jul 22, 2011, 5:19:05 PM (14 years ago)
Author:
[email protected]
Message:

Patch by Sommer Panage <[email protected]> on 2011-07-22
Reviewed by Oliver Hunt.

export JSContextCreateBacktrace as SPI in JSContextRefPrivate.h
https://bugs.webkit.org/show_bug.cgi?id=64981

UIAutomation for iOS would like to support a Javascript backtrace in our error logs.
Currently, the C API does not provide the tools to do this. However, the private API
does expose the necessary functionality to get a backtrace
(via Interpreter::retrieveLastCaller). We recognize this information may result in
failure in the cases of programs run by 'eval', stack frames beneath host function
call frames, and in programs run from other programs. Thus, we propose exporting our
JSContextCreateBacktrace in JSContextRefPrivate.h. This will provide us with the tools
we need while not advertising an API that isn't really ready for full use.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSContextRef.cpp

    r91194 r91627  
    3030#include "APICast.h"
    3131#include "InitializeThreading.h"
     32#include <interpreter/CallFrame.h>
     33#include <interpreter/Interpreter.h>
    3234#include "JSCallbackObject.h"
    3335#include "JSClassRef.h"
    3436#include "JSGlobalObject.h"
    3537#include "JSObject.h"
     38#include "UStringBuilder.h"
    3639#include <wtf/text/StringHash.h>
     40
    3741
    3842#if OS(DARWIN)
     
    178182    return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
    179183}
     184   
     185JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
     186{
     187    ExecState* exec = toJS(ctx);
     188    JSLock lock(exec);
     189
     190    unsigned count = 0;
     191    UStringBuilder builder;
     192    CallFrame* callFrame = exec;
     193    UString functionName;
     194    if (exec->callee()) {
     195        if (asObject(exec->callee())->inherits(&InternalFunction::s_info)) {
     196            functionName = asInternalFunction(exec->callee())->name(exec);
     197            builder.append("#0 ");
     198            builder.append(functionName);
     199            builder.append("() ");
     200            count++;
     201        }
     202    }
     203    while (true) {
     204        ASSERT(callFrame);
     205        int signedLineNumber;
     206        intptr_t sourceID;
     207        UString urlString;
     208        JSValue function;
     209       
     210        UString levelStr = UString::number(count);
     211       
     212        exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
     213
     214        if (function)
     215            functionName = asFunction(function)->name(exec);
     216        else {
     217            // Caller is unknown, but if frame is empty we should still add the frame, because
     218            // something called us, and gave us arguments.
     219            if (count)
     220                break;
     221        }
     222        unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0;
     223        if (!builder.isEmpty())
     224            builder.append("\n");
     225        builder.append("#");
     226        builder.append(levelStr);
     227        builder.append(" ");
     228        builder.append(functionName);
     229        builder.append("() at ");
     230        builder.append(urlString);
     231        builder.append(":");
     232        builder.append(UString::number(lineNumber));
     233        if (!function || ++count == maxStackSize)
     234            break;
     235        callFrame = callFrame->callerFrame();
     236    }
     237    return OpaqueJSString::create(builder.toUString()).leakRef();
     238}
     239
     240
Note: See TracChangeset for help on using the changeset viewer.