mirror of https://github.com/svaarala/duktape.git
Sami Vaarala
9 years ago
6 changed files with 692 additions and 13 deletions
@ -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); |
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
Loading…
Reference in new issue