+
+JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
+{
+ if (!ctx) {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+ ExecState* exec = toJS(ctx);
+ APIEntryShim entryShim(exec);
+
+ return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
+}
+
+JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
+{
+ if (!ctx) {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+ ExecState* exec = toJS(ctx);
+ JSLockHolder lock(exec);
+ StringBuilder builder;
+ Vector<StackFrame> stackTrace;
+ Interpreter::getStackTrace(&exec->vm(), stackTrace, maxStackSize);
+
+ for (size_t i = 0; i < stackTrace.size(); i++) {
+ String urlString;
+ String functionName;
+ StackFrame& frame = stackTrace[i];
+ JSValue function = frame.callee.get();
+ if (frame.callee)
+ functionName = frame.friendlyFunctionName(exec);
+ else {
+ // Caller is unknown, but if frame is empty we should still add the frame, because
+ // something called us, and gave us arguments.
+ if (i)
+ break;
+ }
+ unsigned lineNumber;
+ unsigned column;
+ frame.computeLineAndColumn(lineNumber, column);
+ if (!builder.isEmpty())
+ builder.append('\n');
+ builder.append('#');
+ builder.appendNumber(i);
+ builder.append(' ');
+ builder.append(functionName);
+ builder.appendLiteral("() at ");
+ builder.append(urlString);
+ if (frame.codeType != StackFrameNativeCode) {
+ builder.append(':');
+ builder.appendNumber(lineNumber);
+ }
+ if (!function)
+ break;
+ }
+ return OpaqueJSString::create(builder.toString()).leakRef();
+}
+
+