use lib './lib';
use strict;
use warnings;
use JavaScript::Embedded;
use Data::Dumper;

require './t/helper.pl';

my $js = JavaScript::Embedded->new();
my $duk = $js->duk;

sub init_test_values {
    $duk->set_top(0);

    # Simple */
    $duk->push_int(123);

    # Object with toString() */
    $duk->eval_string("({ toString: function () { return 'toString result'; } })");

    # toString() throws an error */
    $duk->eval_string("({ toString: function () { throw new Error('toString error'); } })");

    # toString() throws an error which cannot be string coerced */
    $duk->eval_string("({ toString: function () { var e = new Error('cannot string coerce me');"
                        . "                           e.toString = function () { throw new Error('coercion error'); };"
                        . "                           throw e; } })");

    # XXX: add an infinite loop and timeout case */
}

sub test_1 {

    # $duk->safe_to_string() */
    init_test_values();
    my $n = $duk->get_top();
    for (my $i = 0; $i < $n; $i++) {
        printf("top=%ld\n", $duk->get_top());
        printf("duk_safe_to_string[%ld] = '%s'\n", $i, $duk->safe_to_string($i));
    }

    # $duk->safe_to_lstring() with NULL arg */
    init_test_values();
    $n = $duk->get_top();
    for (my $i = 0; $i < $n; $i++) {
        printf("top=%ld\n", $duk->get_top());
        my $str = $duk->safe_to_lstring($i, my $t);
        printf("duk_safe_to_lstring_null[%ld] = '%s'\n", $i, $str);
    }

    # $duk->safe_to_lstring() */
    init_test_values();
    $n = $duk->get_top();
    for (my $i = 0; $i < $n; $i++) {
        my $len;
        printf("top=%ld\n", $duk->get_top());
        my $str = $duk->safe_to_lstring($i, $len);
        printf("duk_safe_to_lstring[%ld] = '%s', len %lu\n", $i, $str, $len);
    }

    # $duk->safe_to_lstring() with negative stack indices */
    init_test_values();
    $n = $duk->get_top();
    for (my $i = 0; $i < $n; $i++) {
        my $len;
        printf("top=%ld\n", $duk->get_top());
        my $str = $duk->safe_to_lstring(-4 + $i, $len);
        printf("duk_safe_to_lstring[%ld] = '%s', len %lu\n", $i, $str, $len);
    }

    return 0;
}

TEST_SAFE_CALL($duk, \&test_1, 'test_1');


test_stdout();

__DATA__
*** test_1 (duk_safe_call)
top=4
duk_safe_to_string[0] = '123'
top=4
duk_safe_to_string[1] = 'toString result'
top=4
duk_safe_to_string[2] = 'Error: toString error'
top=4
duk_safe_to_string[3] = 'Error'
top=4
duk_safe_to_lstring_null[0] = '123'
top=4
duk_safe_to_lstring_null[1] = 'toString result'
top=4
duk_safe_to_lstring_null[2] = 'Error: toString error'
top=4
duk_safe_to_lstring_null[3] = 'Error'
top=4
duk_safe_to_lstring[0] = '123', len 3
top=4
duk_safe_to_lstring[1] = 'toString result', len 15
top=4
duk_safe_to_lstring[2] = 'Error: toString error', len 21
top=4
duk_safe_to_lstring[3] = 'Error', len 5
top=4
duk_safe_to_lstring[0] = '123', len 3
top=4
duk_safe_to_lstring[1] = 'toString result', len 15
top=4
duk_safe_to_lstring[2] = 'Error: toString error', len 21
top=4
duk_safe_to_lstring[3] = 'Error', len 5
==> rc=0, result='undefined'
