You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

248 lines
6.6 KiB

/*===
*** test_1 (duk_safe_call)
me
rc=0, result='21'
==> rc=0, result='undefined'
*** test_2 (duk_safe_call)
object 123
rc=0, result='21'
==> rc=0, result='undefined'
*** test_3 (duk_safe_call)
number 123
rc=0, result='21'
==> rc=0, result='undefined'
*** test_4 (duk_safe_call)
rc=1, result='Error: my error'
==> rc=0, result='undefined'
*** test_5 (duk_safe_call)
rc=1, result='TypeError: cannot read property 'foo' of undefined'
==> rc=0, result='undefined'
*** test_6 (duk_safe_call)
rc=1, result='RangeError: getter error'
==> rc=0, result='undefined'
*** test_7 (duk_safe_call)
rc=1, result='RangeError: invalid stack index -6'
==> rc=0, result='undefined'
*** test_8 (duk_safe_call)
rc=1, result='TypeError: undefined not callable (property [object Object] of [object Object])'
==> rc=0, result='undefined'
*** test_9 (duk_safe_call)
==> rc=1, result='TypeError: invalid args'
*** test_10 (duk_safe_call)
rc=1, result='TypeError: undefined not callable (property 'bar' of [object Object])'
==> rc=0, result='undefined'
final top: 0
===*/
static duk_ret_t test_1(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* basic success case: own property */
duk_eval_string(ctx, "({ name: 'me', foo: function (x,y) { print(this.name); return x+y; } })"); /* idx 1 */
duk_push_string(ctx, "foo");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 2);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_2(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* use plain number as 'this', add function to Number.prototype; non-strict handler
* causes this to be coerced to Number.
*/
duk_eval_string(ctx, "Number.prototype.func_nonstrict = function (x,y) { print(typeof this, this); return x+y; };");
duk_pop(ctx); /* pop result */
duk_push_int(ctx, 123); /* obj */
duk_push_string(ctx, "func_nonstrict");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, -4, 2); /* use relative index for a change */
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_3(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* use plain number as 'this', add function to Number.prototype; strict handler
* causes this to remain a plain number.
*/
duk_eval_string(ctx, "Number.prototype.func_strict = function (x,y) { 'use strict'; print(typeof this, this); return x+y; };");
duk_pop(ctx); /* pop result */
duk_push_int(ctx, 123); /* obj */
duk_push_string(ctx, "func_strict");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 2);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_4(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* basic error case */
duk_eval_string(ctx, "({ name: 'me', foo: function (x,y) { throw new Error('my error'); } })"); /* idx 1 */
duk_push_string(ctx, "foo");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 2);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_5(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* property lookup fails: base value does not allow property lookup */
duk_push_undefined(ctx);
duk_push_string(ctx, "foo");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 2);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_6(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* property lookup fails: getter throws */
duk_eval_string(ctx, "({ get prop() { throw new RangeError('getter error'); } })");
duk_push_string(ctx, "prop");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 2);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_7(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* invalid object index */
duk_eval_string(ctx, "({ foo: 1, bar: 2 })");
duk_push_string(ctx, "foo");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, -6, 2);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_8(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* invalid arg count, causes 'key' to be identified with the object in the stack */
duk_eval_string(ctx, "({ foo: function () { print('foo called'); } })");
duk_push_string(ctx, "foo");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 3);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_9(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* Invalid arg count, 'key' would be below start of stack. This
* results in an actual (uncaught) error at the moment, and matches
* the behavior of other protected call API functions.
*/
duk_eval_string(ctx, "({ foo: function () { print('foo called'); } })");
duk_push_string(ctx, "foo");
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
rc = duk_pcall_prop(ctx, 1, 8);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
static duk_ret_t test_10(duk_context *ctx, void *udata) {
duk_ret_t rc;
(void) udata;
/* Test error message, which now includes summary of key and target. */
duk_eval_string(ctx, "({ foo: function () { print('foo called'); } })");
duk_push_string(ctx, "bar");
duk_push_uint(ctx, 123);
duk_push_uint(ctx, 234);
rc = duk_pcall_prop(ctx, 1 /*obj_idx*/, 2 /*nargs*/);
printf("rc=%d, result='%s'\n", (int) rc, duk_safe_to_string(ctx, -1));
duk_pop(ctx); /* res */
duk_pop(ctx); /* obj */
return 0;
}
void test(duk_context *ctx) {
/* dummy just to offset the object index from 0 */
duk_push_string(ctx, "foo");
TEST_SAFE_CALL(test_1);
TEST_SAFE_CALL(test_2);
TEST_SAFE_CALL(test_3);
TEST_SAFE_CALL(test_4);
TEST_SAFE_CALL(test_5);
TEST_SAFE_CALL(test_6);
TEST_SAFE_CALL(test_7);
TEST_SAFE_CALL(test_8);
TEST_SAFE_CALL(test_9);
TEST_SAFE_CALL(test_10);
duk_pop(ctx); /* dummy */
printf("final top: %ld\n", (long) duk_get_top(ctx));
}