Browse Source

API testcase for dump/load bytecode

pull/264/head
Sami Vaarala 9 years ago
parent
commit
028e28bbd7
  1. 2
      tests/api/test-base64.c
  2. 703
      tests/api/test-dump-load-basic.c
  3. 4
      tests/api/test-hex.c

2
tests/api/test-base64.c

@ -8,7 +8,7 @@ base64 decode: test string
top after: 2
==> rc=0, result='undefined'
*** test_decode_invalid_char (duk_safe_call)
==> rc=1, result='TypeError: base64 decode failed'
==> rc=1, result='TypeError: decode failed'
===*/
static duk_ret_t test_encode(duk_context *ctx) {

703
tests/api/test-dump-load-basic.c

@ -0,0 +1,703 @@
/*
* Bytecode dump/load
*
* This testcase is a little fragile because it dumps bytecode, pc2line
* data etc.
*/
#define MANDELBROT ( \
"function mandel() {\n" \
" var w = 76, h = 28, iter = 100;\n" \
" var i, j, k, c;\n" \
" var x0, y0, xx, yy, xx2, yy2;\n" \
" var line;\n" \
" for (i = 0; i < h; i++) {\n" \
" y0 = (i / h) * 2.5 - 1.25;\n" \
" for (j = 0, line = []; j < w; j++) {\n" \
" x0 = (j / w) * 3.0 - 2.0;\n" \
" for (k = 0, xx = 0, yy = 0, c = '#'; k < iter; k++) {\n" \
" xx2 = xx*xx; yy2 = yy*yy;\n" \
"\n" \
" if (xx2 + yy2 < 4.0) {\n" \
" yy = 2*xx*yy + y0;\n" \
" xx = xx2 - yy2 + x0;\n" \
" } else {\n" \
" /* xx^2 + yy^2 >= 4.0 */\n" \
" if (k < 3) { c = '.'; }\n" \
" else if (k < 5) { c = ','; }\n" \
" else if (k < 10) { c = '-'; }\n" \
" else { c = '='; }\n" \
" break;\n" \
" }\n" \
" }\n" \
" line.push(c);\n" \
" }\n" \
" print(line.join(''));\n" \
" }\n" \
"}\n" \
)
/*===
*** test_basic (duk_safe_call)
dump result type: 7
ff000000000e0000000300000001000900000000000100000001300004c0000000f300400052000040c200000114000101400001414c800041c3800082030101403000014100000081420180403000004000000000ef00000000057072696e74000000000568656c6c6f0140091eb851eb851f000000030000000000000000000300020000000100000001300604400080009a000080af0000006f000000020000000561646465720000000f66616b6546696c656e616d652e6a730000000d03000000010000000c000000000000000178000000000000000179000000010000000000000001780000000179000000000000000000000006676c6f62616c0000000f66616b6546696c656e616d652e6a730000000e0e000000010000000c00000000000000000000000000
load result type: 6
hello 3 3.14
call result type: 1
call result: undefined
final top: 1
==> rc=0, result='undefined'
===*/
/* Basic dump/load test which exercises all constant types and has an inner
* function. Hex dumping the bytecode provides an exact test case dependency
* to the dump format so that any accidental changes break the test.
*/
static duk_ret_t test_basic(duk_context *ctx) {
unsigned char *p;
duk_size_t i, sz;
/* Integer constants generate LDINT now so also use a fractional
* constant to exercise number constants.
*
* Compiled as a program; force source filename.
*/
duk_push_string(ctx, "print('hello', (function adder(x,y) { return x+y; })(1, 2), 3.14);");
duk_push_string(ctx, "fakeFilename.js");
duk_compile(ctx, 0);
duk_dump_function(ctx);
printf("dump result type: %d\n", (int) duk_get_type(ctx, -1));
fflush(stdout);
p = (unsigned char *) duk_get_buffer(ctx, -1, &sz);
for (i = 0; i < sz; i++) {
printf("%02x", (int) p[i]);
}
printf("\n");
fflush(stdout);
/* Load test function from dump and execute it. */
duk_load_function(ctx);
printf("load result type: %d\n", (int) duk_get_type(ctx, -1));
fflush(stdout);
duk_call(ctx, 0);
printf("call result type: %d\n", (int) duk_get_type(ctx, -1));
fflush(stdout);
printf("call result: %s\n", duk_safe_to_string(ctx, -1));
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_mandel (duk_safe_call)
Mandelbrot source length: 884
ff000000006c000000100000000000140000000000010000001e300604c0801300038007004380190083000008338000196e800001ae80000403000400c00080c3ab0003802d800000ee800017ae0000c3b67ffffeae0080c39d8003839c8083839b00038200000048338000136e8000022e80000403000401000004423300044340000103ab0003802d800000ee8000112e000103b67ffffeae0001039d8103839c8183839b000381c00000883380000d6e8000032e800004030004014080000443000442408000048300048280000104c20004c180010143ab0003802d800000ee80000a2e000143b67ffffeae0482439c000382c00502839c000383000602c39a828383ab0003806d8000022e04c0c39c0503839c0403839a000382800602c39b0383839a000382407ffffbae810143ab0003806d800000ee00018382000381808000042e838143ab0003806d800000ee0002038200038180800002ae848143ab0003806d800000ee00028382000381808000012e0002c382000381808000006e7ffff62e0000887300034380000303c20783839800018400008380307fffef2e00004873004343920003440000038442088404180003c48200840030008380307fffe8ae000008730000006f014004000000000000013ff400000000000001400800000000000001400000000000000000000000012301401000000000000000000000012e01401400000000000000000000012c01402400000000000000000000012d00000000013d00000000047075736800000000057072696e7400000000046a6f696e000000000000000000000000066d616e64656c000000096d616e64656c2e6a730000002a6c00000002000000140000000f0000002000000028801004002008000409100022420100822501080210000000017700000000000000016800000001000000046974657200000002000000016900000003000000016a00000004000000016b000000050000000163000000060000000278300000000700000002793000000008000000027878000000090000000279790000000a000000037878320000000b000000037979320000000c000000046c696e650000000d0000000000000000
..........................,,,,,,,,,,,,,,,,,,,,,,,,,.........................
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
................,,,,,,,,,,,,,,,,,,,,,,,,,,,---=----,,,,,,,,,,...............
.............,,,,,,,,,,,,,,,,,,,,,,,,,,,,------====--,,,,,,,,,,,............
..........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------====------,,,,,,,,,,,.........
........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------=#####==-------,,,,,,,,,,.......
......,,,,,,,,,,,,,,,,,,,,,,,,,,,----------==######=----------,,,,,,,,,.....
.....,,,,,,,,,,,,,,,,,,,,,,,-------=========#########=#=-====--,,,,,,,,,....
....,,,,,,,,,,,,,,,,,,--------------=######################==---,,,,,,,,,...
...,,,,,,,,,,,,,,----------------==########################=-----,,,,,,,,,..
..,,,,,,,,,,,,----==----==------===##########################==--,,,,,,,,,,.
.,,,,,,,,,,---------==#==#========###########################=---,,,,,,,,,,,
.,,,,,,,,---------===##########==############################=---,,,,,,,,,,,
.,,,,,,--------=====########################################=----,,,,,,,,,,,
.#########################################################==-----,,,,,,,,,,,
.,,,,,,--------=====########################################=----,,,,,,,,,,,
.,,,,,,,,---------===##########==############################=---,,,,,,,,,,,
.,,,,,,,,,,---------==#==#========###########################=---,,,,,,,,,,,
..,,,,,,,,,,,,----==----==------===##########################==--,,,,,,,,,,.
...,,,,,,,,,,,,,,----------------==########################=-----,,,,,,,,,..
....,,,,,,,,,,,,,,,,,,--------------=######################==---,,,,,,,,,...
.....,,,,,,,,,,,,,,,,,,,,,,,-------=========#########=#=-====--,,,,,,,,,....
......,,,,,,,,,,,,,,,,,,,,,,,,,,,----------==######=----------,,,,,,,,,.....
........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------=#####==-------,,,,,,,,,,.......
..........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------====------,,,,,,,,,,,.........
.............,,,,,,,,,,,,,,,,,,,,,,,,,,,,------====--,,,,,,,,,,,............
................,,,,,,,,,,,,,,,,,,,,,,,,,,,---=----,,,,,,,,,,...............
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
call result: undefined
final top: 1
==> rc=0, result='undefined'
===*/
/* Dump/load mandelbrot. No inner functions but a bit more code. */
static duk_ret_t test_mandel(duk_context *ctx) {
unsigned char *p;
duk_size_t i, sz;
printf("Mandelbrot source length: %ld\n", (long) strlen(MANDELBROT));
/* Compiled as a function; force source filename. */
duk_push_string(ctx, MANDELBROT);
duk_push_string(ctx, "mandel.js");
duk_compile(ctx, DUK_COMPILE_FUNCTION);
duk_dump_function(ctx);
p = (unsigned char *) duk_get_buffer(ctx, -1, &sz);
for (i = 0; i < sz; i++) {
printf("%02x", (int) p[i]);
}
printf("\n");
fflush(stdout);
/* Load test function from dump and execute it. */
duk_load_function(ctx);
duk_call(ctx, 0);
printf("call result: %s\n", duk_safe_to_string(ctx, -1));
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_large_func (duk_safe_call)
9999
call result: undefined
final top: 1
==> rc=0, result='undefined'
===*/
/* Test dumping of a large function to exercise buffer resizes. */
static duk_ret_t test_large_func(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" var res = [];\n"
" res.push('(function myFunc() {');\n"
" var i;\n"
" for (i = 0; i < 5e4; i++) {\n"
" res.push('var test' + i + ' = ' + i + ';');\n"
" }\n"
" res.push('print(test9999);')\n"
" res.push('})');\n"
" return eval(res.join('\\n'));\n"
"})()");
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0);
printf("call result: %s\n", duk_safe_to_string(ctx, -1));
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_properties (duk_safe_call)
.length: {"value":3,"writable":false,"enumerable":false,"configurable":false}
.name: {"value":"test","writable":false,"enumerable":false,"configurable":false}
.fileName: {"value":"fakeFilename.js","writable":true,"enumerable":false,"configurable":true}
.prototype: {"value":{},"writable":true,"enumerable":false,"configurable":false}
._Formals: {value:["a","b","c"],writable:false,enumerable:false,configurable:false}
._Varmap: {value:{a:0,b:1,c:2,x:3},writable:false,enumerable:false,configurable:false}
._Pc2line: {value:|04000000020000000c00000000|,writable:true,enumerable:false,configurable:true}
typeof .prototype: object
typeof .prototype.constructor: function
.prototype.constructor === func: true
descriptor of .prototype: {"value":{},"writable":true,"enumerable":false,"configurable":false}
descriptor of .prototype.constructor: {"writable":true,"enumerable":false,"configurable":true}
final top: 0
==> rc=0, result='undefined'
===*/
/* Properties and property attributes of a loaded function. */
static duk_ret_t test_properties(duk_context *ctx) {
/* Compile explicitly to force fileName. */
duk_push_string(ctx,
"(function () {\n"
" var f = function test(a, b, c) { var x = 123; y = 234; };\n"
" return f;\n"
"})()");
duk_push_string(ctx, "fakeFilename.js");
duk_compile(ctx, DUK_COMPILE_EVAL);
duk_call(ctx, 0);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_eval_string(ctx,
"(function (v) {\n"
" var pfx = Duktape.dec('hex', 'ff');\n"
" [ 'length', 'name', 'fileName', 'prototype' ].forEach(function (k) {\n"
" print('.' + k + ': ' + JSON.stringify(Object.getOwnPropertyDescriptor(v, k)));\n"
" });\n"
" // internal properties; print with JX to print buffer\n"
" [ 'Formals', 'Varmap', 'Pc2line' ].forEach(function (k) {\n"
" print('._' + k + ': ' + Duktape.enc('jx', Object.getOwnPropertyDescriptor(v, pfx + k)));\n"
" });\n"
" // .prototype\n"
" print('typeof .prototype: ' + typeof v.prototype);\n"
" print('typeof .prototype.constructor: ' + typeof v.prototype.constructor);\n"
" print('.prototype.constructor === func: ' + (v === v.prototype.constructor));\n"
" print('descriptor of .prototype: ' + JSON.stringify(Object.getOwnPropertyDescriptor(v, 'prototype')));\n"
" print('descriptor of .prototype.constructor: ' + JSON.stringify(Object.getOwnPropertyDescriptor(v.prototype, 'constructor')));\n"
"})");
duk_dup(ctx, -2),
duk_call(ctx, 1);
duk_pop(ctx);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_program_code (duk_safe_call)
{"value":123,"writable":true,"enumerable":true,"configurable":false}
{"value":234,"writable":true,"enumerable":true,"configurable":false}
final top: 0
==> rc=0, result='undefined'
===*/
/* Test serialization of Program (instead of function) code:
*
* - Bindings established via Eval code are not configurable
* (E5 Section 10.5 step 2).
*/
static duk_ret_t test_program_code(duk_context *ctx) {
/* Demonstrate behavior without dump/load. */
duk_compile_string(ctx, 0,
"var testProgram1 = 123;"
);
duk_call(ctx, 0);
duk_pop(ctx);
duk_eval_string_noresult(ctx,
"print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testProgram1')));"
);
/* Same with dump/load. */
duk_compile_string(ctx, 0,
"var testProgram2 = 234;"
);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0);
duk_pop(ctx);
duk_eval_string_noresult(ctx,
"print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testProgram2')));"
);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_eval_code (duk_safe_call)
{"value":123,"writable":true,"enumerable":true,"configurable":true}
{"value":234,"writable":true,"enumerable":true,"configurable":true}
final top: 0
==> rc=0, result='undefined'
===*/
/* Test serialization of Eval (instead of function) code:
*
* - Bindings established via Eval code are configurable; bindings
* established from program and function code are not. (E5 Section
* 10.5 step 2).
*
* Here we bytecode dump an eval function that is then loaded and executed
* in the global scope.
*/
static duk_ret_t test_eval_code(duk_context *ctx) {
/* Demonstrate behavior without dump/load. */
duk_compile_string(ctx, DUK_COMPILE_EVAL,
"var testEval1 = 123;"
);
duk_call(ctx, 0);
duk_pop(ctx);
duk_eval_string_noresult(ctx,
"print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testEval1')));"
);
/* Same with dump/load. */
duk_compile_string(ctx, DUK_COMPILE_EVAL,
"var testEval2 = 234;"
);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0);
duk_pop(ctx);
duk_eval_string_noresult(ctx,
"print(JSON.stringify(Object.getOwnPropertyDescriptor(this, 'testEval2')));"
);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_strict (duk_safe_call)
strict: false
strict: true
final top: 0
==> rc=0, result='undefined'
===*/
/* Strictness status is preserved. */
static duk_ret_t test_strict(duk_context *ctx) {
duk_compile_string(ctx, DUK_COMPILE_FUNCTION,
"function () {\n"
" var strict = (function () { return !this; })();\n"
" print('strict: ' + strict);\n"
"}");
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0);
duk_pop(ctx);
duk_compile_string(ctx, DUK_COMPILE_FUNCTION,
"function () {\n"
" 'use strict';\n"
" var strict = (function () { return !this; })();\n"
" print('strict: ' + strict);\n"
"}");
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_varmap (duk_safe_call)
hello world
123
final top: 0
==> rc=0, result='undefined'
===*/
/* _Varmap is preserved if function needs it. */
static duk_ret_t test_varmap(duk_context *ctx) {
/* Get access to _Varmap by creating a function that provides
* an 'eval service' in a function scope.
*/
duk_compile_string(ctx, DUK_COMPILE_FUNCTION,
"function (code) {\n"
" var foo = 123;\n"
" eval(code);\n"
"}");
duk_dump_function(ctx);
duk_load_function(ctx);
duk_dup(ctx, -1);
duk_push_string(ctx, "print('hello world');");
duk_call(ctx, 1);
duk_pop(ctx);
/* Eval code will use GETVAR to read 'foo', and _Varmap is
* needed for that.
*/
duk_dup(ctx, -1);
duk_push_string(ctx, "print(foo);");
duk_call(ctx, 1);
duk_pop(ctx);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_arguments_object (duk_safe_call)
object [object Arguments]
foo bar
123 bar
object [object Arguments]
foo bar
123 bar
final top: 0
==> rc=0, result='undefined'
===*/
/* Arguments object still works after dump/load, relies on e.g. _Formals. */
static duk_ret_t test_arguments_object(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" var f = function test(x,y) {\n"
" print(typeof arguments, Object.prototype.toString.call(arguments));\n"
" print(arguments[0], arguments[1]);\n"
" arguments[0] = 123;\n"
" print(x, y);\n"
" };\n"
" return f;\n"
"})()");
duk_dup_top(ctx);
duk_push_string(ctx, "foo");
duk_push_string(ctx, "bar");
duk_call(ctx, 2);
duk_pop(ctx);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_push_string(ctx, "foo");
duk_push_string(ctx, "bar");
duk_call(ctx, 2);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_pc2line (duk_safe_call)
hello world
Error: aiee 5
hello world
Error: aiee 5
final top: 0
==> rc=0, result='undefined'
===*/
/* _Pc2line is preserved, check by traceback line numbers. */
static duk_ret_t test_pc2line(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" var f = function test() {\n"
" print('hello world');\n"
" try {\n"
" throw new Error('aiee');\n"
" } catch (e) {\n"
" print(e, e.lineNumber);\n"
" }\n"
" };\n"
" return f;\n"
"})()");
duk_dup_top(ctx);
duk_call(ctx, 0); /* undumped */
duk_pop(ctx);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0); /* dump/load */
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_name_binding_funcexpr (duk_safe_call)
i am a function
i am a function
5
4
3
2
1
0
7
6
5
4
3
2
1
0
final top: 0
==> rc=0, result='undefined'
===*/
/* Name binding for function expressions is preserved, it is important
* for recursive functions.
*/
static duk_ret_t test_name_binding_funcexpr(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" var f = function test() { print('i am a ' + typeof test); };\n"
" return f;\n"
"})()");
duk_dup_top(ctx);
duk_call(ctx, 0); /* undumped */
duk_pop(ctx);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0); /* dump/load */
duk_pop(ctx);
duk_eval_string(ctx,
"(function () {\n"
" var f = function test(n) { print(n); if (n > 0) { test(n - 1); } };\n"
" return f;\n"
"})()");
duk_dup_top(ctx);
duk_push_int(ctx, 5);
duk_call(ctx, 1); /* undumped */
duk_pop(ctx);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_push_int(ctx, 7);
duk_call(ctx, 1); /* dump/load */
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_name_binding_funcdecl (duk_safe_call)
i am a number
final top: 1
==> rc=0, result='undefined'
===*/
/* Self-references for a function established through a function declaration
* is unfortunately not automatically supported. The self-reference generates
* bytecode that performs a slow path GETVAR for the function name; the GETVAR
* normally gets satisfied by looking it up from the global object. But if
* we dump/load the function, only the function object is resurrected while the
* global binding is not.
*/
static duk_ret_t test_name_binding_funcdecl(duk_context *ctx) {
duk_compile_string(ctx, 0 /*flags: program*/,
"function declaredTest() {\n"
" print('i am a ' + typeof declaredTest);\n"
"}");
duk_call(ctx, 0);
duk_pop(ctx);
duk_get_global_string(ctx, "declaredTest");
duk_dump_function(ctx);
duk_eval_string_noresult(ctx, "declaredTest = 123;"); /* lose original */
duk_load_function(ctx);
duk_call(ctx, 0);
/* Because the declaredTest binding itself is not resurrected (only
* the function itself is), the "typeof declaredTest" will refer to
* the fake "declaredTest = 123" value, i.e. a number.
*/
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_bound_rejected (duk_safe_call)
dummythis x-arg y-arg
==> rc=1, result='TypeError: not compiledfunction'
===*/
/* Bound functions are rejected with TypeError. */
static duk_ret_t test_bound_rejected(duk_context *ctx) {
/* XXX: TypeError message is not very good. */
/* XXX: Perhaps rework bound function support so that the final non-bound
* function is serialized instead?
*/
duk_eval_string(ctx,
"(function () {\n"
" var f = function test(x,y) { print(this, x, y); };\n"
" return f.bind('dummythis', 'x-arg', 'y-arg');\n"
"})()");
duk_dup_top(ctx);
duk_call(ctx, 0);
duk_pop(ctx);
duk_dump_function(ctx);
duk_load_function(ctx);
duk_call(ctx, 0);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_external_prototype_lost (duk_safe_call)
inst prototype is Function.prototype: false
inst prototype is custom prototype: true
myValue
f prototype is Function.prototype: 1
myProperty: undefined
final top: 0
==> rc=0, result='undefined'
===*/
/* Custom external prototype is lost during a dump/load. */
static duk_ret_t test_external_prototype_lost(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" var f = function test() {};\n"
" var proto = { myProperty: 'myValue' };\n"
" f.prototype = proto;\n"
" var inst = new f();\n"
" print('inst prototype is Function.prototype: ' + (Object.getPrototypeOf(inst) === Function.prototype));\n"
" print('inst prototype is custom prototype: ' + (Object.getPrototypeOf(inst) === proto));\n"
" print(inst.myProperty);\n"
" return f;\n"
"})()");
duk_dump_function(ctx);
duk_load_function(ctx);
duk_get_prototype(ctx, -1);
duk_eval_string(ctx, "Function.prototype");
printf("f prototype is Function.prototype: %d\n", (int) duk_strict_equals(ctx, -1, -2));
duk_pop_2(ctx);
duk_new(ctx, 0);
duk_get_prop_string(ctx, -1, "myProperty");
printf("myProperty: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
duk_pop(ctx);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}
/*===
*** test_internal_prototype_lost (duk_safe_call)
myValue
myProperty: undefined
f prototype is Function.prototype: 1
final top: 0
==> rc=0, result='undefined'
===*/
/* Custom internal prototype is lost during a dump/load. */
static duk_ret_t test_internal_prototype_lost(duk_context *ctx) {
duk_eval_string(ctx,
"(function () {\n"
" var f = function test() {};\n"
" Object.setPrototypeOf(f, { myProperty: 'myValue' });\n"
" print(f.myProperty);\n"
" return f;\n"
"})()");
duk_dump_function(ctx);
duk_load_function(ctx);
duk_get_prop_string(ctx, -1, "myProperty");
printf("myProperty: %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx);
duk_get_prototype(ctx, -1);
duk_eval_string(ctx, "Function.prototype");
printf("f prototype is Function.prototype: %d\n", (int) duk_strict_equals(ctx, -1, -2));
duk_pop_2(ctx);
duk_pop(ctx);
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_mandel);
TEST_SAFE_CALL(test_large_func);
TEST_SAFE_CALL(test_properties);
TEST_SAFE_CALL(test_program_code);
TEST_SAFE_CALL(test_eval_code);
TEST_SAFE_CALL(test_strict);
TEST_SAFE_CALL(test_varmap);
TEST_SAFE_CALL(test_arguments_object);
TEST_SAFE_CALL(test_pc2line);
TEST_SAFE_CALL(test_name_binding_funcexpr);
TEST_SAFE_CALL(test_name_binding_funcdecl);
TEST_SAFE_CALL(test_bound_rejected);
TEST_SAFE_CALL(test_external_prototype_lost);
TEST_SAFE_CALL(test_internal_prototype_lost);
}

4
tests/api/test-hex.c

@ -8,9 +8,9 @@ hex decode: test string
top after: 2
==> rc=0, result='undefined'
*** test_decode_odd_length (duk_safe_call)
==> rc=1, result='TypeError: hex decode failed'
==> rc=1, result='TypeError: decode failed'
*** test_decode_invalid_char (duk_safe_call)
==> rc=1, result='TypeError: hex decode failed'
==> rc=1, result='TypeError: decode failed'
===*/
static duk_ret_t test_encode(duk_context *ctx) {

Loading…
Cancel
Save