use 5.006;
use strict;
use warnings;

=head1 NAME

EJS::Template::Executor - Executes JavaScript generated by EJS::Template

=cut

package EJS::Template::Executor;
use base 'EJS::Template::Base';

use EJS::Template::IO;
use EJS::Template::JSAdapter;
use EJS::Template::Runtime;

=head1 Methods

=head2 execute

Executes JavaScript code.

    $executor->execute($input, $variables, $output);

The C<$input> is used as the JavaScript source code, C<$variables> is a hash
ref of variables for JavaScript, and C<$output> is the output destination

=cut

sub execute {
    my ($self, $input, $variables, $output) = @_;
    my $engine = EJS::Template::JSAdapter->create($self->{config}{engine});
    
    my ($out, $out_close) = EJS::Template::IO->output($output);
    my $ret;
    
    eval {
        my $runtime = EJS::Template::Runtime->new($self);
        $engine->bind({print => sub { print $out @_ }});
        $engine->bind({EJS => $runtime->make_map()});
        $engine->bind($variables);
        
        my ($in, $in_close) = EJS::Template::IO->input($input);
        
        eval {
            local $/;
            
            if (defined(my $js = <$in>)) {
                $ret = $engine->eval($js);
                die $@ if $@;
            } else {
                $ret = 1;
            }
        };
        
        my $e = $@;
        close $in if $in_close;
        die $e if $e;
    };
    
    my $e = $@;
    close $out if $out_close;
    die $e if $e;
    
    return $ret;
}

=head1 SEE ALSO

=over 4

=item * L<EJS::Template>

=back

=cut

1;
