blob: bc64f6406a829b6d79fba6a03fc86c0e4e2248aa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.lib.v8debug.vars;
import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import org.netbeans.lib.v8debug.PropertyLong;
/**
*
* @author Martin Entlicher
*/
public class V8Object extends V8Value {
private final String className;
private final PropertyLong constructorFunctionHandle;
private final PropertyLong protoObjectHandle;
private final PropertyLong prototypeObjectHandle;
private final Map<String, Property> properties;
private final Array array;
public V8Object(long handle, V8Value.Type type, String className,
PropertyLong constructorFunctionHandle,
PropertyLong protoObjectHandle, PropertyLong prototypeObjectHandle,
Map<String, Property> properties, Array array, String text) {
super(handle, type, text);
this.className = className;
this.constructorFunctionHandle = constructorFunctionHandle;
this.protoObjectHandle = protoObjectHandle;
this.prototypeObjectHandle = prototypeObjectHandle;
this.properties = properties;
this.array = array;
}
protected V8Object(long handle, V8Value.Type type, String className,
PropertyLong constructorFunctionHandle,
PropertyLong protoObjectHandle, PropertyLong prototypeObjectHandle,
Map<String, Property> properties, String text) {
this(handle, type, className, constructorFunctionHandle,
protoObjectHandle, prototypeObjectHandle, properties, null, text);
}
public String getClassName() {
return className;
}
public PropertyLong getConstructorFunctionHandle() {
return constructorFunctionHandle;
}
public PropertyLong getProtoObjectHandle() {
return protoObjectHandle;
}
public PropertyLong getPrototypeObjectHandle() {
return prototypeObjectHandle;
}
public Map<String, Property> getProperties() {
return properties;
}
public Array getArray() {
return array;
}
public static final class Property {
public static enum Type {
Normal,
Field,
Constant,
Callbacks,
Handler,
Interceptor,
Transition,
Nonexistent
}
public static final int ATTR_NONE = 0;
public static final int ATTR_READ_ONLY = 1;
public static final int ATTR_DONT_ENUM = 2;
public static final int ATTR_DONT_DELETE = 4;
public static final int ATTR_SEALED = ATTR_DONT_DELETE;
public static final int ATTR_FROZEN = ATTR_SEALED | ATTR_READ_ONLY;
public static final int ATTR_STRING = 8;
public static final int ATTR_SYMBOLIC = 16;
public static final int ATTR_PRIVATE_SYMBOL = 32;
public static final int ATTR_DONT_SHOW = ATTR_DONT_ENUM | ATTR_SYMBOLIC | ATTR_PRIVATE_SYMBOL;
public static final int ATTR_ABSENT = 64;
private final String name;
private final Type type;
private final int attributes;
private final long reference;
public Property(String name, Type type, int attributes, long reference) {
this.name = name;
this.type = type;
this.attributes = attributes;
this.reference = reference;
}
public String getName() {
return name;
}
public Type getType() {
return type;
}
public int getAttributes() {
return attributes;
}
public long getReference() {
return reference;
}
}
public static interface Array {
long getReferenceAt(long index) throws NoSuchElementException;
IndexIterator getIndexIterator();
boolean isContiguous();
long[] getContiguousReferences() throws UnsupportedOperationException;
long getLength();
}
public static interface IndexIterator {
boolean hasNextIndex();
long nextIndex() throws NoSuchElementException;
}
public static final class DefaultArray implements Array {
private long[] references;
private long[] indexes;
private int length;
public DefaultArray(long[] references) {
this.references = references;
this.indexes = null;
this.length = references.length;
}
public DefaultArray() {
this.references = new long[0];
this.indexes = null;
this.length = 0;
}
public void putReferenceAt(long index, long reference) {
if (indexes == null) {
// we're contiguous so far
if (index < length) {
references[(int) index] = reference;
} else if (index == length) {
if (references.length <= index) {
int newLength = getNewLength();
references = Arrays.copyOf(references, newLength);
}
references[length++] = reference;
} else {
// switch to non-contiguous
int newLength = references.length;
if (!(newLength > length)) {
newLength = getNewLength();
references = Arrays.copyOf(references, newLength);
}
indexes = new long[newLength];
for (int i = 0; i < length; i++) {
indexes[i] = i;
}
indexes[length] = index;
references[length] = reference;
length++;
}
} else {
if (references.length <= length) {
int newLength = getNewLength();
references = Arrays.copyOf(references, newLength);
indexes = Arrays.copyOf(indexes, newLength);
}
indexes[length] = index;
references[length] = reference;
length++;
}
}
private int getNewLength() {
int newLength = length + (length >> 1);
if (newLength < 10) {
newLength = 10;
}
if (!(newLength > length)) {
// overflow
newLength = Integer.MAX_VALUE - 8;
if (!(newLength > length)) {
if (length == Integer.MAX_VALUE) {
throw new OutOfMemoryError("Unable to allocate an array longer than "+Integer.MAX_VALUE+" bytes.");
}
newLength = Integer.MAX_VALUE;
}
}
return newLength;
}
@Override
public long getReferenceAt(long index) throws NoSuchElementException {
if (indexes == null) {
if (index >= length) {
throw new NoSuchElementException("No reference at "+index+", array length is "+length);
}
return references[(int) index];
} else {
int pos = getPositionOf(index);
if (pos < 0) {
throw new NoSuchElementException("No reference at "+index);
}
return references[pos];
}
}
private int getPositionOf(long index) {
int p1 = 0;
int p2 = length - 1;
while (p1 <= p2) {
int p = p1 + (p2 - p1)/2;
long pi = indexes[p];
if (pi == index) {
return p;
}
if (p1 == p2) {
return -1;
}
if (pi < index) {
if (p1 == p) {
p1++;
} else {
p1 = p;
}
} else {
p2 = p;
}
}
return -1;
}
@Override
public IndexIterator getIndexIterator() {
return new DefaultIndexIterator();
}
@Override
public boolean isContiguous() {
return indexes == null;
}
@Override
public long[] getContiguousReferences() throws UnsupportedOperationException {
if (indexes == null) {
if (references.length > length) {
// trim
references = Arrays.copyOf(references, length);
}
return references;
} else {
throw new UnsupportedOperationException("The array is not contiguous.");
}
}
@Override
public long getLength() {
if (indexes == null) {
return length;
} else {
if (length == 0) {
return 0;
} else {
long maxIndex = indexes[length-1];
return maxIndex + 1;
}
}
}
private final class DefaultIndexIterator implements IndexIterator {
private int pos = 0;
@Override
public boolean hasNextIndex() {
return pos < length;
}
@Override
public long nextIndex() throws NoSuchElementException {
if (pos >= length) {
throw new NoSuchElementException("Length = "+length);
}
if (indexes == null) {
return pos++;
} else {
return indexes[pos++];
}
}
}
}
}