Browse Source

Testcases changes for duk_harray

pull/703/head
Sami Vaarala 9 years ago
parent
commit
5ee98a6649
  1. 156
      tests/api/test-def-prop-virtual.c
  2. 17
      tests/api/test-def-prop.c
  3. 10
      tests/ecmascript/test-bi-json-enc-fastpath.js
  4. 423
      tests/ecmascript/test-dev-duk-harray.js
  5. 65
      tests/ecmascript/test-dev-enum-abandoned-array.js
  6. 34
      tests/ecmascript/test-dev-rom-builtins-1.js

156
tests/api/test-def-prop-virtual.c

@ -0,0 +1,156 @@
/*
* Test DUK_DEFPROP_FORCE for virtual properties.
*/
/*===
*** test_array_length_enumerable_noforce (duk_safe_call)
set array .length enumerable
==> rc=1, result='TypeError: not configurable'
*** test_array_length_enumerable_force (duk_safe_call)
set array .length enumerable
==> rc=1, result='TypeError: property is virtual'
*** test_array_length_configurable_noforce (duk_safe_call)
set array .length configurable
==> rc=1, result='TypeError: not configurable'
*** test_array_length_configurable_force (duk_safe_call)
set array .length configurable
==> rc=1, result='TypeError: property is virtual'
*** test_array_length_overwrite_same_noforce (duk_safe_call)
["foo","bar","quux"]
final top: 0
==> rc=0, result='undefined'
*** test_array_length_overwrite_same_force (duk_safe_call)
["foo","bar","quux"]
final top: 0
==> rc=0, result='undefined'
*** test_array_length_overwrite_bigger_noforce (duk_safe_call)
==> rc=1, result='TypeError: not configurable'
*** test_array_length_overwrite_bigger_force (duk_safe_call)
["foo","bar","quux",null,null]
final top: 0
==> rc=0, result='undefined'
*** test_array_length_overwrite_smaller_noforce (duk_safe_call)
==> rc=1, result='TypeError: array length non-writable'
*** test_array_length_overwrite_smaller_force (duk_safe_call)
["foo"]
final top: 0
==> rc=0, result='undefined'
===*/
static duk_ret_t test__array_length_enumerable(duk_context *ctx, int force) {
duk_push_array(ctx);
duk_push_string(ctx, "length");
printf("set array .length enumerable\n");
fflush(stdout);
duk_def_prop(ctx, -2, DUK_DEFPROP_SET_ENUMERABLE | (force ? DUK_DEFPROP_FORCE : 0));
duk_eval_string(ctx,
"(function (v) { print(Duktape.enc('jx', Object.getOwnPropertyDescriptor(v, 'length' ))); })");
duk_dup(ctx, -2);
duk_call(ctx, 1);
duk_pop_2(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_array_length_enumerable_noforce(duk_context *ctx, void *udata) {
(void) udata;
return test__array_length_enumerable(ctx, 0);
}
static duk_ret_t test_array_length_enumerable_force(duk_context *ctx, void *udata) {
(void) udata;
return test__array_length_enumerable(ctx, 1);
}
static duk_ret_t test__array_length_configurable(duk_context *ctx, int force) {
duk_push_array(ctx);
duk_push_string(ctx, "length");
printf("set array .length configurable\n");
fflush(stdout);
duk_def_prop(ctx, -2, DUK_DEFPROP_SET_CONFIGURABLE | (force ? DUK_DEFPROP_FORCE : 0));
duk_eval_string(ctx,
"(function (v) { print(Duktape.enc('jx', Object.getOwnPropertyDescriptor(v, 'length' ))); })");
duk_dup(ctx, -2);
duk_call(ctx, 1);
duk_pop_2(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_array_length_configurable_noforce(duk_context *ctx, void *udata) {
(void) udata;
return test__array_length_configurable(ctx, 0);
}
static duk_ret_t test_array_length_configurable_force(duk_context *ctx, void *udata) {
(void) udata;
return test__array_length_configurable(ctx, 1);
}
static duk_ret_t test__length_overwrite(duk_context *ctx, int force, int new_len) {
duk_eval_string(ctx,
"(function () {\n"
" var arr = [ 'foo', 'bar', 'quux' ];\n"
" Object.defineProperty(arr, 'length', { writable: false });\n"
" return arr;\n"
"})()\n");
/* Array .length is not writable; with DUK_DEFPROP_FORCE we can still
* write it.
*/
duk_push_string(ctx, "length");
duk_push_int(ctx, new_len);
duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | (force ? DUK_DEFPROP_FORCE : 0));
duk_eval_string(ctx,
"(function (v) { print(Duktape.enc('jx', v)); })");
duk_dup(ctx, -2);
duk_call(ctx, 1);
duk_pop_2(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_array_length_overwrite_same_noforce(duk_context *ctx, void *udata) {
(void) udata;
return test__length_overwrite(ctx, 0, 3);
}
static duk_ret_t test_array_length_overwrite_same_force(duk_context *ctx, void *udata) {
(void) udata;
return test__length_overwrite(ctx, 1, 3);
}
static duk_ret_t test_array_length_overwrite_bigger_noforce(duk_context *ctx, void *udata) {
(void) udata;
return test__length_overwrite(ctx, 0, 5);
}
static duk_ret_t test_array_length_overwrite_bigger_force(duk_context *ctx, void *udata) {
(void) udata;
return test__length_overwrite(ctx, 1, 5);
}
static duk_ret_t test_array_length_overwrite_smaller_noforce(duk_context *ctx, void *udata) {
(void) udata;
return test__length_overwrite(ctx, 0, 1);
}
static duk_ret_t test_array_length_overwrite_smaller_force(duk_context *ctx, void *udata) {
(void) udata;
return test__length_overwrite(ctx, 1, 1);
}
void test(duk_context *ctx) {
TEST_SAFE_CALL(test_array_length_enumerable_noforce);
TEST_SAFE_CALL(test_array_length_enumerable_force);
TEST_SAFE_CALL(test_array_length_configurable_noforce);
TEST_SAFE_CALL(test_array_length_configurable_force);
TEST_SAFE_CALL(test_array_length_overwrite_same_noforce);
TEST_SAFE_CALL(test_array_length_overwrite_same_force);
TEST_SAFE_CALL(test_array_length_overwrite_bigger_noforce);
TEST_SAFE_CALL(test_array_length_overwrite_bigger_force);
TEST_SAFE_CALL(test_array_length_overwrite_smaller_noforce);
TEST_SAFE_CALL(test_array_length_overwrite_smaller_force);
}

17
tests/api/test-def-prop.c

@ -162,38 +162,38 @@ final top: 1
final top: 1
==> rc=0, result='undefined'
*** test_fail_array_smaller (duk_safe_call)
"length" {value:4,writable:true,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
"1" {value:"bar",writable:true,enumerable:true,configurable:true} no-getter no-setter
"2" {value:"quux",writable:true,enumerable:true,configurable:false} no-getter no-setter
"3" {value:"baz",writable:true,enumerable:true,configurable:true} no-getter no-setter
"length" {value:4,writable:true,enumerable:false,configurable:false} no-getter no-setter
==> rc=1, result='TypeError: array length write failed'
*** test_force_array_smaller (duk_safe_call)
"length" {value:4,writable:true,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
"1" {value:"bar",writable:true,enumerable:true,configurable:true} no-getter no-setter
"2" {value:"quux",writable:true,enumerable:true,configurable:false} no-getter no-setter
"3" {value:"baz",writable:true,enumerable:true,configurable:true} no-getter no-setter
"length" {value:4,writable:true,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
"length" {value:1,writable:true,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
json: ["foo"]
final top: 1
==> rc=0, result='undefined'
*** test_fail_array_smaller_nonwritablelength (duk_safe_call)
"length" {value:4,writable:false,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
"1" {value:"bar",writable:true,enumerable:true,configurable:true} no-getter no-setter
"2" {value:"quux",writable:true,enumerable:true,configurable:false} no-getter no-setter
"3" {value:"baz",writable:true,enumerable:true,configurable:true} no-getter no-setter
"length" {value:4,writable:false,enumerable:false,configurable:false} no-getter no-setter
==> rc=1, result='TypeError: array length non-writable'
*** test_force_array_smaller_nonwritablelength (duk_safe_call)
"length" {value:4,writable:false,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
"1" {value:"bar",writable:true,enumerable:true,configurable:true} no-getter no-setter
"2" {value:"quux",writable:true,enumerable:true,configurable:false} no-getter no-setter
"3" {value:"baz",writable:true,enumerable:true,configurable:true} no-getter no-setter
"length" {value:4,writable:false,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
"length" {value:1,writable:false,enumerable:false,configurable:false} no-getter no-setter
"0" {value:"foo",writable:true,enumerable:true,configurable:true} no-getter no-setter
json: ["foo"]
final top: 1
==> rc=0, result='undefined'
@ -927,6 +927,11 @@ static duk_ret_t test_force_accessor2data(duk_context *ctx, void *udata) {
/* Make array smaller, ignoring non-configurable elements. */
static duk_ret_t test_force_array_smaller_raw(duk_context *ctx, duk_bool_t length_writable, duk_bool_t forced) {
/* The array will have a non-configurable element (not very common)
* which causes the array part to be abandoned and affects enumeration
* order; in Duktape 2.0 'length' will enumerate before the properties
* because .length is virtual.
*/
if (length_writable) {
duk_eval_string(ctx,
"(function () {\n"

10
tests/ecmascript/test-bi-json-enc-fastpath.js

@ -59,12 +59,13 @@ top level value test
6 "foo"
7 {"foo":123}
8 ["foo"]
9 undefined
10 "1970-01-01T00:00:00.123Z"
11 undefined
9 [null,null,null,null,null,null,null,null,null,null]
10 undefined
11 "1970-01-01T00:00:00.123Z"
12 undefined
13 undefined
14 {"type":"Buffer","data":[65,66,67,68,69,70,71,72]}
14 undefined
15 {"type":"Buffer","data":[65,66,67,68,69,70,71,72]}
===*/
/* Top level value */
@ -73,6 +74,7 @@ function jsonStringifyFastPathTopLevelValueTest() {
var values = [
undefined, null, true, false, 123, 123.456, 'foo',
{ foo: 123 }, [ 'foo' ],
new Array(10), // .length is larger than underlying array part length
function myfunc() {},
new Date(123),
Duktape.dec('hex', 'deadbeef'),

423
tests/ecmascript/test-dev-duk-harray.js

@ -0,0 +1,423 @@
/*
* Dev testcases when adding duk_harray
*
* https://github.com/svaarala/duktape/pull/703
*/
/*===
array literal test
3
1,2,3
===*/
function arrayLiteralTest() {
var arr;
arr = [ 1, 2, 3 ];
print(arr.length);
print(arr);
}
try {
print('array literal test');
arrayLiteralTest();
} catch (e) {
print(e.stack || e);
}
/*===
array constructor test
10 [null,null,null,null,null,null,null,null,null,null]
10 [null,null,null,null,null,"foo",null,null,null,null]
6 [1,2,3,"foo","bar","quux"]
6 [1,2,3,"foo","bar","baz"]
256
===*/
function arrayConstructorTest() {
var arr;
var i;
// Create Array using numeric argument
arr = new Array(10);
print(arr.length, JSON.stringify(arr));
arr[5] = 'foo';
print(arr.length, JSON.stringify(arr));
for (i = 0; i < 256; i++) {
arr = new Array(i);
if (arr.length !== i) {
throw new Error('failed for index ' + i);
}
}
// Create Array from initializer arguments
arr = new Array(1, 2, 3, 'foo', 'bar', 'quux');
print(arr.length, JSON.stringify(arr));
arr[5] = 'baz';
print(arr.length, JSON.stringify(arr));
// Create Array with a lot of initializer arguments (more than value stack reserve).
arr = new Array(
// 256
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
);
print(arr.length);
}
try {
print('array constructor test');
arrayConstructorTest();
} catch (e) {
print(e.stack || e);
}
/*===
array enumeration test
0,1,2,3,length
0,1,2,3
0,1,2,3,4,length
0,1,2,3,4
0,1,2,3,4,length,foo
0,1,2,3,4,foo
===*/
function arrayEnumerationTest() {
var arr;
arr = [ 1,2,3,4 ];
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
arr[4] = 5;
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
arr.foo = 'bar';
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
}
try {
print('array enumeration test');
arrayEnumerationTest();
} catch (e) {
print(e.stack || e);
}
/*===
array .length property descriptor test
6 true false false
6 [1,2,3,4,5,6]
5 [1,2,3,4,5]
5 [1,2,3,4,5]
5 [1,2,3,4,5]
5 false false false
defineProperty
5 [1,2,3,4,5]
5 [1,2,3,4,5]
TypeError: array length non-writable
TypeError: not configurable
TypeError: not configurable
TypeError: not configurable
TypeError: not configurable
2 [null,null]
===*/
function arrayLengthPropertyDescriptorTest() {
var arr, pd;
// Make .length non-writable.
arr = [ 1, 2, 3, 4, 5, 6 ];
pd = Object.getOwnPropertyDescriptor(arr, 'length');
print(pd.value, pd.writable, pd.enumerable, pd.configurable);
print(arr.length, JSON.stringify(arr));
arr.length = 5;
print(arr.length, JSON.stringify(arr));
Object.defineProperty(arr, 'length', { writable: false });
print(arr.length, JSON.stringify(arr));
arr.length = 4;
print(arr.length, JSON.stringify(arr));
pd = Object.getOwnPropertyDescriptor(arr, 'length');
print(pd.value, pd.writable, pd.enumerable, pd.configurable);
print('defineProperty');
try {
Object.defineProperty(arr, 'length', { value: 5 }); // no change, ok
print(arr.length, JSON.stringify(arr));
} catch (e) {
print(e.stack || e);
}
try {
Object.defineProperty(arr, 'length', { value: 5, writable: false, enumerable: false, configurable: false }); // no change, ok
print(arr.length, JSON.stringify(arr));
} catch (e) {
print(e.stack || e);
}
try {
Object.defineProperty(arr, 'length', { value: 4 }); // Not OK
print('never here');
print(arr.length, JSON.stringify(arr));
} catch (e) {
//print(e.stack);
print(e);
}
try {
Object.defineProperty(arr, 'length', { writable: true }); // Not OK
print('never here');
print(arr.length, JSON.stringify(arr));
} catch (e) {
//print(e.stack);
print(e);
}
try {
Object.defineProperty(arr, 'length', { enumerable: true }); // Not OK
print('never here');
print(arr.length, JSON.stringify(arr));
} catch (e) {
//print(e.stack);
print(e);
}
try {
Object.defineProperty(arr, 'length', { configurable: true }); // Not OK
print('never here');
print(arr.length, JSON.stringify(arr));
} catch (e) {
//print(e.stack);
print(e);
}
try {
Object.defineProperty(arr, 'length', { set: function () {}, get: function () {} }); // Not OK
print('never here');
print(arr.length, JSON.stringify(arr));
} catch (e) {
//print(e.stack);
print(e);
}
// Set .length using Object.defineProperty().
arr = [];
Object.defineProperty(arr, 'length', { value: 2 });
print(arr.length, JSON.stringify(arr));
}
try {
print('array .length property descriptor test');
arrayLengthPropertyDescriptorTest();
} catch (e) {
print(e.stack || e);
}
/*===
array length test
false
TypeError: not configurable
4
4
true
0,1,2,length
true
1,2,3,4,5,6,7,8,9,10
1,2,3,4,5,foo,7,8,9,10
TypeError: not writable
1,2,3,4,5,foo,7,8,9,10
===*/
function arrayLengthTest() {
var arr;
var obj;
// Attempt to delete Array .length fails; result false in non-strict
// mode, error in strict mode.
arr = [ 1, 2, 3, 4, 5 ];
print(delete arr.length);
try {
(function deleteTest() { 'use strict'; delete arr.length; })();
} catch (e) {
//print(e.stack);
print(e);
}
// Attempt to write a non-writable Array .length.
arr = [ 1, 2, 3, 4 ];
Object.defineProperty(arr, 'length', { writable: false });
print(arr.length);
arr.length = 2;
print(arr.length);
// Property existence for Array .length.
arr = [ 1, 2, 3 ];
print('length' in arr);
print(Object.getOwnPropertyNames(arr));
obj = Object.create(arr); // inherit from 'arr'
print('length' in obj);
print(Object.getOwnPropertyNames(obj));
// Writing to an Array when .length is write protected.
arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
Object.defineProperty(arr, 'length', { writable: false });
print(arr);
arr[5] = 'foo'; // OK, length not changed
print(arr);
try {
arr[10] = 'foo';
} catch (e) {
//print(e.stack);
print(e);
}
print(arr);
}
try {
print('array length test');
arrayLengthTest();
} catch (e) {
print(e.stack || e);
}
/*===
enumeration order for sparse arrays
0,1,2,length
0,1,2
0,1,2,length,foo
0,1,2,foo
length,0,1,2,foo
0,1,2,foo
length,0,1,2,foo,bar
0,1,2,foo,bar
===*/
/* The enumeration order for sparse arrays (= arrays whose array part has been
* abandoned) changes with the introduction of duk_harray. The enumeration
* order is: (1) array part, (2) virtual .length property, (3) entry part.
* The virtual .length only comes into play when also non-enumerable own
* properties are listed, e.g. Object.getOwnPropertyNames() is used.
*
* For a three-member dense array this would result in the enumeration order
* 0,1,2,length. When that array becomes sparse, Duktape 1.x would still
* enumerate it as 0,1,2,length because .length was stored explicitly and
* could thus be moved to the entry part. Duktape 2.x has a virtual Array
* .length and the sparse array will thus enumerate as length,0,1,2.
*
* ((o) Duktape 1.5.0 (v1.4.0-421-g8e90d3d-dirty)
* duk> a = [1,2,3]; a[100] = 1; a.length = 3;
* = 3
* duk> Object.getOwnPropertyNames(a)
* = 0,1,2,length
*
* ((o) Duktape [linenoise] 1.99.99 (v1.5.0-168-g86373ab-dirty)
* duk> a = [1,2,3]; a[100] = 1; a.length = 3;
* = 3
* duk> Object.getOwnPropertyNames(a)
* = length,0,1,2
*/
function sparseArrayEnumTest() {
var arr;
arr = [ 1, 2, 3 ];
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
arr.foo = 'bar';
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
arr[100] = 1; arr.length = 3; // make sparse
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
arr.bar = 'quux';
print(Object.getOwnPropertyNames(arr));
print(Object.keys(arr));
}
try {
print('enumeration order for sparse arrays');
sparseArrayEnumTest();
} catch (e) {
print(e.stack || e);
}
/*===
Array.prototype test
[object Array]
[object Array]
0 foo bar quux undefined
0 foo undefined undefined undefined
0 undefined undefined undefined undefined
dummy
undefined
===*/
function arrayPrototypeTest() {
var arr;
// Array.prototype is an Array instance.
// This is useful to check for ROM built-ins.
print(Object.prototype.toString.call([]));
print(Object.prototype.toString.call(Array.prototype));
// It can also be written to (unusual but required).
Array.prototype.push('foo', 'bar', 'quux');
arr = [];
print(arr.length, arr[0], arr[1], arr[2], arr[3]);
Array.prototype.length = 1;
print(arr.length, arr[0], arr[1], arr[2], arr[3]);
Array.prototype.length = 0;
print(arr.length, arr[0], arr[1], arr[2], arr[3]);
// Array.prototype is dense by default; make it sparse.
//print(Duktape.enc('jx', Duktape.info(Array.prototype)));
Array.prototype[1000] = 'dummy';
//print(Duktape.enc('jx', Duktape.info(Array.prototype)));
arr = [];
print(arr[1000]);
Array.prototype.length = 0;
//print(Duktape.enc('jx', Duktape.info(Array.prototype)));
print(arr[1000]);
}
try {
print('Array.prototype test');
arrayPrototypeTest();
} catch (e) {
print(e.stack || e);
}
/*===
100
1000000000
===*/
function arrayMiscTest() {
var arr;
// Creating an Array with a small count creates a dense array
// with a preallocated array part.
arr = new Array(100);
print(arr.length);
// Creating an Array with a huge count creates a dense array
// but with no preallocated array part.
arr = new Array(1e9);
print(arr.length);
}
try {
arrayMiscTest();
} catch (e) {
print(e.stack || e);
}

65
tests/ecmascript/test-dev-enum-abandoned-array.js

@ -0,0 +1,65 @@
/*
* Enumeration order for abandoned array part changed in Duktape 2.x.
* This testcase illustrates the change. The change is related to array
* instance .length which is non-enumerable, so that the change only affects
* Object.getOwnPropertyNames() and duk_enum() calls which request enumeration
* of non-enumerable properties.
*/
/*===
with array part
- 0
- 1
- 2
- length
- myProperty
without array part
- length
- 0
- 1
- 2
- myProperty
array index added after abandoning array part
- length
- 0
- 1
- 2
- myProperty
- 3
===*/
function test() {
var arr = [ 'foo', 'bar', 'quux' ];
arr.myProperty = true;
// When array part is present the array index properties enumerate first,
// then the virtual .length property, and finally any other properties.
print('with array part');
Object.getOwnPropertyNames(arr).forEach(function (k) { print('-', k); });
arr[100] = 'dummy'; // abandon array part
arr.length = 3;
// When array part is not present, the virtual .length property enumerates
// first, followed by index properties moved into the entry part, followed
// by other properties (and any array index writes which happen after the
// array part is abandoned.
//
// In Duktape 1.x the .length property is concrete and would be enumerated
// after the index properties moved into the entry part. Array indexes
// added after array part abandonment would still appear last.
print('without array part');
Object.getOwnPropertyNames(arr).forEach(function (k) { print('-', k); });
arr.push('baz');
print('array index added after abandoning array part');
Object.getOwnPropertyNames(arr).forEach(function (k) { print('-', k); });
}
try {
test();
} catch (e) {
print(e.stack || e);
}

34
tests/ecmascript/test-dev-rom-builtins-1.js

@ -383,19 +383,29 @@ function romObjectRegExpTest() {
/*===
--- Error.prototype setter/getter
fileName
{get:{_func:true},set:{_func:true},enumerable:false,configurable:false}
get length: 0, set length: 0
lineNumber
{get:{_func:true},set:{_func:true},enumerable:false,configurable:false}
get length: 0, set length: 0
stack
{get:{_func:true},set:{_func:true},enumerable:false,configurable:false}
get length: 0, set length: 0
===*/
function romObjectErrorPrototypeAccessorTest() {
function test(key) {
var pd = Object.getOwnPropertyDescriptor(Error.prototype, key);
print(Duktape.enc('jx', pd));
print('get length: ' + pd.get.length + ', set length: ' + pd.set.length);
print(key);
try {
var pd = Object.getOwnPropertyDescriptor(Error.prototype, key);
print(Duktape.enc('jx', pd));
print('get length: ' + pd.get.length + ', set length: ' + pd.set.length);
} catch (e) {
print(typeof e, typeof e.message, typeof e.name, e.message, e.name);
print(e instanceof Error);
print(e.stack || e);
}
}
test('fileName');
@ -415,6 +425,21 @@ function romObjectAccessorTest() {
print(global.__proto__ == Object.getPrototypeOf(global));
}
/*===
--- Array.prototype test
[object Array]
[object Array]
0
===*/
function romObjectArrayPrototypeTest() {
// Array.prototype is also an Array instance; this affects the
// ROM init data and is thus useful to check.
print(Object.prototype.toString.call([]));
print(Object.prototype.toString.call(Array.prototype));
print(Array.prototype.length);
}
// Read-only code paths related to object properties which aren't covered:
//
// duk_hobject_props.c:duk_realloc_props(): assert, can't be exercised directly.
@ -463,6 +488,9 @@ try {
print('--- Accessor test')
romObjectAccessorTest();
print('--- Array.prototype test');
romObjectArrayPrototypeTest();
} catch (e) {
print(e.stack || e);
}

Loading…
Cancel
Save