--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/StackFrame.java Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,309 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.core.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.chromium.debug.core.ChromiumDebugPlugin;
+import org.chromium.sdk.CallFrame;
+import org.chromium.sdk.JsArray;
+import org.chromium.sdk.JsFunction;
+import org.chromium.sdk.JsObject;
+import org.chromium.sdk.JsScope;
+import org.chromium.sdk.JsValue;
+import org.chromium.sdk.JsVariable;
+import org.chromium.sdk.Script;
+import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IRegisterGroup;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * An IStackFrame implementation over a JsStackFrame instance.
+ */
+public class StackFrame extends DebugElementImpl implements IStackFrame {
+
+ private final JavascriptThread thread;
+
+ private final CallFrame stackFrame;
+
+ private IVariable[] variables;
+
+ /**
+ * Constructs a stack frame for the given handler using the FrameMirror data
+ * from the remote V8 VM.
+ *
+ * @param debugTarget the global parent
+ * @param thread for which the stack frame is created
+ * @param stackFrame an underlying SDK stack frame
+ */
+ public StackFrame(IChromiumDebugTarget debugTarget, JavascriptThread thread, CallFrame stackFrame) {
+ super(debugTarget);
+ this.thread = thread;
+ this.stackFrame = stackFrame;
+ }
+
+ public CallFrame getCallFrame() {
+ return stackFrame;
+ }
+
+ public IThread getThread() {
+ return thread;
+ }
+
+ public IVariable[] getVariables() throws DebugException {
+ if (variables == null) {
+ try {
+ variables = wrapScopes(getDebugTarget(), stackFrame.getVariableScopes(),
+ stackFrame.getReceiverVariable());
+ } catch (RuntimeException e) {
+ // We shouldn't throw RuntimeException from here, because calling
+ // ElementContentProvider#update will forget to call update.done().
+ throw new DebugException(new Status(IStatus.ERROR, ChromiumDebugPlugin.PLUGIN_ID,
+ "Failed to read variables", e)); //$NON-NLS-1$
+ }
+ }
+ return variables;
+ }
+
+ static IVariable[] wrapVariables(
+ IChromiumDebugTarget debugTarget, Collection<? extends JsVariable> jsVars,
+ Collection <? extends JsVariable> jsInternalProperties) {
+ List<Variable> vars = new ArrayList<Variable>(jsVars.size());
+ for (JsVariable jsVar : jsVars) {
+ vars.add(new Variable(debugTarget, jsVar, false));
+ }
+ for (JsVariable jsMetaVar : jsInternalProperties) {
+ vars.add(new Variable(debugTarget, jsMetaVar, true));
+ }
+ return vars.toArray(new IVariable[vars.size()]);
+ }
+
+ static IVariable[] wrapScopes(IChromiumDebugTarget debugTarget, List<? extends JsScope> jsScopes,
+ JsVariable receiverVariable) {
+ List<Variable> vars = new ArrayList<Variable>();
+
+ for (JsScope scope : jsScopes) {
+ if (scope.getType() == JsScope.Type.GLOBAL) {
+ if (receiverVariable != null) {
+ vars.add(new Variable(debugTarget, receiverVariable, false));
+ receiverVariable = null;
+ }
+ vars.add(new Variable(debugTarget, wrapScopeAsVariable(scope), false));
+ } else {
+ for (JsVariable var : scope.getVariables()) {
+ vars.add(new Variable(debugTarget, var, false));
+ }
+ }
+ }
+ if (receiverVariable != null) {
+ vars.add(new Variable(debugTarget, receiverVariable, false));
+ }
+
+ IVariable[] result = new IVariable[vars.size()];
+ // Return in reverse order.
+ for (int i = 0; i < result.length; i++) {
+ result[result.length - i - 1] = vars.get(i);
+ }
+ return result;
+ }
+
+ private static JsVariable wrapScopeAsVariable(final JsScope jsScope) {
+ class ScopeObjectVariable implements JsVariable, JsObject {
+ public String getFullyQualifiedName() {
+ return getName();
+ }
+ public String getName() {
+ // TODO(peter.rybin): should we localize it?
+ return "<" + jsScope.getType() + ">";
+ }
+ public JsValue getValue() throws UnsupportedOperationException {
+ return this;
+ }
+ public boolean isMutable() {
+ return false;
+ }
+ public boolean isReadable() {
+ return true;
+ }
+ public void setValue(String newValue, SetValueCallback callback)
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+ public JsArray asArray() {
+ return null;
+ }
+ public JsFunction asFunction() {
+ return null;
+ }
+ public String getClassName() {
+ // TODO(peter.rybin): should we localize it?
+ return "#Scope";
+ }
+ public Collection<? extends JsVariable> getProperties() throws MethodIsBlockingException {
+ return jsScope.getVariables();
+ }
+ public Collection<? extends JsVariable> getInternalProperties()
+ throws MethodIsBlockingException {
+ return Collections.emptyList();
+ }
+ public JsVariable getProperty(String name) {
+ for (JsVariable var : getProperties()) {
+ if (var.getName().equals(name)) {
+ return var;
+ }
+ }
+ return null;
+ }
+ public JsObject asObject() {
+ return this;
+ }
+ public Type getType() {
+ return Type.TYPE_OBJECT;
+ }
+ public String getValueString() {
+ return getClassName();
+ }
+ public String getRefId() {
+ return null;
+ }
+ }
+ return new ScopeObjectVariable();
+ }
+
+ public boolean hasVariables() throws DebugException {
+ return stackFrame.getReceiverVariable() != null || stackFrame.getVariableScopes().size() > 0;
+ }
+
+ public int getLineNumber() throws DebugException {
+ // convert 0-based to 1-based
+ return stackFrame.getLineNumber() + 1;
+ }
+
+ public int getCharStart() throws DebugException {
+ return stackFrame.getCharStart();
+ }
+
+ public int getCharEnd() throws DebugException {
+ return -1;
+ }
+
+ public String getName() throws DebugException {
+ String name = stackFrame.getFunctionName();
+ Script script = stackFrame.getScript();
+ if (script == null) {
+ return Messages.StackFrame_UnknownScriptName;
+ }
+ int line = script.getStartLine() + getLineNumber();
+ if (line != -1) {
+ name = NLS.bind(Messages.StackFrame_NameFormat, new Object[] {name, script.getName(), line});
+ }
+ return name;
+ }
+
+ public IRegisterGroup[] getRegisterGroups() throws DebugException {
+ return null;
+ }
+
+ public boolean hasRegisterGroups() throws DebugException {
+ return false;
+ }
+
+ public boolean canStepInto() {
+ return getThread().canStepInto();
+ }
+
+ public boolean canStepOver() {
+ return getThread().canStepOver();
+ }
+
+ public boolean canStepReturn() {
+ return getThread().canStepReturn();
+ }
+
+ public boolean isStepping() {
+ return getThread().isStepping();
+ }
+
+ public void stepInto() throws DebugException {
+ getThread().stepInto();
+ }
+
+ public void stepOver() throws DebugException {
+ getThread().stepOver();
+ }
+
+ public void stepReturn() throws DebugException {
+ getThread().stepReturn();
+ }
+
+ public boolean canResume() {
+ return getThread().canResume();
+ }
+
+ public boolean canSuspend() {
+ return getThread().canSuspend();
+ }
+
+ public boolean isSuspended() {
+ return getThread().isSuspended();
+ }
+
+ public void resume() throws DebugException {
+ getThread().resume();
+ }
+
+ public void suspend() throws DebugException {
+ getThread().suspend();
+ }
+
+ public boolean canTerminate() {
+ return getThread().canTerminate();
+ }
+
+ public boolean isTerminated() {
+ return getThread().isTerminated();
+ }
+
+ public void terminate() throws DebugException {
+ getThread().terminate();
+ }
+
+ /**
+ * Returns the name of the source file this stack frame is associated with.
+ *
+ * @return the name of the source file this stack frame is associated with
+ */
+ String getSourceName() {
+ Script script = stackFrame.getScript();
+ if (script == null) {
+ return Messages.StackFrame_UnknownScriptName;
+ }
+ return script.getName();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof StackFrame) {
+ StackFrame other = (StackFrame) obj;
+ return other.stackFrame.equals(this.stackFrame);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return stackFrame.hashCode();
+ }
+
+}