blob: e8d25b4ff59f6e62fa5f0f0343e55ba362d8d14c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.rhino.debugger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.JSONConstants;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.debug.DebugFrame;
/**
* Rhino implementation of thread data
*
* @since 1.0
*/
public class ThreadData {
private final LinkedList contexts = new LinkedList();
private final Long threadId;
private final RhinoDebuggerImpl debugger;
private long currentContextId = 0L;
private long currentFrameId = 0L;
/**
* Constructor
*
* @param threadId
* @param debugger
*/
public ThreadData(Long threadId, RhinoDebuggerImpl debugger) {
this.threadId = threadId;
this.debugger = debugger;
}
/**
* @return a JSON object for this data
*/
public synchronized Object toJSON() {
Map result = new HashMap();
result.put(JSONConstants.THREAD_ID, threadId);
if (contexts.isEmpty()) {
result.put(JSONConstants.STATE, JSONConstants.RUNNING);
} else {
Context top = (Context) contexts.getFirst();
result.put(JSONConstants.STATE, ((ContextData) top.getDebuggerContextData()).getState());
}
ArrayList contextIds = new ArrayList(contexts.size());
for (Iterator iterator = contexts.iterator(); iterator.hasNext();) {
Context context = (Context) iterator.next();
ContextData data = (ContextData) context.getDebuggerContextData();
contextIds.add(data.getId());
}
result.put(JSONConstants.CONTEXTS, contextIds);
return result;
}
/**
* Caches that the given context has been created
*
* @param context
*/
public synchronized void contextCreated(Context context) {
context.setGeneratingDebug(true);
context.setOptimizationLevel(-1);
ContextData contextData = new ContextData(threadId, new Long(currentContextId++), debugger);
context.setDebugger(debugger, contextData);
contexts.addFirst(context);
}
/**
* Removes the context from the top of the stack
*
* @param context
*/
public synchronized void contextReleased(Context context) {
if(hasContext()) {
contexts.removeFirst();
}
}
/**
* @return true if there are any known contexts to this thread data
*/
public synchronized boolean hasContext() {
return !contexts.isEmpty();
}
/**
* Returns all of the frame ids from all of the known contexts in this thread data or an empty list, never <code>null</code>
*
* @return the complete list of frame ids from all known contexts
*/
public synchronized List getFrameIds() {
ArrayList result = new ArrayList(contexts.size());
for (Iterator iterator = contexts.iterator(); iterator.hasNext();) {
Context context = (Context) iterator.next();
ContextData data = (ContextData) context.getDebuggerContextData();
result.addAll(data.getFrameIds());
}
return result;
}
/**
* Suspends the first context on the stack. has no effect if there are no known contexts for this thread data
*/
public synchronized void suspend() {
if(hasContext()) {
Context context = (Context) contexts.getFirst();
if (context == null) {
return;
}
ContextData data = (ContextData) context.getDebuggerContextData();
data.suspend();
}
}
/**
* Resumes the top context for the given type. Has no effect if there are no known contexts
*
* @param stepType
*
* @see JSONConstants#STEP_IN
* @see JSONConstants#STEP_NEXT
* @see JSONConstants#STEP_OUT
* @see JSONConstants#STEP_ANY
*/
public synchronized void resume(String stepType) {
if(hasContext()) {
Context context = (Context) contexts.getFirst();
if (context == null) {
return;
}
ContextData data = (ContextData) context.getDebuggerContextData();
data.resume(stepType);
}
}
/**
* Returns the {@link DebugFrame} with the given id from the first context containing such a frame. Returns <code>null</code> if no such frame exists with the given id.
*
* @param frameId
* @return the {@link DebugFrame} with the given id or <code>null</code>
*/
public synchronized StackFrame getFrame(Long frameId) {
for (Iterator iterator = contexts.iterator(); iterator.hasNext();) {
Context context = (Context) iterator.next();
ContextData data = (ContextData) context.getDebuggerContextData();
StackFrame frame = data.getFrame(frameId);
if (frame != null)
return frame;
}
return null;
}
/**
* Creates a new {@link DebugFrame} for the given attributes.
*
* @param context
* @param function
* @param script
* @return a new {@link DebugFrame}
*/
public synchronized DebugFrame getFrame(Context context, FunctionSource function, ScriptSource script) {
return new StackFrame(new Long(currentFrameId++), context, function, script);
}
}