Package org.chromium.sdk.internal.v8native.value

Source Code of org.chromium.sdk.internal.v8native.value.ValueMirror

// Copyright (c) 2011 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.sdk.internal.v8native.value;

import java.util.EnumSet;
import java.util.Set;

import org.chromium.sdk.JsValue;
import org.chromium.sdk.JsValue.Type;
import org.chromium.sdk.internal.v8native.V8Helper;
import org.chromium.sdk.internal.v8native.protocol.input.data.FunctionValueHandle;
import org.chromium.sdk.internal.v8native.protocol.input.data.ObjectValueHandle;
import org.chromium.sdk.internal.v8native.protocol.input.data.RefWithDisplayData;
import org.chromium.sdk.internal.v8native.protocol.input.data.ValueHandle;
import org.chromium.sdk.internal.v8native.value.LoadableString.Factory;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.JSONParser;

/**
* A representation of a datum (value) in the remote JavaScript VM. The class must be immutable.
* When additional (or more recent) data arrives, new instance should be put into
* {@link ValueLoader} map.
*/
public abstract class ValueMirror {
  /**
   * Merges to {@link ValueMirror}s into one. Since {@link ValueMirror} is immutable
   * this is the right way to gather data.
   * @return possibly new {@link ValueMirror}, or any of the old ones, making a preference for
   *      'base' parameter.
   */
  static ValueMirror merge(ValueMirror base, ValueMirror alternative) {
    if (base.hasProperties()) {
      if (alternative.hasProperties()) {
        // Fall through.
      } else {
        return base;
      }
    } else {
      if (alternative.hasProperties()) {
        return alternative;
      } else {
        // Fall through.
      }
    }
    int lenDiff = base.getStringLength() - alternative.getStringLength();
    if (lenDiff < 0) {
      return alternative;
    } else {
      return base;
    }
  }

  /**
   * Tries to construct the full {@link ValueMirror} from V8 debugger display data (preview)
   * if it's possible.
   */
  public static ValueMirror createIfSure(final RefWithDisplayData refWithDisplayData) {
    long ref = refWithDisplayData.ref();
    final Type type = V8Helper.calculateType(refWithDisplayData.type(),
        refWithDisplayData.className(), false);

    if (!TYPES_WITH_ACCURATE_DISPLAY.contains(type)) {
      return null;
    }

    return new ValueMirror(ref) {
      @Override
      public Type getType() {
        return type;
      }

      @Override
      public String getClassName() {
        return refWithDisplayData.className();
      }

      @Override
      public LoadableString getStringValue() {
        // try another format
        Object valueObj = refWithDisplayData.value();
        String valueStr;
        if (valueObj == null) {
          valueStr = refWithDisplayData.type(); // e.g. "undefined"
        } else {
          // Works poorly for strings, but we do not allow strings here.
          valueStr = JSONValue.toJSONString(valueObj);
          if (type == Type.TYPE_NUMBER && valueStr.lastIndexOf('E') != -1) {
            // Make accurate rendering of what V8 does.
            valueStr = valueStr.toLowerCase();
          }
        }
        return new LoadableString.Immutable(valueStr);
      }

      @Override
      public boolean hasProperties() {
        return false;
      }

      @Override
      public SubpropertiesMirror getProperties() {
        return null;
      }
    };
  }

  /**
   * Lists types that we can accept in 'display data' form (preview property format).
   * Object types are not here because we cannot get either proper class name or
   * string representation. String isn't here because it may be truncated and we
   * have no clue about it (well, we can check that it ends like truncated string
   * ends, but it's not too robust).
   */
  private static final Set<Type> TYPES_WITH_ACCURATE_DISPLAY =
      EnumSet.of(Type.TYPE_NUMBER, Type.TYPE_BOOLEAN, Type.TYPE_NULL, Type.TYPE_UNDEFINED);

  /**
   * Constructs a ValueMirror given a V8 debugger object specification.
   * @param valueHandle containing the object specification from the V8 debugger
   */
  public static ValueMirror create(final ValueHandle valueHandle, final Factory factory) {
    Long ref = valueHandle.handle();

    final Type type = V8Helper.calculateType(valueHandle.type(), valueHandle.className(), true);

    return new ValueMirror(ref) {
      @Override
      public Type getType() {
        return type;
      }

      @Override
      public LoadableString getStringValue() {
        return V8Helper.createLoadableString(valueHandle, factory);
      }

      @Override
      public SubpropertiesMirror getProperties() {
        ObjectValueHandle objectValueHandle = valueHandle.asObject();
        if (objectValueHandle == null) {
          return SubpropertiesMirror.EMPTY;
        }
        int refId = (int) valueHandle.handle();
        SubpropertiesMirror subpropertiesMirror;
        if (type == Type.TYPE_FUNCTION) {
          FunctionValueHandle functionValueHandle = objectValueHandle.asFunction();
          subpropertiesMirror = new SubpropertiesMirror.FunctionValueBased(functionValueHandle);
        } else {
          subpropertiesMirror = new SubpropertiesMirror.ObjectValueBased(objectValueHandle);
        }
        return subpropertiesMirror;
      }

      @Override
      public boolean hasProperties() {
        return true;
      }

      @Override
      public String getClassName() {
        return valueHandle.className();
      }
    };
  }

  public static ValueMirror create(Long ref, final Type type,
      final String className, final LoadableString loadableString,
      final SubpropertiesMirror subpropertiesMirror) {
    return new ValueMirror(ref) {
      @Override
      public JsValue.Type getType() {
        return type;
      }

      @Override
      public String getClassName() {
        return className;
      }

      @Override
      public LoadableString getStringValue() {
        return loadableString;
      }

      @Override
      public SubpropertiesMirror getProperties() {
        return subpropertiesMirror;
      }

      @Override
      public boolean hasProperties() {
        return getProperties() != null;
      }
    };
  }

  private final Long ref;

  protected ValueMirror(Long ref) {
    assert ref != null;
    this.ref = ref;
  }

  public abstract JsValue.Type getType();

  public abstract SubpropertiesMirror getProperties();

  public Long getRef() {
    return ref;
  }

  public abstract LoadableString getStringValue();

  public abstract String getClassName();

  public abstract boolean hasProperties();

  int getStringLength() {
    LoadableString loadableString = getStringValue();
    if (loadableString == null) {
      return 0;
    }
    return loadableString.getCurrentString().length();
  }
}
TOP

Related Classes of org.chromium.sdk.internal.v8native.value.ValueMirror

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.