/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ package netscape.jsdebug; /** * The Value class represents a JavaScript jsval which may be one of many types * and may or may not have properties * * @author John Bandhauer * @version 1.1 * @since 1.1 */ public final class Value { private Value() {} // can only be constructed natively public native boolean isObject(); public native boolean isNumber(); public native boolean isInt(); public native boolean isDouble(); public native boolean isString(); public native boolean isBoolean(); public native boolean isNull(); public native boolean isVoid(); public native boolean isPrimitive(); public native boolean isFunction(); public native boolean isNative(); public native boolean getBoolean(); public native int getInt(); public native double getDouble(); /** * does a JavaScript toString conversion if value is not already a string */ public String getString() { if(null == _string) _string = _getString(); return _string; } public String getFunctionName() { if(null == _functionName && isFunction()) _functionName = _getFunctionName(); return _functionName; } public Value getPrototype() { if(null == _proto && !_getFlag(GOT_PROTO) && isObject()) { _proto = _getPrototype(); _setFlag(GOT_PROTO); } return _proto; } public Value getParent() { if(null == _parent && !_getFlag(GOT_PARENT) && isObject()) { _parent = _getParent(); _setFlag(GOT_PARENT); } return _parent; } public Value getConstructor() { if(null == _ctor && !_getFlag(GOT_CTOR) && isObject()) { _ctor = _getConstructor(); _setFlag(GOT_CTOR); } return _ctor; } public String getClassName() { if(null == _className && isObject()) { _className = _getClassName(); } return _className; } public Property[] getProperties() { if(null == _props && !_getFlag(GOT_PROPS) && isObject()) { _props = _getProperties(); _setFlag(GOT_PROPS); // if we have any hints, then try to find or add their props if(null != _hints && 0 != _hints.length) { Property[] newProps = new Property[_hints.length]; int made = 0; do_prop: for(int k = 0; k < _hints.length; k++) { String name = _hints[k]; if(null == name || 0 == name.length()) continue; // see if it already exists if(null != _props) { for(int i = 0; i < _props.length; i++) if(name.equals(_props[i].getNameString())) continue do_prop; } // not in our array, try to get the named prop Property prop = _getProperty(name); if(null != prop) newProps[made++] = prop; } if(0 != made) { if(null != _props) { Property[] combinedProps = new Property[_props.length+made]; System.arraycopy(_props, 0, combinedProps, 0, _props.length); System.arraycopy(newProps, 0, combinedProps, _props.length, made); _props = combinedProps; } else { Property[] realProps = new Property[made]; System.arraycopy(newProps, 0, realProps, 0, made); _props = realProps; } } } } return _props; } public Property getProperty(String name) { if(null == name) return null; Property[] props = getProperties(); if(null == props) return null; for(int i = 0; i < props.length; i++) if(name.equals(props[i].getNameString())) return props[i]; Property prop = _getProperty(name); if(null != prop) { Property[] newProps = new Property[props.length+1]; System.arraycopy(props, 0, newProps, 0, props.length); newProps[props.length] = prop; _props = newProps; } return prop; } public String[] getPropertyHints() {return _hints;} public void setPropertyHints(String[] hints) {_hints = hints;} public void refresh() { _refresh(); _flags = 0; _string = null; _functionName = null; _className = null; _props = null; _proto = null; _parent = null; _ctor = null; _string4toString = null; } // override Object public boolean equals(Object obj) { try { return _equals(_nativeJSVal, ((Value)obj)._nativeJSVal); } catch(ClassCastException e) { return false; } } public int hashCode() {return _nativeJSVal;} public String toString() { if(null == _string4toString) { _string4toString = _typeString(); _string4toString += " "; _string4toString += _shortValString(this); if(isObject() && !isNull()) { _string4toString += ", "; _string4toString += _countOfProps() + " props"; if(isFunction()) { _string4toString += ", "; _string4toString += "functionName = " + getFunctionName(); } _string4toString += ", "; _string4toString += "classname = " + getClassName(); _string4toString += ", "; _string4toString += "proto = " + _shortValString(getPrototype()); _string4toString += ", "; _string4toString += "parent = " + _shortValString(getParent()); _string4toString += ", "; _string4toString += "ctor = " + _shortValString(getConstructor()); } } return _string4toString; } // private toString formatting stuff... private String _shortValString(Value v) { if(null == v) return "null"; else if(v.isFunction()) return "[function "+v.getFunctionName()+"]"; else return v.getString(); } private int _countOfProps() { Property[] p = getProperties(); if(null == p) return 0; return p.length; } private String _typeString() { StringBuffer sb = new StringBuffer(11); sb.append(isObject() ? 'o' : '.'); sb.append(isNumber() ? 'n' : '.'); sb.append(isInt() ? 'i' : '.'); sb.append(isDouble() ? 'd' : '.'); sb.append(isString() ? 's' : '.'); sb.append(isBoolean() ? 'b' : '.'); sb.append(isNull() ? 'N' : '.'); sb.append(isVoid() ? 'V' : '.'); sb.append(isPrimitive() ? 'p' : '.'); sb.append(isFunction() ? 'f' : '.'); sb.append(isNative() ? 'n' : '.'); return sb.toString(); } // private flagage... private static final short GOT_PROTO = (short) (1 << 0); private static final short GOT_PROPS = (short) (1 << 1); private static final short GOT_PARENT = (short) (1 << 2); private static final short GOT_CTOR = (short) (1 << 3); private final boolean _getFlag(short b) {return 0 != (_flags & b);} private final void _setFlag(short b) {_flags |= b;} private final void _clearFlag(short b) {_flags &= ~b;} private short _flags; // private natives... protected native void finalize(); private native void _refresh(); private native String _getString(); private native String _getFunctionName(); private native String _getClassName(); private native Property[] _getProperties(); private native Value _getPrototype(); private native Value _getParent(); private native Value _getConstructor(); private native boolean _equals(int nativeJSVal, int other_nativeJSVal); private native Property _getProperty(String name); // private data... private int _nativeJSVal; private String _string; private String _functionName; private String _className; private Property[] _props; private Value _proto; private Value _parent; private Value _ctor; private String _string4toString; private String[] _hints; }