Make getOwnPropertyDescriptor and defineProperty work property for arrays.
Allows getting and setting attributes on index properties when the array is in dense mode. git-svn-id: svn://10.0.0.236/trunk@257702 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -505,6 +505,59 @@ public class NativeArray extends IdScriptableObject
|
||||
return super.getDefaultValue(hint);
|
||||
}
|
||||
|
||||
private ScriptableObject defaultIndexPropertyDescriptor(Object value) {
|
||||
Scriptable scope = getParentScope();
|
||||
if (scope == null) scope = this;
|
||||
ScriptableObject desc = new NativeObject();
|
||||
ScriptRuntime.setObjectProtoAndParent(desc, scope);
|
||||
desc.defineProperty("value", value, EMPTY);
|
||||
desc.defineProperty("writable", true, EMPTY);
|
||||
desc.defineProperty("enumerable", true, EMPTY);
|
||||
desc.defineProperty("configurable", true, EMPTY);
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) {
|
||||
if (dense != null) {
|
||||
int index = toIndex(id);
|
||||
if (0 <= index && index < length) {
|
||||
Object value = dense[index];
|
||||
return defaultIndexPropertyDescriptor(value);
|
||||
}
|
||||
}
|
||||
return super.getOwnPropertyDescriptor(cx, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineOwnProperty(Context cx, Object id, ScriptableObject desc) {
|
||||
if (dense != null) {
|
||||
Object[] values = dense;
|
||||
dense = null;
|
||||
denseOnly = false;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (values[i] != NOT_FOUND) {
|
||||
put(i, this, values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
int index = toIndex(id);
|
||||
if (index >= length) {
|
||||
length = index + 1;
|
||||
}
|
||||
super.defineOwnProperty(cx, id, desc);
|
||||
}
|
||||
|
||||
private int toIndex(Object id) {
|
||||
if (id instanceof String) {
|
||||
return (int) toArrayIndex((String) id);
|
||||
} else if (id instanceof Number) {
|
||||
return ((Number) id).intValue();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See ECMA 15.4.1,2
|
||||
*/
|
||||
|
||||
48
mozilla/js/rhino/testsrc/doctests/arrays.doctest
Normal file
48
mozilla/js/rhino/testsrc/doctests/arrays.doctest
Normal file
@@ -0,0 +1,48 @@
|
||||
js> [1,2,undefined,4].join(';')
|
||||
1;2;;4
|
||||
js> [1,2,null,4].join(';')
|
||||
1;2;;4
|
||||
js> var arr = []; arr[0] = 1; arr[1] = 2; arr[3] = 4; arr.join(';')
|
||||
1;2;;4
|
||||
js> var arr = [1,2,3,4]; delete arr[2]; arr.join(';')
|
||||
1;2;;4
|
||||
|
||||
js> var arr = ["a","b","c","d"];
|
||||
js> var _ = arr.length = 2;
|
||||
js> arr[2] === undefined
|
||||
true
|
||||
js> arr[1] === "b"
|
||||
true
|
||||
|
||||
js> [1,2,3].reverse().toSource()
|
||||
[3, 2, 1]
|
||||
|
||||
js> [2,1,3].sort().toSource()
|
||||
[1, 2, 3]
|
||||
|
||||
js> var arr = [1,2,3]; arr.push(4); arr.toSource()
|
||||
[1, 2, 3, 4]
|
||||
|
||||
js> var arr = [1,2,3]; arr.pop();
|
||||
3
|
||||
js> arr.toSource()
|
||||
[1, 2]
|
||||
|
||||
js> var arr = [1,2,3]; arr.shift();
|
||||
1
|
||||
js> arr.toSource()
|
||||
[2, 3]
|
||||
|
||||
js> var arr = [2,3]; arr.unshift(1); arr.toSource()
|
||||
[1, 2, 3]
|
||||
|
||||
js> var arr = [1,2,3]; arr.splice(1, 1, "a", "b").toSource()
|
||||
[2]
|
||||
js> arr.toSource()
|
||||
[1, "a", "b", 3]
|
||||
|
||||
js> [1,2,3].concat([4,5,6]).toSource()
|
||||
[1, 2, 3, 4, 5, 6]
|
||||
|
||||
js> [1,2,3].indexOf(2)
|
||||
1
|
||||
@@ -171,3 +171,14 @@ js> // make sure defineProperty works properly with numbers as ids
|
||||
js> Object.defineProperty({}, 0, {value:1, enumerable:true})['0']
|
||||
1
|
||||
|
||||
js> // make sure defineProperty works properly with arrays
|
||||
js> Object.defineProperty([], 0, {value:1, enumerable:true})[0]
|
||||
1
|
||||
|
||||
js> // make sure defineProperty works properly with arrays
|
||||
js> Object.defineProperty([], 'a', {value:1, enumerable:true})['a']
|
||||
1
|
||||
|
||||
js> // make sure defineProperty updates length properly for arrays
|
||||
js> Object.defineProperty([], 0, {value:1}).length
|
||||
1
|
||||
|
||||
@@ -54,3 +54,25 @@ js> Object.getOwnPropertyDescriptor({undefined: 1}, undefined).toSource()
|
||||
js> Object.getOwnPropertyDescriptor({0:1}, 0).toSource()
|
||||
({value:1, writable:true, enumerable:true, configurable:true})
|
||||
|
||||
js> Object.getOwnPropertyDescriptor([1], 0).toSource()
|
||||
({value:1, writable:true, enumerable:true, configurable:true})
|
||||
|
||||
js> Object.getOwnPropertyDescriptor([1], '0').toSource()
|
||||
({value:1, writable:true, enumerable:true, configurable:true})
|
||||
|
||||
js> Object.getOwnPropertyDescriptor([1], 1) === undefined
|
||||
true
|
||||
|
||||
js> Object.getOwnPropertyDescriptor([1], -1) === undefined
|
||||
true
|
||||
|
||||
js> var arr = [];
|
||||
js> arr.a = 1;
|
||||
1
|
||||
js> Object.getOwnPropertyDescriptor(arr, 'a').toSource()
|
||||
({value:1, writable:true, enumerable:true, configurable:true})
|
||||
|
||||
js> var arr = Object.defineProperty([], 'a', {value:1, writable:false,})
|
||||
js> var desc = Object.getOwnPropertyDescriptor(arr, 'a'); ([desc.value, desc.writable]).toSource()
|
||||
[1, false]
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.mozilla.javascript.tests;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.junit.matchers.JUnitMatchers.hasItem;
|
||||
import static org.junit.matchers.JUnitMatchers.both;
|
||||
|
||||
import org.mozilla.javascript.NativeArray;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NativeArrayTest {
|
||||
|
||||
@Test
|
||||
public void getIdsShouldIncludeBothIndexAndNormalProperties() {
|
||||
NativeArray array = new NativeArray(1);
|
||||
array.put(0, array, "index");
|
||||
array.put("a", array, "normal");
|
||||
|
||||
assertThat(array.getIds(), is(new Object[]{0, "a"}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteShouldRemoveIndexProperties() {
|
||||
NativeArray array = new NativeArray(new Object[]{"a"});
|
||||
array.delete(0);
|
||||
assertThat(array.has(0, array), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteShouldRemoveNormalProperties() {
|
||||
NativeArray array = new NativeArray(1);
|
||||
array.put("p", array, "a");
|
||||
array.delete("p");
|
||||
assertThat(array.has("p", array), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putShouldAddIndexProperties() {
|
||||
NativeArray array = new NativeArray(1);
|
||||
array.put(0, array, "a");
|
||||
assertThat(array.has(0, array), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putShouldAddNormalProperties() {
|
||||
NativeArray array = new NativeArray(1);
|
||||
array.put("p", array, "a");
|
||||
assertThat(array.has("p", array), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getShouldReturnIndexProperties() {
|
||||
NativeArray array = new NativeArray(new Object[]{"a"});
|
||||
assertThat(array.get(0, array), is((Object)"a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getShouldReturnNormalProperties() {
|
||||
NativeArray array = new NativeArray(1);
|
||||
array.put("p", array, "a");
|
||||
assertThat(array.get("p", array), is((Object)"a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasShouldBeFalseForANewArray() {
|
||||
NativeArray array = new NativeArray(0);
|
||||
assertThat(array.has(0, array), is(false));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user