Files
jerryscript/jerry-main/main-jerry.c
T
Zoltan Herczeg 112ad83aaa Rework external function handlers (#4599)
Instead of a fixed number of arguments, a call info structure is passed
to the handlers, which can be extended in the future without breaknig the
API. This structure holds new.target value, so its getter function is removed.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
2021-02-17 17:52:19 +01:00

337 lines
9.0 KiB
C

/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jerryscript.h"
#include "jerryscript-ext/debugger.h"
#include "jerryscript-ext/handler.h"
#include "jerryscript-port.h"
#include "jerryscript-port-default.h"
#include "main-utils.h"
#include "main-options.h"
/**
* Temporal buffer size.
*/
#define JERRY_BUFFER_SIZE 256u
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
/**
* The alloc function passed to jerry_create_context
*/
static void *
context_alloc (size_t size,
void *cb_data_p)
{
(void) cb_data_p; /* unused */
return malloc (size);
} /* context_alloc */
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
int
main (int argc,
char **argv)
{
union
{
double d;
unsigned u;
} now = { .d = jerry_port_get_current_time () };
srand (now.u);
JERRY_VLA (main_source_t, sources_p, argc);
main_args_t arguments;
arguments.sources_p = sources_p;
main_parse_args (argc, argv, &arguments);
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
jerry_context_t *context_p = jerry_create_context (JERRY_GLOBAL_HEAP_SIZE * 1024, context_alloc, NULL);
jerry_port_default_set_current_context (context_p);
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
restart:
main_init_engine (&arguments);
int return_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
jerry_value_t ret_value;
for (uint32_t source_index = 0; source_index < arguments.source_count; source_index++)
{
main_source_t *source_file_p = sources_p + source_index;
const char *file_path_p = argv[source_file_p->path_index];
size_t source_size;
uint8_t *source_p = jerry_port_read_source (file_path_p, &source_size);
if (source_p == NULL)
{
goto exit;
}
uint32_t parse_opts = JERRY_PARSE_NO_OPTS;
switch (source_file_p->type)
{
case SOURCE_SNAPSHOT:
{
ret_value = jerry_exec_snapshot ((uint32_t *) source_p,
source_size,
source_file_p->snapshot_index,
JERRY_SNAPSHOT_EXEC_COPY_DATA);
jerry_port_release_source (source_p);
break;
}
case SOURCE_MODULE:
{
parse_opts = JERRY_PARSE_MODULE;
/* FALLTHRU */
}
default:
{
assert (source_file_p->type == SOURCE_SCRIPT
|| source_file_p->type == SOURCE_MODULE);
if (!jerry_is_valid_utf8_string ((jerry_char_t *) source_p, (jerry_size_t) source_size))
{
jerry_port_release_source (source_p);
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.");
goto exit;
}
ret_value = jerry_parse ((jerry_char_t *) file_path_p,
strlen (file_path_p),
source_p,
source_size,
parse_opts);
jerry_port_release_source (source_p);
if (!jerry_value_is_error (ret_value) && !(arguments.option_flags & OPT_FLAG_PARSE_ONLY))
{
jerry_value_t func_val = ret_value;
ret_value = jerry_run (func_val);
jerry_release_value (func_val);
}
break;
}
}
if (jerry_value_is_error (ret_value))
{
if (main_is_value_reset (ret_value))
{
jerry_cleanup ();
goto restart;
}
main_print_unhandled_exception (ret_value);
goto exit;
}
jerry_release_value (ret_value);
}
if (arguments.option_flags & OPT_FLAG_WAIT_SOURCE)
{
while (true)
{
jerry_debugger_wait_for_source_status_t receive_status;
receive_status = jerry_debugger_wait_for_client_source (main_wait_for_source_callback,
NULL,
&ret_value);
if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Connection aborted before source arrived.");
goto exit;
}
if (receive_status == JERRY_DEBUGGER_SOURCE_END)
{
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "No more client source.\n");
break;
}
assert (receive_status == JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED
|| receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
if (receive_status == JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED
|| main_is_value_reset (ret_value))
{
jerry_cleanup ();
goto restart;
}
assert (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
jerry_release_value (ret_value);
}
}
else if (arguments.option_flags & OPT_FLAG_USE_STDIN)
{
char buffer[JERRY_BUFFER_SIZE];
char *source_p = NULL;
size_t source_size = 0;
while (!feof (stdin))
{
size_t read_bytes = fread (buffer, 1u, JERRY_BUFFER_SIZE, stdin);
size_t new_size = source_size + read_bytes;
source_p = realloc (source_p, new_size);
memcpy (source_p + source_size, buffer, read_bytes);
source_size = new_size;
}
ret_value = jerry_parse (NULL, 0, (jerry_char_t *) source_p, source_size, JERRY_PARSE_NO_OPTS);
free (source_p);
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
goto exit;
}
jerry_value_t func_val = ret_value;
ret_value = jerry_run (func_val);
jerry_release_value (func_val);
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
goto exit;
}
jerry_release_value (ret_value);
}
else if (arguments.source_count == 0)
{
const char *prompt = (arguments.option_flags & OPT_FLAG_NO_PROMPT) ? "" : "jerry> ";
char buffer[JERRY_BUFFER_SIZE];
while (true)
{
printf ("%s", prompt);
char *str_p = fgets (buffer, JERRY_BUFFER_SIZE, stdin);
if (str_p == NULL)
{
printf ("\n");
break;
}
size_t len = strlen (str_p);
if (len == 0)
{
continue;
}
if (!jerry_is_valid_utf8_string ((jerry_char_t *) str_p, (jerry_size_t) len))
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n");
continue;
}
ret_value = jerry_parse (NULL, 0, (jerry_char_t *) str_p, len, JERRY_PARSE_NO_OPTS);
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
continue;
}
jerry_value_t func_val = ret_value;
ret_value = jerry_run (func_val);
jerry_release_value (func_val);
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
continue;
}
const jerry_value_t args[] = { ret_value };
jerry_value_t ret_val_print = jerryx_handler_print (NULL, args, 1);
jerry_release_value (ret_val_print);
jerry_release_value (ret_value);
ret_value = jerry_run_all_enqueued_jobs ();
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
continue;
}
jerry_release_value (ret_value);
}
}
ret_value = jerry_run_all_enqueued_jobs ();
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
goto exit;
}
jerry_release_value (ret_value);
if (arguments.exit_cb_name_p != NULL)
{
jerry_value_t global = jerry_get_global_object ();
jerry_value_t name_str = jerry_create_string ((jerry_char_t *) arguments.exit_cb_name_p);
jerry_value_t callback_fn = jerry_get_property (global, name_str);
jerry_release_value (global);
jerry_release_value (name_str);
if (jerry_value_is_function (callback_fn))
{
ret_value = jerry_call_function (callback_fn, jerry_create_undefined (), NULL, 0);
if (jerry_value_is_error (ret_value))
{
main_print_unhandled_exception (ret_value);
goto exit;
}
jerry_release_value (ret_value);
}
jerry_release_value (callback_fn);
}
return_code = JERRY_STANDALONE_EXIT_CODE_OK;
exit:
jerry_cleanup ();
#if defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1)
free (context_p);
#endif /* defined (JERRY_EXTERNAL_CONTEXT) && (JERRY_EXTERNAL_CONTEXT == 1) */
return return_code;
} /* main */