Skip to content

Commit

Permalink
ADD: JavaDoc / using list.add if last element is added
Browse files Browse the repository at this point in the history
  • Loading branch information
rPraml authored and gbrail committed Oct 14, 2021
1 parent f0ba830 commit 43793a4
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
46 changes: 44 additions & 2 deletions src/org/mozilla/javascript/NativeJavaList.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,45 @@
import java.util.ArrayList;
import java.util.List;

/**
* <code>NativeJavaList</code> is a wrapper for java objects implementing <code>java.util.List
* </code> interface. This wrapper delegates index based access in javascript (like <code>
* value[x] = 3</code>) to the according {@link List#get(int)}, {@link List#set(int, Object)} and
* {@link List#add(Object)} methods. This allows you to use java lists in many places like a
* javascript <code>Array</code>.
*
* <p>Supported functions:
*
* <ul>
* <li>index based access is delegated to List.get/set/add. If <code>index &gt;= length</code>,
* the skipped elements will be filled with <code>null</code> values
* <li>iterator support with <code>for...of</code> (provided by NativeJavaObject for all
* iterables)
* <li>when iterating with <code>for .. in</code> (or <code>for each .. in</code>) then <code>
* getIds
* </code> + index based access is used.
* <li>reading and setting <code>length</code> property. When modifying the length property, the
* list is either truncated or will be filled with <code>null</code> values up to <code>length
* </code>
* <li>deleting entries: <code>delete value[index]</code> will be equivalent with <code>
* value[index] = null</code> and is implemented to provide array compatibility.
* </ul>
*
* <b>Important:</b> JavaList does not support sparse arrays. So setting the length property to a
* high value or writing to a high index may allocate a lot of memory.
*
* <p><b>Note:</b> Although <code>JavaList</code> looks like a javascript-<code>Array</code>, it is
* not an <code>
* Array</code>. Some methods behave very similar like <code>Array.indexOf</code> and <code>
* java.util.List.indexOf</code>, others are named differently like <code>Array.includes</code> vs.
* <code>java.util.List.contains</code>. Especially <code>forEach</code> is different in <code>Array
* </code> and <code>java.util.List</code>. Also deleting entries will set entries to <code>null
* </code> instead to <code>Undefined</code>
*/
public class NativeJavaList extends NativeJavaObject {

private static final long serialVersionUID = 660285467829047519L;

private List<Object> list;

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -86,8 +123,13 @@ public Object get(Symbol key, Scriptable start) {
@Override
public void put(int index, Scriptable start, Object value) {
if (index >= 0) {
ensureCapacity(index + 1);
list.set(index, Context.jsToJava(value, Object.class));
Object javaValue = Context.jsToJava(value, Object.class);
if (index == list.size()) {
list.add(javaValue); // use "add" at the end of list.
} else {
ensureCapacity(index + 1);
list.set(index, javaValue);
}
return;
}
super.put(index, start, value);
Expand Down
13 changes: 13 additions & 0 deletions src/org/mozilla/javascript/NativeJavaMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,21 @@
import java.util.List;
import java.util.Map;

/**
* <code>NativeJavaMap</code> is a wrapper for java objects implementing <code>java.util.Map
* </code> interface. When {@link Context#FEATURE_ENABLE_JAVA_MAP_ACCESS} is enabled, property based
* access like <code>map[key]</code> is delegated to {@link Map#get(Object)} or {@link
* Map#put(Object, Object)} operations so that a <code>JavaMap</code> acts very similar to a
* javascript <code>Object</code> There is also an iterator to iterate over entries with <code>
* for .. of</code>.
*
* <p><b>Limitations:</b> The wrapped map should have <code>String</code> or <code>Integer</code> as
* key. Otherwise, property based access may not work properly.
*/
public class NativeJavaMap extends NativeJavaObject {

private static final long serialVersionUID = -3786257752907047381L;

private Map<Object, Object> map;

static void init(ScriptableObject scope, boolean sealed) {
Expand Down
3 changes: 2 additions & 1 deletion src/org/mozilla/javascript/NativeJavaObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

/**
* This class reflects non-Array Java objects into the JavaScript environment. It reflect fields
* directly, and uses NativeJavaMethod objects to reflect (possibly overloaded) methods.
* directly, and uses NativeJavaMethod objects to reflect (possibly overloaded) methods. It also
* provides iterator support for all iterable objects.
*
* <p>
*
Expand Down
13 changes: 13 additions & 0 deletions testsrc/org/mozilla/javascript/tests/NativeJavaListTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,19 @@ public void testDelete() {
assertEquals("a,,c", runScriptAsString("Array.prototype.join.call(value)", list));
}

public void testAdd() {
List<String> list = new ArrayList<>();
runScriptAsString("value[0] = 'a'", list);
runScriptAsString("value[1] = 'b'", list);
runScriptAsString("value[2] = 'c'", list);
assertEquals("[a, b, c]", list.toString());
runScriptAsString("value[5] = 'f'", list);
assertEquals("[a, b, c, null, null, f]", list.toString());
runScriptAsString("value[4] = 'e'", list);
runScriptAsString("value[3] = 'd'", list);
assertEquals("[a, b, c, d, e, f]", list.toString());
}

public void testKeys() {
List<String> list = new ArrayList<>();
NativeArray resEmpty =
Expand Down

0 comments on commit 43793a4

Please sign in to comment.