Browse Source

Testcases for Duktape.info() and duk_inspect_value()

pull/1125/head
Sami Vaarala 8 years ago
parent
commit
3b4279d8b2
  1. 6
      tests/api/test-dump-load-fastint.c
  2. 38
      tests/api/test-external-buffer.c
  3. 122
      tests/api/test-inspect-value.c
  4. 4
      tests/api/test-put-func-num-list.c
  5. 37
      tests/ecmascript/test-bi-duktape-info-manual.js
  6. 52
      tests/ecmascript/test-bi-duktape-info.js
  7. 24
      tests/ecmascript/test-bug-object-prop-alloc-unbounded.js
  8. 1
      tests/ecmascript/test-dev-array-fastpath.js
  9. 3
      tests/ecmascript/test-dev-duk-harray.js
  10. 15
      tests/ecmascript/test-dev-fastint-basic.js
  11. 6
      tests/ecmascript/test-dev-inlined-unary-lnot.js
  12. 22
      tests/ecmascript/test-dev-lightfunc-accessor.js
  13. 10
      tests/ecmascript/test-dev-lightfunc-finalizer.js
  14. 42
      tests/ecmascript/test-dev-lightfunc.js
  15. 12
      tests/ecmascript/test-dev-logicalnot-refcount.js
  16. 24
      tests/ecmascript/test-dev-named-funcexpr-refcount.js
  17. 8
      tests/ecmascript/util-buffer.js
  18. 55
      tests/ecmascript/util-object.js
  19. 23
      tests/knownissues/test-bi-array-proto-push-2.txt
  20. 748
      tests/knownissues/test-dev-lightfunc-4.txt

6
tests/api/test-dump-load-fastint.c

@ -25,7 +25,7 @@ static duk_ret_t test_1(duk_context *ctx, void *udata) {
duk_eval_string_noresult(ctx,
"Object.defineProperty(Duktape, 'fastintTag', {\n"
" /* Tag number depends on duk_tval packing. */\n"
" value: (Duktape.info(true)[1] >= 0xfff0) ?\n"
" value: (Duktape.info(true).itag >= 0xfff0) ?\n"
" 0xfff1 /* tag for packed duk_tval */ :\n"
" 1 /* tag for unpacked duk_tval */,\n"
" writable: false,\n"
@ -34,8 +34,8 @@ static duk_ret_t test_1(duk_context *ctx, void *udata) {
"});\n"
"Object.defineProperty(Duktape, 'isFastint', {\n"
" value: function (v) {\n"
" return Duktape.info(v)[0] === 4 && /* public type is DUK_TYPE_NUMBER */\n"
" Duktape.info(v)[1] === Duktape.fastintTag; /* internal tag is fastint */\n"
" return Duktape.info(v).type === 4 && /* public type is DUK_TYPE_NUMBER */\n"
" Duktape.info(v).itag === Duktape.fastintTag; /* internal tag is fastint */\n"
" },\n"
" writable: false, enumerable: false, configurable: true\n"
"});\n");

38
tests/api/test-external-buffer.c

@ -16,12 +16,6 @@ final top: 1
==> rc=1, result='TypeError: wrong buffer type'
*** test_3 (duk_safe_call)
==> rc=1, result='TypeError: buffer required, found [object Object] (stack index -1)'
*** test_4 (duk_safe_call)
["censoredtag","censoredpointer","censoredrefcount","censoredheapsize"]
["censoredtag","censoredpointer","censoredrefcount","censoredheapsize",256]
["censoredtag","censoredpointer","censoredrefcount","censoredheapsize",16]
final top: 0
==> rc=0, result='undefined'
===*/
unsigned char global_buffer[256];
@ -115,41 +109,9 @@ static duk_ret_t test_3(duk_context *ctx, void *udata) {
return 0;
}
/* Check Duktape.info() for external buffers. */
static duk_ret_t test_4(duk_context *ctx, void *udata) {
unsigned char buf[16];
(void) udata;
/* Censor refcount too because e.g. in shuffle torture test the
* refcount will be different than otherwise.
*/
duk_eval_string(ctx,
"(function (b1, b2, b3) {\n"
" [ b1, b2, b3 ].forEach(function (b) {\n"
" var t = Duktape.info(b);\n"
" t[0] = 'censoredtag';\n"
" t[1] = 'censoredpointer';\n"
" t[2] = 'censoredrefcount';\n"
" t[3] = 'censoredheapsize';\n"
" print(Duktape.enc('jx', t));\n"
" });\n"
"})");
duk_push_fixed_buffer(ctx, 1024);
duk_push_dynamic_buffer(ctx, 256);
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, (void *) buf, 16);
duk_call(ctx, 3 /*nargs*/);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
void test(duk_context *ctx) {
TEST_SAFE_CALL(test_1);
TEST_SAFE_CALL(test_2a);
TEST_SAFE_CALL(test_2b);
TEST_SAFE_CALL(test_3);
TEST_SAFE_CALL(test_4);
}

122
tests/api/test-inspect-value.c

@ -0,0 +1,122 @@
/*
* duk_inspect_value()
*
* The internal implementation for duk_inspect_value() and Duktape.info() is
* exactly the same, so just that the C binding minimally works and rely on
* Duktape.info() tests for the rest.
*
* One important case to test here is inspecting an out-of-bounds index.
* The result should have the type tag DUK_TYPE_NONE.
*/
/*===
*** test_basic (duk_safe_call)
top after inspect: 4
result is object: 1
result.type: 4 (public type number)
final top: 5
==> rc=0, result='undefined'
*** test_buffer_variants (duk_safe_call)
[7,0]
[7,1]
[7,2]
final top: 0
==> rc=0, result='undefined'
*** test_invalid_index1 (duk_safe_call)
top after inspect: 2
result is object: 1
result.type: 0 (public type number)
final top: 3
==> rc=0, result='undefined'
*** test_invalid_index2 (duk_safe_call)
top after inspect: 1
result is object: 1
result.type: 0 (public type number)
final top: 2
==> rc=0, result='undefined'
===*/
static duk_ret_t test_basic(duk_context *ctx, void *udata) {
(void) udata;
duk_push_string(ctx, "dummy");
duk_push_number(ctx, 123.4);
duk_push_string(ctx, "dummy");
duk_inspect_value(ctx, -2);
printf("top after inspect: %ld\n", (long) duk_get_top(ctx));
printf("result is object: %ld\n", (long) duk_is_object(ctx, -1));
duk_get_prop_string(ctx, -1, "type");
printf("result.type: %ld (public type number)\n", (long) duk_to_int(ctx, -1));
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_buffer_variants(duk_context *ctx, void *udata) {
unsigned char buf[16];
(void) udata;
duk_eval_string(ctx,
"(function (b1, b2, b3) {\n"
" [ b1, b2, b3 ].forEach(function (b) {\n"
" var info = Duktape.info(b);\n"
" var t = [ info.type, info.variant ];\n"
" print(Duktape.enc('jx', t));\n"
" });\n"
"})");
duk_push_fixed_buffer(ctx, 1024);
duk_push_dynamic_buffer(ctx, 256);
duk_push_external_buffer(ctx);
duk_config_buffer(ctx, -1, (void *) buf, 16);
duk_call(ctx, 3 /*nargs*/);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_invalid_index1(duk_context *ctx, void *udata) {
(void) udata;
duk_push_string(ctx, "dummy");
duk_inspect_value(ctx, -2);
printf("top after inspect: %ld\n", (long) duk_get_top(ctx));
printf("result is object: %ld\n", (long) duk_is_object(ctx, -1));
duk_get_prop_string(ctx, -1, "type");
printf("result.type: %ld (public type number)\n", (long) duk_to_int(ctx, -1));
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
static duk_ret_t test_invalid_index2(duk_context *ctx, void *udata) {
(void) udata;
duk_inspect_value(ctx, DUK_INVALID_INDEX);
printf("top after inspect: %ld\n", (long) duk_get_top(ctx));
printf("result is object: %ld\n", (long) duk_is_object(ctx, -1));
duk_get_prop_string(ctx, -1, "type");
printf("result.type: %ld (public type number)\n", (long) duk_to_int(ctx, -1));
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
void test(duk_context *ctx) {
TEST_SAFE_CALL(test_basic);
TEST_SAFE_CALL(test_buffer_variants);
TEST_SAFE_CALL(test_invalid_index1);
TEST_SAFE_CALL(test_invalid_index2);
}

4
tests/api/test-put-func-num-list.c

@ -90,8 +90,8 @@ static duk_ret_t test_1(duk_context *ctx, void *udata) {
/* Fastint compatible values are fastint downgraded. */
duk_eval_string_noresult(ctx,
"print(Duktape.info(MyModule.meaning)[1] === Duktape.info(MyModule.FLAG_FOO)[1])\n" /* match: both are fastints */
"print(Duktape.info(MyModule.meaning)[1] !== Duktape.info(MyModule.nonFast)[1])\n" /* no match: nonFast is not fastint */
"print(Duktape.info(MyModule.meaning).itag === Duktape.info(MyModule.FLAG_FOO).itag)\n" /* match: both are fastints */
"print(Duktape.info(MyModule.meaning).itag !== Duktape.info(MyModule.nonFast).itag)\n" /* no match: nonFast is not fastint */
);
printf("final top: %ld\n", (long) duk_get_top(ctx));

37
tests/ecmascript/test-bi-duktape-info-manual.js

@ -0,0 +1,37 @@
/*
* Duktape.info()
*
* To be executed manually.
*/
/*---
{
"skip": true
}
---*/
/*===
===*/
function test() {
// Test public type tags.
[
void 0, null, true, false, 123, 123.1,
'', 'foo', { foo: 123 }, [ 1, 2, 3 ],
Math.cos, function foo() {},
new ArrayBuffer(10),
new Uint32Array(4),
ArrayBuffer.allocPlain(10),
Duktape.Pointer('foo'), new Duktape.Pointer('foo'),
new Duktape.Thread(function () {})
].forEach(function (v, idx) {
var info = Duktape.info(v);
print(idx, typeof v, String(v), typeof info, Duktape.enc('jx', info));
});
}
try {
test();
} catch (e) {
print(e.stack || e);
}

52
tests/ecmascript/test-bi-duktape-info.js

@ -0,0 +1,52 @@
/*
* Duktape.info()
*
* While the results are version specific, test for (some) currently
* provided results.
*/
/*===
0 undefined object 1
1 object object 2
2 boolean object 3
3 boolean object 3
4 number object 4
5 number object 4
6 string object 5
7 string object 5
8 object object 6
9 object object 6
10 function object 6
11 function object 6
12 object object 6
13 object object 6
14 object object 7
15 pointer object 8
16 object object 6
17 object object 6
===*/
function test() {
// Test public type tags.
[
void 0, null, true, false, 123, 123.1,
'', 'foo', { foo: 123 }, [ 1, 2, 3 ],
Math.cos, function foo() {},
new ArrayBuffer(10),
new Uint32Array(4),
ArrayBuffer.allocPlain(10),
Duktape.Pointer('foo'), new Duktape.Pointer('foo'),
new Duktape.Thread(function () {})
].forEach(function (v, idx) {
var info = Duktape.info(v);
print(idx, typeof v, typeof info, info.type);
});
// XXX
}
try {
test();
} catch (e) {
print(e.stack || e);
}

24
tests/ecmascript/test-bug-object-prop-alloc-unbounded.js

@ -34,6 +34,8 @@
* so this is not a major issue performance-wise.
*/
/*@include util-object.js@*/
/*===
without compaction
entry count < 100: true
@ -46,7 +48,7 @@ entry count < 100: true
function objectEntryPartResizeTest(doCompact) {
var sparse = { 0: 0 };
var i;
var t, entryCount, entryNext;
var t, entrySize, entryNext;
for (i = 1; i < 10000; i++) {
sparse[i] = i;
@ -70,24 +72,16 @@ function objectEntryPartResizeTest(doCompact) {
* when adding a new key, and is not necessarily 1 here.
*/
t = Duktape.info(sparse);
//print(t);
entryCount = t[5]; // version dependent, property entry allocated count
entryNext = t[6]; // version dependent, property entry next index
//print('entry next:', entryNext);
//print('entry count:', entryCount);
print('entry count < 100:', (entryCount < 100));
entrySize = getObjectEntrySize(sparse);
entryNext = getObjectEntryNext(sparse);
print('entry count < 100:', (entrySize < 100));
/* With the bug present, a compaction "fixes" the object. */
Duktape.compact(sparse);
t = Duktape.info(sparse);
//print(t);
entryCount = t[5]; // version dependent, property entry allocated count
entryNext = t[6]; // version dependent, property entry next index
//print('entry next:', entryNext);
//print('entry count:', entryCount);
print('entry count < 100:', (entryCount < 100));
entrySize = getObjectEntrySize(sparse);
entryNext = getObjectEntryNext(sparse);
print('entry count < 100:', (entrySize < 100));
}
try {

1
tests/ecmascript/test-dev-array-fastpath.js

@ -24,7 +24,6 @@ function pushPopTest() {
print(arr.length);
// XXX: At the moment there's no shrink check in the fast path.
//print(Duktape.info(arr));
}
try {

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

@ -404,13 +404,10 @@ function arrayPrototypeTest() {
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]);
}

15
tests/ecmascript/test-dev-fastint-basic.js

@ -18,6 +18,8 @@
* 4294967295
*/
/*@include util-object.js@*/
/*---
{
"custom": true,
@ -83,21 +85,18 @@ function printFastint(v) {
else { prefix = '-'; }
}
// Duktape.info() for a non-heap-allocated type has public type tag
// followed by internal type tag. The internal type tag depends on
// the duk_tval unpacked/packed layout. This is pretty fragile but
// useful for this testcase.
// The internal type tag depends on the duk_tval unpacked/packed layout.
if (typeof Duktape !== 'object') {
isfast = ' NOT-DUKTAPE';
} else if (Duktape.info(true)[1] >= 0xfff0) {
} else if (getValueInternalTag(true) >= 0xfff0) {
// packed duk_tval
if (Duktape.info(v)[1] === 0xfff1) {
if (getValueInternalTag(v) === 0xfff1) {
isfast = ' fastint';
}
} else if (Duktape.info(true)[1] === 4) {
} else if (getValueInternalTag(true) === 4) {
// non-packed duk_tval
if (Duktape.info(v)[1] === 1) {
if (getValueInternalTag(v) === 1) {
isfast = ' fastint';
}
} else {

6
tests/ecmascript/test-dev-inlined-unary-lnot.js

@ -2,6 +2,8 @@
* Some tests for unary logical not inline optimizations.
*/
/*@include util-object.js@*/
/*===
comparison
-Infinity false
@ -76,9 +78,7 @@ function test() {
}
function getBytecodeSize(f) {
var info = Duktape.info(f);
//print(info[9]);
return info[9]; // function data size: bytecode, consts, inner funcs
return getObjectBytecodeSize(f);
}
try {

22
tests/ecmascript/test-dev-lightfunc-accessor.js

@ -8,16 +8,14 @@
* and will not match the original values.
*/
/*@include util-object.js@*/
/*---
{
"custom": true
}
---*/
function isLightFunc(x) {
return Duktape.info(x)[0] == 9; // tag
}
/*===
Object.defineProperty
pd_in
@ -90,9 +88,9 @@ function lightfuncAsAccessorTest() {
print('pd_in');
print('typeof get:', typeof pd_in.get);
print('isLightFunc get:', isLightFunc(pd_in.get));
print('isLightFunc get:', valueIsLightFunc(pd_in.get));
print('typeof set:', typeof pd_in.set);
print('isLightFunc set:', isLightFunc(pd_in.set));
print('isLightFunc set:', valueIsLightFunc(pd_in.set));
print('get(=Math.min)(9,-3,11,4):', pd_in.get(9, -3, 11, 4));
print('set(=Math.max)(9,-3,11,4):', pd_in.set(9, -3, 11, 4));
@ -101,9 +99,9 @@ function lightfuncAsAccessorTest() {
print('pd_out');
print('typeof get:', typeof pd_out.get);
print('isLightFunc get:', isLightFunc(pd_out.get));
print('isLightFunc get:', valueIsLightFunc(pd_out.get));
print('typeof set:', typeof pd_out.set);
print('isLightFunc set:', isLightFunc(pd_out.set));
print('isLightFunc set:', valueIsLightFunc(pd_out.set));
print('get(=Math.min)(9,-3,11,4):', pd_out.get(9, -3, 11, 4));
print('set(=Math.max)(9,-3,11,4):', pd_out.set(9, -3, 11, 4));
@ -131,9 +129,9 @@ function lightfuncAsAccessorTest() {
print('pd_in');
print('typeof get:', typeof pd_in.get);
print('isLightFunc get:', isLightFunc(pd_in.get));
print('isLightFunc get:', valueIsLightFunc(pd_in.get));
print('typeof set:', typeof pd_in.set);
print('isLightFunc set:', isLightFunc(pd_in.set));
print('isLightFunc set:', valueIsLightFunc(pd_in.set));
print('get(=Math.min)(9,-3,11,4):', pd_in.get(9, -3, 11, 4));
print('set(=Math.max)(9,-3,11,4):', pd_in.set(9, -3, 11, 4));
@ -142,9 +140,9 @@ function lightfuncAsAccessorTest() {
print('pd_out');
print('typeof get:', typeof pd_out.get);
print('isLightFunc get:', isLightFunc(pd_out.get));
print('isLightFunc get:', valueIsLightFunc(pd_out.get));
print('typeof set:', typeof pd_out.set);
print('isLightFunc set:', isLightFunc(pd_out.set));
print('isLightFunc set:', valueIsLightFunc(pd_out.set));
print('get(=Math.min)(9,-3,11,4):', pd_out.get(9, -3, 11, 4));
print('set(=Math.max)(9,-3,11,4):', pd_out.set(9, -3, 11, 4));

10
tests/ecmascript/test-dev-lightfunc-finalizer.js

@ -11,16 +11,14 @@
* This testcase demonstrates that lightfunc finalizers don't work.
*/
/*@include util-object.js@*/
/*---
{
"custom": true
}
---*/
function isLightFunc(x) {
return Duktape.info(x)[0] == 9; // tag
}
/*===
true
TypeError
@ -30,7 +28,7 @@ function lightfuncFinalizerTest() {
var lfunc = Math.max;
// Verify built-ins are lightfuncs
print(isLightFunc(lfunc));
print(valueIsLightFunc(lfunc));
// Attempt to set a finalizer on the lightfunc directly fails.
try {
@ -43,7 +41,7 @@ function lightfuncFinalizerTest() {
// Finalizer can be set to Function.prototype but it won't get called
// because lightfuncs are primitive values without a refcount field.
Duktape.fin(Function.prototype, function (v) {
if (isLightFunc(v)) {
if (valueIsLightFunc(v)) {
print('inherited finalizer for lightfunc');
}
});

42
tests/ecmascript/test-dev-lightfunc.js

@ -16,6 +16,7 @@
/*@include util-buffer.js@*/
/*@include util-string.js@*/
/*@include util-object.js@*/
/*---
{
@ -68,7 +69,7 @@ function sanitizeLfunc(x) {
}
function isLightFunc(x) {
return Duktape.info(x)[0] == 9; // tag
return valueIsLightFunc(x);
}
function printTypedJx(v, name) {
@ -89,24 +90,11 @@ function testTypedJx(func, name) {
/*===
light func support test
info.length: 2
typeof: function
9
true
===*/
function lightFuncSupportTest() {
/* Duktape.info() can be used to detect that light functions are
* supported.
*/
var fun = getLightFunc();
var info = Duktape.info(fun);
/* Value is primitive (no prop allocations etc) but still callable. */
print('info.length:', info.length);
print('typeof:', typeof fun);
print(Duktape.enc('jx', Duktape.info(fun)[0]));
// fun[1] is internal type tag which we don't want to test here
print(valueIsLightFunc(getLightFunc()));
}
try {
@ -1142,24 +1130,24 @@ function boundFunctionTest() {
var F = Math.max; // length 2, varargs
print('F:', sanitizeLfunc(String(F)));
print('F type tag:', Duktape.info(F)[0]);
print('F type tag:', getValuePublicType(F));
// 'G' will be a full Function object but will still have a lightfunc
// 'name' as a result of ToObject coercion, which is intentional but
// somewhat confusing. This would be fixable in the ToObject() coercion.
var G = F.bind('myThis', 234); // bound once
print('G:', sanitizeLfunc(String(G)));
print('G type tag:', Duktape.info(G)[0]);
print('G type tag:', getValuePublicType(G));
print('G.length:', G.length); // length 1, one argument was bound
var H = G.bind('foo', 345); // bound twice
print('H:', sanitizeLfunc(String(H)));
print('H type tag:', Duktape.info(H)[0]);
print('H type tag:', getValuePublicType(H));
print('H.length:', H.length); // length 0, two arguments are bound
var I = H.bind('foo', 345); // bound three times
print('I:', sanitizeLfunc(String(I)));
print('I type tag:', Duktape.info(I)[0]);
print('I type tag:', getValuePublicType(I));
print('I.length:', I.length); // length 0, doesn't become negative
// Another simple test
@ -1506,7 +1494,7 @@ function propertyAccessorThisBindingTest() {
print('this == lightFunc:', this == lightFunc);
print('this === lightFunc:', this === lightFunc);
print('this.name:', sanitizeLfunc(this.name));
print('type tag:', Duktape.info(this)[0]);
print('type tag:', getValuePublicType(this));
return 'getter retval';
},
set: function () {
@ -1516,7 +1504,7 @@ function propertyAccessorThisBindingTest() {
print('this == lightFunc:', this == lightFunc);
print('this === lightFunc:', this === lightFunc);
print('this.name:', sanitizeLfunc(this.name));
print('type tag:', Duktape.info(this)[0]);
print('type tag:', getValuePublicType(this));
},
enumerable: false,
configurable: true
@ -1529,7 +1517,7 @@ function propertyAccessorThisBindingTest() {
print('this == lightFunc:', this == lightFunc);
print('this === lightFunc:', this === lightFunc);
print('this.name:', sanitizeLfunc(this.name));
print('type tag:', Duktape.info(this)[0]);
print('type tag:', getValuePublicType(this));
return 'getter retval';
},
set: function () {
@ -1538,7 +1526,7 @@ function propertyAccessorThisBindingTest() {
print('this == lightFunc:', this == lightFunc);
print('this === lightFunc:', this === lightFunc);
print('this.name:', sanitizeLfunc(this.name));
print('type tag:', Duktape.info(this)[0]);
print('type tag:', getValuePublicType(this));
},
enumerable: false,
configurable: true
@ -2402,7 +2390,7 @@ function duktapeBuiltinTest() {
var lfunc = Math.cos;
// avoid printing internal tag type
testTypedJx(function () { return Duktape.info(lfunc)[0]; }, 'info');
testTypedJx(function () { return getValuePublicType(lfunc); }, 'info');
// doesn't really make sense
testTypedJx(function () { return Duktape.act(lfunc); }, 'act');
@ -2986,8 +2974,8 @@ function objectValueOfTest() {
t = lfunc.valueOf();
print(typeof lfunc, typeof t);
print(lfunc === t);
print(Duktape.info(lfunc)[0]); // tag 9: lightfunc
print(Duktape.info(t)[0]); // tag 6: object
print(getValuePublicType(lfunc)); // tag 9: lightfunc
print(getValuePublicType(t)); // tag 6: object
}
try {

12
tests/ecmascript/test-dev-logicalnot-refcount.js

@ -1,3 +1,5 @@
/*@include util-object.js@*/
/*---
{
"custom": true
@ -5,9 +7,9 @@
---*/
/*===
2
3
2
4
3
false
===*/
@ -21,11 +23,11 @@ var z = 1;
function test() {
var tmp;
print(Duktape.info(dummy)[2]);
print(getObjectRefcount(dummy));
tmp = dummy;
print(Duktape.info(dummy)[2]);
print(getObjectRefcount(dummy));
tmp = !z;
print(Duktape.info(dummy)[2]);
print(getObjectRefcount(dummy));
print(tmp);
}

24
tests/ecmascript/test-dev-named-funcexpr-refcount.js

@ -4,6 +4,8 @@
* named and anonymous function expressions at the moment.
*/
/*@include util-object.js@*/
/*---
{
"custom": true
@ -11,15 +13,15 @@
---*/
/*===
anon refcount: 4
anon refcount: 3
anon refcount: 3
anon refcount: 2
anon refcount: 2
assign null
finalized
force gc
named refcount: 5
named refcount: 4
named refcount: 4
named refcount: 3
named refcount: 3
assign null
typeof named: undefined
force gc
@ -31,16 +33,16 @@ function anonTest() {
// Print refcount, expected is 3: variable, call argument,
// f_anon.prototype.constructor.
print('anon refcount:', Duktape.info(f)[2]);
print('anon refcount:', getObjectRefcount(f));
// Break ref loop, should decrease refcount by 1.
f.prototype.constructor = null;
print('anon refcount:', Duktape.info(f)[2]);
print('anon refcount:', getObjectRefcount(f));
// Set finalizer, no effect on refcount (function points to
// finalizer, not vice versa).
Duktape.fin(f, function () { print('finalized'); });
print('anon refcount:', Duktape.info(f)[2]);
print('anon refcount:', getObjectRefcount(f));
// Should refcount collect here.
print('assign null');
@ -54,22 +56,22 @@ function anonTest() {
function namedTest() {
var f = function named() {};
// Print refcount, expected is 4: variable, call argument,
// Print refcount, expected is 5: variable, call arguments,
// f_anon.prototype.constructor, and internal environment
// record holding the "named"->func binding
print('named refcount:', Duktape.info(f)[2]);
print('named refcount:', getObjectRefcount(f));
// Break prototype reference loop, should decrease refcount by 1.
// Doesn't break the scope reference loop: the function points
// to the environment record, and the environment record points
// to the function.
f.prototype.constructor = null;
print('named refcount:', Duktape.info(f)[2]);
print('named refcount:', getObjectRefcount(f));
// Set finalizer, no effect on refcount (function points to
// finalizer, not vice versa).
Duktape.fin(f, function () { print('finalized'); });
print('named refcount:', Duktape.info(f)[2]);
print('named refcount:', getObjectRefcount(f));
// Ideally would refcount collect here, but the environment record
// reference loop prevents this from happening. This should be fixed

8
tests/ecmascript/util-buffer.js

@ -11,9 +11,7 @@ var isMixedDouble;
// Detect plain buffer, in Duktape 2.x plain buffers mimic ArrayBuffer so check
// indirectly via the API type tag.
function isPlainBuffer(x) {
var tag;
tag = Duktape.info(x)[0]; // api tag, 7=plain buffer, 6=object
return tag === 7;
return Duktape.info(x).type === 7; // api tag, 7=plain buffer, 6=object
}
// Create a plain buffer, (a) of a specified size, (b) copying a string's
@ -270,10 +268,6 @@ function stringToBuffer(str) {
return new Uint8Array(new Buffer(str)).buffer;
}
function isPlainBuffer(x) {
return Duktape.info(x)[0] === 7; // tag 7: plain buffer
}
function printableNodejsBuffer(buf) {
var tmp = [];
var i, n;

55
tests/ecmascript/util-object.js

@ -1,10 +1,49 @@
/* Get object property count using Duktape.info(). */
function getObjectPropertyCount(obj) {
var i = Duktape.info(obj);
if (typeof i === 'object' && 6 in i) {
return i[6];
} else if (typeof i === 'object' && 'enext' in i) {
return i.enext;
function getDuktapeInfoField(val, arrIdx, propName) {
var i = Duktape.info(val);
if (typeof i === 'object' && i[arrIdx] !== void 0) {
return i[arrIdx];
} else if (typeof i === 'object' && i[propName] !== void 0) {
return i[propName];
}
throw new Error('getObjectPropertyCount() relies on Duktape.info(), cannot parse result');
throw new Error('cannot parse Duktape.info() result, propName: ' + propName);
}
// Get object property count.
function getObjectPropertyCount(obj) {
return getDuktapeInfoField(obj, 6, 'enext');
}
// Get object refcount.
function getObjectRefcount(obj) {
return getDuktapeInfoField(obj, 2, 'refc');
}
// Get object bytecode size.
function getObjectBytecodeSize(obj) {
return getDuktapeInfoField(obj, 9, 'bcbytes');
}
// Get object entry part size.
function getObjectEntrySize(obj) {
return getDuktapeInfoField(obj, 5, 'esize');
}
// Get object entry part 'next' field.
function getObjectEntryNext(obj) {
return getDuktapeInfoField(obj, 6, 'enext');
}
// Check if value is a lightfunc.
function valueIsLightFunc(val) {
return getDuktapeInfoField(val, 0, 'type') === 9;
}
// Get public type number for a value.
function getValuePublicType(val) {
return getDuktapeInfoField(val, 0, 'type');
}
// Get internal type tag of a value; depends on duk_tval packing.
function getValueInternalTag(val) {
return getDuktapeInfoField(val, 1, 'itag');
}

23
tests/knownissues/test-bi-array-proto-push-2.txt

@ -0,0 +1,23 @@
summary: array length above 2^32-1 not supported
---
basic
object number 2 number:1,number:2 --> number 2 --> object number 2 number:1,number:2
object number 2 number:1,number:2 --> number 3 --> object number 3 number:1,number:2,number:3
object number 2 number:1,number:2 --> number 5 --> object number 5 number:1,number:2,number:3,number:4,number:5
object number 2 number:1,number:2 --> number 4 --> object number 4 number:1,number:2,object:3,4,object:5,6
object string 5 nonexistent,nonexistent,nonexistent,nonexistent,nonexistent --> number 5 --> object number 5 nonexistent,nonexistent,nonexistent,nonexistent,nonexistent
4294967295
RangeError: invalid length
coercion
undefined --> TypeError --> undefined
null --> TypeError --> null
boolean undefined undefined --> number 0 --> boolean undefined undefined
boolean undefined undefined --> number 0 --> boolean undefined undefined
number undefined undefined --> number 0 --> number undefined undefined
string number 3 string:f,string:o,string:o --> TypeError --> string number 3 string:f,string:o,string:o
object number 2 number:1,number:2 --> number 2 --> object number 2 number:1,number:2
object undefined undefined --> number 0 --> object number 0
object number 2 string:foo,string:bar --> number 2 --> object number 2 string:foo,string:bar
non-extensible
object number 3 number:1,number:2,number:3 --> TypeError --> object number 3 number:1,number:2,number:3
object number 3 string:foo,string:bar,string:quux --> TypeError --> object number 3 string:foo,string:bar,string:quux

748
tests/knownissues/test-dev-lightfunc-4.txt

@ -0,0 +1,748 @@
summary: requires DUK_USE_LIGHTFUNC_BUILTINS
---
light func support test
false
typeof test
function
property assignment test
strPlainNonStrict: success
strPlainStrict: TypeError
strObjectNonStrict: success
strObjectStrict: success
strObjectNonextNonStrict: success
strObjectNonextStrict: TypeError
lfuncNonStrict1: success
lfuncNonStrict2: success
lfuncStrict1: TypeError
lfuncStrict2: success
instanceof test
{} instanceof lightfunc: TypeError
false
{} instanceof func-wo-prototype: TypeError
lightFunc instanceof Function: true
lightFunc instanceof Number: false
lightFunc instanceof Object: true
comparison test
0 0 true true
0 1 false false
0 2 false false
0 3 true true
0 4 false false
0 5 false false
0 6 false false
1 0 false false
1 1 true true
1 2 false false
1 3 false false
1 4 true true
1 5 false false
1 6 false false
2 0 false false
2 1 false false
2 2 true true
2 3 false false
2 4 false false
2 5 true true
2 6 false false
3 0 true true
3 1 false false
3 2 false false
3 3 true true
3 4 false false
3 5 false false
3 6 false false
4 0 false false
4 1 true true
4 2 false false
4 3 false false
4 4 true true
4 5 false false
4 6 false false
5 0 false false
5 1 false false
5 2 true true
5 3 false false
5 4 false false
5 5 true true
5 6 false false
6 0 false false
6 1 false false
6 2 false false
6 3 false false
6 4 false false
6 5 false false
6 6 true true
arithmetic test
string: testfunction cos() { [native code] }function sin() { [native code] }
string: function cos() { [native code] }function sin() { [native code] }
string: function foo() { [ecmascript code] }function bar() { [ecmascript code] }
toString() test
function max() { [native code] }
function max() { [native code] }
function max() { [native code] }
true
true
toObject() test
caching: true
length: 2 2
name: max max
typeof: function function
internal prototype is Function.prototype: true true
external prototype is not set: true
internal prototypes match: true
external prototypes match (do not exist): true
isExtensible: true true
Math.max test: 9 9
length: 1 1
toBoolean() test
true
true
toBuffer() test
object: function cos() { [native code] }
object: function sin() { [native code] }
toPointer() test
pointer false
object false
number coercion test
NaN
NaN
0
0
0
0
0
0
call and apply test
call
321
apply
987
this coercion test
function false
function false
inherit from Function.prototype test
testValue
Object.prototype.toString() test
[object Function]
JSON/JX/JC test
json
undefined
undefined
jx
{_func:true}
{_func:true}
jc
{"_func":true}
{"_func":true}
json
undefined
undefined
jx
{_func:true}
{_func:true}
jc
{"_func":true}
{"_func":true}
json
{"array":[100,null,200,null,300]}
{
"array": [
100,
null,
200,
null,
300
]
}
jx
{lf:{_func:true},nf:{_func:true},array:[100,{_func:true},200,{_func:true},300]}
{
lf: {_func:true},
nf: {_func:true},
array: [
100,
{_func:true},
200,
{_func:true},
300
]
}
jc
{"lf":{"_func":true},"nf":{"_func":true},"array":[100,{"_func":true},200,{"_func":true},300]}
{
"lf": {"_func":true},
"nf": {"_func":true},
"array": [
100,
{"_func":true},
200,
{"_func":true},
300
]
}
json
"toJsonRetval"
"toJsonRetval"
jx
"toJsonRetval"
"toJsonRetval"
jc
"toJsonRetval"
"toJsonRetval"
json
"toJsonRetval"
"toJsonRetval"
jx
"toJsonRetval"
"toJsonRetval"
jc
"toJsonRetval"
"toJsonRetval"
json
{"lf":"toJsonRetval","nf":"toJsonRetval","array":[100,"toJsonRetval",200,"toJsonRetval",300]}
{
"lf": "toJsonRetval",
"nf": "toJsonRetval",
"array": [
100,
"toJsonRetval",
200,
"toJsonRetval",
300
]
}
jx
{lf:"toJsonRetval",nf:"toJsonRetval",array:[100,"toJsonRetval",200,"toJsonRetval",300]}
{
lf: "toJsonRetval",
nf: "toJsonRetval",
array: [
100,
"toJsonRetval",
200,
"toJsonRetval",
300
]
}
jc
{"lf":"toJsonRetval","nf":"toJsonRetval","array":[100,"toJsonRetval",200,"toJsonRetval",300]}
{
"lf": "toJsonRetval",
"nf": "toJsonRetval",
"array": [
100,
"toJsonRetval",
200,
"toJsonRetval",
300
]
}
json
0
0
jx
0
0
jc
0
0
json
0
0
jx
0
0
jc
0
0
json
{"lf":null,"nf":null,"array":[100,1,200,3,300]}
{
"lf": null,
"nf": null,
"array": [
100,
1,
200,
3,
300
]
}
jx
{lf:NaN,nf:NaN,array:[100,1,200,3,300]}
{
lf: NaN,
nf: NaN,
array: [
100,
1,
200,
3,
300
]
}
jc
{"lf":{"_nan":true},"nf":{"_nan":true},"array":[100,1,200,3,300]}
{
"lf": {"_nan":true},
"nf": {"_nan":true},
"array": [
100,
1,
200,
3,
300
]
}
bound function test
F: function max() { [native code] }
F type tag: 6
G: function bound max() { [bound code] }
G type tag: 6
G.length: 1
H: function bound bound max() { [bound code] }
H type tag: 6
H.length: 0
I: function bound bound bound max() { [bound code] }
I type tag: 6
I.length: 0
G(123): 234
G(123,987): 987
property get test
length directly: 2
toString coerced object (return "length")
objLengthKey coerced to string: length
toString coerced object (return "length")
length through object coercion: 2
read from length -> 2
read from prototype -> undefined
read from name -> max
toString coerced object (return "length")
toString coerced object (return "length")
read from length -> 2
read from testWritable -> 123
read from testNonWritable -> 234
read from call -> function call() { [native code] }
read from apply -> function apply() { [native code] }
read from nonexistent -> 123
property put test
write to length -> silent error
write to prototype -> silent error
write to name -> silent error
toString coerced object (return "length")
toString coerced object (return "length")
write to length -> silent error
write to testWritable -> silent error
write to testNonWritable -> silent error
write to call -> silent error
write to apply -> silent error
write to nonexistent -> silent error
write to length -> TypeError
never here: prototype
write to name -> TypeError
toString coerced object (return "length")
toString coerced object (return "length")
write to length -> TypeError
never here: testWritable
write to testNonWritable -> TypeError
never here: call
never here: apply
never here: nonexistent
property has test
existence: length -> true
existence: prototype -> true
existence: name -> true
toString coerced object (return "length")
toString coerced object (return "length")
existence: length -> true
existence: testWritable -> true
existence: testNonWritable -> true
existence: call -> true
existence: apply -> true
existence: nonexistent -> true
property delete test
delete: length -> false
delete: prototype -> true
delete: name -> false
toString coerced object (return "length")
toString coerced object (return "length")
delete: length -> false
delete: testWritable -> true
delete: testNonWritable -> true
delete: call -> true
delete: apply -> true
delete: nonexistent -> true
delete: length -> TypeError
delete: prototype -> true
delete: name -> TypeError
toString coerced object (return "length")
toString coerced object (return "length")
delete: length -> TypeError
delete: testWritable -> true
delete: testNonWritable -> true
delete: call -> true
delete: apply -> true
delete: nonexistent -> true
non-strict: true
strict: true
property accessor this binding test
getter, strict
strict getter "this" binding test
typeof this: function
this == lightFunc: true
this === lightFunc: true
this.name: max
type tag: 6
getter retval
setter, strict
strict setter "this" binding test
typeof this: function
this == lightFunc: true
this === lightFunc: true
this.name: max
type tag: 6
getter, non-strict
non-strict getter "this" binding test
typeof this: function
this == lightFunc: true
this === lightFunc: true
this.name: max
type tag: 6
getter retval
setter, non-strict
non-strict setter "this" binding test
typeof this: function
this == lightFunc: true
this === lightFunc: true
this.name: max
type tag: 6
property misc test
isSealed: false
isFrozen: false
isExtensible: true
for-in: "inheritTestProperty"
Object.getOwnPropertyNames: "length"
Object.getOwnPropertyNames: "name"
lightFunc.name matches regexp: false
censored lightFunc.name: max_
traceback test
URIError: invalid input
at [anon] (duk_bi_global.c:NNN) internal
at decodeURIComponent () native strict preventsyield
at tracebackTest (TESTCASE:NNN)
at global (TESTCASE:NNN) preventsyield
Duktape.act() test
Error: for traceback
at callback (TESTCASE:NNN) preventsyield
at forEach () native strict preventsyield
at duktapeActTest (TESTCASE:NNN)
at global (TESTCASE:NNN) preventsyield
-1 ["lineNumber","pc","function"] act
-2 ["lineNumber","pc","function"] callback
-3 ["lineNumber","pc","function"] forEach
-4 ["lineNumber","pc","function"] duktapeActTest
-5 ["lineNumber","pc","function"] global
exempt built-ins test
Math.max (is lightfunc): function false
eval: function false
yield: function false
resume: function false
require: function false
Object: function false
Function: function false
Array: function false
String: function false
Boolean: function false
Number: function false
Date: function false
RegExp: function false
Error: function false
EvalError: function false
RangeError: function false
ReferenceError: function false
SyntaxError: function false
TypeError: function false
URIError: function false
Proxy: function false
Duktape.Pointer: function false
Duktape.Thread: function false
Duktape.Logger: function false
Duktape: object false
Math: object false
JSON: object false
getOwnPropertyNames() test
length,name
length
name
getOwnPropertyDescriptor() test
key: name
value: string cos
writable: boolean false
enumerable: boolean false
configurable: boolean false
key: length
value: number 1
writable: boolean false
enumerable: boolean false
configurable: boolean false
key: nonExistent
no descriptor
hasOwnProperty() test
true
true
false
false
propertyIsEnumerable() test
false
false
false
false
defineProperty() test
nonexistent: success
name: TypeError
length: success
defineProperties() test
nonexistent: success
name: TypeError
length: success
getPrototypeOf() test
true
true
setPrototypeOf() test
TypeError
never here
TypeError
never here
success
success
success
success
Array built-in test
Array: object [{_func:true}]
new Array: object [{_func:true}]
isArray: boolean false
toString: string "[object Function]"
valueOf: function {_func:true}
concat: object [{_func:true}]
pop: TypeError
push: TypeError
sort: function {_func:true}
splice: TypeError
reverse: function {_func:true}
shift: TypeError
unshift: TypeError
every: TypeError
some: TypeError
forEach: TypeError
map: TypeError
filter: TypeError
reduce: TypeError
reduceRight: TypeError
Boolean built-in test
Boolean: boolean true
new Boolean: object true
toString: TypeError
valueOf: TypeError
Duktape.Buffer built-in test
Duktape.Buffer: TypeError
new Duktape.buffer: TypeError
toString: TypeError
valueOf: TypeError
Date built-in test
Date: string "string"
new Date: string "object"
parse: number NaN
UTC: number NaN
now: string "number"
toString: TypeError
valueOf: TypeError
toDateString: TypeError
toTimeString: TypeError
toLocaleString: TypeError
toLocaleDateString: TypeError
toLocaleTimeString: TypeError
getTime: TypeError
getFullYear: TypeError
getUTCFullYear: TypeError
getMonth: TypeError
getUTCFullMonth: TypeError
getDate: TypeError
getUTCDate: TypeError
getDay: TypeError
getUTCDay: TypeError
getHours: TypeError
getUTCHours: TypeError
getMinutes: TypeError
getUTCMinutes: TypeError
getSeconds: TypeError
getUTCSeconds: TypeError
getMilliseconds: TypeError
getUTCMilliseconds: TypeError
getTimezoneOffset: TypeError
setTime: TypeError
setMilliseconds: TypeError
setUTCMilliseconds: TypeError
setSeconds: TypeError
setUTCSeconds: TypeError
setMinutes: TypeError
setUTCMinutes: TypeError
setHours: TypeError
setUTCHours: TypeError
setDate: TypeError
setUTCDate: TypeError
setMonth: TypeError
setUTCMonth: TypeError
setFullYear: TypeError
setUTCFullYear: TypeError
toUTCString: TypeError
toISOString: TypeError
toJSON: TypeError
setYear: TypeError
getYear: TypeError
Duktape built-in test
info: number 6
act: undefined undefined
gc: boolean true
fin-get: undefined undefined
fin-set: undefined undefined
encdec-hex: string "function cos() { [native code] }"
dec-hex: TypeError
compact: function {_func:true}
Error built-in test
Error: object {}
new Error: object {}
toString: string "cos"
valueOf: function {_func:true}
Function built-in test
Function: SyntaxError
new Function: SyntaxError
toString: string "function cos() { [native code] }"
valueOf: function {_func:true}
global built-in test
eval: function {_func:true}
parseInt: number NaN
parseFloat: number NaN
isNaN: boolean true
isFinite: boolean false
decodeURI: string "function cos() { [native code] }"
decodeURIComponent: string "function cos() { [native code] }"
encodeURI: string "string"
encodeURIComponent: string "string"
escape: string "string"
unescape: string "string"
JSON built-in test
parse: SyntaxError
stringify: undefined undefined
Duktape.Logger built-in test
Duktape.Logger: TypeError
new Duktape.Logger: object {}
fmt: TypeError
raw: TypeError
TIMESTAMP INF test: My light func is: function cos() { [native code] }
Math built-in test
abs: number NaN
acos: number NaN
asin: number NaN
atan: number NaN
atan2: number NaN
ceil: number NaN
cos: number NaN
exp: number NaN
floor: number NaN
log: number NaN
max: number NaN
min: number NaN
pow: number NaN
random: string "number"
round: number NaN
sin: number NaN
sqrt: number NaN
tan: number NaN
Number built-in test
Number: number NaN
new Number: object NaN
toString: TypeError
toLocaleString: TypeError
valueOf: TypeError
toFixed: TypeError
toExponential: TypeError
toPrecision: TypeError
Object built-in test
Object: function {_func:true}
new Object: function {_func:true}
getPrototypeOf: function {_func:true}
setPrototypeOf: function {_func:true}
seal: function {_func:true}
freeze: function {_func:true}
preventExtensions: function {_func:true}
isSealed: boolean true
isFrozen: boolean true
isExtensible: boolean false
toString: string "[object Function]"
toLocaleString: string "[object Function]"
valueOf: function {_func:true}
isPrototypeOf: boolean false
Duktape.Pointer built-in test
false
false
toString: TypeError
valueOf: TypeError
Proxy built-in test
get
this: object false [object Object]
target: function false [object Function]
key: string name
proxy.name: cos
get
this: object false [object Object]
target: function false [object Function]
key: string length
proxy.length: 1
get
this: object false [object Object]
target: function false [object Function]
key: string nonExistent
proxy.nonExistent: dummy
proxy.foo: bar
proxy.nonExistent: undefined
RegExp built-in test
RegExp: object {}
new RegExp: object {}
exec: TypeError
test: TypeError
toString: TypeError
valueOf: function {_func:true}
String built-in test
String: string "[object Function]"
new String: string "[object Function]"
new String: string "object"
fromCharCode: string "\x00"
toString: TypeError
valueOf: TypeError
charAt: string "["
charCodeAt: number 91
concat: string "[object Function][object Function]"
indexOf: number 0
lastIndexOf: number 0
localeCompare: number 0
match: object ["o"]
replace: string "undefined"
search: number 1
slice: string "[object Function]"
split: object ["",""]
substring: string "[object Function]"
toLowerCase: string "[object function]"
toLocaleLowerCase: string "[object function]"
toUpperCase: string "[OBJECT FUNCTION]"
toLocaleUpperCase: string "[OBJECT FUNCTION]"
trim: string "[object Function]"
substr: string "[object Function]"
Duktape.Thread built-in test
TypeError
TypeError
Object .valueOf() test
true
function function
true
6
6
Loading…
Cancel
Save