org.chromium.sdk/src/org/chromium/sdk/internal/CallFrameImpl.java
changeset 2 e4420d2515f1
child 52 f577ea64429e
equal deleted inserted replaced
1:ef76fc2ac88c 2:e4420d2515f1
       
     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.sdk.internal;
       
     6 
       
     7 import java.util.ArrayList;
       
     8 import java.util.Collection;
       
     9 import java.util.Collections;
       
    10 import java.util.List;
       
    11 
       
    12 import org.chromium.sdk.CallFrame;
       
    13 import org.chromium.sdk.CallbackSemaphore;
       
    14 import org.chromium.sdk.JsScope;
       
    15 import org.chromium.sdk.JsVariable;
       
    16 import org.chromium.sdk.Script;
       
    17 import org.chromium.sdk.SyncCallback;
       
    18 import org.chromium.sdk.internal.InternalContext.ContextDismissedCheckedException;
       
    19 import org.chromium.sdk.internal.protocol.CommandResponse;
       
    20 import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
       
    21 import org.chromium.sdk.internal.protocol.data.ValueHandle;
       
    22 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
       
    23 import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
       
    24 import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
       
    25 import org.chromium.sdk.internal.tools.v8.V8Helper;
       
    26 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessage;
       
    27 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory;
       
    28 
       
    29 /**
       
    30  * A generic implementation of the CallFrame interface.
       
    31  */
       
    32 public class CallFrameImpl implements CallFrame {
       
    33 
       
    34   /** The frame ID as reported by the JavaScript VM. */
       
    35   private final int frameId;
       
    36 
       
    37   /** The debug context this call frame belongs in. */
       
    38   private final InternalContext context;
       
    39 
       
    40   /** The underlying frame data from the JavaScript VM. */
       
    41   private final FrameMirror frameMirror;
       
    42 
       
    43   /** The variables known in this call frame. */
       
    44   private Collection<JsVariableImpl> variables = null;
       
    45 
       
    46   /** The scopes known in this call frame. */
       
    47   private List<? extends JsScope> scopes = null;
       
    48 
       
    49   /** The receiver variable known in this call frame. May be null. */
       
    50   private JsVariable receiverVariable;
       
    51   private boolean receiverVariableLoaded = false;
       
    52 
       
    53   /**
       
    54    * Constructs a call frame for the given handler using the FrameMirror data
       
    55    * from the remote JavaScript VM.
       
    56    *
       
    57    * @param mirror frame in the VM
       
    58    * @param index call frame id (0 is the stack top)
       
    59    * @param context in which the call frame is created
       
    60    */
       
    61   public CallFrameImpl(FrameMirror mirror, int index, InternalContext context) {
       
    62     this.context = context;
       
    63     this.frameId = index;
       
    64     this.frameMirror = mirror;
       
    65   }
       
    66 
       
    67   public InternalContext getInternalContext() {
       
    68     return context;
       
    69   }
       
    70 
       
    71   @Deprecated
       
    72   public Collection<JsVariableImpl> getVariables() {
       
    73     ensureVariables();
       
    74     return variables;
       
    75   }
       
    76 
       
    77   public List<? extends JsScope> getVariableScopes() {
       
    78     ensureScopes();
       
    79     return scopes;
       
    80   }
       
    81 
       
    82   public JsVariable getReceiverVariable() {
       
    83     ensureReceiver();
       
    84     return this.receiverVariable;
       
    85   }
       
    86 
       
    87   private void ensureVariables() {
       
    88     if (variables == null) {
       
    89       this.variables = Collections.unmodifiableCollection(createVariables());
       
    90     }
       
    91   }
       
    92 
       
    93   private void ensureScopes() {
       
    94     if (scopes == null) {
       
    95       this.scopes = Collections.unmodifiableList(createScopes());
       
    96     }
       
    97   }
       
    98 
       
    99   private void ensureReceiver() {
       
   100     if (!receiverVariableLoaded) {
       
   101       PropertyReference ref = frameMirror.getReceiverRef();
       
   102       if (ref == null) {
       
   103         this.receiverVariable = null;
       
   104       } else {
       
   105         ValueLoader valueLoader = context.getValueLoader();
       
   106         ValueMirror mirror =
       
   107             valueLoader.getOrLoadValueFromRefs(Collections.singletonList(ref)).get(0);
       
   108         this.receiverVariable = new JsVariableImpl(this, mirror, ref.getName());
       
   109       }
       
   110       this.receiverVariableLoaded = true;
       
   111     }
       
   112   }
       
   113 
       
   114   public int getLineNumber() {
       
   115     Script script = frameMirror.getScript();
       
   116     // Recalculate respective to the script start
       
   117     // (frameMirror.getLine() returns the line offset in the resource).
       
   118     return script != null
       
   119         ? frameMirror.getLine() - script.getStartLine()
       
   120         : -1;
       
   121   }
       
   122 
       
   123   public int getCharStart() {
       
   124     return -1;
       
   125   }
       
   126 
       
   127   public int getCharEnd() {
       
   128     return -1;
       
   129   }
       
   130 
       
   131   public String getFunctionName() {
       
   132     return frameMirror.getFunctionName();
       
   133   }
       
   134 
       
   135   public Script getScript() {
       
   136     return frameMirror.getScript();
       
   137   }
       
   138 
       
   139   public void evaluateSync(String expression, EvaluateCallback evaluateCallback)
       
   140       throws MethodIsBlockingException {
       
   141     CallbackSemaphore callbackSemaphore = new CallbackSemaphore();
       
   142     evaluateAsync(expression, evaluateCallback, callbackSemaphore);
       
   143     boolean res = callbackSemaphore.tryAcquireDefault();
       
   144     if (!res) {
       
   145       evaluateCallback.failure("Timeout");
       
   146     }
       
   147   }
       
   148 
       
   149   public void evaluateAsync(final String expression, final EvaluateCallback callback,
       
   150       SyncCallback syncCallback) {
       
   151     try {
       
   152       evaluateAsyncImpl(expression, callback, syncCallback);
       
   153     } catch (ContextDismissedCheckedException e) {
       
   154       getInternalContext().getDebugSession().maybeRethrowContextException(e);
       
   155       // or
       
   156       try {
       
   157         callback.failure(e.getMessage());
       
   158       } finally {
       
   159         syncCallback.callbackDone(null);
       
   160       }
       
   161     }
       
   162   }
       
   163   public void evaluateAsyncImpl(final String expression, final EvaluateCallback callback,
       
   164       SyncCallback syncCallback) throws ContextDismissedCheckedException {
       
   165     DebuggerMessage message =
       
   166       DebuggerMessageFactory.evaluate(expression, getIdentifier(), null, null);
       
   167 
       
   168     V8CommandProcessor.V8HandlerCallback commandCallback = callback == null
       
   169         ? null
       
   170         : new V8CommandProcessor.V8HandlerCallback() {
       
   171           public void messageReceived(CommandResponse response) {
       
   172             SuccessCommandResponse successResponse = response.asSuccess();
       
   173             if (successResponse != null) {
       
   174               ValueHandle body;
       
   175               try {
       
   176                 body = successResponse.getBody().asEvaluateBody();
       
   177               } catch (JsonProtocolParseException e) {
       
   178                 throw new RuntimeException(e);
       
   179               }
       
   180               JsVariable variable =
       
   181                   new JsVariableImpl(CallFrameImpl.this, V8Helper.createMirrorFromLookup(
       
   182                       body).getValueMirror(), expression);
       
   183               if (variable != null) {
       
   184                 callback.success(variable);
       
   185               } else {
       
   186                 callback.failure("Evaluation failed");
       
   187               }
       
   188             } else {
       
   189               callback.failure(response.asFailure().getMessage());
       
   190             }
       
   191           }
       
   192 
       
   193           public void failure(String message) {
       
   194             callback.failure(message);
       
   195           }
       
   196         };
       
   197 
       
   198     getInternalContext().sendV8CommandAsync(message, true, commandCallback,
       
   199         syncCallback);
       
   200   }
       
   201 
       
   202   /**
       
   203    * @return this call frame's unique identifier within the V8 VM (0 is the top
       
   204    *         frame)
       
   205    */
       
   206   int getIdentifier() {
       
   207     return frameId;
       
   208   }
       
   209 
       
   210   /**
       
   211    * Initializes this frame with variables based on the frameMirror locals.
       
   212    */
       
   213   private Collection<JsVariableImpl> createVariables() {
       
   214     List<PropertyReference> refs = frameMirror.getLocals();
       
   215     List<ValueMirror> mirrors = context.getValueLoader().getOrLoadValueFromRefs(refs);
       
   216     Collection<JsVariableImpl> result = new ArrayList<JsVariableImpl>(refs.size());
       
   217     for (int i = 0; i < refs.size(); i++) {
       
   218       result.add(new JsVariableImpl(this, mirrors.get(i), refs.get(i).getName()));
       
   219     }
       
   220     return result;
       
   221   }
       
   222 
       
   223   private List<JsScopeImpl> createScopes() {
       
   224     List<ScopeMirror> scopes = frameMirror.getScopes();
       
   225     List<JsScopeImpl> result = new ArrayList<JsScopeImpl>(scopes.size());
       
   226     for (ScopeMirror mirror : scopes) {
       
   227       result.add(new JsScopeImpl(this, mirror));
       
   228     }
       
   229     return result;
       
   230   }
       
   231 }