Merge branch 'prepare_for_master' of https://gitlink.org.cn/xuos/xiuos into connection
|
@ -167,7 +167,7 @@ static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
|
|||
serial_cfg.serial_timeout = OTA_RX_TIMEOUT;
|
||||
#else
|
||||
//serial receive timeout 10s
|
||||
serial_cfg.serial_timeout = 100000;
|
||||
serial_cfg.serial_timeout = 10000;
|
||||
#endif
|
||||
serial_cfg.is_ext_uart = 0;
|
||||
#ifdef ADAPTER_EC200T_DRIVER_EXT_PORT
|
||||
|
|
|
@ -355,7 +355,7 @@ static int GetCompleteATReply(ATAgentType agent)
|
|||
PrivMutexObtain(&agent->lock);
|
||||
if (agent->receive_mode == ENTM_MODE) {
|
||||
if (agent->entm_recv_len < ENTM_RECV_MAX) {
|
||||
#ifdef TOOL_USING_MQTT
|
||||
#ifdef LIB_USING_MQTT
|
||||
if((res == 1) && (agent->entm_recv_len < agent->read_len))
|
||||
{
|
||||
agent->entm_recv_buf[agent->entm_recv_len] = ch;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define REPLY_TIME_OUT 10
|
||||
|
||||
#ifdef TOOL_USING_OTA
|
||||
#define ENTM_RECV_MAX OTA_RX_BUFFERSIZE
|
||||
#define ENTM_RECV_MAX (OTA_FRAME_SIZE + 1024)
|
||||
#else
|
||||
#define ENTM_RECV_MAX 256
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
menu "lib using JerryScript"
|
||||
menuconfig LIB_USING_JERRYSCRIPT
|
||||
bool "Enable support JerryScript."
|
||||
default n
|
||||
endmenu
|
|
@ -0,0 +1,20 @@
|
|||
SRC_FILES :=
|
||||
SRC_FILES += jerryscript/build/lib/libjerry-core.a \
|
||||
jerryscript/build/lib/libjerry-ext.a \
|
||||
jerryscript/build/lib/libjerry-math.a
|
||||
|
||||
ifeq ($(CONFIG_BOARD_STM32F407_EVB),y)
|
||||
SRC_FILES += mcu/stm32f4/setjmp.S
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_CORTEX_M4_EVB),y)
|
||||
SRC_FILES += mcu/cortex-m4-emulator/setjmp.S
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_EDU_ARM32_EVB),y)
|
||||
SRC_FILES += mcu/hc32f4a0/setjmp.S
|
||||
endif
|
||||
|
||||
SRC_FILES += jerry_port.c jerry_main.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,60 @@
|
|||
# jerryscript编译步骤,注意本文档依赖 Ubuntu 20.04 操作系统.
|
||||
## 1、jerryscript编译依赖工具链安装
|
||||
|
||||
第一次编译需要安装依赖,在APP_Framework/lib/JerryScript路径下,依次执行:
|
||||
|
||||
```
|
||||
jerryscript/tools/apt-get-install-deps.sh
|
||||
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
sudo apt install \
|
||||
bison flex gettext texinfo libncurses5-dev libncursesw5-dev \
|
||||
gperf automake libtool pkg-config build-essential gperf genromfs \
|
||||
libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev \
|
||||
libexpat-dev gcc-multilib g++-multilib picocom u-boot-tools util-linux
|
||||
```
|
||||
|
||||
## 2、jerryscript源码编译
|
||||
|
||||
当前在XiZi操作系统下,支持HC32F4A0单片机和STM32F4单片机两个系列的开发板,在APP_Framework/lib/JerryScript路径下,以edu-arm32开发板(HC32F4A0单片机)为例,进入到APP_Framework/lib/JerryScript下执行:
|
||||
|
||||
```bash
|
||||
jerryscript/tools/build.py \
|
||||
--clean \
|
||||
--lto=OFF \
|
||||
--jerry-cmdline=OFF \
|
||||
--jerry-math=ON \
|
||||
--amalgam=ON \
|
||||
--mem-heap=70 \
|
||||
--profile=es.next \
|
||||
--toolchain=${PWD}/jerryscript/cmake/toolchain_mcu_hc32f4a0.cmake
|
||||
```
|
||||
|
||||
如果是STM32F4的单片机,将.cmake指定为toolchain_mcu_stm32f4.cmake即可,这一步完成后在APP_Framework/lib/JerryScript/jerryscript/build目录下会编译出几个.a文件,这些文件是接下来的bin包构建过程中需要的。
|
||||
|
||||
## 3、开发板bin包构建
|
||||
|
||||
以edu-arm32开发板为例进行构建,进入到xiuos/Ubiquitous/XiZi_IIoT目录下,执行:
|
||||
|
||||
```makefile
|
||||
make BOARD=edu-arm32 menuconfig
|
||||
```
|
||||
|
||||
然后在menuconfig界面进入APP_Framework → app lib → lib using JerryScript ,完成勾选;
|
||||
|
||||
为了支持javascript文件解析,需要存储.js文件,勾选edu-arm32 feature → Using SD CARD device,使用sd卡进行.js文件的保存;
|
||||
|
||||
保存并退出menuconfig,然后执行编译:
|
||||
|
||||
```makefile
|
||||
make BOARD=edu-arm32
|
||||
```
|
||||
|
||||
完成编译后,进行bin包的烧录,edu-arm32开发板的烧录方式参考xiuos/Ubiquitous/XiZi_IIoT/board/edu-arm32/目录下的README.md。
|
||||
|
||||
APP_Framework/lib/JerryScript/testfile目录下存放了几个.js文件,可以将这些文件拷贝到内存卡中,也可以自行创建一些.js文件,完成烧录后,插入存有.js文件的内存卡,正确完成挂载后执行:
|
||||
|
||||
```shell
|
||||
jerrytest demo.js
|
||||
```
|
||||
|
||||
会执行一个数组的快速排序demo,打印排序后的数组。
|
|
@ -0,0 +1,478 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file jerry_main.c
|
||||
* @brief support jerryscript
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.08.07
|
||||
*/
|
||||
|
||||
#include <transform.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
#include "jerryscript-port.h"
|
||||
#include "setjmp.h"
|
||||
|
||||
|
||||
/* Maximum command line arguments number.*/
|
||||
#define JERRY_MAX_COMMAND_LINE_ARGS (16)
|
||||
|
||||
/*Standalone Jerry exit codes.*/
|
||||
#define JERRY_STANDALONE_EXIT_CODE_OK (0)
|
||||
#define JERRY_STANDALONE_EXIT_CODE_FAIL (1)
|
||||
|
||||
/* Context size of the SYNTAX_ERROR */
|
||||
#define SYNTAX_ERROR_CONTEXT_SIZE 2
|
||||
|
||||
|
||||
static void print_help(char *name)
|
||||
{
|
||||
printf ("Usage: %s [OPTION]... [FILE]...\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" --log-level [0-3]\n"
|
||||
" --mem-stats\n"
|
||||
" --mem-stats-separate\n"
|
||||
" --show-opcodes\n"
|
||||
" --start-debug-server\n"
|
||||
" --debug-server-port [port]\n"
|
||||
"\n",
|
||||
name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read source code into buffer.
|
||||
*
|
||||
* Returned value must be freed with jmem_heap_free_block if it's not NULL.
|
||||
* @return NULL, if read or allocation has failed
|
||||
* pointer to the allocated memory block, otherwise
|
||||
*/
|
||||
static const uint8_t *read_file (const char *file_name, size_t *out_size_p)
|
||||
{
|
||||
FILE *file = fopen (file_name, "r");
|
||||
if (file == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: %s\n", file_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fseek_status = fseek (file, 0, SEEK_END);
|
||||
if (fseek_status != 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to seek (error: %d)\n", fseek_status);
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long script_len = ftell (file);
|
||||
if (script_len < 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Failed to get the file size(error %ld)\n", script_len);
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rewind (file);
|
||||
|
||||
uint8_t *buffer = (uint8_t *) malloc (script_len);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Out of memory error\n");
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t bytes_read = fread (buffer, 1u, script_len, file);
|
||||
|
||||
if (!bytes_read || bytes_read != script_len)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name);
|
||||
free ((void*) buffer);
|
||||
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose (file);
|
||||
|
||||
*out_size_p = bytes_read;
|
||||
return (const uint8_t *) buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string into unsigned integer
|
||||
*
|
||||
* @return converted number
|
||||
*/
|
||||
static uint32_t str_to_uint (const char *num_str_p) /**< string to convert */
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
while (*num_str_p != '\0')
|
||||
{
|
||||
result *= 10;
|
||||
result += (uint32_t) (*num_str_p - '0');
|
||||
num_str_p++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error value
|
||||
*/
|
||||
static void print_unhandled_exception (jerry_value_t error_value, const jerry_char_t *source_p)
|
||||
{
|
||||
error_value = jerry_get_value_from_error (error_value, false);
|
||||
jerry_value_t err_str_val = jerry_value_to_string (error_value);
|
||||
jerry_size_t err_str_size = jerry_get_string_size (err_str_val);
|
||||
jerry_char_t err_str_buf[256];
|
||||
|
||||
jerry_release_value (error_value);
|
||||
|
||||
if (err_str_size >= 256)
|
||||
{
|
||||
const char msg[] = "[Error message too long]";
|
||||
err_str_size = sizeof (msg) / sizeof (char) - 1;
|
||||
memcpy (err_str_buf, msg, err_str_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size);
|
||||
err_str_buf[err_str_size] = 0;
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_ERROR_MESSAGES)
|
||||
&& jerry_get_error_type (error_value) == JERRY_ERROR_SYNTAX)
|
||||
{
|
||||
uint32_t err_line = 0;
|
||||
uint32_t err_col = 0;
|
||||
|
||||
/* 1. parse column and line information */
|
||||
for (uint32_t i = 0; i < sz; i++)
|
||||
{
|
||||
if (!strncmp ((char *) (err_str_buf + i), "[line: ", 7))
|
||||
{
|
||||
i += 7;
|
||||
|
||||
char num_str[8];
|
||||
uint32_t j = 0;
|
||||
|
||||
while (i < sz && err_str_buf[i] != ',')
|
||||
{
|
||||
num_str[j] = (char) err_str_buf[i];
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
num_str[j] = '\0';
|
||||
|
||||
err_line = str_to_uint (num_str);
|
||||
|
||||
if (strncmp ((char *) (err_str_buf + i), ", column: ", 10))
|
||||
{
|
||||
break; /* wrong position info format */
|
||||
}
|
||||
|
||||
i += 10;
|
||||
j = 0;
|
||||
|
||||
while (i < sz && err_str_buf[i] != ']')
|
||||
{
|
||||
num_str[j] = (char) err_str_buf[i];
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
num_str[j] = '\0';
|
||||
|
||||
err_col = str_to_uint (num_str);
|
||||
break;
|
||||
}
|
||||
} /* for */
|
||||
|
||||
if (err_line != 0 && err_col != 0)
|
||||
{
|
||||
uint32_t curr_line = 1;
|
||||
|
||||
bool is_printing_context = false;
|
||||
uint32_t pos = 0;
|
||||
|
||||
/* 2. seek and print */
|
||||
while (source_p[pos] != '\0')
|
||||
{
|
||||
if (source_p[pos] == '\n')
|
||||
{
|
||||
curr_line++;
|
||||
}
|
||||
|
||||
if (err_line < SYNTAX_ERROR_CONTEXT_SIZE
|
||||
|| (err_line >= curr_line
|
||||
&& (err_line - curr_line) <= SYNTAX_ERROR_CONTEXT_SIZE))
|
||||
{
|
||||
/* context must be printed */
|
||||
is_printing_context = true;
|
||||
}
|
||||
|
||||
if (curr_line > err_line)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_printing_context)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "%c", source_p[pos]);
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "\n");
|
||||
|
||||
while (--err_col)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "~");
|
||||
}
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "^\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Script Error: %s\n", err_str_buf);
|
||||
jerry_release_value (err_str_val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a JavaScript function in the global object.
|
||||
*/
|
||||
static void register_js_function (const char *name_p,jerry_external_handler_t handler_p)
|
||||
{
|
||||
jerry_value_t result_val = jerryx_handler_register_global ((const jerry_char_t *) name_p, handler_p);
|
||||
|
||||
if (jerry_value_is_error (result_val))
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Warning: failed to register '%s' method.", name_p);
|
||||
}
|
||||
|
||||
jerry_release_value (result_val);
|
||||
}
|
||||
|
||||
void js_add_function(const jerry_value_t obj, const char *name,
|
||||
jerry_external_handler_t func)
|
||||
{
|
||||
jerry_value_t str = jerry_create_string((const jerry_char_t *)name);
|
||||
jerry_value_t jfunc = jerry_create_external_function(func);
|
||||
|
||||
jerry_set_property(obj, str, jfunc);
|
||||
|
||||
jerry_release_value(str);
|
||||
jerry_release_value(jfunc);
|
||||
}
|
||||
|
||||
void js_set_property(const jerry_value_t obj, const char *name,
|
||||
const jerry_value_t prop)
|
||||
{
|
||||
jerry_value_t str = jerry_create_string((const jerry_char_t *)name);
|
||||
jerry_set_property(obj, str, prop);
|
||||
jerry_release_value (str);
|
||||
}
|
||||
|
||||
int js_console_init(void)
|
||||
{
|
||||
jerry_value_t console = jerry_create_object();
|
||||
jerry_value_t global_obj = jerry_get_global_object();
|
||||
|
||||
js_add_function(console, "log", jerryx_handler_print);
|
||||
|
||||
js_set_property(global_obj, "console", console);
|
||||
|
||||
jerry_release_value(global_obj);
|
||||
jerry_release_value(console);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static jerry_log_level_t jerry_log_level = JERRY_LOG_LEVEL_ERROR;
|
||||
|
||||
|
||||
int jerrytest(int argc, char *argv[])
|
||||
{
|
||||
if (argc > JERRY_MAX_COMMAND_LINE_ARGS)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR,
|
||||
"Too many command line arguments. Current maximum is %d\n",
|
||||
JERRY_MAX_COMMAND_LINE_ARGS);
|
||||
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
const char *file_names[JERRY_MAX_COMMAND_LINE_ARGS];
|
||||
int i;
|
||||
int files_counter = 0;
|
||||
bool start_debug_server = false;
|
||||
uint16_t debug_port = 5001;
|
||||
|
||||
jerry_init_flag_t flags = JERRY_INIT_EMPTY;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp ("-h", argv[i]) || !strcmp ("--help", argv[i]))
|
||||
{
|
||||
print_help (argv[0]);
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
}
|
||||
else if (!strcmp ("--mem-stats", argv[i]))
|
||||
{
|
||||
flags |= JERRY_INIT_MEM_STATS;
|
||||
jerry_log_level = JERRY_LOG_LEVEL_DEBUG;
|
||||
}
|
||||
else if (!strcmp ("--mem-stats-separate", argv[i]))
|
||||
{
|
||||
flags |= JERRY_INIT_MEM_STATS_SEPARATE;
|
||||
jerry_log_level = JERRY_LOG_LEVEL_DEBUG;
|
||||
}
|
||||
else if (!strcmp ("--show-opcodes", argv[i]))
|
||||
{
|
||||
flags |= JERRY_INIT_SHOW_OPCODES | JERRY_INIT_SHOW_REGEXP_OPCODES;
|
||||
jerry_log_level = JERRY_LOG_LEVEL_DEBUG;
|
||||
}
|
||||
else if (!strcmp ("--log-level", argv[i]))
|
||||
{
|
||||
if (++i < argc && strlen (argv[i]) == 1 && argv[i][0] >='0' && argv[i][0] <= '3')
|
||||
{
|
||||
jerry_log_level = argv[i][0] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: wrong format or invalid argument\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
}
|
||||
else if (!strcmp ("--start-debug-server", argv[i]))
|
||||
{
|
||||
start_debug_server = true;
|
||||
}
|
||||
else if (!strcmp ("--debug-server-port", argv[i]))
|
||||
{
|
||||
if (++i < argc)
|
||||
{
|
||||
debug_port = str_to_uint (argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: wrong format or invalid argument\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
file_names[files_counter++] = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
jerry_init (flags);
|
||||
|
||||
if (start_debug_server)
|
||||
{
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (debug_port)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
}
|
||||
|
||||
register_js_function ("gc", jerryx_handler_gc);
|
||||
register_js_function ("print", jerryx_handler_print);
|
||||
js_console_init();
|
||||
|
||||
|
||||
jerry_value_t ret_value = jerry_create_undefined ();
|
||||
|
||||
if (files_counter == 0)
|
||||
{
|
||||
printf ("running a hello world demo:");
|
||||
const jerry_char_t script[] = "var str = 'Hello World'; print(str + ' from JerryScript.')";
|
||||
|
||||
ret_value = jerry_parse (NULL, 0, script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
|
||||
|
||||
if (!jerry_value_is_error (ret_value))
|
||||
{
|
||||
ret_value = jerry_run (ret_value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < files_counter; i++)
|
||||
{
|
||||
size_t source_size;
|
||||
const jerry_char_t *source_p = read_file (file_names[i], &source_size);
|
||||
|
||||
if (source_p == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Source file load error\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
ret_value = jerry_parse ((jerry_char_t *) file_names[i],
|
||||
strlen (file_names[i]),
|
||||
source_p,
|
||||
source_size,
|
||||
JERRY_PARSE_NO_OPTS);
|
||||
|
||||
if (!jerry_value_is_error (ret_value))
|
||||
{
|
||||
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))
|
||||
{
|
||||
print_unhandled_exception (ret_value, source_p);
|
||||
free ((void*) source_p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
free ((void*) source_p);
|
||||
|
||||
jerry_release_value (ret_value);
|
||||
ret_value = jerry_create_undefined ();
|
||||
}
|
||||
}
|
||||
|
||||
int ret_code = JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
|
||||
if (jerry_value_is_error (ret_value))
|
||||
{
|
||||
ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
jerry_release_value (ret_value);
|
||||
|
||||
ret_value = jerry_run_all_enqueued_jobs ();
|
||||
|
||||
if (jerry_value_is_error (ret_value))
|
||||
{
|
||||
ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
jerry_release_value (ret_value);
|
||||
jerry_cleanup ();
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(jerrytest, jerryscript test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file jerry_port.c
|
||||
* @brief support jerryscript
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023.08.07
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
/**
|
||||
* JerryScript log level
|
||||
*/
|
||||
static jerry_log_level_t jerry_log_level = JERRY_LOG_LEVEL_ERROR;
|
||||
|
||||
/**
|
||||
* Sets log level.
|
||||
*/
|
||||
void set_log_level (jerry_log_level_t level)
|
||||
{
|
||||
jerry_log_level = level;
|
||||
} /* set_log_level */
|
||||
|
||||
/**
|
||||
* Aborts the program.
|
||||
*/
|
||||
void jerry_port_fatal (jerry_fatal_code_t code)
|
||||
{
|
||||
exit (1);
|
||||
} /* jerry_port_fatal */
|
||||
|
||||
/**
|
||||
* Provide log message implementation for the engine.
|
||||
*/
|
||||
void
|
||||
jerry_port_log (jerry_log_level_t level, /**< log level */
|
||||
const char *format, /**< format string */
|
||||
...) /**< parameters */
|
||||
{
|
||||
if (level <= jerry_log_level)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
} /* jerry_port_log */
|
||||
|
||||
/**
|
||||
* Determines the size of the given file.
|
||||
* @return size of the file
|
||||
*/
|
||||
static size_t
|
||||
jerry_port_get_file_size (FILE *file_p) /**< opened file */
|
||||
{
|
||||
fseek (file_p, 0, SEEK_END);
|
||||
long size = ftell (file_p);
|
||||
fseek (file_p, 0, SEEK_SET);
|
||||
|
||||
return (size_t) size;
|
||||
} /* jerry_port_get_file_size */
|
||||
|
||||
/**
|
||||
* Opens file with the given path and reads its source.
|
||||
* @return the source of the file
|
||||
*/
|
||||
uint8_t *
|
||||
jerry_port_read_source (const char *file_name_p, /**< file name */
|
||||
size_t *out_size_p) /**< [out] read bytes */
|
||||
{
|
||||
FILE *file_p = fopen (file_name_p, "rb");
|
||||
|
||||
if (file_p == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to open file: %s\n", file_name_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t file_size = jerry_port_get_file_size (file_p);
|
||||
uint8_t *buffer_p = (uint8_t *) malloc (file_size);
|
||||
|
||||
if (buffer_p == NULL)
|
||||
{
|
||||
fclose (file_p);
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to allocate memory for module");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t bytes_read = fread (buffer_p, 1u, file_size, file_p);
|
||||
|
||||
if (!bytes_read)
|
||||
{
|
||||
fclose (file_p);
|
||||
free (buffer_p);
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: failed to read file: %s\n", file_name_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose (file_p);
|
||||
*out_size_p = bytes_read;
|
||||
|
||||
return buffer_p;
|
||||
} /* jerry_port_read_source */
|
||||
|
||||
/**
|
||||
* Release the previously opened file's content.
|
||||
*/
|
||||
void
|
||||
jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
{
|
||||
free (buffer_p);
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size, /**< size of output buffer */
|
||||
char *base_file_p) /**< base file path */
|
||||
{
|
||||
(void) base_file_p;
|
||||
|
||||
size_t len = strlen (in_path_p);
|
||||
if (len + 1 > out_buf_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the original string. */
|
||||
strcpy (out_buf_p, in_path_p);
|
||||
return len;
|
||||
} /* jerry_port_normalize_path */
|
||||
|
||||
/**
|
||||
* Get the module object of a native module.
|
||||
*
|
||||
* @return undefined
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_port_get_native_module (jerry_value_t name) /**< module specifier */
|
||||
{
|
||||
(void) name;
|
||||
return jerry_create_undefined ();
|
||||
} /* jerry_port_get_native_module */
|
||||
|
||||
/**
|
||||
* Dummy function to get the time zone adjustment.
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
double
|
||||
jerry_port_get_local_time_zone_adjustment (double unix_ms, bool is_utc)
|
||||
{
|
||||
/* We live in UTC. */
|
||||
return 0;
|
||||
} /* jerry_port_get_local_time_zone_adjustment */
|
||||
|
||||
/**
|
||||
* Dummy function to get the current time.
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
double
|
||||
jerry_port_get_current_time (void)
|
||||
{
|
||||
return 0;
|
||||
} /* jerry_port_get_current_time */
|
||||
|
||||
/**
|
||||
* Provide the implementation of jerry_port_print_char.
|
||||
* Uses 'printf' to print a single character to standard output.
|
||||
*/
|
||||
void
|
||||
jerry_port_print_char (char c) /**< the character to print */
|
||||
{
|
||||
printf ("%c", c);
|
||||
} /* jerry_port_print_char */
|
||||
|
||||
/**
|
||||
* Provide implementation of jerry_port_sleep.
|
||||
*/
|
||||
void jerry_port_sleep (uint32_t sleep_time) /**< milliseconds to sleep */
|
||||
{
|
||||
usleep ((useconds_t) sleep_time * 1000);
|
||||
} /* jerry_port_sleep */
|
||||
|
||||
/**
|
||||
* Pointer to the current context.
|
||||
*/
|
||||
static jerry_context_t *current_context_p = NULL;
|
||||
|
||||
/**
|
||||
* Set the current_context_p as the passed pointer.
|
||||
*/
|
||||
void
|
||||
jerry_port_default_set_current_context (jerry_context_t *context_p) /**< points to the created context */
|
||||
{
|
||||
current_context_p = context_p;
|
||||
} /* jerry_port_default_set_current_context */
|
||||
|
||||
/**
|
||||
* Get the current context.
|
||||
*
|
||||
* @return the pointer to the current context
|
||||
*/
|
||||
jerry_context_t *
|
||||
jerry_port_get_current_context (void)
|
||||
{
|
||||
return current_context_p;
|
||||
} /* jerry_port_get_current_context */
|
||||
|
||||
/**
|
||||
* Track unhandled promise rejections.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
|
||||
* is enabled.
|
||||
*
|
||||
* @param promise rejected promise
|
||||
* @param operation HostPromiseRejectionTracker operation
|
||||
*/
|
||||
void
|
||||
jerry_port_track_promise_rejection (const jerry_value_t promise,
|
||||
const jerry_promise_rejection_operation_t operation)
|
||||
{
|
||||
(void) operation; /* unused */
|
||||
|
||||
jerry_value_t reason = jerry_get_promise_result (promise);
|
||||
jerry_value_t reason_to_string = jerry_value_to_string (reason);
|
||||
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
|
||||
jerry_char_t str_buf_p[req_sz + 1];
|
||||
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
|
||||
str_buf_p[req_sz] = '\0';
|
||||
|
||||
jerry_release_value (reason_to_string);
|
||||
jerry_release_value (reason);
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Uncaught (in promise) %s\n", str_buf_p);
|
||||
} /* jerry_port_track_promise_rejection */
|
|
@ -0,0 +1,298 @@
|
|||
# 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.
|
||||
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
project (Jerry C)
|
||||
|
||||
# Determining version
|
||||
execute_process(COMMAND python ${CMAKE_SOURCE_DIR}/tools/version.py
|
||||
OUTPUT_VARIABLE JERRY_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# Determining platform
|
||||
set(PLATFORM "${CMAKE_SYSTEM_NAME}")
|
||||
string(TOUPPER "${PLATFORM}" PLATFORM)
|
||||
|
||||
# Determining compiler
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
set(USING_GCC 1)
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(USING_CLANG 1)
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "TI")
|
||||
set(USING_TI 1)
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
set(USING_MSVC 1)
|
||||
endif()
|
||||
|
||||
# Determining build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "MinSizeRel")
|
||||
endif()
|
||||
|
||||
# Optional components
|
||||
set(JERRY_CMDLINE ON CACHE BOOL "Build jerry command line tool?")
|
||||
set(JERRY_CMDLINE_TEST OFF CACHE BOOL "Build jerry test command line tool?")
|
||||
set(JERRY_CMDLINE_SNAPSHOT OFF CACHE BOOL "Build jerry snapshot command line tool?")
|
||||
set(JERRY_LIBFUZZER OFF CACHE BOOL "Build jerry with libfuzzer support?")
|
||||
set(JERRY_PORT_DEFAULT ON CACHE BOOL "Build default jerry port implementation?")
|
||||
set(JERRY_EXT ON CACHE BOOL "Build jerry-ext?")
|
||||
set(JERRY_MATH OFF CACHE BOOL "Build and use jerry-math?")
|
||||
set(UNITTESTS OFF CACHE BOOL "Build unit tests?")
|
||||
set(DOCTESTS OFF CACHE BOOL "Build doc tests?")
|
||||
|
||||
# Optional build settings
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries?")
|
||||
set(ENABLE_AMALGAM OFF CACHE BOOL "Enable amalgamated build?")
|
||||
set(ENABLE_LTO ON CACHE BOOL "Enable LTO build?")
|
||||
set(ENABLE_STRIP ON CACHE BOOL "Enable stripping all symbols from release binary?")
|
||||
set(ENABLE_COMPILE_COMMANDS ON CACHE BOOL "Enable generating compile_commands.json?")
|
||||
|
||||
# Option overrides
|
||||
if(NOT USING_CLANG)
|
||||
set(JERRY_LIBFUZZER OFF)
|
||||
|
||||
set(JERRY_LIBFUZZER_MESSAGE " (FORCED BY COMPILER)")
|
||||
endif()
|
||||
|
||||
if(JERRY_CMDLINE OR JERRY_CMDLINE_TEST OR JERRY_CMDLINE_SNAPSHOT OR JERRY_LIBFUZZER OR UNITTESTS OR DOCTESTS)
|
||||
set(JERRY_PORT_DEFAULT ON)
|
||||
|
||||
set(JERRY_PORT_DEFAULT_MESSAGE " (FORCED BY CMDLINE OR LIBFUZZER OR TESTS)")
|
||||
endif()
|
||||
|
||||
if(JERRY_CMDLINE OR DOCTESTS)
|
||||
set(JERRY_EXT ON)
|
||||
|
||||
set(JERRY_EXT_MESSAGE " (FORCED BY CMDLINE OR TESTS)")
|
||||
endif()
|
||||
|
||||
if("${PLATFORM}" STREQUAL "DARWIN")
|
||||
set(ENABLE_LTO OFF)
|
||||
set(ENABLE_STRIP OFF)
|
||||
|
||||
set(ENABLE_LTO_MESSAGE " (FORCED BY PLATFORM)")
|
||||
set(ENABLE_STRIP_MESSAGE " (FORCED BY PLATFORM)")
|
||||
endif()
|
||||
|
||||
if("${PLATFORM}" STREQUAL "ESP-IDF")
|
||||
set(ENABLE_LTO OFF)
|
||||
set(ENABLE_STRIP OFF)
|
||||
|
||||
set(ENABLE_LTO_MESSAGE " (FORCED BY PLATFORM)")
|
||||
set(ENABLE_STRIP_MESSAGE " (FORCED BY PLATFORM)")
|
||||
endif()
|
||||
|
||||
if(USING_TI)
|
||||
set(ENABLE_STRIP OFF)
|
||||
|
||||
set(ENABLE_STRIP_MESSAGE " (FORCED BY COMPILER)")
|
||||
endif()
|
||||
|
||||
if(USING_MSVC)
|
||||
set(ENABLE_STRIP OFF)
|
||||
|
||||
set(ENABLE_STRIP_MESSAGE " (FORCED BY COMPILER)")
|
||||
endif()
|
||||
|
||||
if(CYGWIN OR MINGW OR MSYS)
|
||||
set(ENABLE_LTO OFF)
|
||||
|
||||
set(ENABLE_LTO_MESSAGE " (FORCED BY PLATFORM)")
|
||||
endif()
|
||||
|
||||
# Generate compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ${ENABLE_COMPILE_COMMANDS})
|
||||
|
||||
# Status messages
|
||||
message(STATUS "CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE})
|
||||
message(STATUS "CMAKE_C_COMPILER_ID " ${CMAKE_C_COMPILER_ID})
|
||||
message(STATUS "CMAKE_SYSTEM_NAME " ${CMAKE_SYSTEM_NAME})
|
||||
message(STATUS "CMAKE_SYSTEM_PROCESSOR " ${CMAKE_SYSTEM_PROCESSOR})
|
||||
message(STATUS "BUILD_SHARED_LIBS " ${BUILD_SHARED_LIBS})
|
||||
message(STATUS "ENABLE_AMALGAM " ${ENABLE_AMALGAM} ${ENABLE_AMALGAM_MESSAGE})
|
||||
message(STATUS "ENABLE_LTO " ${ENABLE_LTO} ${ENABLE_LTO_MESSAGE})
|
||||
message(STATUS "ENABLE_STRIP " ${ENABLE_STRIP} ${ENABLE_STRIP_MESSAGE})
|
||||
message(STATUS "ENABLE_COMPILE_COMMANDS " ${ENABLE_COMPILE_COMMANDS})
|
||||
message(STATUS "JERRY_VERSION " ${JERRY_VERSION})
|
||||
message(STATUS "JERRY_CMDLINE " ${JERRY_CMDLINE} ${JERRY_CMDLINE_MESSAGE})
|
||||
message(STATUS "JERRY_CMDLINE_TEST " ${JERRY_CMDLINE_TEST} ${JERRY_CMDLINE_TEST_MESSAGE})
|
||||
message(STATUS "JERRY_CMDLINE_SNAPSHOT " ${JERRY_CMDLINE_SNAPSHOT} ${JERRY_CMDLINE_SNAPSHOT_MESSAGE})
|
||||
message(STATUS "JERRY_LIBFUZZER " ${JERRY_LIBFUZZER} ${JERRY_LIBFUZZER_MESSAGE})
|
||||
message(STATUS "JERRY_PORT_DEFAULT " ${JERRY_PORT_DEFAULT} ${JERRY_PORT_DEFAULT_MESSAGE})
|
||||
message(STATUS "JERRY_EXT " ${JERRY_EXT} ${JERRY_EXT_MESSAGE})
|
||||
message(STATUS "JERRY_MATH " ${JERRY_MATH} ${JERRY_MATH_MESSAGE})
|
||||
message(STATUS "UNITTESTS " ${UNITTESTS})
|
||||
message(STATUS "DOCTESTS " ${DOCTESTS})
|
||||
|
||||
# Setup directories
|
||||
# Note: This mimics a conventional file system layout in the build directory for
|
||||
# the sake of convenient location of build artefacts. Proper installation to
|
||||
# traditional locations is also supported, e.g., to /usr/local.
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/")
|
||||
|
||||
# Remove rdynamic option
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS )
|
||||
|
||||
# Compile/link flags
|
||||
# Helper macros
|
||||
macro(jerry_add_flags VAR)
|
||||
foreach(_flag ${ARGN})
|
||||
set(${VAR} "${${VAR}} ${_flag}")
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(jerry_add_compile_flags)
|
||||
jerry_add_flags(CMAKE_C_FLAGS ${ARGV})
|
||||
endmacro()
|
||||
|
||||
macro(jerry_add_compile_warnings)
|
||||
foreach(_warning ${ARGV})
|
||||
jerry_add_compile_flags(-W${_warning})
|
||||
jerry_add_compile_flags(-Werror=${_warning})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(jerry_add_link_flags)
|
||||
jerry_add_flags(LINKER_FLAGS_COMMON ${ARGV})
|
||||
endmacro()
|
||||
|
||||
# Architecture-specific compile/link flags
|
||||
jerry_add_compile_flags(${FLAGS_COMMON_ARCH})
|
||||
jerry_add_flags(CMAKE_EXE_LINKER_FLAGS ${FLAGS_COMMON_ARCH})
|
||||
|
||||
# LTO
|
||||
if(ENABLE_LTO)
|
||||
if(USING_GCC OR USING_CLANG)
|
||||
jerry_add_compile_flags(-flto)
|
||||
jerry_add_link_flags(-flto)
|
||||
endif()
|
||||
if(USING_GCC)
|
||||
jerry_add_compile_flags(-fno-fat-lto-objects)
|
||||
# Use gcc-ar and gcc-ranlib to support LTO
|
||||
set(CMAKE_AR "gcc-ar")
|
||||
set(CMAKE_RANLIB "gcc-ranlib")
|
||||
endif()
|
||||
if(USING_TI)
|
||||
jerry_add_link_flags(-lto)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Compiler / Linker flags
|
||||
if("${PLATFORM}" STREQUAL "DARWIN")
|
||||
jerry_add_link_flags(-lSystem)
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Sqc <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup")
|
||||
elseif((NOT CYGWIN AND NOT MINGW AND NOT MSYS) AND (USING_GCC OR USING_CLANG))
|
||||
jerry_add_link_flags(-Wl,-z,noexecstack)
|
||||
endif()
|
||||
|
||||
if(USING_GCC OR USING_CLANG)
|
||||
jerry_add_compile_flags(-std=c99 -pedantic)
|
||||
if(JERRY_MATH)
|
||||
jerry_add_compile_flags(-fno-builtin)
|
||||
endif()
|
||||
jerry_add_compile_warnings(all extra format-nonliteral init-self conversion sign-conversion format-security missing-declarations shadow strict-prototypes undef old-style-definition)
|
||||
jerry_add_compile_flags(-Wno-stack-protector -Wno-attributes -Werror)
|
||||
endif()
|
||||
|
||||
if(USING_GCC)
|
||||
jerry_add_compile_warnings(logical-op)
|
||||
# TODO: Remove workaround for gcc 7 bug if the fallthrough comment detection is fixed.
|
||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 7.0)
|
||||
jerry_add_compile_flags(-Wno-implicit-fallthrough)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USING_CLANG)
|
||||
jerry_add_compile_flags(-Wno-nested-anon-types -Wno-static-in-inline)
|
||||
endif()
|
||||
|
||||
if(USING_TI)
|
||||
jerry_add_compile_flags(--c99)
|
||||
endif()
|
||||
|
||||
if(USING_MSVC)
|
||||
jerry_add_link_flags(/OPT:NOREF)
|
||||
# Disable MSVC warning 4996 globally because it stops us from using standard C functions.
|
||||
jerry_add_compile_flags(/wd4996)
|
||||
endif()
|
||||
|
||||
if(JERRY_LIBFUZZER)
|
||||
jerry_add_compile_flags(-fsanitize=fuzzer-no-link)
|
||||
endif()
|
||||
|
||||
# Strip binary
|
||||
if(ENABLE_STRIP AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
jerry_add_link_flags(-s)
|
||||
endif()
|
||||
|
||||
# External compiler & linker flags
|
||||
if(DEFINED EXTERNAL_COMPILE_FLAGS)
|
||||
jerry_add_compile_flags(${EXTERNAL_COMPILE_FLAGS})
|
||||
endif()
|
||||
|
||||
if(DEFINED EXTERNAL_LINKER_FLAGS)
|
||||
jerry_add_link_flags(${EXTERNAL_LINKER_FLAGS})
|
||||
endif()
|
||||
|
||||
# Used as placeholder to attach amalgamated build targets to
|
||||
add_custom_target(amalgam)
|
||||
|
||||
# Jerry's libm
|
||||
if(JERRY_MATH)
|
||||
add_subdirectory(jerry-math)
|
||||
endif()
|
||||
|
||||
# Jerry's core
|
||||
add_subdirectory(jerry-core)
|
||||
|
||||
# Jerry's extension tools
|
||||
if(JERRY_EXT)
|
||||
add_subdirectory(jerry-ext)
|
||||
endif()
|
||||
|
||||
# Jerry's default port implementation
|
||||
if(JERRY_PORT_DEFAULT)
|
||||
add_subdirectory(jerry-port/default)
|
||||
endif()
|
||||
|
||||
# Jerry command line tool
|
||||
if(JERRY_CMDLINE OR JERRY_CMDLINE_TEST OR JERRY_CMDLINE_SNAPSHOT OR JERRY_LIBFUZZER)
|
||||
add_subdirectory(jerry-main)
|
||||
endif()
|
||||
|
||||
# Unittests
|
||||
if(UNITTESTS)
|
||||
add_subdirectory(tests/unit-core)
|
||||
if(JERRY_MATH)
|
||||
add_subdirectory(tests/unit-math)
|
||||
endif()
|
||||
if(JERRY_EXT)
|
||||
add_subdirectory(tests/unit-ext)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Doctests
|
||||
if(DOCTESTS)
|
||||
add_subdirectory(tests/unit-doc)
|
||||
endif()
|
|
@ -0,0 +1,27 @@
|
|||
version: "{build}"
|
||||
branches:
|
||||
except:
|
||||
- coverity_scan
|
||||
- gh_pages
|
||||
skip_tags: true
|
||||
|
||||
# Build matrix setup.
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
platform:
|
||||
- x64
|
||||
- Win32
|
||||
|
||||
# Steps of a job.
|
||||
init:
|
||||
- cmake -version
|
||||
before_build:
|
||||
- if "%PLATFORM%"=="Win32" cmake -G"Visual Studio 15 2017" -Bbuild -H. -DJERRY_DEBUGGER=ON
|
||||
- if "%PLATFORM%"=="x64" cmake -G"Visual Studio 15 2017 Win64" -Bbuild -H. -DJERRY_DEBUGGER=ON
|
||||
build:
|
||||
project: build\Jerry.sln
|
||||
parallel: false # FIXME: This should not be needed but right now it is: msbuild generates all amalgamated files twice, at the same time in parallel builds, leading to I/O errors.
|
||||
verbosity: minimal
|
|
@ -0,0 +1,29 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME esp-idf)
|
||||
set(CMAKE_SYSTEM_PROCESSOR xtensa)
|
||||
|
||||
set(CMAKE_C_COMPILER xtensa-esp32-elf-gcc)
|
||||
set(CMAKE_CXX_COMPILER xtensa-esp32-elf-g++)
|
||||
set(CMAKE_ASM_COMPILER xtensa-esp32-elf-gcc)
|
||||
|
||||
# uncomment that if you want 4-bytes float (much faster on esp32)
|
||||
#add_definitions(-DJERRY_NUMBER_TYPE_FLOAT64=0)
|
||||
|
||||
set(CMAKE_C_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C Compiler Base Flags")
|
||||
set(CMAKE_CXX_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C++ Compiler Base Flags")
|
||||
|
||||
# Can be removed after gcc 5.2.0 support is removed (ref GCC_NOT_5_2_0)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags")
|
|
@ -0,0 +1,18 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
|
||||
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
|
|
@ -0,0 +1,20 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l-el)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
|
||||
|
||||
set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb)
|
|
@ -0,0 +1,24 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
#
|
||||
# Limit fpu to VFPv3 with d0-d15 registers
|
||||
#
|
||||
# If this is changed, setjmp / longjmp for ARMv7 should be updated accordingly
|
||||
#
|
||||
set(FLAGS_COMMON_ARCH -mthumb -mfpu=vfp -march=armv7)
|
|
@ -0,0 +1,15 @@
|
|||
# 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.
|
||||
|
||||
set(FLAGS_COMMON_ARCH -mfpmath=sse -msse2)
|
|
@ -0,0 +1,22 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME MCU)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
set(CMAKE_SYSTEM_VERSION HC32F4A0)
|
||||
|
||||
set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb -mcpu=cortex-m4 -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=softfp)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
|
@ -0,0 +1,22 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME MCU)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
set(CMAKE_SYSTEM_VERSION STM32F3)
|
||||
|
||||
set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb -mcpu=cortex-m4 -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
|
@ -0,0 +1,22 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME MCU)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
set(CMAKE_SYSTEM_VERSION STM32F4)
|
||||
|
||||
set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb -mcpu=cortex-m4 -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
|
@ -0,0 +1,22 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME MCU)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
set(CMAKE_SYSTEM_VERSION STM32F7)
|
||||
|
||||
set(FLAGS_COMMON_ARCH -mthumb -mcpu=cortex-m7 -march=armv7e-m -mfloat-abi=hard)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
|
@ -0,0 +1,33 @@
|
|||
# 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(CMakeForceCompiler)
|
||||
|
||||
set(CMAKE_SYSTEM_NAME MCU)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
set(CMAKE_SYSTEM_VERSION TIM4F)
|
||||
|
||||
set(FLAGS_COMMON_ARCH --little_endian --silicon_version=7M4 --float_support=FPv4SPD16)
|
||||
|
||||
CMAKE_FORCE_C_COMPILER(armcl TI)
|
||||
|
||||
SET (CMAKE_C_FLAGS_DEBUG_INIT "-g")
|
||||
SET (CMAKE_C_FLAGS_MINSIZEREL_INIT "-o4 -mf0 -DNDEBUG")
|
||||
SET (CMAKE_C_FLAGS_RELEASE_INIT "-o4 -DNDEBUG")
|
||||
SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-o2 -g")
|
||||
|
||||
SET (CMAKE_CXX_FLAGS_DEBUG_INIT "-g")
|
||||
SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT "-o4 -mf0 -DNDEBUG")
|
||||
SET (CMAKE_CXX_FLAGS_RELEASE_INIT "-o4 -DNDEBUG")
|
||||
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-o2 -g")
|
|
@ -0,0 +1,18 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Openwrt)
|
||||
set(CMAKE_SYSTEM_PROCESSOR mips)
|
||||
|
||||
set(CMAKE_C_COMPILER mips-openwrt-linux-gcc)
|
|
@ -0,0 +1,18 @@
|
|||
# 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.
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Openwrt)
|
||||
set(CMAKE_SYSTEM_PROCESSOR mips)
|
||||
|
||||
set(CMAKE_C_COMPILER mipsel-openwrt-linux-gcc)
|
|
@ -0,0 +1,186 @@
|
|||
## Setting up prerequisites
|
||||
|
||||
Currently, only Ubuntu 18.04+ is officially supported as primary development environment.
|
||||
|
||||
There are several dependencies, that should be installed manually. The following list is the absolute minimum for building:
|
||||
|
||||
- `gcc` or any C99-compliant compiler (native or cross, e.g., arm-none-eabi)
|
||||
- `cmake` >= `2.8.12.2`
|
||||
|
||||
Several scripts and tools help the building and development process, thus it is recommended to have the following installed as well:
|
||||
|
||||
- `bash` >= `4.3.11`
|
||||
- `cppcheck` >= `1.61`
|
||||
- `vera++` >= `1.2.1`
|
||||
- `python` >= `2.7.6`
|
||||
|
||||
```bash
|
||||
sudo apt-get install gcc gcc-arm-none-eabi cmake cppcheck vera++ python
|
||||
```
|
||||
|
||||
To make our scripts run correctly, several shell utilities should be available on the system:
|
||||
|
||||
- `awk`
|
||||
- `bc`
|
||||
- `find`
|
||||
- `sed`
|
||||
|
||||
## Building JerryScript
|
||||
|
||||
**To build debug version for Linux**
|
||||
|
||||
```bash
|
||||
python tools/build.py --debug
|
||||
```
|
||||
|
||||
**To build debug version for Linux without LTO (Link Time Optimization)**
|
||||
|
||||
```bash
|
||||
python tools/build.py --debug --lto=off
|
||||
```
|
||||
|
||||
**To enable more verbose outputs for debugging**
|
||||
|
||||
```bash
|
||||
tools/build.py --debug --logging=on --error-messages=on --line-info=on
|
||||
```
|
||||
|
||||
**Add custom arguments to CMake**
|
||||
|
||||
```bash
|
||||
python tools/build.py --cmake-param=CMAKE_PARAM
|
||||
```
|
||||
|
||||
**Set a profile mode (ES.next, ES5.1, minimal)**
|
||||
|
||||
```bash
|
||||
python tools/build.py --profile=es.next|es5.1|minimal
|
||||
```
|
||||
|
||||
See also the related [README.md](https://github.com/jerryscript-project/jerryscript/blob/master/jerry-core/profiles/README.md).
|
||||
|
||||
**Use (compiler-default, external) libc**
|
||||
|
||||
The default libc is the compiler-default libc but you can use an external libc as well:
|
||||
|
||||
- compiler-default libc:
|
||||
|
||||
```bash
|
||||
python tools/build.py
|
||||
```
|
||||
|
||||
- external libc:
|
||||
|
||||
```bash
|
||||
python tools/build.py --compile-flag="-nostdlib -I/path/to/ext-libc/include" --link-lib="ext-c"
|
||||
```
|
||||
|
||||
**Add toolchain file**
|
||||
|
||||
The ```cmake``` dir already contains some usable toolchain files, which you can use in the following format:
|
||||
|
||||
```bash
|
||||
python tools/build.py --toolchain=TOOLCHAIN
|
||||
```
|
||||
|
||||
For example the cross-compile to RaspberryPi 2 is something like this:
|
||||
|
||||
```bash
|
||||
python tools/build.py --toolchain=cmake/toolchain_linux_armv7l.cmake
|
||||
```
|
||||
|
||||
**Use system memory allocator**
|
||||
|
||||
```bash
|
||||
python tools/build.py --system-allocator=on
|
||||
```
|
||||
|
||||
*Note*: System allocator is only supported on 32 bit systems.
|
||||
|
||||
**Enable 32bit compressed pointers**
|
||||
|
||||
```bash
|
||||
python tools/build.py --cpointer-32bit=on
|
||||
```
|
||||
|
||||
*Note*: There is no compression/decompression on 32 bit systems, if enabled.
|
||||
|
||||
**Change default heap size (512K)**
|
||||
|
||||
```bash
|
||||
python tools/build.py --mem-heap=256
|
||||
```
|
||||
|
||||
If you would like to use more than 512K, then you must enable the 32 bit compressed pointers.
|
||||
|
||||
```bash
|
||||
python tools/build.py --cpointer-32bit=on --mem-heap=1024
|
||||
```
|
||||
|
||||
*Note*: The heap size will be allocated statically at compile time, when JerryScript memory
|
||||
allocator is used.
|
||||
|
||||
**To build with libfuzzer support**
|
||||
|
||||
```bash
|
||||
CC=clang python tools/build.py --libfuzzer=on --compile-flag=-fsanitize=address --lto=off
|
||||
```
|
||||
|
||||
Check the documentation of libfuzzer to get the runtime settings of the created fuzzer
|
||||
binary: https://llvm.org/docs/LibFuzzer.html.
|
||||
|
||||
**To get a list of all the available buildoptions for Linux**
|
||||
|
||||
```bash
|
||||
python tools/build.py --help
|
||||
```
|
||||
|
||||
## Checking patch
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --precommit
|
||||
```
|
||||
|
||||
### Running only one type of test
|
||||
|
||||
**To run build option tests**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --buildoption-test
|
||||
```
|
||||
|
||||
**To run unittests**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --unittests
|
||||
```
|
||||
|
||||
**To run jerry-tests**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --jerry-tests
|
||||
```
|
||||
|
||||
**To run signed-off check**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --check-signed-off
|
||||
```
|
||||
|
||||
**To run cppcheck**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --check-cppcheck
|
||||
```
|
||||
|
||||
**To run vera check**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --check-vera
|
||||
```
|
||||
|
||||
**To get a list of all the available test options**
|
||||
|
||||
```bash
|
||||
python tools/run-tests.py --help
|
||||
```
|
|
@ -0,0 +1,338 @@
|
|||
# Configuration
|
||||
|
||||
JerryScript provides a large number of configuration options which can be used to enable or disable specific features, allowing users to fine tune the engine to best suit their needs.
|
||||
A configuration option's value can be changed either by providing specific C preprocessor definitions, by adding CMake defininitions, or by using the arguments of the `tools/build.py` script.
|
||||
This document lists the available configuration options, shows the configuration name for C, CMake, and python, and provides a brief description that explains the effect of the options.
|
||||
|
||||
|
||||
### Amalgamated build
|
||||
|
||||
Enables the amalgamated build process, which aggregates the contents of each source file per library
|
||||
(i.e., JerryScript's core, port, and math libraries), and uses these combined files to compile the project.
|
||||
This process can provide comparable results to link-time optimization, and can be useful when LTO is not available otherwise.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `<none>` |
|
||||
| CMake: | `-DENABLE_AMALGAM=ON/OFF` |
|
||||
| Python: | `--amalgam=ON/OFF` |
|
||||
|
||||
See also: [Amalgamated sources](#amalgamated-sources)
|
||||
|
||||
### Jerry debugger
|
||||
|
||||
Enables debugger support in the engine, which can be used to debug running JavaScript code. For more information on using the debugger see [Debugger](07.DEBUGGER.md).
|
||||
The debugger is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_DEBUGGER=0/1` |
|
||||
| CMake: | `-DJERRY_DEBUGGER=ON/OFF` |
|
||||
| Python: | `--jerry-debugger=ON/OFF` |
|
||||
|
||||
### Line information
|
||||
|
||||
By default, all source code information is discarded after parsing is complete. This option can be used to augment the created bytecode to provide line information during runtime,
|
||||
that can be used by the debugger to identify the currently executed source context. See [Debugger](07.DEBUGGER.md).
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_LINE_INFO=0/1` |
|
||||
| CMake: | `-DJERRY_LINE_INFO=ON/OFF` |
|
||||
| Python: | `--line-info=ON/OFF` |
|
||||
|
||||
### Profiles
|
||||
|
||||
This option can be used to enable/disable available JavaScript language features by providing profile files. Profile files contain a list of C definitions that configure each individual feature.
|
||||
The `path` value for CMake and Python arguments should be a file path to the profile file, or one of `es.next`, `es5.1`, or `minimal`, which are the pre-defined profiles.
|
||||
To see how a profile file should be created, or what configuration options are available in C, see the profile [README](https://github.com/jerryscript-project/jerryscript/blob/master/jerry-core/profiles/README.md).
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `<see description>` |
|
||||
| CMake: | `-DJERRY_PROFILE="path"` |
|
||||
| Python: | `--profile="path"` |
|
||||
|
||||
### External context
|
||||
|
||||
Enables external context support in the engine. By default, JerryScript uses a statically allocated context to store the current state of the engine internals.
|
||||
When this option is enabled, an externally allocated memory region can be provided through the port API to the engine, to be used as the context.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_EXTERNAL_CONTEXT=0/1` |
|
||||
| CMake: | `-DJERRY_EXTERNAL_CONTEXT=ON/OFF` |
|
||||
| Python: | `--external-context=ON/OFF` |
|
||||
|
||||
### Snapshot execution
|
||||
|
||||
This option can be used to enable snapshot execution in the engine.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_SNAPSHOT_EXEC=0/1` |
|
||||
| CMake: | `-DJERRY_SNAPSHOT_EXEC=ON/OFF` |
|
||||
| Python: | `--snapshot-exec=ON/OFF` |
|
||||
|
||||
### Snapshot saving
|
||||
|
||||
This option can be used to enable snapshot saving in the engine.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_SNAPSHOT_SAVE=0/1` |
|
||||
| CMake: | `-DJERRY_SNAPSHOT_SAVE=ON/OFF` |
|
||||
| Python: | `--snapshot-save=ON/OFF` |
|
||||
|
||||
### Jerry parser
|
||||
|
||||
This option can be used to enable or disable the parser. When the parser is disabled all features that depend on source parsing are unavailable (eg. `jerry_parse`, `eval`, Function constructor).
|
||||
This option can be useful in combination with the snapshot feature. The parser is enabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_PARSER=0/1` |
|
||||
| CMake: | `-DJERRY_PARSER=ON/OFF` |
|
||||
| Python: | `--js-parser=ON/OFF` |
|
||||
|
||||
### Dump bytecode
|
||||
|
||||
This option can be used to display created bytecode in a human readable format. See [Internals](04.INTERNALS.md#byte-code) for more details.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_PARSER_DUMP_BYTE_CODE=0/1` |
|
||||
| CMake: | `-DJERRY_PARSER_DUMP_BYTE_CODE=ON/OFF` |
|
||||
| Python: | `--show-opcodes=ON/OFF` |
|
||||
|
||||
### Dump RegExp bytecode
|
||||
|
||||
This option can be used to display created RegExp bytecode in a human readable format. The RegExp bytecode is different from the bytecode used by the virtual machine.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_REGEXP_DUMP_BYTE_CODE=0/1` |
|
||||
| CMake: | `-DJERRY_REGEXP_DUMP_BYTE_CODE=ON/OFF` |
|
||||
| Python: | `--show-regexp-opcodes=ON/OFF` |
|
||||
|
||||
### Strict RegExp
|
||||
|
||||
This option can be used to enable strict RegExp mode. The standard RegExp syntax is a lot stricter than what is common in current JavaScript implementations.
|
||||
When enabled, this flag disables all of the non-standard, quality-of-life RegExp features, that are implemented to provide compatibility with other commonly used engines.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_REGEXP_STRICT_MODE=0/1` |
|
||||
| CMake: | `-DJERRY_REGEXP_STRICT_MODE=ON/OFF` |
|
||||
| Python: | `--regexp-strict-mode=ON/OFF` |
|
||||
|
||||
### Error messages
|
||||
|
||||
Enables error messages for thrown Error objects. By default, error messages are omitted to reduce memory usage.
|
||||
Enabling this feature provides detailed error messages where available, like line information for Syntax errors, variable names for Reference errors, Type/Range error messages for built-in routines, etc.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_ERROR_MESSAGES=0/1` |
|
||||
| CMake: | `--DJERRY_ERROR_MESSAGES=ON/OFF` |
|
||||
| Python: | `--error-messages=ON/OFF` |
|
||||
|
||||
### Logging
|
||||
|
||||
This option can be used to enable log messages during runtime. When enabled the engine will use the `jerry_port_log` port API function to print relevant log messages.
|
||||
This feature is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_LOGGING=0/1` |
|
||||
| CMake: | `-DJERRY_LOGGING=ON/OFF` |
|
||||
| Python: | `--logging=ON/OFF` |
|
||||
|
||||
### LCache
|
||||
|
||||
This option enables the LCache, allowing faster access to object properties. The LCache uses a statically allocated hash-map, which increases memory consumption.
|
||||
See [Internals](04.INTERNALS.md#lcache) for further details.
|
||||
This option is enabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_LCACHE=0/1` |
|
||||
| CMake: | `<none>` |
|
||||
| Python: | `<none>` |
|
||||
|
||||
### Property hashmaps
|
||||
|
||||
This option enables the creation of hashmaps for object properties, which allows faster property access, at the cost of increased memory consumption.
|
||||
See [Internals](04.INTERNALS.md#property-hashmap) for further details.
|
||||
This option is enabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_PROPRETY_HASHMAP=0/1` |
|
||||
| CMake: | `<none>` |
|
||||
| Python: | `<none>` |
|
||||
|
||||
### Memory statistics
|
||||
|
||||
This option can be used to provide memory usage statistics either upon engine termination, or during runtime using the `jerry_get_memory_stats` jerry API function.
|
||||
The feature can create a significant performance overhead, and should only be used for measurement purposes. This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_MEM_STATS=0/1` |
|
||||
| CMake: | `-DJERRY_MEM_STATS=ON/OFF` |
|
||||
| Python: | `--mem-stats=ON/OFF` |
|
||||
|
||||
### Heap size
|
||||
|
||||
This option can be used to adjust the size of the internal heap, represented in kilobytes. The provided value should be an integer. Values larger than 512 require 32-bit compressed pointers to be enabled.
|
||||
The default value is 512.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_GLOBAL_HEAP_SIZE=(int)` |
|
||||
| CMake: | `--DJERRY_GLOBAL_HEAP_SIZE=(int)` |
|
||||
| Python: | `--mem-heap=(int)` |
|
||||
|
||||
### Garbage collection limit
|
||||
|
||||
This option can be used to adjust the maximum allowed heap usage increase until triggering the next garbage collection, in bytes.
|
||||
When the total allocated memory size reaches the current gc limit, garbage collection will be triggered to try and reduce clutter from unreachable objects.
|
||||
If the total allocated memory can't be reduced below the current limit, then the limit will be increased by the amount specified via this option.
|
||||
Similarly, when the total allocated memory goes well below the current gc limit, the limit is reduced by this amount.
|
||||
The default value is 1/32 of the total heap size, but not greater than 8192 bytes.
|
||||
A value of 0 will use the default value.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_GC_LIMIT=(int)` |
|
||||
| CMake: | `-DJERRY_GC_LIMIT=(int)` |
|
||||
| Python: | `--gc-limit=(int)` |
|
||||
|
||||
### GC mark recursion limit
|
||||
|
||||
This option can be used to adjust the maximum recursion depth during the GC mark phase. The provided value should be an integer, which represents the allowed number of recursive calls. Increasing the depth of the recursion reduces the time of GC cycles, however increases stack usage.
|
||||
A value of 0 will prevent any recursive GC calls.
|
||||
|
||||
| Options | |
|
||||
|---------|---------------------------------------------------|
|
||||
| C: | `-DJERRY_GC_MARK_LIMIT=(int)` |
|
||||
| CMake: | `-DJERRY_GC_MARK_LIMIT=(int)` |
|
||||
| Python: | `--gc-mark-limit=(int)` |
|
||||
|
||||
### Stack limit
|
||||
|
||||
This option can be used to cap the stack usage of the engine, and prevent stack overflows due to recursion. The provided value should be an integer, which represents the allowed stack usage in kilobytes.
|
||||
The default value is 0 (unlimited).
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_STACK_LIMIT=(int)` |
|
||||
| CMake: | `-DJERRY_STACK_LIMIT=(int)` |
|
||||
| Python: | `--stack-limit=(int)` |
|
||||
|
||||
### 32-bit compressed pointers
|
||||
|
||||
Enables 32-bit pointers instead of the default 16-bit compressed pointers. This allows the engine to use a much larger heap, but also comes with slightly increased memory usage, as objects can't be packed as tightly.
|
||||
This option must be enabled when using the system allocator.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_CPOINTER_32_BIT=0/1` |
|
||||
| CMake: | `-DJERRY_CPOINTER_32_BIT=ON/OFF` |
|
||||
| Python: | `--cpointer-32bit=ON/OFF` |
|
||||
|
||||
### System allocator
|
||||
|
||||
This option enables the use of malloc/free instead of the internal JerryScript allocator. This feature requires 32-bit compressed pointers, and is unsupported on 64-bit architectures.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_SYSTEM_ALLOCATOR=0/1` |
|
||||
| CMake: | `-DJERRY_SYSTEM_ALLOCATOR=ON/OFF` |
|
||||
| Python: | `--system-allocator=ON/OFF` |
|
||||
|
||||
### Valgrind support
|
||||
|
||||
This option enables valgrind support for the internal allocator. When enabled, valgrind will be able to properly identify allocated memory regions, and report leaks or out-of-bounds memory accesses.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_VALGRIND=0/1` |
|
||||
| CMake: | `-DJERRY_VALGRIND=ON/OFF` |
|
||||
| Python: | `--valgrind=ON/OFF` |
|
||||
|
||||
### Memory stress test
|
||||
|
||||
This option can be used to stress test memory management, by running garbage collection before every allocation attempt.
|
||||
This option is disabled by default.
|
||||
|
||||
| Options | |
|
||||
|---------|----------------------------------------------|
|
||||
| C: | `-DJERRY_MEM_GC_BEFORE_EACH_ALLOC=0/1` |
|
||||
| CMake: | `-DJERRY_MEM_GC_BEFORE_EACH_ALLOC=ON/OFF` |
|
||||
| Python: | `--mem-stress-test=ON/OFF` |
|
||||
|
||||
|
||||
# Amalgamated sources
|
||||
|
||||
The sources of JerryScript can be combined into a handful of files to allow their easy integration
|
||||
in other projects. To achieve this, the following command can be executed to create a set of files
|
||||
into the `amalgam` directory:
|
||||
|
||||
```sh
|
||||
$ python tools/amalgam.py --output-dir amalgam --jerry-core --jerry-port-default --jerry-math
|
||||
```
|
||||
|
||||
(Note: In the example above, the command is executed from the project's root directory, but that is
|
||||
not mandatory.)
|
||||
|
||||
The command creates the following files in the `amalgam` dir:
|
||||
|
||||
* `jerryscript.c`
|
||||
* `jerryscript.h`
|
||||
* `jerryscript-config.h`
|
||||
* `jerryscript-port-default.c`
|
||||
* `jerryscript-port-default.h`
|
||||
* `jerryscript-math.c`
|
||||
* `math.h`
|
||||
|
||||
**Important**: the `jerryscript-config.h` contains the configurations mentioned above and
|
||||
should be adapted to the required use-case. See the file contents for more details and for the
|
||||
default configuration. (Note: This config file is created from the the `jerry-core/config.h` file.)
|
||||
|
||||
These files can be directly compiled with an application using the JerryScript API.
|
||||
E.g., using a command similar to the one below:
|
||||
|
||||
```sh
|
||||
$ gcc -Wall -o demo_app demo_app.c amalgam/jerryscript.c amalgam/jerryscript-port-default.c amalgam/jerryscript-math.c -Iamalgam/
|
||||
```
|
||||
|
||||
(Note: The headers must be available on the include path.)
|
||||
|
||||
This approach is also under the hood of the [amalgamated build](#amalgamated-build) process.
|
||||
|
||||
# Target specific information
|
||||
|
||||
## x86 with GCC
|
||||
|
||||
When building for Intel 32 bit architecture it is possible that GCC uses conservative options, thus assuming the most
|
||||
basic floating-point support (that is it does not generate SSE or others instructions).
|
||||
However this could lead to loss off precision and/or different results than what is required by the JavaScript standard
|
||||
in regards of floating-point values and arithmetic.
|
||||
|
||||
To resolve this precision problem it is advised to use at least SSE2.
|
||||
To do this with GCC please provide the `-mfpmath=sse -msse2` options during build.
|
||||
|
||||
These options can also be specified via the `build.py` script:
|
||||
|
||||
```sh
|
||||
$ ./tools/build.py --compile-flag=-mfpmath=sse --compile-flag=-msse2 --compile-flag=-m32
|
||||
```
|
|
@ -0,0 +1,334 @@
|
|||
# High-Level Design
|
||||

|
||||
|
||||
The diagram above shows the interactions between the major components of JerryScript: Parser and Virtual Machine (VM). Parser performs translation of input ECMAScript application into the byte-code with the specified format (refer to [Bytecode](#byte-code) and [Parser](#parser) page for details). Prepared bytecode is executed by the Virtual Machine that performs interpretation (refer to [Virtual Machine](#virtual-machine) and [ECMA](#ecma) pages for details).
|
||||
|
||||
# Parser
|
||||
|
||||
The parser is implemented as a recursive descent parser. The parser converts the JavaScript source code directly into byte-code without building an Abstract Syntax Tree. The parser depends on the following subcomponents.
|
||||
|
||||
## Lexer
|
||||
|
||||
The lexer splits input string (ECMAScript program) into sequence of tokens. It is able to scan the input string not only forward, but it is possible to move to an arbitrary position. The token structure described by structure `lexer_token_t` in `./jerry-core/parser/js/js-lexer.h`.
|
||||
|
||||
## Scanner
|
||||
|
||||
Scanner (`./jerry-core/parser/js/js-parser-scanner.c`) pre-scans the input string to find certain tokens. For example, scanner determines whether the keyword `for` defines a general for or a for-in loop. Reading tokens in a while loop is not enough because a slash (`/`) can indicate the start of a regular expression or can be a division operator.
|
||||
|
||||
## Expression Parser
|
||||
|
||||
Expression parser is responsible for parsing JavaScript expressions. It is implemented in `./jerry-core/parser/js/js-parser-expr.c`.
|
||||
|
||||
## Statement Parser
|
||||
|
||||
JavaScript statements are parsed by this component. It uses the [Expression parser](#expression-parser) to parse the constituent expressions. The implementation of Statement parser is located in `./jerry-core/parser/js/js-parser-statm.c`.
|
||||
|
||||
Function `parser_parse_source` carries out the parsing and compiling of the input ECMAScript source code. When a function appears in the source `parser_parse_source` calls `parser_parse_function` which is responsible for processing the source code of functions recursively including argument parsing and context handling. After the parsing, function `parser_post_processing` dumps the created opcodes and returns an `ecma_compiled_code_t*` that points to the compiled bytecode sequence.
|
||||
|
||||
The interactions between the major components shown on the following figure.
|
||||
|
||||

|
||||
|
||||
# Byte-code
|
||||
|
||||
This section describes the compact byte-code (CBC) representation. The key focus is reducing memory consumption of the byte-code representation without sacrificing considerable performance. Other byte-code representations often focus on performance only so inventing this representation is an original research.
|
||||
|
||||
CBC is a CISC like instruction set which assigns shorter instructions for frequent operations. Many instructions represent multiple atomic tasks which reduces the bytecode size. This technique is basically a data compression method.
|
||||
|
||||
## Compiled Code Format
|
||||
|
||||
The memory layout of the compiled bytecode is the following.
|
||||
|
||||

|
||||
|
||||
The header is a `cbc_compiled_code` structure with several fields. These fields contain the key properties of the compiled code.
|
||||
|
||||
The literals part is an array of ecma values. These values can contain any ECMAScript value types, e.g. strings, numbers, functions and regexp templates. The number of literals is stored in the `literal_end` field of the header.
|
||||
|
||||
CBC instruction list is a sequence of bytecode instructions which represents the compiled code.
|
||||
|
||||
## Byte-code Format
|
||||
|
||||
The memory layout of a byte-code is the following:
|
||||
|
||||

|
||||
|
||||
Each byte-code starts with an opcode. The opcode is one byte long for frequent and two byte long for rare instructions. The first byte of the rare instructions is always zero (`CBC_EXT_OPCODE`), and the second byte represents the extended opcode. The name of common and rare instructions start with `CBC_` and `CBC_EXT_` prefix respectively.
|
||||
|
||||
The maximum number of opcodes is 511, since 255 common (zero value excluded) and 256 rare instructions can be defined. Currently around 215 frequent and 70 rare instructions are available.
|
||||
|
||||
There are three types of bytecode arguments in CBC:
|
||||
|
||||
* __byte argument__: A value between 0 and 255, which often represents the argument count of call like opcodes (function call, new, eval, etc.).
|
||||
|
||||
* __literal argument__: An integer index which is greater or equal than zero and less than the `literal_end` field of the header. For further information see next section Literals (next).
|
||||
|
||||
* __relative branch__: An 1-3 byte long offset. The branch argument might also represent the end of an instruction range. For example the branch argument of `CBC_EXT_WITH_CREATE_CONTEXT` shows the end of a `with` statement. More precisely the position after the last instruction in the with clause.
|
||||
|
||||
Argument combinations are limited to the following seven forms:
|
||||
|
||||
* no arguments
|
||||
* a literal argument
|
||||
* a byte argument
|
||||
* a branch argument
|
||||
* a byte and a literal arguments
|
||||
* two literal arguments
|
||||
* three literal arguments
|
||||
|
||||
## Literals
|
||||
|
||||
Literals are organized into groups whose represent various literal types. Having these groups consuming less space than assigning flag bits to each literal.
|
||||
(In the followings, the mentioned ranges represent those indicies which are greater than or equal to the left side and less than the right side of the range. For example a range between `ident_end` and `literal_end` fields of the byte-code header contains those indicies, which are greater than or equal to `ident_end`
|
||||
and less than `literal_end`. If `ident_end` equals to `literal_end` the range is empty.)
|
||||
|
||||
The two major group of literals are _identifiers_ and _values_.
|
||||
|
||||
* __identifier__: A named reference to a variable. Literals between zero and `ident_end` of the header belongs to here. All of these literals must be a string or undefined. Undefined can only be used for those literals which cannot be accessed by a literal name. For example `function (arg,arg)` has two arguments, but the `arg` identifier only refers to the second argument. In such cases the name of the first argument is undefined. Furthermore optimizations such as *CSE* may also introduce literals without name.
|
||||
|
||||
* __value__: A reference to an immediate value. Literals between `ident_end` and `const_literal_end` are constant values such as numbers or strings. These literals can be used directly by the Virtual Machine. Literals between `const_literal_end` and `literal_end` are template literals. A new object needs to be constructed each time when their value is accessed. These literals are functions and regular expressions.
|
||||
|
||||
There are two other sub-groups of identifiers. *Registers* are those identifiers which are stored in the function call stack. *Arguments* are those registers which are passed by a caller function.
|
||||
|
||||
There are two types of literal encoding in CBC. Both are variable length, where the length is one or two byte long.
|
||||
|
||||
* __small__: maximum 511 literals can be encoded.
|
||||
|
||||
One byte encoding for literals 0 - 254.
|
||||
|
||||
```c
|
||||
byte[0] = literal_index
|
||||
```
|
||||
|
||||
Two byte encoding for literals 255 - 510.
|
||||
|
||||
```c
|
||||
byte[0] = 0xff
|
||||
byte[1] = literal_index - 0xff
|
||||
```
|
||||
|
||||
* __full__: maximum 32767 literal can be encoded.
|
||||
|
||||
One byte encoding for literals 0 - 127.
|
||||
|
||||
```c
|
||||
byte[0] = literal_index
|
||||
```
|
||||
|
||||
Two byte encoding for literals 128 - 32767.
|
||||
|
||||
```c
|
||||
byte[0] = (literal_index >> 8) | 0x80
|
||||
byte[1] = (literal_index & 0xff)
|
||||
```
|
||||
|
||||
Since most functions require less than 255 literal, small encoding provides a single byte literal index for all literals. Small encoding consumes less space than full encoding, but it has a limited range.
|
||||
|
||||
## Literal Store
|
||||
|
||||
JerryScript does not have a global string table for literals, but stores them into the Literal Store. During the parsing phase, when a new literal appears with the same identifier that has already occurred before, the string won't be stored once again, but the identifier in the Literal Store will be used. If a new literal is not in the Literal Store yet, it will be inserted.
|
||||
|
||||
## Byte-code Categories
|
||||
|
||||
Byte-codes can be placed into four main categories.
|
||||
|
||||
### Push Byte-codes
|
||||
|
||||
Byte-codes of this category serve for placing objects onto the stack. As there are many instructions representing multiple atomic tasks in CBC, there are also many instructions for pushing objects onto the stack according to the number and the type of the arguments. The following table list a few of these opcodes with a brief description.
|
||||
|
||||
<span class="CSSTableGenerator" markdown="block">
|
||||
|
||||
| byte-code | description |
|
||||
| --------------------- | ----------------------------------------------------- |
|
||||
| CBC_PUSH_LITERAL | Pushes the value of the given literal argument. |
|
||||
| CBC_PUSH_TWO_LITERALS | Pushes the values of the given two literal arguments. |
|
||||
| CBC_PUSH_UNDEFINED | Pushes an undefined value. |
|
||||
| CBC_PUSH_TRUE | Pushes a logical true. |
|
||||
| CBC_PUSH_PROP_LITERAL | Pushes a property whose base object is popped from the stack, and the property name is passed as a literal argument. |
|
||||
|
||||
</span>
|
||||
|
||||
### Call Byte-codes
|
||||
|
||||
The byte-codes of this category perform calls in different ways.
|
||||
|
||||
<span class="CSSTableGenerator" markdown="block">
|
||||
|
||||
| byte-code | description |
|
||||
| --------------------- | ------------------------------------------------------------------------------------ |
|
||||
| CBC_CALL0 | Calls a function without arguments. The return value won't be pushed onto the stack. |
|
||||
| CBC_CALL1 | Calls a function with one argument. The return value won't be pushed onto the stack. |
|
||||
| CBC_CALL | Calls a function with n arguments. n is passed as a byte argument. The return value won't be pushed onto the stack. |
|
||||
| CBC_CALL0_PUSH_RESULT | Calls a function without arguments. The return value will be pushed onto the stack. |
|
||||
| CBC_CALL1_PUSH_RESULT | Calls a function with one argument. The return value will be pushed onto the stack. |
|
||||
| CBC_CALL2_PROP | Calls a property function with two arguments. The base object, the property name, and the two arguments are on the stack. |
|
||||
|
||||
</span>
|
||||
|
||||
### Arithmetic, Logical, Bitwise and Assignment Byte-codes
|
||||
|
||||
The opcodes of this category perform arithmetic, logical, bitwise and assignment operations.
|
||||
|
||||
<span class="CSSTableGenerator" markdown="block">
|
||||
|
||||
| byte-code | description |
|
||||
| ----------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| CBC_LOGICAL_NOT | Negates the logical value that popped from the stack. The result is pushed onto the stack. |
|
||||
| CBC_LOGICAL_NOT_LITERAL | Negates the logical value that given in literal argument. The result is pushed onto the stack. |
|
||||
| CBC_ADD | Adds two values that are popped from the stack. The result is pushed onto the stack. |
|
||||
| CBC_ADD_RIGHT_LITERAL | Adds two values. The left one popped from the stack, the right one is given as literal argument. |
|
||||
| CBC_ADD_TWO_LITERALS | Adds two values. Both are given as literal arguments. |
|
||||
| CBC_ASSIGN | Assigns a value to a property. It has three arguments: base object, property name, value to assign. |
|
||||
| CBC_ASSIGN_PUSH_RESULT | Assigns a value to a property. It has three arguments: base object, property name, value to assign. The result will be pushed onto the stack. |
|
||||
|
||||
</span>
|
||||
|
||||
### Branch Byte-codes
|
||||
|
||||
Branch byte-codes are used to perform conditional and unconditional jumps in the byte-code. The arguments of these instructions are 1-3 byte long relative offsets. The number of bytes is part of the opcode, so each byte-code with a branch argument has three forms. The direction (forward, backward) is also defined by the opcode since the offset is an unsigned value. Thus, certain branch instructions has six forms. Some examples can be found in the following table.
|
||||
|
||||
<span class="CSSTableGenerator" markdown="block">
|
||||
|
||||
| byte-code | description |
|
||||
| -------------------------- | ----------------------------------------------------------- |
|
||||
| CBC_JUMP_FORWARD | Jumps forward by the 1 byte long relative offset argument. |
|
||||
| CBC_JUMP_FORWARD_2 | Jumps forward by the 2 byte long relative offset argument. |
|
||||
| CBC_JUMP_FORWARD_3 | Jumps forward by the 3 byte long relative offset argument. |
|
||||
| CBC_JUMP_BACKWARD | Jumps backward by the 1 byte long relative offset argument. |
|
||||
| CBC_JUMP_BACKWARD_2 | Jumps backward by the 2 byte long relative offset argument. |
|
||||
| CBC_JUMP_BACKWARD_3 | Jumps backward by the 3 byte long relative offset argument. |
|
||||
| CBC_BRANCH_IF_TRUE_FORWARD | Jumps forward if the value on the top of the stack is true by the 1 byte long relative offset argument. |
|
||||
|
||||
</span>
|
||||
|
||||
## Snapshot
|
||||
|
||||
The compiled byte-code can be saved into a snapshot, which also can be loaded back for execution. Directly executing the snapshot saves the costs of parsing the source in terms of memory consumption and performance. The snapshot can also be executed from ROM, in which case the overhead of loading it into the memory can also be saved.
|
||||
|
||||
|
||||
# Virtual Machine
|
||||
|
||||
Virtual machine is an interpreter which executes byte-code instructions one by one. The function that starts the interpretation is `vm_run` in `./jerry-core/vm/vm.c`. `vm_loop` is the main loop of the virtual machine, which has the peculiarity that it is *non-recursive*. This means that in case of function calls it does not calls itself recursively but returns, which has the benefit that it does not burdens the stack as a recursive implementation.
|
||||
|
||||
# ECMA
|
||||
|
||||
ECMA component of the engine is responsible for the following notions:
|
||||
|
||||
* Data representation
|
||||
* Runtime representation
|
||||
* Garbage collection (GC)
|
||||
|
||||
## Data Representation
|
||||
|
||||
The major structure for data representation is `ECMA_value`. The lower three bits of this structure encode value tag, which determines the type of the value:
|
||||
|
||||
* simple
|
||||
* number
|
||||
* string
|
||||
* object
|
||||
* symbol
|
||||
* error
|
||||
|
||||

|
||||
|
||||
In case of number, string and object the value contains an encoded pointer, and
|
||||
simple value is a pre-defined constant which can be:
|
||||
|
||||
* undefined
|
||||
* null
|
||||
* true
|
||||
* false
|
||||
* empty (uninitialized value)
|
||||
|
||||
### Compressed Pointers
|
||||
|
||||
Compressed pointers were introduced to save heap space.
|
||||
|
||||

|
||||
|
||||
These pointers are 8 byte aligned 16 bit long pointers which can address 512 Kb of
|
||||
memory which is also the maximum size of the JerryScript heap. To support even more
|
||||
memory the size of compressed pointers can be extended to 32 bit to cover the entire
|
||||
address space of a 32 bit system by passing "--cpointer_32_bit on" to the build
|
||||
system. These "uncompressed pointers" increases the memory consumption by around 20%.
|
||||
|
||||
### Number
|
||||
|
||||
There are two possible representation of numbers according to standard IEEE 754:
|
||||
The default is 8-byte (double),
|
||||
but the engine supports the 4-byte (single precision) representation by setting JERRY_NUMBER_TYPE_FLOAT64 to 0 as well.
|
||||
|
||||

|
||||
|
||||
Several references to single allocated number are not supported. Each reference holds its own copy of a number.
|
||||
|
||||
### String
|
||||
|
||||
Strings in JerryScript are not just character sequences, but can hold numbers and so-called magic ids too. For common character sequences (defined in `./jerry-core/lit/lit-magic-strings.ini`) there is a table in the read only memory that contains magic id and character sequence pairs. If a string is already in this table, the magic id of its string is stored, not the character sequence itself. Using numbers speeds up the property access. These techniques save memory.
|
||||
|
||||
### Object / Lexical Environment
|
||||
|
||||
An object can be a conventional data object or a lexical environment object. Unlike other data types, object can have references (called properties) to other data types. Because of circular references, reference counting is not always enough to determine dead objects. Hence a chain list is formed from all existing objects, which can be used to find unreferenced objects during garbage collection. The `gc-next` pointer of each object shows the next allocated object in the chain list.
|
||||
|
||||
[Lexical environments](http://www.ecma-international.org/ecma-262/5.1/#sec-10.2) are implemented as objects in JerryScript, since lexical environments contains key-value pairs (called bindings) like objects. This simplifies the implementation and reduces code size.
|
||||
|
||||

|
||||
|
||||
The objects are represented as following structure:
|
||||
|
||||
* Reference counter - number of hard (non-property) references
|
||||
* Next object pointer for the garbage collector
|
||||
* type (function object, lexical environment, etc.)
|
||||
|
||||
### Properties of Objects
|
||||
|
||||

|
||||
|
||||
Objects have a linked list that contains their properties. This list actually contains property pairs, in order to save memory described in the followings:
|
||||
A property has a one byte long descriptor, a two byte long name and four byte long value. Hence 14 bytes consumed by a property pair. Another two bytes is
|
||||
used to show the next property pair, so the total size (16 byte) is divisible by 8.
|
||||
|
||||
#### Property Hashmap
|
||||
|
||||
If the number of property pairs reach a limit (currently this limit is defined to 16), a hash map (called [Property Hashmap](#property-hashmap)) is inserted at the first position of the property pair list, in order to find a property using it, instead of finding it by iterating linearly over the property pairs.
|
||||
|
||||
Property hashmap contains 2<sup>n</sup> elements, where 2<sup>n</sup> is larger than the number of properties of the object. Each element can have tree types of value:
|
||||
|
||||
* null, indicating an empty element
|
||||
* deleted, indicating a deleted property, or
|
||||
* reference to the existing property
|
||||
|
||||
This hashmap is a must-return type cache, meaning that every property that the object have, can be found using it.
|
||||
|
||||
#### Internal Properties
|
||||
|
||||
Internal properties are special properties that carry meta-information that cannot be accessed by the JavaScript code, but important for the engine itself. Some examples of internal properties are listed below:
|
||||
|
||||
* [[Class]] - class (type) of the object (ECMA-defined)
|
||||
* [[Code]] - points where to find bytecode of the function
|
||||
* native code - points where to find the code of a native function
|
||||
* [[PrimitiveValue]] for Boolean - stores the boolean value of a Boolean object
|
||||
* [[PrimitiveValue]] for Number - stores the numeric value of a Number object
|
||||
|
||||
### LCache
|
||||
|
||||
LCache is a hashmap for finding a property specified by an object and by a property name. The object-name-property layout of the LCache presents multiple times in a row as it is shown in the figure below.
|
||||
|
||||

|
||||
|
||||
When a property access occurs, a hash value is extracted from the demanded property name and than this hash is used to index the LCache. After that, in the indexed row the specified object and property name will be searched.
|
||||
|
||||
It is important to note, that if the specified property is not found in the LCache, it does not mean that it does not exist (i.e. LCache is a may-return cache). If the property is not found, it will be searched in the property-list of the object, and if it is found there, the property will be placed into the LCache.
|
||||
|
||||
### Collections
|
||||
|
||||
Collections are array-like data structures, which are optimized to save memory. Actually, a collection is a linked list whose elements are not single elements, but arrays which can contain multiple elements.
|
||||
|
||||
### Exception Handling
|
||||
|
||||
In order to implement a sense of exception handling, the return values of JerryScript functions are able to indicate their faulty or "exceptional" operation. The return values are ECMA values (see section [Data Representation](#data-representation)) and if an erroneous operation occurred the ECMA_VALUE_ERROR simple value is returned.
|
||||
|
||||
### Value Management and Ownership
|
||||
|
||||
Every ECMA value stored by the engine is associated with a virtual "ownership", that defines how to manage the value: when to free it when it is not needed anymore and how to pass the value to an other function.
|
||||
|
||||
Initially, value is allocated by its owner (i.e. with ownership). The owner has the responsibility for freeing the allocated value. When the value is passed to a function as an argument, the ownership of it will not pass, the called function have to make an own copy of the value. However, as long as a function returns a value, the ownership will pass, thus the caller will be responsible for freeing it.
|
|
@ -0,0 +1,449 @@
|
|||
# Reference
|
||||
|
||||
## Termination
|
||||
|
||||
It is questionable whether a library should be able to terminate an application. Any API function can signal an error (ex.: cannot allocate memory), so the engine use the termination approach with this port function.
|
||||
|
||||
```c
|
||||
/**
|
||||
* Signal the port that jerry experienced a fatal failure from which it cannot
|
||||
* recover.
|
||||
*
|
||||
* @param code gives the cause of the error.
|
||||
*
|
||||
* Note:
|
||||
* Jerry expects the function not to return.
|
||||
*
|
||||
* Example: a libc-based port may implement this with exit() or abort(), or both.
|
||||
*/
|
||||
void jerry_port_fatal (jerry_fatal_code_t code);
|
||||
```
|
||||
|
||||
Error codes
|
||||
|
||||
```c
|
||||
typedef enum
|
||||
{
|
||||
ERR_OUT_OF_MEMORY = 10,
|
||||
ERR_REF_COUNT_LIMIT = 12,
|
||||
ERR_DISABLED_BYTE_CODE = 13,
|
||||
ERR_FAILED_INTERNAL_ASSERTION = 120
|
||||
} jerry_fatal_code_t;
|
||||
```
|
||||
|
||||
## I/O
|
||||
|
||||
These are the only I/O functions jerry calls.
|
||||
|
||||
```c
|
||||
/**
|
||||
* Jerry log levels. The levels are in severity order
|
||||
* where the most serious levels come first.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_LOG_LEVEL_ERROR, /**< the engine will terminate after the message is printed */
|
||||
JERRY_LOG_LEVEL_WARNING, /**< a request is aborted, but the engine continues its operation */
|
||||
JERRY_LOG_LEVEL_DEBUG, /**< debug messages from the engine, low volume */
|
||||
JERRY_LOG_LEVEL_TRACE /**< detailed info about engine internals, potentially high volume */
|
||||
} jerry_log_level_t;
|
||||
|
||||
/**
|
||||
* Display or log a debug/error message, and sends it to the debugger client as well.
|
||||
* The function should implement a printf-like interface, where the first argument
|
||||
* specifies the log level and the second argument specifies a format string on how
|
||||
* to stringify the rest of the parameter list.
|
||||
*
|
||||
* This function is only called with messages coming from the jerry engine as
|
||||
* the result of some abnormal operation or describing its internal operations
|
||||
* (e.g., data structure dumps or tracing info).
|
||||
*
|
||||
* It should be the port that decides whether error and debug messages are logged to
|
||||
* the console, or saved to a database or to a file.
|
||||
*
|
||||
* Example: a libc-based port may implement this with vfprintf(stderr) or
|
||||
* vfprintf(logfile), or both, depending on log level.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when JERRY_LOGGING is
|
||||
* enabled. It is also common practice though to use this function in
|
||||
* application code.
|
||||
*/
|
||||
void jerry_port_log (jerry_log_level_t level, const char *fmt, ...);
|
||||
```
|
||||
|
||||
The `jerry_port_print_char` is currenlty not used by the jerry-core directly.
|
||||
However, it provides a port specifc way for `jerry-ext` components to print
|
||||
information.
|
||||
|
||||
```c
|
||||
/**
|
||||
* Print a character to stdout.
|
||||
*/
|
||||
void jerry_port_print_char (char c);
|
||||
```
|
||||
|
||||
### Jerry Module system
|
||||
|
||||
The port API provides functions that can be used by the module system to open
|
||||
and close source files, and normalize file paths.
|
||||
The `jerry_port_get_native_module` port function can be used to provide native
|
||||
modules to the engine. This function will be called when an import/export
|
||||
statement is encountered with an unknown module specifier, which embedders can
|
||||
use to supply native module objects based on the module name argument.
|
||||
|
||||
```c
|
||||
/**
|
||||
* Opens file with the given path and reads its source.
|
||||
* @return the source of the file
|
||||
*/
|
||||
uint8_t *
|
||||
jerry_port_read_source (const char *file_name_p, /**< file name */
|
||||
size_t *out_size_p) /**< [out] read bytes */
|
||||
{
|
||||
// open file from given path
|
||||
// return its source
|
||||
} /* jerry_port_read_source */
|
||||
|
||||
/**
|
||||
* Release the previously opened file's content.
|
||||
*/
|
||||
void
|
||||
jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
{
|
||||
free (buffer_p);
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size, /**< size of output buffer */
|
||||
char *base_file_p) /**< base file path */
|
||||
{
|
||||
// normalize in_path_p by expanding relative paths etc.
|
||||
// if base_file_p is not NULL, in_path_p is relative to that file
|
||||
// write to out_buf_p the normalized path
|
||||
// return length of written path
|
||||
} /* jerry_port_normalize_path */
|
||||
|
||||
/**
|
||||
* Get the module object of a native module.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when JERRY_MODULE_SYSTEM
|
||||
* is enabled.
|
||||
*
|
||||
* @param name String value of the module specifier.
|
||||
*
|
||||
* @return Undefined, if 'name' is not a native module
|
||||
* jerry_value_t containing the module object, otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_port_get_native_module (jerry_value_t name) /**< module specifier */
|
||||
{
|
||||
(void) name;
|
||||
return jerry_create_undefined ();
|
||||
}
|
||||
```
|
||||
|
||||
## Promise
|
||||
|
||||
```c
|
||||
/**
|
||||
* HostPromiseRejectionTracker operations
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_PROMISE_REJECTION_OPERATION_REJECT, /**< promise is rejected without any handlers */
|
||||
JERRY_PROMISE_REJECTION_OPERATION_HANDLE, /**< handler is added to a rejected promise for the first time */
|
||||
} jerry_promise_rejection_operation_t;
|
||||
|
||||
/**
|
||||
* Track unhandled promise rejections.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when JERRY_BUILTIN_PROMISE
|
||||
* is enabled.
|
||||
*
|
||||
* @param promise rejected promise
|
||||
* @param operation HostPromiseRejectionTracker operation
|
||||
*/
|
||||
void jerry_port_track_promise_rejection (const jerry_value_t promise,
|
||||
const jerry_promise_rejection_operation_t operation);
|
||||
```
|
||||
|
||||
## Date
|
||||
|
||||
```c
|
||||
/**
|
||||
* Get local time zone adjustment, in milliseconds, for the given timestamp.
|
||||
* The timestamp can be specified in either UTC or local time, depending on
|
||||
* the value of is_utc. Adding the value returned from this function to
|
||||
* a timestamp in UTC time should result in local time for the current time
|
||||
* zone, and subtracting it from a timestamp in local time should result in
|
||||
* UTC time.
|
||||
*
|
||||
* Ideally, this function should satisfy the stipulations applied to LocalTZA
|
||||
* in section 20.3.1.7 of the ECMAScript version 9.0 spec.
|
||||
*
|
||||
* See Also:
|
||||
* ECMA-262 v9, 20.3.1.7
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when
|
||||
* JERRY_BUILTIN_DATE is set to 1. Otherwise this function is
|
||||
* not used.
|
||||
*
|
||||
* @param unix_ms The unix timestamp we want an offset for, given in
|
||||
* millisecond precision (could be now, in the future,
|
||||
* or in the past). As with all unix timestamps, 0 refers to
|
||||
* 1970-01-01, a day is exactly 86 400 000 milliseconds, and
|
||||
* leap seconds cause the same second to occur twice.
|
||||
* @param is_utc Is the given timestamp in UTC time? If false, it is in local
|
||||
* time.
|
||||
*
|
||||
* @return milliseconds between local time and UTC for the given timestamp,
|
||||
* if available
|
||||
*. 0 if not available / we are in UTC.
|
||||
*/
|
||||
double jerry_port_get_local_time_zone_adjustment (double unix_ms, bool is_utc);
|
||||
|
||||
/**
|
||||
* Get system time
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when
|
||||
* JERRY_BUILTIN_DATE is set to 1. It is also common practice
|
||||
* in application code to use this function for the initialization of the
|
||||
* random number generator.
|
||||
*
|
||||
* @return milliseconds since Unix epoch
|
||||
*/
|
||||
double jerry_port_get_current_time (void);
|
||||
```
|
||||
|
||||
## External context
|
||||
|
||||
Allow user to provide external buffer for isolated engine contexts, so that user
|
||||
can configure the heap size at runtime and run multiple JS applications
|
||||
simultaneously.
|
||||
|
||||
```c
|
||||
/**
|
||||
* Get the current context of the engine. Each port should provide its own
|
||||
* implementation of this interface.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when
|
||||
* JERRY_EXTERNAL_CONTEXT is enabled. Otherwise this function is not
|
||||
* used.
|
||||
*
|
||||
* @return the pointer to the engine context.
|
||||
*/
|
||||
struct jerry_context_t *jerry_port_get_current_context (void);
|
||||
```
|
||||
|
||||
## Sleep
|
||||
|
||||
```c
|
||||
/**
|
||||
* Makes the process sleep for a given time.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when JERRY_DEBUGGER is set to 1.
|
||||
* Otherwise this function is not used.
|
||||
*
|
||||
* @param sleep_time milliseconds to sleep.
|
||||
*/
|
||||
void jerry_port_sleep (uint32_t sleep_time);
|
||||
```
|
||||
|
||||
# How to port JerryScript
|
||||
|
||||
This section describes a basic port implementation which was created for Unix based systems.
|
||||
|
||||
## Termination
|
||||
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
/**
|
||||
* Default implementation of jerry_port_fatal.
|
||||
*/
|
||||
void jerry_port_fatal (jerry_fatal_code_t code)
|
||||
{
|
||||
exit (code);
|
||||
} /* jerry_port_fatal */
|
||||
```
|
||||
|
||||
## I/O
|
||||
|
||||
```c
|
||||
#include <stdarg.h>
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
/**
|
||||
* Provide log message implementation for the engine.
|
||||
*
|
||||
* Note:
|
||||
* This example ignores the log level.
|
||||
*/
|
||||
void
|
||||
jerry_port_log (jerry_log_level_t level, /**< log level */
|
||||
const char *format, /**< format string */
|
||||
...) /**< parameters */
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
} /* jerry_port_log */
|
||||
```
|
||||
|
||||
```c
|
||||
/**
|
||||
* Print a character to stdout with putchar.
|
||||
*/
|
||||
void
|
||||
jerry_port_print_char (char c)
|
||||
{
|
||||
putchar (c);
|
||||
} /* jerr_port_print_char */
|
||||
```
|
||||
|
||||
## Date
|
||||
|
||||
```c
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
/**
|
||||
* Default implementation of jerry_port_get_local_time_zone_adjustment.
|
||||
*/
|
||||
double jerry_port_get_local_time_zone_adjustment (double unix_ms, /**< ms since unix epoch */
|
||||
bool is_utc) /**< is the time above in UTC? */
|
||||
{
|
||||
struct tm tm;
|
||||
time_t now = (time_t) (unix_ms / 1000);
|
||||
localtime_r (&now, &tm);
|
||||
if (!is_utc)
|
||||
{
|
||||
now -= tm.tm_gmtoff;
|
||||
localtime_r (&now, &tm);
|
||||
}
|
||||
return ((double) tm.tm_gmtoff) * 1000;
|
||||
} /* jerry_port_get_local_time_zone_adjustment */
|
||||
|
||||
/**
|
||||
* Default implementation of jerry_port_get_current_time.
|
||||
*/
|
||||
double jerry_port_get_current_time (void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (gettimeofday (&tv, NULL) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((double) tv.tv_sec) * 1000.0 + ((double) tv.tv_usec) / 1000.0;
|
||||
} /* jerry_port_get_current_time */
|
||||
```
|
||||
|
||||
## External context
|
||||
|
||||
```c
|
||||
#include "jerryscript-port.h"
|
||||
#include "jerryscript-port-default.h"
|
||||
|
||||
/**
|
||||
* Pointer to the current context.
|
||||
* Note that it is a global variable, and is not a thread safe implementation.
|
||||
*/
|
||||
static jerry_context_t *current_context_p = NULL;
|
||||
|
||||
/**
|
||||
* Set the current_context_p as the passed pointer.
|
||||
*/
|
||||
void
|
||||
jerry_port_default_set_current_context (jerry_context_t *context_p) /**< points to the created context */
|
||||
{
|
||||
current_context_p = context_p;
|
||||
} /* jerry_port_default_set_current_context */
|
||||
|
||||
/**
|
||||
* Get the current context.
|
||||
*
|
||||
* @return the pointer to the current context
|
||||
*/
|
||||
jerry_context_t *
|
||||
jerry_port_get_current_context (void)
|
||||
{
|
||||
return current_context_p;
|
||||
} /* jerry_port_get_current_context */
|
||||
```
|
||||
|
||||
## Sleep
|
||||
|
||||
```c
|
||||
#include "jerryscript-port.h"
|
||||
#include "jerryscript-port-default.h"
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#elif defined (HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_TIME_H */
|
||||
|
||||
#if defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1)
|
||||
void jerry_port_sleep (uint32_t sleep_time)
|
||||
{
|
||||
#ifdef HAVE_TIME_H
|
||||
nanosleep (&(const struct timespec)
|
||||
{
|
||||
(time_t) sleep_time / 1000, ((long int) sleep_time % 1000) * 1000000L /* Seconds, nanoseconds */
|
||||
}
|
||||
, NULL);
|
||||
#elif defined (HAVE_UNISTD_H)
|
||||
usleep ((useconds_t) sleep_time * 1000);
|
||||
#endif /* HAVE_TIME_H */
|
||||
(void) sleep_time;
|
||||
} /* jerry_port_sleep */
|
||||
#endif /* defined (JERRY_DEBUGGER) && (JERRY_DEBUGGER == 1) */
|
||||
```
|
||||
|
||||
## Promise
|
||||
|
||||
```c
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
/**
|
||||
* Default implementation of jerry_port_track_promise_rejection.
|
||||
* Prints the reason of the unhandled rejections.
|
||||
*/
|
||||
void
|
||||
jerry_port_track_promise_rejection (const jerry_value_t promise, /**< rejected promise */
|
||||
const jerry_promise_rejection_operation_t operation) /**< operation */
|
||||
{
|
||||
(void) operation; /* unused */
|
||||
|
||||
jerry_value_t reason = jerry_get_promise_result (promise);
|
||||
jerry_value_t reason_to_string = jerry_value_to_string (reason);
|
||||
jerry_size_t req_sz = jerry_get_utf8_string_size (reason_to_string);
|
||||
jerry_char_t str_buf_p[req_sz + 1];
|
||||
jerry_string_to_utf8_char_buffer (reason_to_string, str_buf_p, req_sz);
|
||||
str_buf_p[req_sz] = '\0';
|
||||
|
||||
jerry_release_value (reason_to_string);
|
||||
jerry_release_value (reason);
|
||||
|
||||
printf ("Uncaught (in promise) %s\n", str_buf_p);
|
||||
} /* jerry_port_track_promise_rejection */
|
||||
```
|
|
@ -0,0 +1,176 @@
|
|||
## Reference counting in JerryScript
|
||||
|
||||
In JerryScript all `jerry_value_t` values are independent
|
||||
references to internal objects. Values returned by JerryScript
|
||||
API functions are always live references and must be released
|
||||
by `jerry_release_value`.
|
||||
|
||||
```c
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
/* The value stored in the 'global' variable contains a live
|
||||
* reference to the global object. The system also keeps its
|
||||
* own live reference to the global object. These two references
|
||||
* are independent, and both must be destroyed before the global
|
||||
* object can be freed. */
|
||||
|
||||
jerry_release_value (global);
|
||||
|
||||
/* Without jerry_release_value() the global object will not
|
||||
* be freed even by jerry_cleanup(). After the reference
|
||||
* is released it becomes a dead reference and cannot be
|
||||
* used anymore. */
|
||||
```
|
||||
|
||||
Multiple references might refer to the same internal object
|
||||
even though their `jerry_value_t` representation might be different.
|
||||
|
||||
```c
|
||||
jerry_value_t pi_ref1 = jerry_create_number (3.14);
|
||||
jerry_value_t pi_ref2 = jerry_acquire_value (pi_ref1);
|
||||
|
||||
/* Both pi_ref1 and pi_ref2 refer to the same 3.14 value
|
||||
* although they might not be equal in C (pi_ref1 != pi_ref2). */
|
||||
|
||||
/* Both references must be released. */
|
||||
jerry_release_value (pi_ref1);
|
||||
jerry_release_value (pi_ref2);
|
||||
```
|
||||
|
||||
Releasing the same `jerry_value_t` twice to release two live
|
||||
references is not allowed and it might cause crashes. Hence the
|
||||
following code is an **INCORRECT WAY** of releasing the 3.14 value.
|
||||
|
||||
```c
|
||||
jerry_release_value (pi_ref1);
|
||||
jerry_release_value (pi_ref1);
|
||||
```
|
||||
|
||||
JerryScript API functions returning with a `jerry_value_t` always
|
||||
return with a new live reference. Passing a `jerry_value_t` to
|
||||
an API function never releases its reference (unless explicitly
|
||||
stated in the documentation). The next example shows this
|
||||
behaviour through property getting and setting.
|
||||
|
||||
```c
|
||||
jerry_value_t prop_value = jerry_get_property (...);
|
||||
|
||||
/* The prop_value must be released later because both the base
|
||||
* object and the prop_value have an independent reference to
|
||||
* the same JavaScript value. When the operation fails, the
|
||||
* prop_value contains a live reference to an error object.
|
||||
* This reference must be released as well. */
|
||||
|
||||
if (jerry_value_is_error (prop_value))
|
||||
{
|
||||
/* Errors can be handled here. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The application has a live reference to the property
|
||||
* value even if the base object is freed by the garbage
|
||||
* collector. */
|
||||
}
|
||||
|
||||
/* The prop_value must be released. */
|
||||
jerry_release_value (prop_value);
|
||||
|
||||
/* Property setting is the same. */
|
||||
|
||||
jerry_value_t new_prop_value = jerry_create_number (2.718);
|
||||
jerry_value_t result = jerry_set_property (..., new_prop_value);
|
||||
|
||||
/* If the property set is successful, a new reference is created
|
||||
* for the value referenced by new_prop_value. The new_prop_value
|
||||
* reference must be released regardless of whether the operation
|
||||
* is successful. */
|
||||
|
||||
/* The new_prop_value can be passed to other JerryScript API
|
||||
* functions before the jerry_release_value () call. */
|
||||
|
||||
jerry_release_value (new_prop_value);
|
||||
|
||||
/* The reference stored in the 'result' variable is live whether
|
||||
* the operation is successful or not, and must also be freed. */
|
||||
|
||||
if (jerry_value_is_error (result))
|
||||
{
|
||||
/* Errors can be handled here. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A reference to a true primitive value is returned. */
|
||||
}
|
||||
|
||||
jerry_release_value (result);
|
||||
```
|
||||
|
||||
The simplest form of setting a property without error checking
|
||||
is the following:
|
||||
|
||||
```c
|
||||
/* There are no 'ifs' in this snippet. */
|
||||
jerry_release_value (jerry_set_property (..., new_prop_value));
|
||||
jerry_release_value (new_prop_value);
|
||||
```
|
||||
|
||||
The reference returned by a `jerry_external_handler_t` callback
|
||||
transfers the ownership of the live reference. Otherwise the
|
||||
referenced object could be freed by the garbage collector.
|
||||
|
||||
```c
|
||||
jerry_value_t my_external_handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_count
|
||||
{
|
||||
/* Do not release function_obj, this_val, and args_p because
|
||||
* these references are automatically released after the handler
|
||||
* is returned. This approach reduces code size which is useful
|
||||
* on embedded systems. However you can create other references
|
||||
* to them by calling jerry_acquire_value () if needed. */
|
||||
|
||||
/* Since the ownership of the reference is transferred to the
|
||||
* caller the following snippet is valid. */
|
||||
|
||||
/* If the value to be returned is needed for other purposes the
|
||||
* jerry_acquire_value () can be used to create new references. */
|
||||
return jerry_create_string (...);
|
||||
}
|
||||
```
|
||||
|
||||
Duplicating a `jerry_value_t` in C does not create another live reference.
|
||||
|
||||
```c
|
||||
jerry_value_t undef = jerry_create_undefined ();
|
||||
jerry_value_t undef2 = undef;
|
||||
|
||||
/* Releasing either undef or undef2 is valid but not both.
|
||||
* After the release both references become dead (invalid). */
|
||||
jerry_release_value (undef2);
|
||||
|
||||
/* Dead references can be reassigned again. */
|
||||
undef = jerry_create_boolean (true);
|
||||
```
|
||||
|
||||
References can be duplicated in C as long as only one of them is freed.
|
||||
|
||||
```c
|
||||
jerry_value_t a = jerry_create_boolean (true);
|
||||
|
||||
jerry_value_t b = a;
|
||||
jerry_value_t c = a;
|
||||
|
||||
/* A new reference is assigned to 'a'. */
|
||||
a = jerry_create_boolean (false);
|
||||
|
||||
[...]
|
||||
|
||||
jerry_release_value (a);
|
||||
/* The 'a' (boolean false) reference becomes dead (invalid). */
|
||||
|
||||
jerry_release_value (c);
|
||||
/* Both 'b' and 'c' (boolean true) references become dead. */
|
||||
|
||||
/* Since all references are released, no memory leak occurs. */
|
||||
```
|
|
@ -0,0 +1,443 @@
|
|||
## JerryScript debugger interface
|
||||
|
||||
JerryScript provides a remote debugger which allows debugging
|
||||
JavaScript programs. The debugger has two main components:
|
||||
a server which is part of the JerryScript binary and a
|
||||
separate client application. Currently a Python-based debugger
|
||||
client is available in the /jerry-debugger subdirectory.
|
||||
This simple application demonstrates the communication protocol
|
||||
between the client and server, and can be reused by integrated
|
||||
development environments.
|
||||
|
||||
## Setting up the debugger server
|
||||
|
||||
The following arguments must be passed to `tools/build.py`:
|
||||
|
||||
`--jerry-debugger=on`
|
||||
|
||||
The transport layer of the communication protocol is pluggable.
|
||||
At the moment, a WebSocket-based implementation is provided as a
|
||||
JerryScript extension, which transmits messages over TCP/IP networks.
|
||||
If necessary/implemented, any reliable stream or datagram based
|
||||
protocol can be used for transmitting debugger messages.
|
||||
|
||||
## Debugging JavaScript applications
|
||||
|
||||
The debugger client must be connected to the server before the
|
||||
JavaScript application runs. On-the-fly attachment is supported
|
||||
for more than one file, right after the engine initialization
|
||||
(this feature is available with the python client). The debugging
|
||||
information (e.g. line index of each possible breakpoint location)
|
||||
is not preserved by JerryScript. The client is expected to be run
|
||||
on a system with much more resources and it should be capable of
|
||||
storing this information. JerryScript frees all debug information
|
||||
after it is transmitted to the client to save memory.
|
||||
|
||||
The following argument makes JerryScript wait for a client
|
||||
connection:
|
||||
|
||||
`--start-debug-server`
|
||||
|
||||
The following argument makes JerryScript wait for a client
|
||||
source code:
|
||||
|
||||
`--debugger-wait-source`
|
||||
|
||||
It is also recommended to increase the log level to see
|
||||
the *Waiting for client connection* message:
|
||||
|
||||
`--log-level 2`
|
||||
|
||||
The Python client can connect to the server by specifying its
|
||||
IP address on the command line. The address can be localhost
|
||||
if the server and the client are running on the same machine.
|
||||
|
||||
After the connection is established the execution can be
|
||||
controlled by the debugger. The debugger always stops at
|
||||
the first possible breakpoint location. The effect is the
|
||||
same as using the `stop` command. This allows inserting
|
||||
breakpoints right before the meaningful part of the execution
|
||||
starts.
|
||||
|
||||
All available commands of the client can be queried by the
|
||||
`help` command.
|
||||
|
||||
## Integrating debugger support into applications using JerryScript
|
||||
|
||||
When using the extension-provided WebSocket transport layer, the
|
||||
debugger can be enabled by calling `jerryx_debugger_after_connect
|
||||
(jerryx_debugger_tcp_create (debug_port) && jerryx_debugger_ws_create ())`
|
||||
after the `jerry_init ()` function. It initializes the debugger and
|
||||
blocks until a client connects.
|
||||
(Custom transport layers may be implemented and initialized similarly.
|
||||
Currently, `jerryx_debugger_rp_create ()` for raw packet transport layer and
|
||||
`jerryx_debugger_serial_create (const char* config)` for serial protocol
|
||||
are also available.)
|
||||
|
||||
The resource name provided to `jerry_parse ()` is used by the client
|
||||
to identify the resource name of the source code. This resource name
|
||||
is usually a file name.
|
||||
|
||||
## JerryScript debugger C-API interface
|
||||
|
||||
The following section describes the debugger functions
|
||||
available to the host application.
|
||||
|
||||
## JerryScript debugger types
|
||||
|
||||
## jerry_debugger_wait_for_source_callback_t
|
||||
|
||||
**Summary**
|
||||
|
||||
This callback function is called by
|
||||
[jerry_debugger_wait_for_client_source](#jerry_debugger_wait_for_client_source)
|
||||
when a source code is received successfully.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef jerry_value_t
|
||||
(*jerry_debugger_wait_for_source_callback_t) (const jerry_char_t *resource_name_p,
|
||||
size_t resource_name_size,
|
||||
const jerry_char_t *source_p,
|
||||
size_t source_size, void *user_p);
|
||||
```
|
||||
|
||||
- `resource_name_p` - resource (usually a file) name of the source code
|
||||
- `resource_name_size` - size of resource name
|
||||
- `source_p` - source code character data
|
||||
- `source_size` - size of source code
|
||||
- `user_p` - custom pointer passed to [jerry_debugger_wait_for_client_source](#jerry_debugger_wait_for_client_source)
|
||||
|
||||
|
||||
## JerryScript debugger functions
|
||||
|
||||
### jerry_debugger_is_connected
|
||||
|
||||
**Summary**
|
||||
|
||||
Returns true if a remote debugger client is connected.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool
|
||||
jerry_debugger_is_connected (void);
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
if (jerry_debugger_is_connected ())
|
||||
{
|
||||
printf ("A remote debugger client is connected.");
|
||||
}
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_debugger_stop
|
||||
|
||||
**Summary**
|
||||
|
||||
Stops execution at the next available breakpoint if a remote
|
||||
debugger client is connected and the engine is not waiting at
|
||||
a breakpoint. The engine will stop regardless the breakpoint
|
||||
is enabled or not.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_debugger_stop (void)
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
jerry_debugger_stop ();
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_debugger_continue](#jerry_debugger_continue)
|
||||
|
||||
### jerry_debugger_continue
|
||||
|
||||
**Summary**
|
||||
|
||||
If the engine would stop at the next available breakpoint it
|
||||
cancels this effect. The engine will still stop at enabled
|
||||
breakpoints. This function effectively negates the effect of
|
||||
[jerry_debugger_stop ()](#jerry_debugger_stop) calls or stop
|
||||
requests issued by the debugger client.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_debugger_continue (void)
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
jerry_debugger_continue ();
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_debugger_stop](#jerry_debugger_stop)
|
||||
|
||||
### jerry_debugger_stop_at_breakpoint
|
||||
|
||||
**Summary**
|
||||
|
||||
Enables or disables stopping at breakpoints. When stopping is
|
||||
disabled all breakpoints are ignored including user enabled
|
||||
breakpoints. This allows hidden execution of ECMAScript code.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_debugger_stop_at_breakpoint (bool enable_stop_at_breakpoint)
|
||||
```
|
||||
|
||||
- `enable_stop_at_breakpoint` - enable (=`true`) or disable (=`false`) stopping at breakpoints
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
jerry_debugger_stop_at_breakpoint (true);
|
||||
|
||||
// Protected execution of JavaScript code.
|
||||
const jerry_char_t script[] = "42";
|
||||
jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
|
||||
|
||||
jerry_debugger_stop_at_breakpoint (false);
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_debugger_wait_for_client_source
|
||||
|
||||
**Summary**
|
||||
|
||||
Asks the client to provide the next source code. The function
|
||||
waits until the whole source code is received. As a reply the
|
||||
the client may request a context reset or notify that no more
|
||||
source is available. These notifications are passed back as the
|
||||
return value of the function.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_debugger_wait_for_source_status_t
|
||||
jerry_debugger_wait_for_client_source (jerry_debugger_wait_for_source_callback_t callback_p,
|
||||
void *user_p, jerry_value_t *return_value)
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
/**
|
||||
* Runs the source code received by jerry_debugger_wait_for_client_source.
|
||||
*/
|
||||
static jerry_value_t
|
||||
wait_for_source_callback (const jerry_char_t *resource_name_p, /**< resource name */
|
||||
size_t resource_name_size, /**< size of resource name */
|
||||
const jerry_char_t *source_p, /**< source code */
|
||||
size_t source_size, /**< source code size */
|
||||
void *user_p /**< user pointer */)
|
||||
{
|
||||
(void) user_p;
|
||||
|
||||
jerry_value_t ret_val = jerry_parse (resource_name_p,
|
||||
resource_name_size,
|
||||
source_p,
|
||||
source_size,
|
||||
JERRY_PARSE_NO_OPTS);
|
||||
|
||||
if (!jerry_value_is_error (ret_val))
|
||||
{
|
||||
jerry_value_t func_val = ret_val;
|
||||
ret_val = jerry_run (func_val);
|
||||
jerry_release_value (func_val);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
} /* wait_for_source_callback */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_debugger_wait_for_source_status_t receive_status;
|
||||
|
||||
do
|
||||
{
|
||||
/* Create a new JerryScript instance when a context reset is
|
||||
* received. Applications usually registers their core bindings
|
||||
* here as well (e.g. print, setTimeout). */
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
do
|
||||
{
|
||||
jerry_value_t run_result;
|
||||
|
||||
receive_status = jerry_debugger_wait_for_client_source (wait_for_source_callback,
|
||||
NULL,
|
||||
&run_result);
|
||||
|
||||
jerry_release_value (run_result);
|
||||
}
|
||||
while (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVED);
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
while (receive_status == JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED);
|
||||
|
||||
if (receive_status == JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED)
|
||||
{
|
||||
// Handle the failure (e.g. display an error).
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_debugger_send_output
|
||||
|
||||
**Summary**
|
||||
|
||||
Sends the program's output to the debugger client.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_debugger_send_output (const jerry_char_t *buffer, jerry_size_t string_size)
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
jerry_char_t my_output[] = "Hey, this should be sent too!";
|
||||
jerry_size_t my_output_size = sizeof (my_output);
|
||||
|
||||
jerry_debugger_send_output (my_output, my_output_size);
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_debugger_send_log
|
||||
|
||||
**Summary**
|
||||
|
||||
Sends the program's log to the debugger client.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_debugger_send_log (jerry_log_level_t level, const jerry_char_t *buffer, jerry_size_t string_size)
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="link")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/debugger.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerryx_debugger_after_connect (jerryx_debugger_tcp_create (5001)
|
||||
&& jerryx_debugger_ws_create ());
|
||||
|
||||
jerry_char_t my_log[] = "Custom diagnostics";
|
||||
jerry_size_t my_log_size = sizeof (my_log);
|
||||
|
||||
jerry_debugger_send_log (JERRY_LOG_LEVEL_DEBUG, my_log, my_log_size);
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
|
@ -0,0 +1,803 @@
|
|||
# JerryScript Coding Standards
|
||||
|
||||
This text is a brief overview of JerryScript Coding Standards.
|
||||
Each rule starts with a short description followed by several
|
||||
examples. We believe examples are better than long explanations.
|
||||
Please follow these guidelines when you submit a patch for
|
||||
review.
|
||||
|
||||
## General rules
|
||||
|
||||
* Indentation is two spaces.
|
||||
* Tab characters are not allowed.
|
||||
* Maximum line length is 120 characters (excluding newline).
|
||||
* No trailing white space is allowed.
|
||||
* Run `tools/run-tests.py --check-vera` to check several
|
||||
of the coding conventions automatically.
|
||||
|
||||
## Comments
|
||||
|
||||
Only block comments (`/* */`) are allowed in JerryScript.
|
||||
Comments should be complete sentences (e.g. start with an
|
||||
upper case letter), except for return value, field and
|
||||
argument descriptions (see the exceptions below). The
|
||||
text part of a comment should focus on explaining *why*
|
||||
the code is doing something rather than *what* the code
|
||||
is doing.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
/* A perfect comment. */
|
||||
|
||||
/* A perfect multiline
|
||||
* comment. Each line should
|
||||
* start with an asterisk. */
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
// Double slash comments are not allowed.
|
||||
|
||||
/* not a complete sentence */
|
||||
|
||||
/* A bad mulitiline
|
||||
comment. */
|
||||
```
|
||||
|
||||
All types, constants and functions require a description in
|
||||
JerryScript. These comments should start with `/**`. The starting
|
||||
`/**` and ending `*/` must be on separate lines.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
/**
|
||||
* A correct description.
|
||||
*/
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
/** An incorrect description. */
|
||||
```
|
||||
|
||||
## Preprocessor defines
|
||||
|
||||
The name of a preprocessor macro must be an uppercase string
|
||||
and these macros must be preceded by a description.
|
||||
Abbreviations are allowed but not preferred in new code.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
/**
|
||||
* Short description about the constant.
|
||||
*/
|
||||
#define JERRY_VALUE_SEVEN 7
|
||||
|
||||
/**
|
||||
* Short description about the macro function.
|
||||
*/
|
||||
#define JERRY_ADD_TWO_NUMBERS(arg1, arg2) \
|
||||
((arg1) + (arg2))
|
||||
|
||||
/**
|
||||
* Although this is correct, a reviewer might request
|
||||
* to change NUMS to NUMBERS. Hence it is recommended
|
||||
* to use NUMBERS in the first place.
|
||||
*/
|
||||
#define JERRY_ADD_TWO_NUMS(arg1, arg2) \
|
||||
((arg1) + (arg2))
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
#define JERRY_CONSTANT_WITHOUT_DESCRIPTION 5
|
||||
|
||||
#define JeRrY_mIxEd_CaSe_NaMe "str"
|
||||
```
|
||||
|
||||
## Conditional preprocessor directives
|
||||
|
||||
A comment is required after `#else` and `#endif` in JerryScript.
|
||||
The defined keyword should be omitted from these comments.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
#ifdef JERRY_A
|
||||
|
||||
#else /* !JERRY_A */
|
||||
|
||||
#endif /* JERRY_A */
|
||||
|
||||
#ifdef JERRY_A
|
||||
#if defined JERRY_B && defined JERRY_C && (JERRY_C > 6)
|
||||
|
||||
#else /* !(JERRY_B && JERRY_C && (JERRY_C > 6)) */
|
||||
|
||||
#endif /* JERRY_B && JERRY_C && (JERRY_C > 6) */
|
||||
#endif /* JERRY_A */
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
#ifdef JERRY_A
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef JERRY_A
|
||||
|
||||
#endif /* defined JERRY_A */
|
||||
|
||||
#ifdef JERRY_B
|
||||
/* Missing comment after else. */
|
||||
#else
|
||||
|
||||
#endif /* JERRY_B */
|
||||
```
|
||||
|
||||
## Code blocks
|
||||
|
||||
Each code block must be enclosed in curly braces even
|
||||
if it is a single line statement. These braces must
|
||||
be on separate lines. There must be a single space
|
||||
before the opening parenthesis of the expression
|
||||
after if/while/switch keywords.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
if (value > 6)
|
||||
{
|
||||
function_call ();
|
||||
}
|
||||
|
||||
if (value > 1)
|
||||
{
|
||||
function_call_a ();
|
||||
}
|
||||
else
|
||||
{
|
||||
function_call_b ();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
function_call ();
|
||||
value++;
|
||||
}
|
||||
while (value < 6);
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case A:
|
||||
{
|
||||
/* FALLTHRU comment is allowed if a
|
||||
* switch-case is not terminated by
|
||||
* break/continue/return. */
|
||||
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case B:
|
||||
case C:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case D:
|
||||
{
|
||||
/* We can use continue if we are in a loop. */
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
if (value > 6)
|
||||
function_call_a ();
|
||||
else
|
||||
function_call_b ();
|
||||
|
||||
if (value > 6) {
|
||||
function_call_a ();
|
||||
}
|
||||
|
||||
if (value > 6) function_call_a ();
|
||||
else { function_call_b (); }
|
||||
|
||||
if
|
||||
(value > 6)
|
||||
{
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case 0: break;
|
||||
default: {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case A:
|
||||
{
|
||||
if (value > 6)
|
||||
{
|
||||
CASE B:
|
||||
{
|
||||
/* This is allowed in C but
|
||||
* not in JerryScript. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
value++;
|
||||
while (value < 5);
|
||||
|
||||
do {
|
||||
value++;
|
||||
} while (value < 5);
|
||||
|
||||
do
|
||||
{
|
||||
value++;
|
||||
} while (value < 5);
|
||||
```
|
||||
|
||||
## Newlines
|
||||
|
||||
A newline in JerryScript is a separator which separates different
|
||||
parts of the source code. Its primary purpose is to improve
|
||||
readability. Unlike other rules developers have some freedom
|
||||
to add newlines to their code. However there are some rules.
|
||||
|
||||
* Only a single newline separator is allowed.
|
||||
* Source files must be terminated by a newline.
|
||||
* Global declarations must be separated by a newline.
|
||||
* Newlines are not allowed after an opening curly brace or before
|
||||
a closing curly brace
|
||||
* No newlines are allowed between control statements (if-else, while,
|
||||
for, switch, etc.) and their code blocks.
|
||||
* There should be a newline after the variable declarations
|
||||
if they are the first statements of a block.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
if (a > 5)
|
||||
{
|
||||
/* Newline must be present after the first
|
||||
* variable declarations of a code block. */
|
||||
int j = a - 1;
|
||||
int k = a * 2;
|
||||
|
||||
return j + k;
|
||||
}
|
||||
|
||||
while (a < 5)
|
||||
{
|
||||
a++;
|
||||
|
||||
/* It is recommended to put a newline after
|
||||
* intermediate variable declarations. */
|
||||
int i = a * 2;
|
||||
|
||||
b = i - 3;
|
||||
}
|
||||
|
||||
/* It is a recommended to put newlines around asserts. */
|
||||
a = b + 5;
|
||||
|
||||
JERRY_ASSERT (a < 20);
|
||||
|
||||
c = a + 7;
|
||||
|
||||
/* It is a good practice to put a newline after a multiline
|
||||
* function call (see Function calls later). */
|
||||
f (a,
|
||||
b,
|
||||
c);
|
||||
|
||||
a = 6;
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
/* No newlines are allowed after an opening curly
|
||||
* brace or before a closing curly brace */
|
||||
|
||||
while (a > 0)
|
||||
{
|
||||
|
||||
a = 6;
|
||||
|
||||
}
|
||||
|
||||
if (a > 5)
|
||||
{
|
||||
while (b < 6)
|
||||
{
|
||||
|
||||
b++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Two or more newlines are not allowed. */
|
||||
a = 6;
|
||||
|
||||
|
||||
b = 7;
|
||||
|
||||
/* No newlines are allowed between control staments
|
||||
* and their code blocks. */
|
||||
|
||||
if (a > 6)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
do
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
while (a < 6);
|
||||
```
|
||||
|
||||
## Expressions
|
||||
|
||||
Spaces are required around binary operators. No space is
|
||||
needed otherwise.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
a = b + c;
|
||||
a = (b + c) << 3;
|
||||
a = b = c + ~d;
|
||||
a += ++c + d++;
|
||||
call_function (a * (b + !!c) - d + (e % f));
|
||||
if (a)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
a=b+c;
|
||||
a = b+c;
|
||||
a += c + ( d );
|
||||
/* Introduce temporary variables or macros
|
||||
* if the expression is too long. Occures rarely.. */
|
||||
a = b
|
||||
+ c;
|
||||
if ( a + b > 0 )
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
## Logical operators
|
||||
|
||||
All expressions with && and || logical operators must be
|
||||
enclosed in parentheses. A single and multiline form is
|
||||
allowed for these expressions. In the latter case each
|
||||
line must start with the logical operator and each line
|
||||
must be aligned to the column right after the opening
|
||||
parenthesis.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
/* Single line form. */
|
||||
a = ((c && d) || (e && f));
|
||||
|
||||
a = (c
|
||||
&& d);
|
||||
|
||||
a = (c
|
||||
&& (d || e)
|
||||
&& f);
|
||||
|
||||
do
|
||||
{
|
||||
}
|
||||
while (a
|
||||
&& b);
|
||||
|
||||
/* This form is rarely used but it is ok. */
|
||||
if (a
|
||||
&& (b
|
||||
|| c
|
||||
|| d)
|
||||
&& e)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
if (a || b ||
|
||||
c)
|
||||
{
|
||||
}
|
||||
|
||||
/* Parentheses are missing. */
|
||||
a = b || c;
|
||||
|
||||
/* Misaligned &&. */
|
||||
if (a
|
||||
&& b)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
## Ternary conditional operators
|
||||
|
||||
A special form of ternary conditional operators are allowed
|
||||
in JerryScript where the ? and : operators are on separate
|
||||
lines in the same column.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
a = (b ? c
|
||||
: d);
|
||||
|
||||
/* Single line form is accepted as well. */
|
||||
a = (b ? c : d);
|
||||
|
||||
/* This form is rarely used but it is ok. */
|
||||
if (a ? b
|
||||
: (c ? d
|
||||
: e))
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
a = b ?
|
||||
c : d;
|
||||
|
||||
while (a ? b
|
||||
: c)
|
||||
{
|
||||
}
|
||||
|
||||
if (a
|
||||
? b
|
||||
: c)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
## Function calls
|
||||
|
||||
There must be a space after the function name. Each argument
|
||||
must be in the same or separated lines. In the former case
|
||||
there must be a space before the next argument and in the
|
||||
latter case all arguments must be aligned to the same column.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
function_a ();
|
||||
function_b (a);
|
||||
function_c (a, b, c);
|
||||
|
||||
function_c (a,
|
||||
b,
|
||||
c);
|
||||
|
||||
function_c (a,
|
||||
b,
|
||||
function_c (a,
|
||||
b,
|
||||
c);
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
/* No space before the opening parenthesis. */
|
||||
function_f();
|
||||
|
||||
function_f (
|
||||
);
|
||||
|
||||
function_g(a);
|
||||
|
||||
function_g
|
||||
(a
|
||||
);
|
||||
|
||||
/* Two arguments on the same line. */
|
||||
function_h (a, b,
|
||||
c);
|
||||
|
||||
function_h (a,
|
||||
b, c);
|
||||
|
||||
/* Misaligned arguments. */
|
||||
function_h (a,
|
||||
b,
|
||||
c);
|
||||
```
|
||||
|
||||
## Variable declarations
|
||||
|
||||
JerryScript is a pure C99 codebase so variable
|
||||
declarations can be anywhere in the code including
|
||||
inside for-loops. It is recommended to declare a
|
||||
variable before the first use.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int j = i + 1;
|
||||
while (j < 10)
|
||||
{
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiline form of for loops. */
|
||||
for (int i = 0;
|
||||
i < 10;
|
||||
i++)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
## Type casting
|
||||
|
||||
There must be a space after the closing parenthesis
|
||||
of the type cast. Type casting has no multiline form
|
||||
in JerryScript.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
int a = (int) double_variable;
|
||||
|
||||
int a = (int) (long) (float) double_variable;
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
/* Wrong spaces. */
|
||||
int a = ( int )double_variable;
|
||||
|
||||
/* No multiline form. */
|
||||
int a = (int)
|
||||
double_variable;
|
||||
```
|
||||
|
||||
## Pointers and asterisk character
|
||||
|
||||
Each pointer in JerryScript must be a lowercase string
|
||||
which is ending with a `_p` suffix. Furthermore there
|
||||
must be a space before the asterisk character.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
int *int_p;
|
||||
|
||||
/* No need to add multiple _p-s for multiple indirections.
|
||||
* It is recommended to avoid these constructs using typedef
|
||||
* declarations. A reviewer might request such a change. */
|
||||
int ***int_p;
|
||||
|
||||
/* This rule applies for type casting as well. */
|
||||
char = *(char *) type_p;
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
/* No _p after the name. */
|
||||
int *ptr;
|
||||
|
||||
/* Wrong asterisk position. */
|
||||
int* ptr_p;
|
||||
|
||||
char_p = * (char*)type_p;
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
Each type in JerryScript must be a lowercase string
|
||||
which ends with a `_t` suffix. Furthermore each type
|
||||
declaration must be preceded by a short description
|
||||
of the type and each field must have a short description
|
||||
as well.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
/**
|
||||
* Short description of the following structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* Field descriptions do not start with capital letters
|
||||
* and there is no full stop at the end. */
|
||||
field1_t field1; /**< description of field 1 */
|
||||
field2_t field2; /**< description of field 2 */
|
||||
|
||||
field_n_t field_n; /**< description of field n */
|
||||
} structure_name_t;
|
||||
|
||||
/**
|
||||
* Another integer type.
|
||||
*/
|
||||
typedef int jerry_int;
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
field_t field_without_description;
|
||||
} structure_without_description_t;
|
||||
|
||||
typedef struct { int a; } single_line_struct;
|
||||
|
||||
typedef
|
||||
union {
|
||||
}
|
||||
wrong_newlines_t;
|
||||
|
||||
/*
|
||||
* Bad comment format.
|
||||
*/
|
||||
typedef
|
||||
char wrong_newlines_again_t;
|
||||
```
|
||||
|
||||
### Type usage conventions
|
||||
|
||||
- Passing the number of arguments for a function call is always `uint32_t`
|
||||
- String size/length/position related operation should use `lit_utf8_size_t`
|
||||
- Extended objects internal fields must be `uint32_t`
|
||||
|
||||
## Function declarations
|
||||
|
||||
Function declarations in JerryScript are verbose but this format
|
||||
reduces the maintenance cost and allows faster understanding of
|
||||
the code.
|
||||
|
||||
```diff
|
||||
+++ Good +++
|
||||
```
|
||||
|
||||
```c
|
||||
/**
|
||||
* Short overview about the purpose of this function.
|
||||
*
|
||||
* A more detailed explanation if needed.
|
||||
*
|
||||
* Note:
|
||||
* Extra notes if needed.
|
||||
*
|
||||
* @return short description about the value
|
||||
* returned by the function
|
||||
*/
|
||||
return_value_type_t
|
||||
function_name (argument1, /**< description of argument1 */
|
||||
argument2, /**< description of argument2 */
|
||||
...
|
||||
argument_n, /**< description of argument n */
|
||||
{
|
||||
|
||||
/* Function body. */
|
||||
|
||||
} /* function_name */
|
||||
```
|
||||
|
||||
```diff
|
||||
--- Bad ---
|
||||
```
|
||||
|
||||
```c
|
||||
static int
|
||||
print (char *text) /**< description of text argument */
|
||||
{
|
||||
/* Missing comment before the function. */
|
||||
} /* print */
|
||||
|
||||
/**
|
||||
* Prints the text received by the function.
|
||||
*
|
||||
* @return number of characters printed by the function
|
||||
*/
|
||||
int print(char *text)
|
||||
{
|
||||
/* No description of text argument. */
|
||||
/* Missing comment at the end of the function. */
|
||||
}
|
||||
```
|
|
@ -0,0 +1,855 @@
|
|||
# jerryx_arg types
|
||||
|
||||
## jerryx_arg_t
|
||||
|
||||
**Summary**
|
||||
|
||||
The structure defining a single validation/transformation step.
|
||||
|
||||
*Note*: For commonly used validators, `arg.h` provides helpers to create the `jerryx_arg_t`s.
|
||||
For example, `jerryx_arg_number ()`, `jerryx_arg_boolean ()`, etc.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
/** the transform function */
|
||||
jerryx_arg_transform_func_t func;
|
||||
/** pointer to destination where func should store the result */
|
||||
void *dest;
|
||||
/** extra information, specific to func */
|
||||
uintptr_t extra_info;
|
||||
} jerryx_arg_t;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_number](#jerryx_arg_number)
|
||||
- [jerryx_arg_boolean](#jerryx_arg_boolean)
|
||||
- [jerryx_arg_string](#jerryx_arg_string)
|
||||
- [jerryx_arg_utf8_string](#jerryx_arg_utf8_string)
|
||||
- [jerryx_arg_function](#jerryx_arg_function)
|
||||
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
||||
- [jerryx_arg_ignore](#jerryx_arg_ignore)
|
||||
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||
|
||||
## jerryx_arg_object_props_t
|
||||
|
||||
**Summary**
|
||||
|
||||
The structure is used in `jerryx_arg_object_properties`. It provides the properties' names,
|
||||
its corresponding JS-to-C mapping and other related information.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
const jerry_char_t **name_p; /**< property name list of the JS object */
|
||||
jerry_length_t name_cnt; /**< count of the name list */
|
||||
const jerryx_arg_t *c_arg_p; /**< points to the array of transformation steps */
|
||||
jerry_length_t c_arg_cnt; /**< the count of the `c_arg_p` array */
|
||||
} jerryx_arg_object_props_t;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||
|
||||
## jerryx_arg_array_items_t
|
||||
|
||||
**Summary**
|
||||
|
||||
The structure is used in `jerryx_arg_array`. It provides the array items' corresponding
|
||||
JS-to-C mappings and count.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
const jerryx_arg_t *c_arg_p; /**< points to the array of transformation steps */
|
||||
jerry_length_t c_arg_cnt; /**< the count of the `c_arg_p` array */
|
||||
} jerryx_arg_array_items_t;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_array](#jerryx_arg_array)
|
||||
|
||||
## jerryx_arg_transform_func_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Signature of the transform function.
|
||||
|
||||
Users can create custom transformations by implementing a transform function
|
||||
and using `jerryx_arg_custom ()`.
|
||||
|
||||
The function is expected to return `undefined` if it ran successfully or
|
||||
return an `Error` in case it failed. The function can use the iterator and the
|
||||
helpers `jerryx_arg_js_iterator_pop ()` and `jerryx_arg_js_iterator_peek ()` to
|
||||
get the next input value.
|
||||
|
||||
*Note*: A transform function is allowed to consume any number of input values!
|
||||
This enables complex validation like handling different JS function signatures,
|
||||
mapping multiple input arguments to a C struct, etc.
|
||||
|
||||
The function is expected to store the result of
|
||||
a successful transformation into `c_arg_p->dest`. In case the validation did
|
||||
not pass, the transform should not modify `c_arg_p->dest`.
|
||||
|
||||
Additional parameters can be provided to the function through `c_arg_p->extra_info`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef jerry_value_t (*jerryx_arg_transform_func_t) (jerryx_arg_js_iterator_t *js_arg_iter_p,
|
||||
const jerryx_arg_t *c_arg_p);
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_custom](#jerryx_arg_custom)
|
||||
- [jerryx_arg_js_iterator_pop](#jerryx_arg_js_iterator_pop)
|
||||
- [jerryx_arg_js_iterator_peek](#jerryx_arg_js_iterator_peek)
|
||||
|
||||
|
||||
## jerryx_arg_coerce_t
|
||||
|
||||
Enum that indicates whether an argument is allowed to be coerced into the expected JS type.
|
||||
|
||||
- JERRYX_ARG_COERCE - the transform will invoke toNumber, toBoolean, toString, etc.
|
||||
- JERRYX_ARG_NO_COERCE - the type coercion is not allowed. The transform will fail if the type does not match the expectation.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_number](#jerryx_arg_number)
|
||||
- [jerryx_arg_boolean](#jerryx_arg_boolean)
|
||||
- [jerryx_arg_string](#jerryx_arg_string)
|
||||
|
||||
## jerryx_arg_optional_t
|
||||
|
||||
Enum that indicates whether an argument is optional or required.
|
||||
|
||||
- JERRYX_ARG_OPTIONAL - The argument is optional. If the argument is `undefined` the transform is successful and `c_arg_p->dest` remains untouched.
|
||||
- JERRYX_ARG_REQUIRED - The argument is required. If the argument is `undefined` the transform will fail and `c_arg_p->dest` remains untouched.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_number](#jerryx_arg_number)
|
||||
- [jerryx_arg_boolean](#jerryx_arg_boolean)
|
||||
- [jerryx_arg_string](#jerryx_arg_string)
|
||||
- [jerryx_arg_function](#jerryx_arg_function)
|
||||
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
||||
|
||||
## jerryx_arg_round_t
|
||||
|
||||
Enum that indicates the rounding policy which will be chosen to transform an integer.
|
||||
|
||||
- JERRYX_ARG_ROUND - use round() method.
|
||||
- JERRYX_ARG_FLOOR - use floor() method.
|
||||
- JERRYX_ARG_CEIL - use ceil() method.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_uint8](#jerryx_arg_uint8)
|
||||
- [jerryx_arg_uint16](#jerryx_arg_uint16)
|
||||
- [jerryx_arg_uint32](#jerryx_arg_uint32)
|
||||
- [jerryx_arg_int8](#jerryx_arg_int8)
|
||||
- [jerryx_arg_int16](#jerryx_arg_int16)
|
||||
- [jerryx_arg_int32](#jerryx_arg_int32)
|
||||
|
||||
|
||||
## jerryx_arg_clamp_t
|
||||
|
||||
Indicates the clamping policy which will be chosen to transform an integer.
|
||||
If the policy is NO_CLAMP, and the number is out of range,
|
||||
then the transformer will throw a range error.
|
||||
|
||||
- JERRYX_ARG_CLAMP - clamp the number when it is out of range
|
||||
- JERRYX_ARG_NO_CLAMP - throw a range error
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_uint8](#jerryx_arg_uint8)
|
||||
- [jerryx_arg_uint16](#jerryx_arg_uint16)
|
||||
- [jerryx_arg_uint32](#jerryx_arg_uint32)
|
||||
- [jerryx_arg_int8](#jerryx_arg_int8)
|
||||
- [jerryx_arg_int16](#jerryx_arg_int16)
|
||||
- [jerryx_arg_int32](#jerryx_arg_int32)
|
||||
|
||||
# Main functions
|
||||
|
||||
## jerryx_arg_transform_this_and_args
|
||||
|
||||
**Summary**
|
||||
|
||||
Validate the this value and the JS arguments, and assign them to the native arguments.
|
||||
This function is useful to perform input validation inside external function handlers (see `jerry_external_handler_t`).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_transform_this_and_args (const jerry_value_t this_val,
|
||||
const jerry_value_t *js_arg_p,
|
||||
const jerry_length_t js_arg_cnt,
|
||||
const jerryx_arg_t *c_arg_p,
|
||||
jerry_length_t c_arg_cnt)
|
||||
```
|
||||
|
||||
- `this_val` - `this` value. Note this is processed as the first value, before the array of arguments.
|
||||
- `js_arg_p` - points to the array with JS arguments.
|
||||
- `js_arg_cnt` - the count of the `js_arg_p` array.
|
||||
- `c_arg_p` - points to the array of validation/transformation steps
|
||||
- `c_arg_cnt` - the count of the `c_arg_p` array.
|
||||
- return value - a `jerry_value_t` representing `undefined` if all validators passed or an `Error` if a validator failed.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/arg.h"
|
||||
|
||||
/* JS signature: function (requiredBool, requiredString, optionalNumber) */
|
||||
static jerry_value_t
|
||||
my_external_handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_count)
|
||||
{
|
||||
bool required_bool;
|
||||
char required_str[16];
|
||||
double optional_num = 1234.567; // default value
|
||||
|
||||
/* "mapping" defines the steps to transform input arguments to C variables. */
|
||||
const jerryx_arg_t mapping[] =
|
||||
{
|
||||
/* `this` is the first value. No checking needed on `this` for this function. */
|
||||
jerryx_arg_ignore (),
|
||||
|
||||
jerryx_arg_boolean (&required_bool, JERRYX_ARG_NO_COERCE, JERRYX_ARG_REQUIRED),
|
||||
jerryx_arg_string (required_str, sizeof (required_str), JERRYX_ARG_NO_COERCE, JERRYX_ARG_REQUIRED),
|
||||
jerryx_arg_number (&optional_num, JERRYX_ARG_NO_COERCE, JERRYX_ARG_OPTIONAL),
|
||||
};
|
||||
|
||||
/* Validate and transform. */
|
||||
const jerry_value_t rv = jerryx_arg_transform_this_and_args (this_val,
|
||||
args_p,
|
||||
args_count,
|
||||
mapping,
|
||||
4);
|
||||
|
||||
if (jerry_value_is_error (rv))
|
||||
{
|
||||
/* Handle error. */
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validated and transformed successfully!
|
||||
* required_bool, required_str and optional_num can now be used.
|
||||
*/
|
||||
|
||||
return jerry_create_undefined (); /* Or return something more meaningful. */
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_ignore](#jerryx_arg_ignore)
|
||||
- [jerryx_arg_number](#jerryx_arg_number)
|
||||
- [jerryx_arg_boolean](#jerryx_arg_boolean)
|
||||
- [jerryx_arg_string](#jerryx_arg_string)
|
||||
- [jerryx_arg_function](#jerryx_arg_function)
|
||||
- [jerryx_arg_native_pointer](#jerryx_arg_native_pointer)
|
||||
- [jerryx_arg_custom](#jerryx_arg_custom)
|
||||
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||
|
||||
|
||||
## jerryx_arg_transform_args
|
||||
|
||||
**Summary**
|
||||
|
||||
Validate an array of `jerry_value_t` and assign them to the native arguments.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_transform_args (const jerry_value_t *js_arg_p,
|
||||
const jerry_length_t js_arg_cnt,
|
||||
const jerryx_arg_t *c_arg_p,
|
||||
jerry_length_t c_arg_cnt)
|
||||
```
|
||||
|
||||
- `js_arg_p` - points to the array with JS arguments.
|
||||
- `js_arg_cnt` - the count of the `js_arg_p` array.
|
||||
- `c_arg_p` - points to the array of validation/transformation steps
|
||||
- `c_arg_cnt` - the count of the `c_arg_p` array.
|
||||
- return value - a `jerry_value_t` representing `undefined` if all validators passed or an `Error` if a validator failed.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
|
||||
## jerryx_arg_transform_object_properties
|
||||
|
||||
**Summary**
|
||||
|
||||
Validate the properties of a JS object and assign them to the native arguments.
|
||||
|
||||
*Note*: This function transforms properties of a single JS object into native C values.
|
||||
To transform multiple objects in one pass (for example when converting multiple arguments
|
||||
to an external handler), please use `jerryx_arg_object_properties` together with
|
||||
`jerryx_arg_transform_this_and_args` or `jerryx_arg_transform_args`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_transform_object_properties (const jerry_value_t obj_val,
|
||||
const jerry_char_t **name_p,
|
||||
const jerry_length_t name_cnt,
|
||||
const jerryx_arg_t *c_arg_p,
|
||||
jerry_length_t c_arg_cnt);
|
||||
|
||||
```
|
||||
|
||||
- `obj_val` - the JS object.
|
||||
- `name_p` - points to the array of property names.
|
||||
- `name_cnt` - the count of the `name_p` array.
|
||||
- `c_arg_p` - points to the array of validation/transformation steps
|
||||
- `c_arg_cnt` - the count of the `c_arg_p` array.
|
||||
- return value - a `jerry_value_t` representing `undefined` if all validators passed or an `Error` if a validator failed.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_object_properties](#jerryx_arg_object_properties)
|
||||
|
||||
## jerryx_arg_transform_array
|
||||
|
||||
**Summary**
|
||||
|
||||
Validate the JS array and assign its items to the native arguments.
|
||||
|
||||
*Note*: This function transforms items of a single JS array into native C values.
|
||||
To transform multiple JS arguments in one pass, please use `jerryx_arg_array` together with
|
||||
`jerryx_arg_transform_this_and_args` or `jerryx_arg_transform_args`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_transform_array (const jerry_value_t array_val,
|
||||
const jerryx_arg_t *c_arg_p,
|
||||
jerry_length_t c_arg_cnt);
|
||||
|
||||
```
|
||||
|
||||
- `array_val` - the JS array.
|
||||
- `c_arg_p` - points to the array of validation/transformation steps
|
||||
- `c_arg_cnt` - the count of the `c_arg_p` array.
|
||||
- return value - a `jerry_value_t` representing `undefined` if all validators passed or an `Error` if a validator failed.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_array](#jerryx_arg_array)
|
||||
|
||||
|
||||
# Helpers for commonly used validations
|
||||
|
||||
## jerryx_arg_uint8
|
||||
|
||||
## jerryx_arg_uint16
|
||||
|
||||
## jerryx_arg_uint32
|
||||
|
||||
## jerryx_arg_int8
|
||||
|
||||
## jerryx_arg_int16
|
||||
|
||||
## jerryx_arg_int32
|
||||
|
||||
**Summary**
|
||||
|
||||
All above jerryx_arg_[u]intX functions are used to create a validation/transformation step
|
||||
(`jerryx_arg_t`) that expects to consume one `number` JS argument
|
||||
and stores it into a C integer (uint8, int8, uint16, ...)
|
||||
|
||||
**Prototype**
|
||||
|
||||
Take jerryx_arg_int32 as an example
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_int32 (int32_t *dest,
|
||||
jerryx_arg_round_t round_flag,
|
||||
jerryx_arg_clamp_t clamp_flag,
|
||||
jerryx_arg_coerce_t coerce_flag,
|
||||
jerryx_arg_optional_t opt_flag);
|
||||
```
|
||||
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the `int32_t` where the result should be stored.
|
||||
- `round_flag` - the rounding policy.
|
||||
- `clamp_flag` - the clamping policy.
|
||||
- `coerce_flag` - whether type coercion is allowed.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
|
||||
## jerryx_arg_number
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to consume
|
||||
one `number` JS argument and stores it into a C `double`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_number (double *dest,
|
||||
jerryx_arg_coerce_t coerce_flag,
|
||||
jerryx_arg_optional_t opt_flag)
|
||||
```
|
||||
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the `double` where the result should be stored.
|
||||
- `coerce_flag` - whether type coercion is allowed.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
## jerryx_arg_boolean
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `boolean` JS argument and stores it into a C `bool`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_boolean (bool *dest,
|
||||
jerryx_arg_coerce_t coerce_flag,
|
||||
jerryx_arg_optional_t opt_flag)
|
||||
```
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the `bool` where the result should be stored.
|
||||
- `coerce_flag` - whether type coercion is allowed.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
|
||||
## jerryx_arg_string
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `string` JS argument and stores it into a CESU-8 C `char` array.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_string (char *dest,
|
||||
uint32_t size,
|
||||
jerryx_arg_coerce_t coerce_flag,
|
||||
jerryx_arg_optional_t opt_flag)
|
||||
```
|
||||
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the native char array where the result should be stored.
|
||||
- `size` - the size of native char array.
|
||||
- `coerce_flag` - whether type coercion is allowed.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
- [jerry_arg_utf8_string](#jerry_arg_utf8_string)
|
||||
|
||||
|
||||
## jerryx_arg_utf8_string
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `string` JS argument and stores it into a UTF-8 C `char` array.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_utf8_string (char *dest,
|
||||
uint32_t size,
|
||||
jerryx_arg_coerce_t coerce_flag,
|
||||
jerryx_arg_optional_t opt_flag)
|
||||
```
|
||||
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the native char array where the result should be stored.
|
||||
- `size` - the size of native char array.
|
||||
- `coerce_flag` - whether type coercion is allowed.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
- [jerry_arg_string](#jerry_arg_string)
|
||||
|
||||
|
||||
## jerryx_arg_function
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `function` JS argument and stores it into a C `jerry_value_t`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_function (jerry_value_t *dest,
|
||||
jerryx_arg_optional_t opt_flag)
|
||||
|
||||
```
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the `jerry_value_t` where the result should be stored.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
## jerryx_arg_native_pointer
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `object` JS argument that is 'backed' with a native pointer with
|
||||
a given type info. In case the native pointer info matches, the transform
|
||||
will succeed and the object's native pointer will be assigned to `*dest`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_native_pointer (void **dest,
|
||||
const jerry_object_native_info_t *info_p,
|
||||
jerryx_arg_optional_t opt_flag)
|
||||
```
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to where the resulting native pointer should be stored.
|
||||
- `info_p` - expected the type info.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
## jerryx_arg_object_properties
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `object` JS argument and call `jerryx_arg_transform_object_properties` inside
|
||||
to transform its properties to native arguments.
|
||||
User should prepare the `jerryx_arg_object_props_t` instance, and pass it to this function.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_object_properties (const jerryx_arg_object_props_t *object_props_p,
|
||||
jerryx_arg_optional_t opt_flag);
|
||||
```
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `object_props_p` - provides information for properties transform.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/arg.h"
|
||||
|
||||
/**
|
||||
* The binding function expects args_p[0] is an object, which has 3 properties:
|
||||
* "enable": boolean
|
||||
* "data": number
|
||||
* "extra_data": number, optional
|
||||
*/
|
||||
static jerry_value_t
|
||||
my_external_handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_count)
|
||||
{
|
||||
bool required_bool;
|
||||
double required_num;
|
||||
double optional_num = 1234.567; // default value
|
||||
|
||||
/* "prop_name_p" defines the name list of the expected properties' names. */
|
||||
const char *prop_name_p[] = { "enable", "data", "extra_data" };
|
||||
|
||||
/* "prop_mapping" defines the steps to transform properties to C variables. */
|
||||
const jerryx_arg_t prop_mapping[] =
|
||||
{
|
||||
jerryx_arg_boolean (&required_bool, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||
jerryx_arg_number (&required_num, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||
jerryx_arg_number (&optional_num, JERRYX_ARG_COERCE, JERRYX_ARG_OPTIONAL)
|
||||
};
|
||||
|
||||
/* Prepare the jerryx_arg_object_props_t instance. */
|
||||
const jerryx_arg_object_props_t prop_info =
|
||||
{
|
||||
.name_p = (const jerry_char_t **) prop_name_p,
|
||||
.name_cnt = 3,
|
||||
.c_arg_p = prop_mapping,
|
||||
.c_arg_cnt = 3
|
||||
};
|
||||
|
||||
/* It is the mapping used in the jerryx_arg_transform_args. */
|
||||
const jerryx_arg_t mapping[] =
|
||||
{
|
||||
jerryx_arg_object_properties (&prop_info, JERRYX_ARG_REQUIRED)
|
||||
};
|
||||
|
||||
/* Validate and transform. */
|
||||
const jerry_value_t rv = jerryx_arg_transform_args (args_p,
|
||||
args_count,
|
||||
mapping,
|
||||
1);
|
||||
|
||||
if (jerry_value_is_error (rv))
|
||||
{
|
||||
/* Handle error. */
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validated and transformed successfully!
|
||||
* required_bool, required_num and optional_num can now be used.
|
||||
*/
|
||||
|
||||
return jerry_create_undefined (); /* Or return something more meaningful. */
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
- [jerryx_arg_transform_object_properties](#jerryx_arg_transform_object_properties)
|
||||
|
||||
## jerryx_arg_array
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a validation/transformation step (`jerryx_arg_t`) that expects to
|
||||
consume one `array` JS argument and call `jerryx_arg_transform_array_items` inside
|
||||
to transform its items to native arguments.
|
||||
User should prepare the `jerryx_arg_array_items_t` instance, and pass it to this function.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_array (const jerryx_arg_array_items_t *array_items_p, jerryx_arg_optional_t opt_flag);
|
||||
```
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `array_items_p` - provides items information for transform.
|
||||
- `opt_flag` - whether the argument is optional.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/arg.h"
|
||||
|
||||
/**
|
||||
* The binding function expects args_p[0] is an array, which has 3 items:
|
||||
* first: boolean
|
||||
* second: number
|
||||
* third: number, optional
|
||||
*/
|
||||
static jerry_value_t
|
||||
my_external_handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_count)
|
||||
{
|
||||
bool required_bool;
|
||||
double required_num;
|
||||
double optional_num = 1234.567; // default value
|
||||
|
||||
/* "item_mapping" defines the steps to transform array items to C variables. */
|
||||
const jerryx_arg_t item_mapping[] =
|
||||
{
|
||||
jerryx_arg_boolean (&required_bool, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||
jerryx_arg_number (&required_num, JERRYX_ARG_COERCE, JERRYX_ARG_REQUIRED),
|
||||
jerryx_arg_number (&optional_num, JERRYX_ARG_COERCE, JERRYX_ARG_OPTIONAL)
|
||||
};
|
||||
|
||||
/* Prepare the jerryx_arg_array_items_t instance. */
|
||||
const jerryx_arg_array_items_t array_info =
|
||||
{
|
||||
.c_arg_p = item_mapping,
|
||||
.c_arg_cnt = 3
|
||||
};
|
||||
|
||||
/* It is the mapping used in the jerryx_arg_transform_args. */
|
||||
const jerryx_arg_t mapping[] =
|
||||
{
|
||||
jerryx_arg_array (&array_info, JERRYX_ARG_REQUIRED)
|
||||
};
|
||||
|
||||
/* Validate and transform. */
|
||||
const jerry_value_t rv = jerryx_arg_transform_args (args_p,
|
||||
args_count,
|
||||
mapping,
|
||||
1);
|
||||
|
||||
if (jerry_value_is_error (rv))
|
||||
{
|
||||
/* Handle error. */
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validated and transformed successfully!
|
||||
* required_bool, required_num and optional_num can now be used.
|
||||
*/
|
||||
|
||||
return jerry_create_undefined (); /* Or return something more meaningful. */
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
- [jerryx_arg_transform_object_properties](#jerryx_arg_transform_object_properties)
|
||||
|
||||
# Functions to create custom validations
|
||||
|
||||
## jerryx_arg_custom
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a jerryx_arg_t instance with custom transform.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
static inline jerryx_arg_t
|
||||
jerryx_arg_custom (void *dest,
|
||||
uintptr_t extra_info,
|
||||
jerryx_arg_transform_func_t func)
|
||||
|
||||
```
|
||||
- return value - the created `jerryx_arg_t` instance.
|
||||
- `dest` - pointer to the native argument where the result should be stored.
|
||||
- `extra_info` - the extra parameter data, specific to the transform function.
|
||||
- `func` - the custom transform function.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_arg_transform_this_and_args](#jerryx_arg_transform_this_and_args)
|
||||
|
||||
|
||||
|
||||
## jerryx_arg_js_iterator_pop
|
||||
|
||||
**Summary**
|
||||
|
||||
Pop the current `jerry_value_t` argument from the iterator.
|
||||
It will change the `js_arg_idx` and `js_arg_p` value in the iterator.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_js_iterator_pop (jerryx_arg_js_iterator_t *js_arg_iter_p)
|
||||
```
|
||||
- return value - the `jerry_value_t` argument that was popped.
|
||||
- `js_arg_iter_p` - the JS arg iterator from which to pop.
|
||||
|
||||
## jerryx_arg_js_iterator_peek
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the current JS argument from the iterator, without moving the iterator forward.
|
||||
*Note:* Unlike `jerryx_arg_js_iterator_pop ()`, it will not change `js_arg_idx` and
|
||||
`js_arg_p` value in the iterator.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_js_iterator_peek (jerryx_arg_js_iterator_t *js_arg_iter_p)
|
||||
```
|
||||
- return value - the current `jerry_value_t` argument.
|
||||
- `js_arg_iter_p` - the JS arg iterator from which to peek.
|
||||
|
||||
## jerryx_arg_js_iterator_restore
|
||||
|
||||
**Summary**
|
||||
|
||||
Restore the last item popped from the stack. This can be called as
|
||||
many times as there are arguments on the stack -- if called when the
|
||||
first element in the array is the current top of the stack, this
|
||||
function does nothing.
|
||||
|
||||
*Note:* This function relies on the underlying implementation of the
|
||||
arg stack as an array, as its function is to simply back up the "top
|
||||
of stack" pointer to point to the previous element of the array.
|
||||
|
||||
*Note:* Like `jerryx_arg_js_iterator_pop ()`, this function will
|
||||
change the `js_arg_idx` and `js_arg_p` values in the iterator.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_arg_js_iterator_restore (jerryx_arg_js_iterator_t *js_arg_iter_p)
|
||||
```
|
||||
- return value - the the new top of the stack.
|
||||
- `js_arg_iter_p` - the JS arg iterator to restore.
|
||||
|
||||
|
||||
## jerryx_arg_js_iterator_index
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the index of the current JS argument from the iterator.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_length_t
|
||||
jerryx_arg_js_iterator_index (jerryx_arg_js_iterator_t *js_arg_iter_p)
|
||||
```
|
||||
- return value - the index of current JS argument.
|
||||
- `js_arg_iter_p` - the JS arg iterator from which to peek.
|
|
@ -0,0 +1,604 @@
|
|||
# Common methods to handle properties
|
||||
|
||||
The `jerryscript-ext/handler.h` header defines a set of convenience methods
|
||||
which makes the property access a bit straightforward.
|
||||
|
||||
## jerryx_set_property_str
|
||||
|
||||
**Summary**
|
||||
|
||||
Set a property on a target object with a given name.
|
||||
|
||||
*Note*:
|
||||
- The property name must be a zero terminated UTF-8 string.
|
||||
- There should be no '\0' (NULL) character in the name excluding the string terminator.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
|
||||
is no longer needed.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_set_property_str (const jerry_value_t target_object,
|
||||
const char *name,
|
||||
const jerry_value_t value);
|
||||
```
|
||||
|
||||
- `target_object` - the object where the property should be set
|
||||
- `name` - name of the property
|
||||
- `value` - property value to be set
|
||||
- return value
|
||||
- JS true value, if success
|
||||
- thrown error, if there was a problem setting the property
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
jerry_value_t value = jerry_create_number (3.3);
|
||||
jerry_value_t result = jerryx_set_property_str (global, "value", value);
|
||||
if (jerry_value_is_error (result))
|
||||
{
|
||||
/* The error type/reason can be extracted via the `jerry_get_value_from_error` method */
|
||||
printf ("Error during property configuration\r\n");
|
||||
}
|
||||
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (value);
|
||||
jerry_release_value (global);
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## jerryx_get_property_str
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the value of a property from the specified object with the given name.
|
||||
|
||||
*Notes*:
|
||||
- The property name must be a zero terminated UTF-8 string.
|
||||
- There should be no '\0' (NULL) character in the name excluding the string terminator.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
|
||||
is no longer needed.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
jerry_value_t
|
||||
jerryx_get_property_str (const jerry_value_t target_object,
|
||||
const char *name);
|
||||
```
|
||||
|
||||
- `target_object` - object on which the property name is accessed
|
||||
- `name` - property name as an UTF-8 `char*`
|
||||
- return value
|
||||
- value of property, if success
|
||||
- thrown error, if there was a problem accessing the property
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
jerry_value_t math_object = jerryx_get_property_str (global, "Math");
|
||||
|
||||
/* use math_object */
|
||||
|
||||
jerry_release_value (math_object);
|
||||
jerry_release_value (global);
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## jerryx_has_property_str
|
||||
|
||||
**Summary**
|
||||
|
||||
Check if a property exists on an object.
|
||||
|
||||
*Notes*:
|
||||
- The operation performed is the same as what the `jerry_has_property` method.
|
||||
- The property name must be a zero terminated UTF-8 string.
|
||||
- There should be no '\0' (NULL) character in the name excluding the string terminator.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
bool
|
||||
jerryx_has_property_str (const jerry_value_t target_object,
|
||||
const char *name);
|
||||
```
|
||||
|
||||
- `target_object` - object on which the property name is accessed
|
||||
- `name` - property name as an UTF-8 `char*`
|
||||
- return value
|
||||
- true, if the given property name exsits on the object
|
||||
- false, if there is no such property name or there was an error accessing the property
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
|
||||
bool have_math = jerryx_has_property_str (global, "Math");
|
||||
|
||||
jerry_release_value (global);
|
||||
jerry_cleanup();
|
||||
|
||||
return have_math ? 0 : 1;
|
||||
}
|
||||
```
|
||||
|
||||
# Utility to register multiple properties in bulk
|
||||
|
||||
In some cases it is useful to register multiple properties for a given object
|
||||
for this the following utility structures and methods are provided.
|
||||
|
||||
## jerryx_property_entry
|
||||
|
||||
**Summary**
|
||||
|
||||
Structure to define an array of properties with `name` and `value` fields which
|
||||
can be registered to a target object.
|
||||
|
||||
The engine must be initialied before specifying the `jerry_value_t` in the struct.
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
const char *name;
|
||||
jerry_value_t value;
|
||||
} jerryx_function_list_entry;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_set_properties](#jerryx_set_properties)
|
||||
|
||||
|
||||
## jerryx_register_result
|
||||
|
||||
**Summary**
|
||||
|
||||
Structure returned as the result of the [jerryx_set_properties](#jerryx_set_properties) operation.
|
||||
The `result` field will either be a JavaScript undefined value or an error object.
|
||||
In every case the `registered` field is used to indicated the number of
|
||||
successfully registered methods.
|
||||
|
||||
This must be passed for the [jerryx_release_property_entry](#jerryx_release_property_entry) method
|
||||
after the property registration.
|
||||
|
||||
If any error occured during the property registration the `result` field of the structure
|
||||
must be manually released after processing the error value.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
jerry_value_t result;
|
||||
uint32_t registered;
|
||||
} jerryx_register_result;
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_set_properties](#jerryx_set_properties)
|
||||
- [jerryx_release_property_entry](#jerryx_release_property_entry)
|
||||
|
||||
|
||||
## jerryx_set_properties
|
||||
|
||||
**Summary**
|
||||
|
||||
Set multiple properties on a target object.
|
||||
|
||||
The properties are an array of (name, jerry_value_t) pairs and
|
||||
this list must end with a (NULL, 0) entry.
|
||||
|
||||
Important notes:
|
||||
* Each property value in the input array is released after a successful property registration.
|
||||
* The method [jerryx_release_property_entry](#jerryx_release_property_entry) must be called if there is any failed registration
|
||||
to release the values in the entries array.
|
||||
It is safe to call this cleanup method in every case not just in case of failure.
|
||||
* If the error value is reported via the result it must be freed manually.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerryx_register_result
|
||||
jerryx_set_properties (const jerry_value_t target_object,
|
||||
const jerryx_property_entry entries[]);
|
||||
```
|
||||
|
||||
- `target_object` - object on which the entries will be set.
|
||||
- `entries` - array of (name, jerry_value_t) pairs.
|
||||
- return a [jerryx_register_result](#jerryx_register_result).
|
||||
- if everything is ok, the struct's `result` field is set to a JS undefined value.
|
||||
- otherwise the `result` field is an error object indicating the problem.
|
||||
- in every case the `registered` field contains the number of successfully registered properties.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
static jerry_value_t
|
||||
handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_cnt)
|
||||
{
|
||||
printf ("native handler called!\n");
|
||||
|
||||
return jerry_create_boolean (true);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerryx_property_entry methods[] =
|
||||
{
|
||||
{ "demo", jerry_create_external_function (handler) },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
jerryx_register_result reg = jerryx_set_properties (global, methods);
|
||||
/* if `reg.result` is undefined all methods are registered */
|
||||
if (jerry_value_is_error (reg.result))
|
||||
{
|
||||
printf ("Only registered %d properties\r\n", reg.registered);
|
||||
/* clean up not registered property values */
|
||||
jerryx_release_property_entry (methods, reg);
|
||||
|
||||
/* clean up the error */
|
||||
jerry_release_value (reg.result);
|
||||
}
|
||||
|
||||
jerry_release_value (global);
|
||||
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**Convenience macros**
|
||||
|
||||
To make property registration convenient, there are a set of macros to use
|
||||
when setting a property entry:
|
||||
|
||||
* `JERRYX_PROPERTY_NUMBER(NAME, NUMBER)` - creates a number entry.
|
||||
* `JERRYX_PROPERTY_STRING(NAME, STR)` - creates an UTF-8 string entry. This string must be zero terminated.
|
||||
* `JERRYX_PROPERTY_STRING_SZ(NAME, STR, SIZE)` - creates an UTF-8 string entry using only `SIZE` bytes from the string.
|
||||
* `JERRYX_PROPERTY_BOOLEAN(NAME, VALUE)` - creates a boolean entry.
|
||||
* `JERRYX_PROPERTY_FUNCTION(NAME, NATIVE)` - creates a native C function entry.
|
||||
* `JERRYX_PROPERTY_UNDEFINED(NAME)` - creates an undefined property entry.
|
||||
* `JERRYX_PROPERTY_LIST_END()` - indicates the end of the property list.
|
||||
|
||||
**Example usage of Convenience macros**
|
||||
|
||||
[doctest]: # ()
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
static jerry_value_t
|
||||
handler (const jerry_value_t function_obj,
|
||||
const jerry_value_t this_val,
|
||||
const jerry_value_t args_p[],
|
||||
const jerry_length_t args_cnt)
|
||||
{
|
||||
printf ("native handler called!\n");
|
||||
|
||||
return jerry_create_boolean (true);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
/**
|
||||
* Create a array of properties to be registered.
|
||||
* This must be done after initializing the engine as creating `jerry_value_t`
|
||||
* elements are invalid before `jerry_init`.
|
||||
*/
|
||||
jerryx_property_entry methods[] =
|
||||
{
|
||||
JERRYX_PROPERTY_FUNCTION ("demo", handler),
|
||||
JERRYX_PROPERTY_NUMBER ("test_num", 2.3),
|
||||
JERRYX_PROPERTY_UNDEFINED ("this_is_undefined"),
|
||||
JERRYX_PROPERTY_LIST_END(),
|
||||
};
|
||||
|
||||
jerry_value_t global = jerry_get_global_object ();
|
||||
jerryx_register_result reg = jerryx_set_properties (global, methods);
|
||||
/* if `reg.result` is undefined all methods are registered */
|
||||
if (jerry_value_is_error (reg.result))
|
||||
{
|
||||
printf ("Only registered %d properties\r\n", reg.registered);
|
||||
/* clean up not registered property values */
|
||||
jerryx_release_property_entry (methods, reg);
|
||||
|
||||
/* clean up the error */
|
||||
jerry_release_value (reg.result);
|
||||
}
|
||||
|
||||
jerry_release_value (global);
|
||||
|
||||
jerry_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_property_entry](#jerryx_property_entry)
|
||||
- [jerryx_release_property_entry](#jerryx_release_property_entry)
|
||||
- [jerryx_register_result](#jerryx_register_result)
|
||||
|
||||
## jerryx_release_property_entry
|
||||
|
||||
**Summary**
|
||||
|
||||
Release all `jerry_value_t` in a `jerryx_property_entry` array based on a previous [jerryx_set_properties](#jerryx_set_properties) call
|
||||
and also the error value (if any) in the `jerryx_register_result` structure.
|
||||
In case of a successful registration it is safe to call this method.
|
||||
|
||||
After the method call the `ęntries` array should not be used as all values are released.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
void
|
||||
jerryx_release_property_entry (const jerryx_property_entry entries[],
|
||||
const jerryx_register_result register_result);
|
||||
```
|
||||
|
||||
- `entires` - array of [jerryx_property_entry](#jerryx_property_entry).
|
||||
- `register_result` - result of a previous [jerryx_set_properties](#jerryx_set_properties) call.
|
||||
|
||||
**Example**
|
||||
|
||||
For example usage see [jerryx_set_properties](#jerryx_set_properties).
|
||||
|
||||
|
||||
# Common external function handlers
|
||||
|
||||
## jerryx_handler_assert_fatal
|
||||
|
||||
**Summary**
|
||||
|
||||
Hard assert for scripts. The routine calls `jerry_port_fatal` on assertion failure.
|
||||
|
||||
If the `JERRY_FEATURE_LINE_INFO` runtime feature is enabled (build option: `JERRY_LINE_INFO`)
|
||||
a backtrace is also printed out.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_handler_assert_fatal (const jerry_value_t func_obj_val, const jerry_value_t this_p,
|
||||
const jerry_value_t args_p[], const jerry_length_t args_cnt);
|
||||
```
|
||||
|
||||
- `func_obj_val` - the function object that was called (unused).
|
||||
- `this_p` - the `this` value of the call (unused).
|
||||
- `args_p` - the array of function arguments.
|
||||
- `args_cnt` - the number of function arguments.
|
||||
- return value - `jerry_value_t` representing boolean true, if only one argument
|
||||
was passed and that argument was a boolean true. Note that the function does
|
||||
not return otherwise.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_handler_register_global](#jerryx_handler_register_global)
|
||||
|
||||
|
||||
## jerryx_handler_assert_throw
|
||||
|
||||
**Summary**
|
||||
|
||||
Soft assert for scripts. The routine throws an error on assertion failure.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_handler_assert_throw (const jerry_value_t func_obj_val, const jerry_value_t this_p,
|
||||
const jerry_value_t args_p[], const jerry_length_t args_cnt);
|
||||
```
|
||||
|
||||
- `func_obj_val` - the function object that was called (unused).
|
||||
- `this_p` - the `this` value of the call (unused).
|
||||
- `args_p` - the array of function arguments.
|
||||
- `args_cnt` - the number of function arguments.
|
||||
- return value - `jerry_value_t` representing boolean true, if only one argument
|
||||
was passed and that argument was a boolean true, an error otherwise.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_handler_register_global](#jerryx_handler_register_global)
|
||||
|
||||
|
||||
## jerryx_handler_assert
|
||||
|
||||
**Summary**
|
||||
|
||||
An alias to `jerryx_handler_assert_fatal`.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_handler_assert_fatal](#jerryx_handler_assert_fatal)
|
||||
|
||||
|
||||
## jerryx_handler_gc
|
||||
|
||||
**Summary**
|
||||
|
||||
Expose garbage collector to scripts. If the first argument of the function
|
||||
is logical true, it performs a high pressure gc. Otherwise a low pressure
|
||||
gc is performed, which is also the default if no parameters passed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_handler_gc (const jerry_value_t func_obj_val, const jerry_value_t this_p,
|
||||
const jerry_value_t args_p[], const jerry_length_t args_cnt);
|
||||
```
|
||||
|
||||
- `func_obj_val` - the function object that was called (unused).
|
||||
- `this_p` - the `this` value of the call (unused).
|
||||
- `args_p` - the array of function arguments (unused).
|
||||
- `args_cnt` - the number of function arguments (unused).
|
||||
- return value - `jerry_value_t` representing `undefined`.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_handler_register_global](#jerryx_handler_register_global)
|
||||
|
||||
|
||||
## jerryx_handler_print
|
||||
|
||||
**Summary**
|
||||
|
||||
Provide a `print` implementation for scripts. The routine converts all of its
|
||||
arguments to strings and outputs them char-by-char using
|
||||
`jerry_port_print_char`. The NUL character is output as "\u0000",
|
||||
other characters are output bytewise.
|
||||
|
||||
*Note*: This implementation does not use standard C `printf` to print its
|
||||
output. This allows more flexibility but also extends the core JerryScript
|
||||
engine port API. Applications that want to use `jerryx_handler_print` must
|
||||
ensure that their port implementation also provides
|
||||
`jerry_port_print_char`.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_handler_print (const jerry_value_t func_obj_val, const jerry_value_t this_p,
|
||||
const jerry_value_t args_p[], const jerry_length_t args_cnt);
|
||||
```
|
||||
|
||||
- `func_obj_val` - the function object that was called (unused).
|
||||
- `this_p` - the `this` value of the call (unused).
|
||||
- `args_p` - the array of function arguments.
|
||||
- `args_cnt` - the number of function arguments.
|
||||
- return value - `jerry_value_t` representing `undefined` if all arguments could
|
||||
be converted to strings, an `Error` otherwise.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerryx_handler_register_global](#jerryx_handler_register_global)
|
||||
- [jerry_port_print_char](05.PORT-API.md#jerry_port_print_char)
|
||||
|
||||
|
||||
# Handler registration helper
|
||||
|
||||
## jerryx_handler_register_global
|
||||
|
||||
**Summary**
|
||||
|
||||
Register a JavaScript function in the global object.
|
||||
|
||||
*Note*: Returned value must be freed with `jerry_release_value`, when it is no
|
||||
longer needed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_handler_register_global (const jerry_char_t *name_p,
|
||||
jerry_external_handler_t handler_p);
|
||||
```
|
||||
|
||||
- `name_p` - the name of the function to be registered.
|
||||
- `handler_p` - the address of the external function handler.
|
||||
- return value - `jerry_value_t` representing boolean true, if the operation was
|
||||
successful, an `Error` otherwise.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handler.h"
|
||||
|
||||
static const struct {
|
||||
const char *name_p;
|
||||
jerry_external_handler_t handler_p;
|
||||
} common_functions[] =
|
||||
{
|
||||
{ "assert", jerryx_handler_assert },
|
||||
{ "gc", jerryx_handler_gc },
|
||||
{ "print", jerryx_handler_print },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
register_common_functions (void)
|
||||
{
|
||||
jerry_value_t ret = jerry_create_undefined ();
|
||||
|
||||
for (int i = 0; common_functions[i].name_p != NULL && !jerry_value_is_error (ret); i++)
|
||||
{
|
||||
ret = jerryx_handler_register_global ((const jerry_char_t *) common_functions[i].name_p,
|
||||
common_functions[i].handler_p);
|
||||
}
|
||||
|
||||
jerry_release_value (ret);
|
||||
}
|
||||
```
|
|
@ -0,0 +1,50 @@
|
|||
# Autorelease values
|
||||
|
||||
## JERRYX_AR_VALUE_T
|
||||
|
||||
**Summary**
|
||||
|
||||
Macro for `const jerry_value_t` for which jerry_release_value() is
|
||||
automatically called when the variable goes out of scope.
|
||||
|
||||
*Note*: The macro depends on compiler support. For GCC and LLVM/clang, the macro is implemented
|
||||
using the `__cleanup__` variable attribute. For other compilers, no support has been added yet.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile", name="11.EXT-REFERENCE-AUTORELEASE.c")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/autorelease.h"
|
||||
|
||||
static void
|
||||
foo (bool enable)
|
||||
{
|
||||
JERRYX_AR_VALUE_T bar = jerry_create_string ((const jerry_char_t *) "...");
|
||||
|
||||
if (enable)
|
||||
{
|
||||
JERRYX_AR_VALUE_T baz = jerry_get_global_object ();
|
||||
|
||||
/* bar and baz can now be used. */
|
||||
|
||||
/*
|
||||
* jerry_release_value (baz) and jerry_release_value (bar) is called automatically before
|
||||
* returning, because `baz` and `bar` go out of scope.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* jerry_release_value (bar) is called automatically when the function returns,
|
||||
* because `bar` goes out of scope.
|
||||
*/
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_value_t](../docs/02.API-REFERENCE.md#jerry_value_t)
|
||||
- [jerry_acquire_value](../docs/02.API-REFERENCE.md#jerry_acquire_value)
|
||||
- [jerry_release_value](../docs/02.API-REFERENCE.md#jerry_release_value)
|
|
@ -0,0 +1,314 @@
|
|||
# Module API
|
||||
|
||||
This is a JerryScript extension that provides a means of loading modules. Fundamentally, a module is a name (stored as
|
||||
a string) that resolves to a `jerry_value_t`. This extension provides the function `jerryx_module_resolve()` which
|
||||
accepts the name of the module being requested as well as an array of so-called "resolvers" - structures containing two
|
||||
function pointers: one for a function which computes a canonical name for the requested module or returns a reference
|
||||
to the requested name, and one that converts a canonical name to a `jerry_value_t`, thus "resolving" or "loading" the
|
||||
requested module.
|
||||
|
||||
The resolvers are first called in sequence to each compute the canonical name of the requested module. This is
|
||||
accomplished by calling the `get_canonical_name` function pointer they provide. If the function pointer is `NULL`, the
|
||||
requested module name is assumed to be what the resolver considers to be its canonical name. `jerryx_module_resolve`
|
||||
searches its cache of loaded modules for each canonical name as returned by a `get_canonical_name` function pointer. If
|
||||
one of the loaded modules in the cache corresponds to a canonical name, it is returned.
|
||||
|
||||
If no cached module is found, `jerryx_module_resolve` calls each resolver's `resolve` function pointer, passing it its
|
||||
previously computed interpretation of the requested module's canonical name. If the resolver successfully creates the
|
||||
`jerry_value_t` that represents the loaded module, it returns `true` and the `jerry_value_t` in its out parameter.
|
||||
|
||||
When `jerryx_module_resolve` receives a value of `true` from a resolver, it stops iterating over the remaining
|
||||
resolvers in the sequence and, if the `jerry_value_t` returned from the resolver's `resolve` does not have the error
|
||||
flag set, it will add the `jerry_value_t` to its cache under the module's canonical name and return it. Thus, on
|
||||
subsequent calls to `jerryx_module_resolve` with a module name whose canonical name is associated with the
|
||||
`jerry_value_t`, no `resolve` callback need be called again.
|
||||
|
||||
The purpose of having resolvers is to be able to account for the fact that different types of modules may be structured
|
||||
differently and thus, for each type of module a module resolver must be supplied at the point where an instance of that
|
||||
type of module is requested.
|
||||
|
||||
Individual modules may be removed from the cache by calling `jerryx_module_clear_cache`. This function behaves
|
||||
identically to `jerryx_module_resolve` in that it first checks the cache for the requested module, except that it
|
||||
removes the module if found. Additionally, it clears the entire cache of all modules if called using a JavaScript value
|
||||
of `undefined` as its first parameter.
|
||||
|
||||
Additionally, this extension provides a means of easily defining so-called "native" JerryScript modules which can be
|
||||
resolved using the native JerryScript module resolver `jerryx_module_native_resolver`, which can be passed to
|
||||
`jerryx_module_resolve()`. Native modules are registered during application startup and by calling `dlopen()` by means
|
||||
of library constructors, support for which can be turned on using the `FEATURE_INIT_FINI` build flag. In the absence of
|
||||
such a flag, the module registration and unregistration functions are exposed as global symbols which can be called
|
||||
explicitly. Note: `FEATURE_INIT_FINI` build flag isn't supported on Windows, because Microsoft Visual C/C++ Compiler
|
||||
doesn't support library constructors and destructors.
|
||||
|
||||
## jerryx_module_resolve
|
||||
|
||||
**Summary**
|
||||
|
||||
Load a copy of a module into the current context or return one that was already loaded if it is found.
|
||||
|
||||
For each resolver passed in via `resolvers_p`, its `get_canonical_name` function pointer gets called in order to
|
||||
establish the resolver's interpretation of what the canonical name for the module should be. If `get_canonical_name` is
|
||||
`NULL`, it is assumed that the requested module's name as passed in is its canonical name.
|
||||
|
||||
Then, for each resolver passed in via `resolvers_p`, its `resolve` function pointer gets called with its interpretation
|
||||
of what the module's canonical name should be, as computed in the previous step.
|
||||
|
||||
If the resolver's `resolve` function pointer returns `true`, the `jerry_value_t` returned in its out-parameter will be
|
||||
returned by `jerryx_module_resolve` as the result of the request. If no error flag is set on the `jerry_value_t` it
|
||||
will be cached under its canonical name so as to avoid loading the same module twice in the event of a subsequent call
|
||||
to `jerryx_module_resolve` with a module name whose canonical name matches an already loaded module.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerryx_module_resolve (const jerry_value_t name,
|
||||
const jerryx_module_resolver_t *resolvers_p,
|
||||
size_t resolver_count);
|
||||
```
|
||||
|
||||
- `name` - the name of the module to load
|
||||
- `resolvers_p` - the list of resolvers to call in sequence
|
||||
- `resolver_count` - the number of resolvers in `resolvers_p`
|
||||
- return value - `jerry_value_t` representing the module that was loaded, or the error that occurred in the process.
|
||||
|
||||
|
||||
## jerryx_module_clear_cache
|
||||
|
||||
**Summary**
|
||||
|
||||
Remove a module from the current context's cache, or clear the cache entirely.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerryx_module_clear_cache (const jerry_value_t name,
|
||||
const jerryx_module_resolver_t *resolvers_p,
|
||||
size_t resolver_count);
|
||||
```
|
||||
|
||||
- `name` - the name of the module to remove from cache or a JavaScript `undefined` to clear the entire cache
|
||||
- `resolvers_p` - the list of resolvers to call in sequence
|
||||
- `resolver_count` - the number of resolvers in `resolvers_p`
|
||||
|
||||
|
||||
## jerryx_module_native_resolver
|
||||
|
||||
**Summary**
|
||||
|
||||
The resolver for native JerryScript modules. A pointer to this structure can be passed in the second parameter to
|
||||
`jerryx_module_resolve` to search for the module among the native JerryScript modules built into the binary. This
|
||||
function is available only if the preprocessor directive `JERRYX_NATIVE_MODULES_SUPPORTED` is defined.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
extern jerry_module_resolver_t jerryx_native_module_resolver;
|
||||
```
|
||||
|
||||
# Module data types
|
||||
|
||||
## jerryx_module_get_canonical_name_t
|
||||
|
||||
**Summary**
|
||||
|
||||
The function pointer type for converting a module's requested name to its canonical name.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef jerry_value_t (*jerryx_module_get_canonical_name_t) (const jerry_value_t name);
|
||||
```
|
||||
|
||||
## jerryx_module_resolve_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Function pointer type for module resolution.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef bool (*jerryx_module_resolve_t) (const jerry_value_t canonical_name,
|
||||
jerry_value_t *result);
|
||||
```
|
||||
|
||||
## jerryx_module_resolver_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Structure defining a module resolver.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
jerryx_module_get_canonical_name_t get_canonical_name_p;
|
||||
jerryx_module_resolve_t resolve_p;
|
||||
} jerryx_module_resolver_t;
|
||||
```
|
||||
|
||||
- `get_canonical_name_p` - function pointer to be called when the canonical name corresponding to the requested name
|
||||
of a module must be established.
|
||||
- `resolve_p` - function pointer to be called when a module with the given canonical name needs to be converted to the
|
||||
`jerry_value_t` that will become the loaded module.
|
||||
|
||||
**Example**
|
||||
```c
|
||||
static bool
|
||||
load_and_evaluate_js_file (const jerry_value_t name, jerry_value_t *result)
|
||||
{
|
||||
bool return_value = false;
|
||||
char *js_file_contents = NULL;
|
||||
int file_size = 0;
|
||||
|
||||
jerry_size_t name_size = jerry_get_utf8_string_size (name);
|
||||
jerry_char_t name_string[name_size + 1];
|
||||
jerry_string_to_utf8_char_buffer (name, name_string, name_size);
|
||||
name_string[name_size] = 0;
|
||||
|
||||
FILE *js_file = fopen (name_string, "r");
|
||||
|
||||
if (js_file)
|
||||
{
|
||||
/* We have successfully opened the file. Now, we establish its size. */
|
||||
file_size = fseek (js_file, 0, SEEK_END);
|
||||
fseek (js_file, 0, SEEK_SET);
|
||||
|
||||
/* We allocate enough memory to store the contents of the file. */
|
||||
js_file_contents = malloc (file_size);
|
||||
if (js_file_contents)
|
||||
{
|
||||
/* We read the file into memory and call jerry_eval (), assigning the result to the out-parameter. */
|
||||
fread (js_file_contents, file_size, 1, js_file);
|
||||
(*result) = jerry_eval (js_file_contents, file_size, JERRY_PARSE_NO_OPTS);
|
||||
|
||||
/* We release the memory holding the contents of the file. */
|
||||
free (js_file_contents);
|
||||
return_value = true;
|
||||
}
|
||||
|
||||
/* We close the file. */
|
||||
fclose (js_file);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static jerry_value_t
|
||||
canonicalize_file_path (const jerry_value_t name)
|
||||
{
|
||||
jerry_value_t absolute_path;
|
||||
|
||||
/**
|
||||
* Since a file on the file system can be referred to by multiple relative paths, but only by one absolute path, the
|
||||
* absolute path becomes the canonical name for the module. Thus, to establish this canonical name, we must search
|
||||
* name for "./" and "../", follow symlinks, etc., then create absolute_path via jerry_create_string () and return
|
||||
* it, because it is the canonical name for this module. Thus, we avoid loading the same JavaScript file twice.
|
||||
*/
|
||||
|
||||
return absolute_path;
|
||||
}
|
||||
|
||||
static jerryx_module_resolver_t js_file_loader
|
||||
{
|
||||
canonicalize_file_path,
|
||||
load_and_evaluate_js_file
|
||||
};
|
||||
```
|
||||
|
||||
We can now load JavaScript files:
|
||||
```c
|
||||
static const jerryx_module_resolver_t *resolvers[] =
|
||||
{
|
||||
/*
|
||||
* Consult the resolver for native JerryScript modules first, in case the requested module is a native JerryScript
|
||||
* module.
|
||||
*/
|
||||
&jerryx_module_native_resolver,
|
||||
|
||||
/*
|
||||
* If the requested module is not a native JerryScript module, assume it is a JavaScript file on disk and use the
|
||||
* above-defined JavaScript file loader to load it.
|
||||
*/
|
||||
&js_file_loader
|
||||
};
|
||||
jerry_value_t js_module = jerryx_module_resolve (requested_module, resolvers, 2);
|
||||
```
|
||||
|
||||
# Module helper macros
|
||||
|
||||
## JERRYX_NATIVE_MODULE
|
||||
|
||||
**Summary**
|
||||
|
||||
Helper macro to define a native JerryScript module. Currently declares a global static structure of type
|
||||
`jerryx_native_module_t` and a constructor/destructor pair that calls `jerryx_native_module_register()` resp.
|
||||
`jerryx_native_module_unregister()`. If the extension is built without the FEATURE_INIT_FINI flag, indicating that
|
||||
support for library constructors and destructors is absent, the constructor and destructor are declared as global
|
||||
symbols so that they may be called explicitly from within the application.
|
||||
|
||||
**Note**: The helper macro must appear at the bottom of a source file, and no semicolon must follow it.
|
||||
|
||||
**Prototype**
|
||||
```c
|
||||
#define JERRYX_NATIVE_MODULE(module_name, on_resolve_cb)
|
||||
```
|
||||
|
||||
- `module_name` - the name of the module without quotes. This value is used as the prefix for the registration and unregistration funtions. For example, when `module_name` is `example_module`, this results in the declaration of two functions `example_module_register()` and `example_module_unregister()`. These functions are declared global if support for library constructors/destructors is absent, allowing you to call them from other parts of the code by
|
||||
first forward-declaring them.
|
||||
- `on_resolve_cb` - the function of type `jerryx_native_module_on_resolve_t` that will be called when the module needs to be
|
||||
loaded.
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/module.h"
|
||||
|
||||
static jerry_value_t
|
||||
my_module_on_resolve (void)
|
||||
{
|
||||
return jerry_create_external_function (very_useful_function);
|
||||
} /* my_module_on_resolve */
|
||||
|
||||
/* Note that there is no semicolon at the end of the next line. This is how it must be. */
|
||||
JERRYX_NATIVE_MODULE (my_module, my_module_on_resolve)
|
||||
```
|
||||
|
||||
**Example Usage When Library Constructors Are Unavailable**
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/module.h"
|
||||
|
||||
/**
|
||||
* Forward-declare the module registration and unregistration function.
|
||||
*/
|
||||
extern void my_module_register (void);
|
||||
extern void my_module_unregister (void);
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
jerryx_module_resolver_t resolvers[] =
|
||||
{
|
||||
jerryx_native_module_resolver
|
||||
};
|
||||
|
||||
/* This plays the role of the library constructor. */
|
||||
my_module_register ();
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
...
|
||||
jerry_value_t my_module = jerryx_module_resolve ("my_module", resolvers, 1);
|
||||
...
|
||||
jerry_cleanup ();
|
||||
|
||||
/* This plays the role of the library destructor */
|
||||
my_module_unregister();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
|
@ -0,0 +1,217 @@
|
|||
# JerryScript debugger transport interface
|
||||
|
||||
The transport interface support allows dynamic selection of transportation
|
||||
layers which can encode/decode or send/receive messages transmitted between
|
||||
the debugger client and server.
|
||||
|
||||
# Types
|
||||
|
||||
## jerry_debugger_transport_receive_context_t
|
||||
|
||||
**Summary**
|
||||
|
||||
This context represents the current status of processing received data.
|
||||
The final state is returned by
|
||||
[jerry_debugger_transport_receive](#jerry_debugger_transport_receive)
|
||||
and must be passed to
|
||||
[jerry_debugger_transport_receive_completed](#jerry_debugger_transport_receive_completed)
|
||||
after the message is processed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *buffer_p; /**< buffer for storing the received data */
|
||||
size_t received_length; /**< number of currently received bytes */
|
||||
uint8_t *message_p; /**< start of the received message */
|
||||
size_t message_length; /**< length of the received message */
|
||||
size_t message_total_length; /**< total length for datagram protocols,
|
||||
* 0 for stream protocols */
|
||||
} jerry_debugger_transport_receive_context_t;
|
||||
```
|
||||
|
||||
## jerry_debugger_transport_header_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Shared header for each transport interface. It mostly contains callback functions
|
||||
used by the JerryScript debugger server.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef struct jerry_debugger_transport_layer_t
|
||||
{
|
||||
/* The following fields must be filled before calling jerry_debugger_transport_add(). */
|
||||
jerry_debugger_transport_close_t close; /**< close connection callback */
|
||||
jerry_debugger_transport_send_t send; /**< send data callback */
|
||||
jerry_debugger_transport_receive_t receive; /**< receive data callback */
|
||||
|
||||
/* The following fields are filled by jerry_debugger_transport_add(). */
|
||||
struct jerry_debugger_transport_layer_t *next_p; /**< next transport layer */
|
||||
} jerry_debugger_transport_header_t;
|
||||
```
|
||||
|
||||
## jerry_debugger_transport_close_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Called when the connection is closed. Must release all resources (including the
|
||||
memory area for the transport interface) allocated for the transport interface.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef void (*jerry_debugger_transport_close_t) (struct jerry_debugger_transport_interface_t *header_p);
|
||||
```
|
||||
|
||||
## jerry_debugger_transport_send_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Called when a message needs to be sent. Must either transmit the message or call
|
||||
the `header_p->next_p->send()` method.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef bool (*jerry_debugger_transport_send_t) (struct jerry_debugger_transport_interface_t *header_p,
|
||||
uint8_t *message_p, size_t message_length);
|
||||
```
|
||||
|
||||
## jerry_debugger_transport_receive_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Called during message processing. If messages are available it must return with
|
||||
the next message.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef bool (*jerry_debugger_transport_receive_t) (struct jerry_debugger_transport_interface_t *header_p,
|
||||
jerry_debugger_transport_receive_context_t *context_p);
|
||||
```
|
||||
|
||||
# Transport interface API functions
|
||||
|
||||
## jerry_debugger_transport_add
|
||||
|
||||
**Summary**
|
||||
|
||||
Add a new interface to the transporation interface chain. The interface
|
||||
will be the first item of the interface chain.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void jerry_debugger_transport_add (jerry_debugger_transport_header_t *header_p,
|
||||
size_t send_message_header_size, size_t max_send_message_size,
|
||||
size_t receive_message_header_size, size_t max_receive_message_size);
|
||||
```
|
||||
|
||||
- `header_p`: header of a transporation interface.
|
||||
- `send_message_header_size`: size of the outgoing message header, can be 0.
|
||||
- `max_send_message_size`: maximum outgoing message size supported by the interface.
|
||||
- `receive_message_header_size`: size of the incoming message header, can be 0.
|
||||
- `max_receive_message_size`: maximum incoming message size supported by the interface.
|
||||
|
||||
## jerry_debugger_transport_start
|
||||
|
||||
**Summary**
|
||||
|
||||
Starts the communication to the debugger client. Must be called after the
|
||||
connection is successfully established.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void jerry_debugger_transport_start (void);
|
||||
```
|
||||
|
||||
## jerry_debugger_transport_is_connected
|
||||
|
||||
**Summary**
|
||||
|
||||
Tells whether a debugger client is connected to the debugger server.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool jerry_debugger_transport_is_connected (void);
|
||||
```
|
||||
|
||||
- return value: `true`, if a client is connected, `false` otherwise.
|
||||
|
||||
## jerry_debugger_transport_close
|
||||
|
||||
**Summary**
|
||||
|
||||
Disconnect from the current debugger client. It does nothing if a client is
|
||||
not connected.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void jerry_debugger_transport_close (void);
|
||||
```
|
||||
|
||||
## jerry_debugger_transport_send
|
||||
|
||||
**Summary**
|
||||
|
||||
Send message to the client.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool jerry_debugger_transport_send (const uint8_t *message_p, size_t message_length);
|
||||
```
|
||||
|
||||
- `message_p`: message to be sent.
|
||||
- `message_length`: message length in bytes.
|
||||
- return value: `true`, if a client is still connected, `false` otherwise.
|
||||
|
||||
## jerry_debugger_transport_receive
|
||||
|
||||
**Summary**
|
||||
|
||||
Receive message from the client.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool jerry_debugger_transport_receive (jerry_debugger_transport_receive_context_t *context_p);
|
||||
```
|
||||
|
||||
- `context_p`: an unused [jerry_debugger_transport_receive_context_t](#jerry_debugger_transport_receive_context_t).
|
||||
- return value: `true`, if a client is still connected, `false` otherwise.
|
||||
|
||||
## jerry_debugger_transport_receive_completed
|
||||
|
||||
**Summary**
|
||||
|
||||
Must be called after [jerry_debugger_transport_receive](#jerry_debugger_transport_receive)
|
||||
returns with a valid message. Must not be called otherwise.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void jerry_debugger_transport_receive_completed (jerry_debugger_transport_receive_context_t *context_p);
|
||||
```
|
||||
|
||||
- `context_p`: a [jerry_debugger_transport_receive_context_t](#jerry_debugger_transport_receive_context_t)
|
||||
passed to [jerry_debugger_transport_receive](#jerry_debugger_transport_receive).
|
||||
|
||||
## jerry_debugger_transport_sleep
|
||||
|
||||
**Summary**
|
||||
|
||||
Can be used to wait for incoming messages. Currently the delay is 100ms.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void jerry_debugger_transport_sleep (void);
|
||||
```
|
|
@ -0,0 +1,112 @@
|
|||
# Handle Scope
|
||||
|
||||
## jerryx_handle_scope
|
||||
|
||||
**Summary**
|
||||
It is often necessary to make the lifespan of handles shorter than the lifespan of a native method. Even though the native code could only use the most recent handle, all of the associated objects would also be kept alive since they all share the same scope.
|
||||
|
||||
To handle this case, JerryScript HandleScope extension provides the ability to establish a new 'scope' to which newly created handles will be associated. Once those handles are no longer required, the scope can be 'closed' and any handles associated with the scope are invalidated. The methods available to open/close scopes are `jerryx_open_handle_scope` and `jerryx_close_handle_scope`.
|
||||
|
||||
JerryScript only supports a single nested hierarchy of scopes. There is only one active scope at any time, and all new handles will be associated with that scope while it is active. Scopes must be closed in the reverse order from which they are opened. In addition, all scopes created within a native method must be closed before returning from that method.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handle-scope.h"
|
||||
|
||||
static jerry_value_t
|
||||
create_object (void)
|
||||
{
|
||||
jerry_value_t obj = jerry_create_object ();
|
||||
return obj;
|
||||
} /* create_object */
|
||||
|
||||
static void
|
||||
test_handle_scope_val (void)
|
||||
{
|
||||
jerryx_handle_scope scope;
|
||||
jerryx_open_handle_scope (&scope);
|
||||
jerry_value_t obj = jerryx_create_handle (create_object ());
|
||||
|
||||
jerryx_close_handle_scope (scope);
|
||||
// now obj has been released
|
||||
} /* test_handle_scope_val */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
test_handle_scope_val ();
|
||||
jerry_gc (JERRY_GC_PRESSURE_LOW);
|
||||
|
||||
jerry_cleanup ();
|
||||
} /* main */
|
||||
```
|
||||
|
||||
## jerryx_escapable_handle_scope
|
||||
|
||||
**Summary**
|
||||
|
||||
It is necessary in common cases that a handle has to be promote to outer scope and prevent from been garbage collected. To handle this case, a escapable handle scope has been proposed from which one object can be promoted to the outer scope. The method available to escape an object from been release at current scope is `jerryx_escape_handle`.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-ext/handle-scope.h"
|
||||
|
||||
static jerry_value_t
|
||||
create_object (void)
|
||||
{
|
||||
jerryx_escapable_handle_scope scope;
|
||||
jerryx_open_escapable_handle_scope (&scope);
|
||||
jerry_value_t obj = jerryx_create_handle (jerry_create_object ());
|
||||
|
||||
jerry_value_t escaped_obj;
|
||||
jerryx_escape_handle(scope, obj, &escaped_obj);
|
||||
jerryx_close_handle_scope (scope);
|
||||
// escaped_obj has now been escaped to outer scope, thus not released at this point
|
||||
|
||||
return escaped_obj;
|
||||
} /* create_object */
|
||||
|
||||
static void
|
||||
test_handle_scope_val (void)
|
||||
{
|
||||
jerryx_handle_scope scope;
|
||||
jerryx_open_handle_scope (&scope);
|
||||
jerry_value_t obj = create_object ();
|
||||
|
||||
jerryx_close_handle_scope (scope);
|
||||
// now obj has been released
|
||||
} /* test_handle_scope_val */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
test_handle_scope_val ();
|
||||
jerry_gc (JERRY_GC_PRESSURE_LOW);
|
||||
|
||||
jerry_cleanup ();
|
||||
} /* main */
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_value_t](../docs/02.API-REFERENCE.md#jerry_value_t)
|
||||
- [jerry_acquire_value](../docs/02.API-REFERENCE.md#jerry_acquire_value)
|
||||
- [jerry_release_value](../docs/02.API-REFERENCE.md#jerry_release_value)
|
||||
|
||||
## Pre-allocated list of handle scopes and handles
|
||||
|
||||
To prevent trapping into system calls frequently, a pre-allocated dedicated list mechanism has been introduced to the implementation of JerryX handle scope.
|
||||
|
||||
To change the size of pre-allocation list, use build definition `JERRYX_HANDLE_PRELIST_SIZE` and `JERRYX_SCOPE_PRELIST_SIZE` to alter the default value of 20.
|
|
@ -0,0 +1,159 @@
|
|||
# ES6 module support for JerryScript
|
||||
|
||||
The module system allows users to write import and export statements in scripts, which can be used to separate the logic of the application into custom modules.
|
||||
The standard's relevant part can be found [here](https://www.ecma-international.org/ecma-262/6.0/#sec-modules).
|
||||
Embedders wishing to use native builtin modules with ES6 imports can use the [Port API](05.PORT-API.md#jerry-module-system) to do so.
|
||||
|
||||
## General
|
||||
|
||||
If a script contains import statements, then JerryScript will open and evaluate the the referenced modules before the main script runs, resolving and creating bindings for the referenced identifiers in the process.
|
||||
It is not necessary to use any specific filename extensions for modules, JerryScript will try to open the given file paths as they are, but will try to normalize them before doing so. The exact normalization process is dependant on the port implementation provided. It is the user's responsibility to verify that the given files are valid EcmaScript modules.
|
||||
|
||||
main.js
|
||||
|
||||
```js
|
||||
import { exported_value } from "./module.js"
|
||||
|
||||
print (exported_value);
|
||||
```
|
||||
|
||||
module.js
|
||||
|
||||
```js
|
||||
var exported_value = 42;
|
||||
|
||||
export exported_value;
|
||||
```
|
||||
|
||||
## Supported features
|
||||
|
||||
* exporting identifiers from the module's lexical environment
|
||||
* specifying export names for the exported values
|
||||
* importing exported identifiers from a module
|
||||
* specifying local binding names for the imported values
|
||||
* module namespace imports
|
||||
* `import * as module from 'module.js`
|
||||
* indirect export statements
|
||||
* `export {variable} from 'module.js'`
|
||||
* star export statements
|
||||
* `export * from 'module.js'`
|
||||
* importing a module for side-effects
|
||||
* `import 'module.js'`
|
||||
* default import and export statements
|
||||
* `export default local_identifier`
|
||||
* `import def from 'module.js'`
|
||||
* anonymous default exports
|
||||
* `export default function () {}`
|
||||
|
||||
### Example
|
||||
|
||||
```js
|
||||
import {
|
||||
engine,
|
||||
version as v
|
||||
} from "./module.js"
|
||||
|
||||
import { getFeatureDetails } from "./module_2.js"
|
||||
|
||||
var version = "v3.1415";
|
||||
|
||||
print("> main.js");
|
||||
|
||||
print(">> Engine: " + engine);
|
||||
print(">> Version: " + v);
|
||||
|
||||
print (">> " + getFeatureDetails());
|
||||
print (">> Script version: " + version);
|
||||
```
|
||||
|
||||
```js
|
||||
// module.js
|
||||
var _engine = "JerryScript";
|
||||
export _engine as engine;
|
||||
|
||||
export var version = "1.0 (e92ae0fb)";
|
||||
```
|
||||
|
||||
```js
|
||||
// module_2.js
|
||||
var featureName = "EcmaScript modules";
|
||||
var year = 2018;
|
||||
|
||||
export function getFeatureDetails() {
|
||||
return "Feature name: " + featureName + " | developed in " + year;
|
||||
}
|
||||
```
|
||||
|
||||
### Module namespace import statements
|
||||
|
||||
A module namespace object can be imported. In this case the local binding will contain an object holding the exported values of the module, including local exports and all indirect exports. Ambiguous exported names are exluded from the namespace object.
|
||||
|
||||
```js
|
||||
import * as module from './module.js';
|
||||
|
||||
print(">> Engine: " + module.engine);
|
||||
print(">> Version: " + module.version);
|
||||
```
|
||||
|
||||
### Indirect export statements
|
||||
|
||||
An export statement can transitively export variables from another module, either via named indirect exports or a star export statement. In this case the resolving process will follow the chain until it reaches a module containing a local binding for that export name. If there are multiple modules which satisfy the export, that means the export is ambiguous, and will result in a SyntaxError.
|
||||
|
||||
```js
|
||||
import { a, b } from 'module.js'
|
||||
|
||||
print (a + b);
|
||||
```
|
||||
|
||||
```js
|
||||
// module.js
|
||||
export var a = 2;
|
||||
export { b } from 'module2.js'
|
||||
```
|
||||
|
||||
```js
|
||||
// module2.js
|
||||
export var b = 40;
|
||||
```
|
||||
|
||||
### Default imports and exports
|
||||
|
||||
Each module can optionally provide a single default export by using the `export default` statement. Default exports can either reference identifiers in the module's lexical environment, or be an anonymous default export, in which case they will only be accessible by an importing script.
|
||||
|
||||
```js
|
||||
import defaultExport, { b as c } from 'module.js'
|
||||
|
||||
print (defaultExport); // 2
|
||||
print (c ()); // 42
|
||||
```
|
||||
|
||||
```js
|
||||
// module.js
|
||||
export default 2;
|
||||
export function b () {
|
||||
return 42;
|
||||
}
|
||||
```
|
||||
|
||||
### Importing modules for side-effects
|
||||
|
||||
Evaluate a module without importing anything. Any errors encountered in the module will be propagated.
|
||||
|
||||
```js
|
||||
import 'module.js' // > module.js
|
||||
// "> module.js" is printed
|
||||
b (); // (ReferenceError) b is not defined
|
||||
```
|
||||
|
||||
```js
|
||||
// module.js
|
||||
export function b () {
|
||||
print ("> module.js");
|
||||
return 42;
|
||||
}
|
||||
b ();
|
||||
```
|
||||
|
||||
## Unsupported features
|
||||
|
||||
* **snapshot**
|
|
@ -0,0 +1,772 @@
|
|||
# Migration guide
|
||||
|
||||
This guide intends to describe the major changes between the JerryScript 1.0 and 2.0 versions.
|
||||
In addtion it is designed to provide a guide on how to modify the 1.0 version code to a
|
||||
2.0 compliant code.
|
||||
|
||||
During the development it was important to minimize the changes in the API functions and types.
|
||||
Each API method removal or chang is described below providing a ***before*** and ***after***
|
||||
code example.
|
||||
For more information on the current API methods please check the [API reference](02.API-REFERENCE.md) document.
|
||||
|
||||
# Short list of removed/renamed headers, types, functions, and macros
|
||||
|
||||
***Removed legacy headers***
|
||||
|
||||
- `jerry-internal.h`
|
||||
|
||||
***Renamed headers***
|
||||
|
||||
- `jerry-api.h` to `jerryscript.h`
|
||||
- `jerry-port.h` to `jerryscript-port.h`
|
||||
|
||||
***Removed API types***
|
||||
|
||||
- `jerry_char_ptr_t` usage replaced with `jerry_char_t *`
|
||||
- `jerry_object_free_callback_t` replaced by `jerry_object_native_free_callback_t`
|
||||
|
||||
***Removed API methods***
|
||||
|
||||
- `jerry_get_memory_limits`
|
||||
- `jerry_get_object_native_handle` replaced by `jerry_get_object_native_pointer`
|
||||
- `jerry_set_object_native_handle` replaced by `jerry_set_object_native_pointer`
|
||||
- `jerry_value_set_abort_flag` replaced by `jerry_create_abort_from_value`
|
||||
- `jerry_value_has_abort_flag` replaced by `jerry_value_is_abort`
|
||||
- `jerry_value_set_error_flag` replaced by `jerry_create_error_from_value`
|
||||
- `jerry_value_has_error_flag` replaced by `jerry_value_is_error`
|
||||
- `jerry_value_clear_error_flag` replaced by `jerry_get_value_from_error`
|
||||
- `jerry_get_value_without_error_flag` replaced by `jerry_get_value_from_error`
|
||||
- `jerry_parse_and_save_snapshot` replaced by `jerry_generate_snapshot`
|
||||
- `jerry_parse_and_save_function_snapshot` replaced by `jerry_generate_function_snapshot`
|
||||
|
||||
|
||||
***Removed unused configuration macros***
|
||||
|
||||
- `CONFIG_MEM_DATA_LIMIT_MINUS_HEAP_SIZE`
|
||||
- `CONFIG_MEM_STACK_LIMIT`
|
||||
- `CONFIG_VM_STACK_FRAME_INLINED_VALUES_NUMBER`
|
||||
- `CONFIG_ECMA_GLOBAL_ENVIRONMENT_DECLARATIVE`
|
||||
- All `CONFIG_..` macros have been renamed to use the `JERRY_` prefix format.
|
||||
|
||||
|
||||
# Modified API functions
|
||||
|
||||
## Error manipulating functions
|
||||
|
||||
The most important changes in the API are releated to error handling and manipulation.
|
||||
|
||||
### jerry_value_set_abort_flag
|
||||
|
||||
This function was replaced with [`jerry_create_abort_from_value`](02.API-REFERENCE.md#jerry_create_abort_from_value).
|
||||
Take note of the second argument of the new `jerry_create_abort_from_value` function which controls if the
|
||||
first argument should be usable after the call or not.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_set_abort_flag (&value);
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_t abort = jerry_create_abort_from_value (value, true);
|
||||
// using the 'value' variable after release is invalid
|
||||
|
||||
jerry_release_value (abort);
|
||||
}
|
||||
```
|
||||
|
||||
- OR
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
... // create or acquire value
|
||||
|
||||
jerry_value_t abort = jerry_create_abort_from_value (value, false);
|
||||
// both 'abort' and 'value' can be used and must be released when they are no longer needed
|
||||
|
||||
jerry_release_value (abort);
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_value_has_abort_flag
|
||||
|
||||
This function was renamed to [`jerry_value_is_abort`](02.API-REFERENCE.md#jerry_value_is_abort).
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
if (jerry_value_has_abort_flag (value))
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
if (jerry_value_is_abort (value))
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_value_set_error_flag
|
||||
|
||||
This function was replaced with [`jerry_create_error_from_value`](02.API-REFERENCE.md#jerry_create_error_from_value).
|
||||
Take note of the second argument of the new `jerry_create_error_from_value` function which controls if the
|
||||
first argument should be usable after the call or not.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_set_error_flag (&value);
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_t error = jerry_create_error_from_value (value, true);
|
||||
// using the 'value' variable after release is invalid
|
||||
|
||||
jerry_release_value (error);
|
||||
}
|
||||
```
|
||||
|
||||
- OR
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_t error = jerry_create_error_from_value (value, false);
|
||||
// both 'error' and 'value' can be used and must be released when they are no longer needed
|
||||
|
||||
jerry_release_value (error);
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_value_has_error_flag
|
||||
|
||||
This function was renamed to [`jerry_value_is_error`](02.API-REFERENCE.md#jerry_value_is_error).
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
if (jerry_value_has_error_flag (value))
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
if (jerry_value_is_error (value))
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_value_clear_error_flag AND jerry_get_value_without_error_flag
|
||||
|
||||
These functions were merged into [`jerry_get_value_from_error`](02.API-REFERENCE.md#jerry_get_value_from_error).
|
||||
Please note the second argument of the new function which controls if the first argument passed should be released
|
||||
or not.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_set_error_flag (&value);
|
||||
jerry_value_clear_error_flag (&value);
|
||||
// or
|
||||
jerry_value_t real_value = jerry_get_value_without_error_flag (value);
|
||||
|
||||
jerry_release_value (value);
|
||||
jerry_release_value (real_value);
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
// create or acquire value
|
||||
// ...
|
||||
|
||||
jerry_value_t error = jerry_create_error_from_value (value, true);
|
||||
|
||||
jerry_value_t real_value = jerry_get_value_from_error (error, true);
|
||||
|
||||
jerry_release_value (real_value);
|
||||
}
|
||||
```
|
||||
|
||||
## Other functions changed
|
||||
|
||||
### jerry_register_magic_strings
|
||||
|
||||
In case of the `jerry_register_magic_strings` function the change is that
|
||||
the first argument's base type `jerry_char_ptr_t` was changed to `jerry_char_t*`.
|
||||
For more details see: [`jerry_register_magic_strings`](02.API-REFERENCE.md#jerry_register_magic_strings).
|
||||
|
||||
In the following code parts please take note of the type used for the `magic_string_items` array.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
// must be static, because 'jerry_register_magic_strings' does not copy
|
||||
// the items must be sorted by size at first, then lexicographically
|
||||
static const jerry_char_ptr_t magic_string_items[] = {
|
||||
(const jerry_char_ptr_t) "magicstring1",
|
||||
(const jerry_char_ptr_t) "magicstring2",
|
||||
(const jerry_char_ptr_t) "magicstring3"
|
||||
};
|
||||
uint32_t num_magic_string_items = (uint32_t) (sizeof (magic_string_items) / sizeof (jerry_char_ptr_t));
|
||||
|
||||
// must be static, because 'jerry_register_magic_strings' does not copy
|
||||
static const jerry_length_t magic_string_lengths[] = { 12, 12, 12 };
|
||||
jerry_register_magic_strings (magic_string_items, num_magic_string_items, magic_string_lengths);
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
// must be static, because 'jerry_register_magic_strings' does not copy
|
||||
// the items must be sorted by size at first, then lexicographically
|
||||
static const jerry_char_t *magic_string_items[] = {
|
||||
(const jerry_char_t *) "magicstring1",
|
||||
(const jerry_char_t *) "magicstring2",
|
||||
(const jerry_char_t *) "magicstring3"
|
||||
};
|
||||
uint32_t num_magic_string_items = (uint32_t) (sizeof (magic_string_items) / sizeof (jerry_char_t *));
|
||||
|
||||
// must be static, because 'jerry_register_magic_strings' does not copy
|
||||
static const jerry_length_t magic_string_lengths[] = { 12, 12, 12 };
|
||||
jerry_register_magic_strings (magic_string_items, num_magic_string_items, magic_string_lengths);
|
||||
}
|
||||
```
|
||||
|
||||
## Snapshot generating API
|
||||
|
||||
### jerry_parse_and_save_snapshot
|
||||
|
||||
This function was replaced with [`jerry_generate_snapshot`](02.API-REFERENCE.md#jerry_generate_snapshot).
|
||||
The function returns an error object if there was any problem during snapshot generation and
|
||||
if there was no problem the return value is a number value containing the snapshot size in bytes.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
static uint32_t global_mode_snapshot_buffer[256];
|
||||
const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();";
|
||||
|
||||
size_t global_mode_snapshot_size =
|
||||
jerry_parse_and_save_snapshot (code_to_snapshot_p,
|
||||
strlen ((const char *) code_to_snapshot_p),
|
||||
true,
|
||||
false,
|
||||
global_mode_snapshot_buffer,
|
||||
sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t));
|
||||
// use "global_mode_snapshot_buffer"
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
static uint32_t global_mode_snapshot_buffer[256];
|
||||
const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();";
|
||||
|
||||
jerry_value_t generate_result;
|
||||
generate_result = jerry_generate_snapshot (NULL,
|
||||
0,
|
||||
code_to_snapshot_p,
|
||||
strlen ((const char *) code_to_snapshot_p),
|
||||
global_mode_snapshot_buffer,
|
||||
sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t));
|
||||
if (jerry_value_is_error (generate_result))
|
||||
{
|
||||
// There was a problem during snapshot generation, for example there is a SyntaxError.
|
||||
// Use the "generate_result" to check the error.
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
|
||||
// use "global_mode_snapshot_buffer"
|
||||
}
|
||||
jerry_release_value (generate_result);
|
||||
}
|
||||
```
|
||||
|
||||
### jerry_parse_and_save_function_snapshot
|
||||
|
||||
This function was replaced with [`jerry_generate_function_snapshot`](02.API-REFERENCE.md#jerry_parse_and_save_function_snapshot).
|
||||
The function returns an error object if there was any problem during snapshot generation and
|
||||
if there was no problem the return value is a number value containing the snapshot size in bytes.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
static uint32_t func_snapshot_buffer[1024];
|
||||
|
||||
const jerry_char_t *args_p = (const jerry_char_t *) "a, b";
|
||||
const jerry_char_t *src_p = (const jerry_char_t *) "return a + b;";
|
||||
|
||||
size_t func_snapshot_size =
|
||||
jerry_parse_and_save_function_snapshot (src_p,
|
||||
strlen ((const char *) src_p),
|
||||
args_p,
|
||||
strlen ((const char *) args_p),
|
||||
false,
|
||||
func_snapshot_buffer,
|
||||
sizeof (func_snapshot_buffer) / sizeof (uint32_t));
|
||||
// check "function_snapshot_size" and use "func_snapshot_buffer"
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
static uint32_t func_snapshot_buffer[1024];
|
||||
|
||||
const jerry_char_t *args_p = (const jerry_char_t *) "a, b";
|
||||
const jerry_char_t *src_p = (const jerry_char_t *) "return a + b;";
|
||||
|
||||
jerry_value_t generate_result;
|
||||
generate_result = jerry_generate_function_snapshot (NULL,
|
||||
0,
|
||||
src_p,
|
||||
strlen ((const char *) src_p),
|
||||
args_p,
|
||||
strlen ((const char *) args_p),
|
||||
0,
|
||||
func_snapshot_buffer,
|
||||
sizeof (func_snapshot_buffer) / sizeof (uint32_t));
|
||||
if (jerry_value_is_error (generate_result))
|
||||
{
|
||||
// There was a problem during snapshot generation, for example there is a SyntaxError.
|
||||
// Use the "generate_result" to check the error.
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
|
||||
// use "func_snapshot_buffer"
|
||||
}
|
||||
|
||||
jerry_release_value (generate_result)
|
||||
}
|
||||
```
|
||||
|
||||
## Garbage collection
|
||||
|
||||
### jerry_gc
|
||||
|
||||
The [`jerry_gc`](02.API-REFERENCE.md#jerry_gc) function was modified to handle an argument which represents the pressure for the garbage collector.
|
||||
For more information checkout the [`jerry_gc_mode_t`](02.API-REFERENCE.md#jerry_gc_mode_t) reference.
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_gc ();
|
||||
}
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_gc (JERRY_GC_PRESSURE_LOW);
|
||||
}
|
||||
```
|
||||
|
||||
## jerry_eval
|
||||
|
||||
The third argument of [`jerry_eval`](02.API-REFERENCE.md#jerry_eval) has been changed
|
||||
from `bool` to [`jerry_parse_opts_t`](02.API-REFERENCE.md#jerry_parse_opts_t).
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
const jerry_char_t *str_to_eval = (const jerry_char_t *) "1 + 1";
|
||||
jerry_value_t ret_val = jerry_eval (str_to_eval,
|
||||
strlen ((const char *) str_to_eval),
|
||||
false);
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
const jerry_char_t *str_to_eval = (const jerry_char_t *) "1 + 1";
|
||||
jerry_value_t ret_val = jerry_eval (str_to_eval,
|
||||
strlen ((const char *) str_to_eval),
|
||||
JERRY_PARSE_NO_OPTS);
|
||||
```
|
||||
|
||||
## Port API
|
||||
|
||||
### jerry_port_get_time_zone
|
||||
|
||||
The port API of handling timezones has been changed. The previous interface did not
|
||||
allow timezones to be handled correctly, even if the host system was up to the task.
|
||||
Check [the related issue](https://github.com/jerryscript-project/jerryscript/issues/1661)
|
||||
for more details.
|
||||
|
||||
The new port API function name is [jerry_port_get_local_time_zone_adjustment](05.PORT-API.md#date-1].
|
||||
|
||||
Below is the default implementations for both versions:
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
bool jerry_port_get_time_zone (jerry_time_zone_t *tz_p)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
/* gettimeofday may not fill tz, so zero-initializing */
|
||||
tz.tz_minuteswest = 0;
|
||||
tz.tz_dsttime = 0;
|
||||
|
||||
if (gettimeofday (&tv, &tz) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tz_p->offset = tz.tz_minuteswest;
|
||||
tz_p->daylight_saving_time = tz.tz_dsttime > 0 ? 1 : 0;
|
||||
|
||||
return true;
|
||||
} /* jerry_port_get_time_zone */
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
double jerry_port_get_local_time_zone_adjustment (double unix_ms,
|
||||
bool is_utc)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t now = (time_t) (unix_ms / 1000);
|
||||
localtime_r (&now, &tm);
|
||||
if (!is_utc)
|
||||
{
|
||||
now -= tm.tm_gmtoff;
|
||||
localtime_r (&now, &tm);
|
||||
}
|
||||
return ((double) tm.tm_gmtoff) * 1000;
|
||||
} /* jerry_port_get_local_time_zone_adjustment */
|
||||
```
|
||||
|
||||
## Native pointers
|
||||
|
||||
The assignment of native pointers (previously called handles) have been changed
|
||||
since v1.0. In the previous version only one native pointer could be assigned to
|
||||
a `jerry_value_t`. Now it is allowed to register multiple native infos, which
|
||||
can be accessed with the corresponding
|
||||
[`jerry_object_native_info_t`](02.API-REFERENCE.md#jerry_object_native_info_t).
|
||||
The old functions were removed and replaced by new ones.
|
||||
|
||||
- `jerry_object_free_callback_t` callback type is replaced by `jerry_object_native_info_t`
|
||||
- `jerry_get_object_native_handle` is replaced by [`jerry_get_object_native_pointer`](02.API-REFERENCE.md#jerry_get_object_native_pointer)
|
||||
- `jerry_set_object_native_handle` is replaced by [`jerry_set_object_native_pointer`](02.API-REFERENCE.md#jerry_set_object_native_pointer)
|
||||
|
||||
**Before**
|
||||
|
||||
```c
|
||||
struct
|
||||
{
|
||||
int data;
|
||||
} my_info;
|
||||
|
||||
static void
|
||||
handler_construct_freecb (uintptr_t native_p)
|
||||
{
|
||||
// Invoked when the JS object is released and the
|
||||
// native data should be freed.
|
||||
|
||||
struct my_info *info = (struct my_info *) native_p;
|
||||
free (info);
|
||||
}
|
||||
|
||||
void
|
||||
demo (void)
|
||||
{
|
||||
jerry_value_t this_val;
|
||||
// create or acquire this_val
|
||||
// ...
|
||||
|
||||
struct my_info *info = (struct my_info *) malloc (sizeof (struct my_info));
|
||||
info->data = 11;
|
||||
|
||||
// setting the native handle
|
||||
jerry_set_object_native_handle (this_val,
|
||||
(uintptr_t) info,
|
||||
handler_construct_freecb);
|
||||
// ...
|
||||
// reading back the native handle
|
||||
uintptr_t ptr = (uintptr_t) NULL;
|
||||
bool is_ok = jerry_get_object_native_handle (this_val, &ptr);
|
||||
if (is_ok)
|
||||
{
|
||||
struct my_info *obj_info = (struct my_info *) ptr;
|
||||
// use "obj_info"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**After**
|
||||
|
||||
```c
|
||||
struct
|
||||
{
|
||||
int data;
|
||||
} my_info;
|
||||
|
||||
static void
|
||||
handler_construct_freecb (void *native_p)
|
||||
{
|
||||
// Invoked when the JS object is released and the
|
||||
// native data should be freed.
|
||||
|
||||
struct my_info *info = (struct my_info *) native_p;
|
||||
free (info);
|
||||
}
|
||||
|
||||
static const jerry_object_native_info_t my_info_type_info =
|
||||
{
|
||||
.free_cb = handler_construct_freecb
|
||||
};
|
||||
|
||||
void
|
||||
demo (void)
|
||||
{
|
||||
jerry_value_t this_val;
|
||||
// create or acquire this_val
|
||||
// ...
|
||||
|
||||
struct my_info *info = (struct my_info *) malloc (sizeof (struct my_info));
|
||||
info->data = 11;
|
||||
|
||||
// setting the native handle
|
||||
jerry_set_object_native_pointer (this_val,
|
||||
info,
|
||||
&my_info_type_info);
|
||||
// ...
|
||||
// reading back the native handle pointed by the "my_info_type_info" variable
|
||||
void *ptr = NULL;
|
||||
bool has_p = jerry_get_object_native_pointer (this_val, &ptr, &my_info_type_info);
|
||||
if (has_p)
|
||||
{
|
||||
struct my_info *obj_info = (struct my_info *) ptr;
|
||||
// use "obj_info"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# New API functions
|
||||
|
||||
In this section the new API functions are listed.
|
||||
|
||||
## Built-in objects
|
||||
|
||||
***ArrayBuffer***
|
||||
|
||||
- [`jerry_create_arraybuffer`](02.API-REFERENCE.md#jerry_create_arraybuffer)
|
||||
- [`jerry_create_arraybuffer_external`](02.API-REFERENCE.md#jerry_create_arraybuffer_external)
|
||||
- [`jerry_get_arraybuffer_pointer`](02.API-REFERENCE.md#jerry_get_arraybuffer_pointer)
|
||||
|
||||
***DataView***
|
||||
|
||||
- [`jerry_create_dataview`](02.API-REFERENCE.md#jerry_create_dataview)
|
||||
- [`jerry_value_is_dataview`](02.API-REFERENCE.md#jerry_value_is_dataview)
|
||||
- [`jerry_get_dataview_buffer`](02.API-REFERENCE.md#jerry_get_dataview_buffer)
|
||||
|
||||
***JSON***
|
||||
|
||||
- [`jerry_json_parse`](02.API-REFERENCE.md#jerry_json_parse)
|
||||
- [`jerry_json_stringify`](02.API-REFERENCE.md#jerry_json_stringify)
|
||||
|
||||
***Number***
|
||||
|
||||
- [`jerry_create_number_infinity`](02.API-REFERENCE.md#jerry_create_number_infinity)
|
||||
- [`jerry_create_number_nan`](02.API-REFERENCE.md#jerry_create_number_nan)
|
||||
|
||||
***Promise***
|
||||
|
||||
- [`jerry_run_all_enqueued_jobs`](02.API-REFERENCE.md#jerry_run_all_enqueued_jobs)
|
||||
- [`jerry_create_promise`](02.API-REFERENCE.md#jerry_create_promise)
|
||||
- [`jerry_resolve_or_reject_promise`](02.API-REFERENCE.md#jerry_resolve_or_reject_promise)
|
||||
- [`jerry_value_is_promise`](02.API-REFERENCE.md#jerry_value_is_promise)
|
||||
|
||||
***RegExp***
|
||||
|
||||
- [`jerry_create_regexp`](02.API-REFERENCE.md#jerry_create_regexp)
|
||||
- [`jerry_create_regexp_sz`](02.API-REFERENCE.md#jerry_create_regexp_sz)
|
||||
|
||||
***String***
|
||||
|
||||
- [`jerry_substring_to_utf8_char_buffer`](02.API-REFERENCE.md#jerry_substring_to_utf8_char_buffer)
|
||||
- [`jerry_get_utf8_string_size`](02.API-REFERENCE.md#jerry_get_utf8_string_size)
|
||||
- [`jerry_get_utf8_string_length`](02.API-REFERENCE.md#jerry_get_utf8_string_length)
|
||||
- [`jerry_create_string_from_utf8`](02.API-REFERENCE.md#jerry_create_string_from_utf8)
|
||||
- [`jerry_create_string_sz_from_utf8`](02.API-REFERENCE.md#jerry_create_string_sz_from_utf8)
|
||||
|
||||
***Symbol***
|
||||
|
||||
- [`jerry_create_symbol`](02.API-REFERENCE.md#jerry_create_symbol)
|
||||
- [`jerry_get_symbol_descriptive_string`](02.API-REFERENCE.md#jerry_get_symbol_descriptive_string)
|
||||
- [`jerry_value_is_symbol`](02.API-REFERENCE.md#jerry_value_is_symbol)
|
||||
|
||||
***TypedArray***
|
||||
|
||||
- [`jerry_create_typedarray`](02.API-REFERENCE.md#jerry_create_typedarray)
|
||||
- [`jerry_create_typedarray_for_arraybuffer`](02.API-REFERENCE.md#jerry_create_typedarray_for_arraybuffer)
|
||||
- [`jerry_create_typedarray_for_arraybuffer_sz`](02.API-REFERENCE.md#jerry_create_typedarray_for_arraybuffer_sz)
|
||||
- [`jerry_get_typedarray_type`](02.API-REFERENCE.md#jerry_get_typedarray_type)
|
||||
- [`jerry_get_typedarray_length`](02.API-REFERENCE.md#jerry_get_typedarray_length)
|
||||
- [`jerry_get_typedarray_buffer`](02.API-REFERENCE.md#jerry_get_typedarray_buffer)
|
||||
- [`jerry_value_is_typedarray`](02.API-REFERENCE.md#jerry_value_is_typedarray)
|
||||
|
||||
|
||||
## Instances and memory management
|
||||
|
||||
***JerryScript instances***
|
||||
|
||||
- [`jerry_create_context`](02.API-REFERENCE.md#jerry_create_context)
|
||||
- [`jerry_get_context_data`](02.API-REFERENCE.md#jerry_get_context_data)
|
||||
|
||||
***Memory management***
|
||||
|
||||
- [`jerry_heap_alloc`](02.API-REFERENCE.md#jerry_heap_alloc)
|
||||
- [`jerry_heap_free`](02.API-REFERENCE.md#jerry_heap_free)
|
||||
|
||||
|
||||
## Operations with JavaScript values
|
||||
|
||||
***Binary operations***
|
||||
|
||||
- [`jerry_binary_operation`](02.API-REFERENCE.md#jerry_binary_operation)
|
||||
|
||||
***Error manipulating***
|
||||
|
||||
- [`jerry_get_error_type`](02.API-REFERENCE.md#jerry_get_error_type)
|
||||
- [`jerry_get_backtrace`](02.API-REFERENCE.md#jerry_get_backtrace)
|
||||
|
||||
***Native pointers***
|
||||
|
||||
- [`jerry_delete_object_native_pointer`](02.API-REFERENCE.md#jerry_delete_object_native_pointer)
|
||||
- [`jerry_objects_foreach_by_native_info`](02.API-REFERENCE.md#jerry_objects_foreach_by_native_info)
|
||||
|
||||
***Property***
|
||||
|
||||
- [`jerry_delete_property_by_index`](02.API-REFERENCE.md#jerry_delete_property_by_index)
|
||||
- [`jerry_objects_foreach`](02.API-REFERENCE.md#jerry_objects_foreach)
|
||||
|
||||
|
||||
## Debugger
|
||||
|
||||
- [`jerry_debugger_is_connected`](07.DEBUGGER.md#jerry_debugger_is_connected)
|
||||
- [`jerry_debugger_stop`](07.DEBUGGER.md#jerry_debugger_stop)
|
||||
- [`jerry_debugger_continue`](07.DEBUGGER.md#jerry_debugger_continue)
|
||||
- [`jerry_debugger_stop_at_breakpoint`](07.DEBUGGER.md#jerry_debugger_stop_at_breakpoint)
|
||||
- [`jerry_debugger_wait_for_client_source`](07.DEBUGGER.md#jerry_debugger_wait_for_client_source)
|
||||
- [`jerry_debugger_send_output`](07.DEBUGGER.md#jerry_debugger_send_output)
|
||||
- [`jerry_debugger_send_log`](07.DEBUGGER.md#jerry_debugger_send_log)
|
||||
|
||||
|
||||
## Other
|
||||
|
||||
- [`jerry_is_feature_enabled`](02.API-REFERENCE.md#jerry_is_feature_enabled)
|
||||
- [`jerry_parse_and_save_literals`](02.API-REFERENCE.md#jerry_parse_and_save_literals)
|
||||
- [`jerry_set_vm_exec_stop_callback`](02.API-REFERENCE.md#jerry_set_vm_exec_stop_callback)
|
||||
|
||||
|
||||
## Port API functions
|
||||
|
||||
- [`jerry_port_normalize_path`](05.PORT-API.md#jerry_port_normalize_path)
|
||||
- [`jerry_port_read_source`](05.PORT-API.md#jerry_port_read_source)
|
||||
- [`jerry_port_release_source`](05.PORT-API.md#jerry_port_release_source)
|
||||
- [`jerry_port_print_char`](05.PORT-API.md#jerry_port_print_char)
|
||||
- [`jerry_port_get_current_context`](05.PORT-API.md#jerry_port_get_current_context)
|
||||
- [`jerry_port_fatal`](05.PORT-API.md#jerry_port_fatal)
|
||||
- [`jerry_port_sleep`](05.PORT-API.md#jerry_port_sleep)
|
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 54 KiB |
|
@ -0,0 +1,739 @@
|
|||
# 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.
|
||||
|
||||
cmake_minimum_required (VERSION 2.8.12)
|
||||
set(JERRY_CORE_NAME jerry-core)
|
||||
project (${JERRY_CORE_NAME} C)
|
||||
|
||||
include(CheckLibraryExists)
|
||||
|
||||
# Optional features
|
||||
set(JERRY_CPOINTER_32_BIT OFF CACHE BOOL "Enable 32 bit compressed pointers?")
|
||||
set(JERRY_DEBUGGER OFF CACHE BOOL "Enable JerryScript debugger?")
|
||||
set(JERRY_ERROR_MESSAGES OFF CACHE BOOL "Enable error messages?")
|
||||
set(JERRY_EXTERNAL_CONTEXT OFF CACHE BOOL "Enable external context?")
|
||||
set(JERRY_PARSER ON CACHE BOOL "Enable javascript-parser?")
|
||||
set(JERRY_LINE_INFO OFF CACHE BOOL "Enable line info?")
|
||||
set(JERRY_LOGGING OFF CACHE BOOL "Enable logging?")
|
||||
set(JERRY_MEM_STATS OFF CACHE BOOL "Enable memory statistics?")
|
||||
set(JERRY_MEM_GC_BEFORE_EACH_ALLOC OFF CACHE BOOL "Enable mem-stress test?")
|
||||
set(JERRY_PARSER_DUMP_BYTE_CODE OFF CACHE BOOL "Enable parser byte-code dumps?")
|
||||
set(JERRY_PROFILE "es.next" CACHE STRING "Use default or other profile?")
|
||||
set(JERRY_REGEXP_STRICT_MODE OFF CACHE BOOL "Enable regexp strict mode?")
|
||||
set(JERRY_REGEXP_DUMP_BYTE_CODE OFF CACHE BOOL "Enable regexp byte-code dumps?")
|
||||
set(JERRY_SNAPSHOT_EXEC OFF CACHE BOOL "Enable executing snapshot files?")
|
||||
set(JERRY_SNAPSHOT_SAVE OFF CACHE BOOL "Enable saving snapshot files?")
|
||||
set(JERRY_SYSTEM_ALLOCATOR OFF CACHE BOOL "Enable system allocator?")
|
||||
set(JERRY_VALGRIND OFF CACHE BOOL "Enable Valgrind support?")
|
||||
set(JERRY_VM_EXEC_STOP OFF CACHE BOOL "Enable VM execution stopping?")
|
||||
set(JERRY_GLOBAL_HEAP_SIZE "(512)" CACHE STRING "Size of memory heap, in kilobytes")
|
||||
set(JERRY_GC_LIMIT "(0)" CACHE STRING "Heap usage limit to trigger garbage collection")
|
||||
set(JERRY_STACK_LIMIT "(0)" CACHE STRING "Maximum stack usage size, in kilobytes")
|
||||
set(JERRY_GC_MARK_LIMIT "(8)" CACHE STRING "Maximum depth of recursion during GC mark phase")
|
||||
|
||||
# Option overrides
|
||||
if(JERRY_SYSTEM_ALLOCATOR)
|
||||
set(JERRY_CPOINTER_32_BIT ON)
|
||||
|
||||
set(JERRY_CPOINTER_32_BIT_MESSAGE " (FORCED BY SYSTEM ALLOCATOR)")
|
||||
endif()
|
||||
|
||||
if (JERRY_GLOBAL_HEAP_SIZE GREATER 512)
|
||||
set(JERRY_CPOINTER_32_BIT ON)
|
||||
|
||||
set(JERRY_CPOINTER_32_BIT_MESSAGE " (FORCED BY HEAP SIZE)")
|
||||
endif()
|
||||
|
||||
if(NOT JERRY_PARSER)
|
||||
set(JERRY_SNAPSHOT_EXEC ON)
|
||||
set(JERRY_PARSER_DUMP OFF)
|
||||
|
||||
set(JERRY_SNAPSHOT_EXEC_MESSAGE " (FORCED BY DISABLED JS PARSER)")
|
||||
set(JERRY_PARSER_DUMP_MESSAGE " (FORCED BY DISABLED JS PARSER)")
|
||||
endif()
|
||||
|
||||
if(JERRY_CMDLINE_SNAPSHOT)
|
||||
set(JERRY_SNAPSHOT_SAVE ON)
|
||||
|
||||
set(JERRY_SNAPSHOT_SAVE_MESSAGE " (FORCED BY SNAPSHOT TOOL)")
|
||||
endif()
|
||||
|
||||
if(JERRY_MEM_STATS OR JERRY_PARSER_DUMP_BYTE_CODE OR JERRY_REGEXP_DUMP_BYTE_CODE)
|
||||
set(JERRY_LOGGING ON)
|
||||
|
||||
set(JERRYRE_LOGGING_MESSAGE " (FORCED BY STATS OR DUMP)")
|
||||
endif()
|
||||
|
||||
# Status messages
|
||||
message(STATUS "JERRY_CPOINTER_32_BIT " ${JERRY_CPOINTER_32_BIT} ${JERRY_CPOINTER_32_BIT_MESSAGE})
|
||||
message(STATUS "JERRY_DEBUGGER " ${JERRY_DEBUGGER})
|
||||
message(STATUS "JERRY_ERROR_MESSAGES " ${JERRY_ERROR_MESSAGES})
|
||||
message(STATUS "JERRY_EXTERNAL_CONTEXT " ${JERRY_EXTERNAL_CONTEXT})
|
||||
message(STATUS "JERRY_PARSER " ${JERRY_PARSER})
|
||||
message(STATUS "JERRY_LINE_INFO " ${JERRY_LINE_INFO})
|
||||
message(STATUS "JERRY_LOGGING " ${JERRY_LOGGING} ${JERRY_LOGGING_MESSAGE})
|
||||
message(STATUS "JERRY_MEM_STATS " ${JERRY_MEM_STATS})
|
||||
message(STATUS "JERRY_MEM_GC_BEFORE_EACH_ALLOC " ${JERRY_MEM_GC_BEFORE_EACH_ALLOC})
|
||||
message(STATUS "JERRY_PARSER_DUMP_BYTE_CODE " ${JERRY_PARSER_DUMP_BYTE_CODE} ${JERRY_PARSER_DUMP_MESSAGE})
|
||||
message(STATUS "JERRY_PROFILE " ${JERRY_PROFILE})
|
||||
message(STATUS "JERRY_REGEXP_STRICT_MODE " ${JERRY_REGEXP_STRICT_MODE})
|
||||
message(STATUS "JERRY_REGEXP_DUMP_BYTE_CODE " ${JERRY_REGEXP_DUMP_BYTE_CODE})
|
||||
message(STATUS "JERRY_SNAPSHOT_EXEC " ${JERRY_SNAPSHOT_EXEC} ${JERRY_SNAPSHOT_EXEC_MESSAGE})
|
||||
message(STATUS "JERRY_SNAPSHOT_SAVE " ${JERRY_SNAPSHOT_SAVE} ${JERRY_SNAPSHOT_SAVE_MESSAGE})
|
||||
message(STATUS "JERRY_SYSTEM_ALLOCATOR " ${JERRY_SYSTEM_ALLOCATOR})
|
||||
message(STATUS "JERRY_VALGRIND " ${JERRY_VALGRIND})
|
||||
message(STATUS "JERRY_VM_EXEC_STOP " ${JERRY_VM_EXEC_STOP})
|
||||
message(STATUS "JERRY_GLOBAL_HEAP_SIZE " ${JERRY_GLOBAL_HEAP_SIZE})
|
||||
message(STATUS "JERRY_GC_LIMIT " ${JERRY_GC_LIMIT})
|
||||
message(STATUS "JERRY_STACK_LIMIT " ${JERRY_STACK_LIMIT})
|
||||
message(STATUS "JERRY_GC_MARK_LIMIT " ${JERRY_GC_MARK_LIMIT})
|
||||
|
||||
# Include directories
|
||||
set(INCLUDE_CORE_PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
set(INCLUDE_CORE_PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/api"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/debugger"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ecma/base"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ecma/builtin-objects"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ecma/builtin-objects/typedarray"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ecma/operations"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/jcontext"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/jmem"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/jrt"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lit"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/parser/js"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/parser/regexp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/vm")
|
||||
|
||||
set(INCLUDE_CORE_PUBLIC ${INCLUDE_CORE_PUBLIC} PARENT_SCOPE) # for jerry-port
|
||||
set(INCLUDE_CORE_PRIVATE ${INCLUDE_CORE_PRIVATE} PARENT_SCOPE) # for tests/unit-core
|
||||
|
||||
# Sources
|
||||
# Jerry core
|
||||
set(SOURCE_CORE_FILES
|
||||
api/jerry-debugger-transport.c
|
||||
api/jerry-debugger.c
|
||||
api/jerry-snapshot.c
|
||||
api/jerry.c
|
||||
debugger/debugger.c
|
||||
ecma/base/ecma-alloc.c
|
||||
ecma/base/ecma-gc.c
|
||||
ecma/base/ecma-helpers-collection.c
|
||||
ecma/base/ecma-helpers-conversion.c
|
||||
ecma/base/ecma-helpers-errol.c
|
||||
ecma/base/ecma-helpers-external-pointers.c
|
||||
ecma/base/ecma-helpers-number.c
|
||||
ecma/base/ecma-helpers-string.c
|
||||
ecma/base/ecma-helpers-value.c
|
||||
ecma/base/ecma-helpers.c
|
||||
ecma/base/ecma-init-finalize.c
|
||||
ecma/base/ecma-lcache.c
|
||||
ecma/base/ecma-literal-storage.c
|
||||
ecma/base/ecma-module.c
|
||||
ecma/base/ecma-property-hashmap.c
|
||||
ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.c
|
||||
ecma/builtin-objects/ecma-builtin-array-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-array.c
|
||||
ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-arraybuffer.c
|
||||
ecma/builtin-objects/ecma-builtin-async-function-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-async-function.c
|
||||
ecma/builtin-objects/ecma-builtin-async-generator-function.c
|
||||
ecma/builtin-objects/ecma-builtin-async-generator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-async-generator.c
|
||||
ecma/builtin-objects/ecma-builtin-async-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-bigint-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-bigint.c
|
||||
ecma/builtin-objects/ecma-builtin-boolean-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-boolean.c
|
||||
ecma/builtin-objects/ecma-builtin-dataview-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-dataview.c
|
||||
ecma/builtin-objects/ecma-builtin-date-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-date.c
|
||||
ecma/builtin-objects/ecma-builtin-error-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-error.c
|
||||
ecma/builtin-objects/ecma-builtin-evalerror-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-evalerror.c
|
||||
ecma/builtin-objects/ecma-builtin-function-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-function.c
|
||||
ecma/builtin-objects/ecma-builtin-generator-function.c
|
||||
ecma/builtin-objects/ecma-builtin-generator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-generator.c
|
||||
ecma/builtin-objects/ecma-builtin-global.c
|
||||
ecma/builtin-objects/ecma-builtin-handlers.c
|
||||
ecma/builtin-objects/ecma-builtin-helpers-date.c
|
||||
ecma/builtin-objects/ecma-builtin-helpers-error.c
|
||||
ecma/builtin-objects/ecma-builtin-helpers-json.c
|
||||
ecma/builtin-objects/ecma-builtin-helpers-sort.c
|
||||
ecma/builtin-objects/ecma-builtin-helpers.c
|
||||
ecma/builtin-objects/ecma-builtin-intrinsic.c
|
||||
ecma/builtin-objects/ecma-builtin-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-json.c
|
||||
ecma/builtin-objects/ecma-builtin-map-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-map-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-map.c
|
||||
ecma/builtin-objects/ecma-builtin-math.c
|
||||
ecma/builtin-objects/ecma-builtin-number-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-number.c
|
||||
ecma/builtin-objects/ecma-builtin-object-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-object.c
|
||||
ecma/builtin-objects/ecma-builtin-promise-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-promise.c
|
||||
ecma/builtin-objects/ecma-builtin-proxy.c
|
||||
ecma/builtin-objects/ecma-builtin-rangeerror-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-rangeerror.c
|
||||
ecma/builtin-objects/ecma-builtin-referenceerror-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-referenceerror.c
|
||||
ecma/builtin-objects/ecma-builtin-reflect.c
|
||||
ecma/builtin-objects/ecma-builtin-regexp-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-regexp.c
|
||||
ecma/builtin-objects/ecma-builtin-set-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-set-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-set.c
|
||||
ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-string-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-string.c
|
||||
ecma/builtin-objects/ecma-builtin-symbol-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-symbol.c
|
||||
ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-syntaxerror.c
|
||||
ecma/builtin-objects/ecma-builtin-type-error-thrower.c
|
||||
ecma/builtin-objects/ecma-builtin-typeerror-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-typeerror.c
|
||||
ecma/builtin-objects/ecma-builtin-urierror-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-urierror.c
|
||||
ecma/builtin-objects/ecma-builtin-weakmap-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-weakmap.c
|
||||
ecma/builtin-objects/ecma-builtin-weakset-prototype.c
|
||||
ecma/builtin-objects/ecma-builtin-weakset.c
|
||||
ecma/builtin-objects/ecma-builtins.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-bigint64array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-bigint64array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-biguint64array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-biguint64array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-float32array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-float32array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-float64array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-float64array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-int16array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-int16array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-int32array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-int32array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-int8array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-int8array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-typedarray.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint16array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint16array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint32array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint32array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint8array-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint8array.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray-prototype.c
|
||||
ecma/builtin-objects/typedarray/ecma-builtin-uint8clampedarray.c
|
||||
ecma/operations/ecma-arguments-object.c
|
||||
ecma/operations/ecma-array-object.c
|
||||
ecma/operations/ecma-arraybuffer-object.c
|
||||
ecma/operations/ecma-async-generator-object.c
|
||||
ecma/operations/ecma-big-uint.c
|
||||
ecma/operations/ecma-bigint-object.c
|
||||
ecma/operations/ecma-bigint.c
|
||||
ecma/operations/ecma-boolean-object.c
|
||||
ecma/operations/ecma-comparison.c
|
||||
ecma/operations/ecma-container-object.c
|
||||
ecma/operations/ecma-conversion.c
|
||||
ecma/operations/ecma-dataview-object.c
|
||||
ecma/operations/ecma-eval.c
|
||||
ecma/operations/ecma-exceptions.c
|
||||
ecma/operations/ecma-function-object.c
|
||||
ecma/operations/ecma-get-put-value.c
|
||||
ecma/operations/ecma-iterator-object.c
|
||||
ecma/operations/ecma-jobqueue.c
|
||||
ecma/operations/ecma-lex-env.c
|
||||
ecma/operations/ecma-number-arithmetic.c
|
||||
ecma/operations/ecma-number-object.c
|
||||
ecma/operations/ecma-objects-general.c
|
||||
ecma/operations/ecma-objects.c
|
||||
ecma/operations/ecma-promise-object.c
|
||||
ecma/operations/ecma-proxy-object.c
|
||||
ecma/operations/ecma-reference.c
|
||||
ecma/operations/ecma-regexp-object.c
|
||||
ecma/operations/ecma-string-object.c
|
||||
ecma/operations/ecma-symbol-object.c
|
||||
ecma/operations/ecma-typedarray-object.c
|
||||
jcontext/jcontext.c
|
||||
jmem/jmem-allocator.c
|
||||
jmem/jmem-heap.c
|
||||
jmem/jmem-poolman.c
|
||||
jrt/jrt-fatals.c
|
||||
lit/lit-char-helpers.c
|
||||
lit/lit-magic-strings.c
|
||||
lit/lit-strings.c
|
||||
parser/js/byte-code.c
|
||||
parser/js/common.c
|
||||
parser/js/js-lexer.c
|
||||
parser/js/js-parser-expr.c
|
||||
parser/js/js-parser-mem.c
|
||||
parser/js/js-parser-module.c
|
||||
parser/js/js-parser-statm.c
|
||||
parser/js/js-parser-tagged-template-literal.c
|
||||
parser/js/js-parser-util.c
|
||||
parser/js/js-parser.c
|
||||
parser/js/js-scanner-ops.c
|
||||
parser/js/js-scanner-util.c
|
||||
parser/js/js-scanner.c
|
||||
parser/regexp/re-bytecode.c
|
||||
parser/regexp/re-compiler.c
|
||||
parser/regexp/re-parser.c
|
||||
vm/opcodes-ecma-arithmetics.c
|
||||
vm/opcodes-ecma-bitwise.c
|
||||
vm/opcodes-ecma-relational-equality.c
|
||||
vm/opcodes.c
|
||||
vm/vm-stack.c
|
||||
vm/vm-utils.c
|
||||
vm/vm.c
|
||||
)
|
||||
|
||||
# Amalgamated JerryScript source/header build.
|
||||
# The process will create the following files:
|
||||
# * jerryscript.c
|
||||
# * jerryscript.h
|
||||
# * jerryscript-config.h
|
||||
if(ENABLE_AMALGAM)
|
||||
|
||||
# Create single C/H file
|
||||
set(HEADER_CORE_FILES
|
||||
api/jerry-snapshot.h
|
||||
debugger/debugger.h
|
||||
ecma/base/ecma-alloc.h
|
||||
ecma/base/ecma-gc.h
|
||||
ecma/base/ecma-globals.h
|
||||
ecma/base/ecma-helpers.h
|
||||
ecma/base/ecma-init-finalize.h
|
||||
ecma/base/ecma-lcache.h
|
||||
ecma/base/ecma-literal-storage.h
|
||||
ecma/base/ecma-module.h
|
||||
ecma/base/ecma-property-hashmap.h
|
||||
ecma/builtin-objects/ecma-builtin-array-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-array-prototype-unscopables.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-array-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-array.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-async-function-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-async-function.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-async-generator-function.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-async-generator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-async-generator.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-async-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-bigint-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-bigint.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-boolean-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-boolean.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-dataview.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-date-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-date.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-error-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-error.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-evalerror-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-evalerror.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-function-prototype.h
|
||||
ecma/builtin-objects/ecma-builtin-function-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-function.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-generator-function.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-generator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-generator.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-global.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-handlers.h
|
||||
ecma/builtin-objects/ecma-builtin-handlers.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-helpers.h
|
||||
ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-intrinsic.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-json.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-map-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-map-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-map.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-math.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-number-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-number.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-object-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-object.h
|
||||
ecma/builtin-objects/ecma-builtin-object.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-promise-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-promise.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-proxy.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-rangeerror-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-rangeerror.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-referenceerror-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-referenceerror.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-reflect.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-regexp.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-set-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-set.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-string-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-string.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-symbol.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-type-error-thrower.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-typeerror-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-typeerror.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-urierror-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-urierror.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-weakmap-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-weakmap.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-weakset-prototype.inc.h
|
||||
ecma/builtin-objects/ecma-builtin-weakset.inc.h
|
||||
ecma/builtin-objects/ecma-builtins-internal.h
|
||||
ecma/builtin-objects/ecma-builtins.h
|
||||
ecma/builtin-objects/ecma-builtins.inc.h
|
||||
ecma/operations/ecma-arguments-object.h
|
||||
ecma/operations/ecma-array-object.h
|
||||
ecma/operations/ecma-arraybuffer-object.h
|
||||
ecma/operations/ecma-async-generator-object.h
|
||||
ecma/operations/ecma-big-uint.h
|
||||
ecma/operations/ecma-bigint-object.h
|
||||
ecma/operations/ecma-bigint.h
|
||||
ecma/operations/ecma-boolean-object.h
|
||||
ecma/operations/ecma-comparison.h
|
||||
ecma/operations/ecma-container-object.h
|
||||
ecma/operations/ecma-conversion.h
|
||||
ecma/operations/ecma-dataview-object.h
|
||||
ecma/operations/ecma-eval.h
|
||||
ecma/operations/ecma-exceptions.h
|
||||
ecma/operations/ecma-function-object.h
|
||||
ecma/operations/ecma-iterator-object.h
|
||||
ecma/operations/ecma-jobqueue.h
|
||||
ecma/operations/ecma-lex-env.h
|
||||
ecma/operations/ecma-number-arithmetic.h
|
||||
ecma/operations/ecma-number-object.h
|
||||
ecma/operations/ecma-objects-general.h
|
||||
ecma/operations/ecma-objects.h
|
||||
ecma/operations/ecma-promise-object.h
|
||||
ecma/operations/ecma-proxy-object.h
|
||||
ecma/operations/ecma-reference.h
|
||||
ecma/operations/ecma-regexp-object.h
|
||||
ecma/operations/ecma-string-object.h
|
||||
ecma/operations/ecma-symbol-object.h
|
||||
ecma/operations/ecma-typedarray-object.h
|
||||
include/jerryscript-compiler.h
|
||||
include/jerryscript-core.h
|
||||
include/jerryscript-debugger-transport.h
|
||||
include/jerryscript-debugger.h
|
||||
include/jerryscript-port.h
|
||||
include/jerryscript-snapshot.h
|
||||
include/jerryscript.h
|
||||
jcontext/jcontext.h
|
||||
jmem/jmem-allocator-internal.h
|
||||
jmem/jmem.h
|
||||
jrt/jrt-bit-fields.h
|
||||
jrt/jrt-libc-includes.h
|
||||
jrt/jrt-types.h
|
||||
jrt/jrt.h
|
||||
lit/lit-char-helpers.h
|
||||
lit/lit-globals.h
|
||||
lit/lit-magic-strings.h
|
||||
lit/lit-magic-strings.inc.h
|
||||
lit/lit-strings.h
|
||||
lit/lit-unicode-conversions-sup.inc.h
|
||||
lit/lit-unicode-conversions.inc.h
|
||||
lit/lit-unicode-folding.inc.h
|
||||
lit/lit-unicode-ranges-sup.inc.h
|
||||
lit/lit-unicode-ranges.inc.h
|
||||
vm/opcodes.h
|
||||
vm/vm-defines.h
|
||||
vm/vm-stack.h
|
||||
vm/vm.h
|
||||
)
|
||||
|
||||
# Generated files
|
||||
set(AMALGAM_CORE_C "${CMAKE_BINARY_DIR}/amalgam/jerryscript.c")
|
||||
set(AMALGAM_CORE_H "${CMAKE_BINARY_DIR}/amalgam/jerryscript.h")
|
||||
set(AMALGAM_CONFIG_H "${CMAKE_BINARY_DIR}/amalgam/jerryscript-config.h")
|
||||
|
||||
add_custom_command(OUTPUT ${AMALGAM_CORE_C} ${AMALGAM_CORE_H}
|
||||
COMMAND python ${CMAKE_SOURCE_DIR}/tools/amalgam.py
|
||||
--jerry-core
|
||||
--output-dir ${CMAKE_BINARY_DIR}/amalgam
|
||||
DEPENDS ${SOURCE_CORE_FILES}
|
||||
${HEADER_CORE_FILES}
|
||||
${CMAKE_SOURCE_DIR}/tools/amalgam.py
|
||||
)
|
||||
|
||||
# The "true" jerryscript-config.h will be generated by the configure_file below,
|
||||
# which contains the default options and the ones passed for the CMake.
|
||||
# The input for this is the jerryscript-config.h generated by the command above.
|
||||
set(JERRYSCRIPT_GEN_CONFIG_H ${CMAKE_CURRENT_BINARY_DIR}/jerryscript-config.h)
|
||||
add_custom_command(OUTPUT ${AMALGAM_CONFIG_H}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${JERRYSCRIPT_GEN_CONFIG_H} ${AMALGAM_CONFIG_H}
|
||||
DEPENDS ${AMALGAM_CORE_C} ${AMALGAM_CORE_H})
|
||||
add_custom_target(amalgam-jerry DEPENDS ${AMALGAM_CORE_C} ${AMALGAM_CORE_H} ${AMALGAM_CONFIG_H})
|
||||
add_dependencies(amalgam amalgam-jerry)
|
||||
|
||||
set(SOURCE_CORE_FILES ${AMALGAM_CORE_C} ${AMALGAM_CORE_H} ${AMALGAM_CONFIG_H})
|
||||
endif()
|
||||
|
||||
# Third-party
|
||||
# Valgrind
|
||||
set(INCLUDE_THIRD_PARTY_VALGRIND "${CMAKE_SOURCE_DIR}/third-party/valgrind")
|
||||
|
||||
# build mode specific compile/link flags
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} $<$<NOT:$<CONFIG:Debug>>:JERRY_NDEBUG>)
|
||||
|
||||
# Jerry heap-section
|
||||
if(DEFINED JERRY_ATTR_GLOBAL_HEAP)
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_ATTR_GLOBAL_HEAP=${JERRY_ATTR_GLOBAL_HEAP})
|
||||
endif()
|
||||
|
||||
# Memory usage limit for triggering garbage collection
|
||||
if(JERRY_GC_LIMIT)
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_GC_LIMIT=${JERRY_GC_LIMIT})
|
||||
endif()
|
||||
|
||||
# Helper macro to set 0/1 switch as Jerry Defines
|
||||
macro(jerry_add_define01 NAME)
|
||||
if(${NAME})
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} ${NAME}=1)
|
||||
else()
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} ${NAME}=0)
|
||||
endif()
|
||||
endmacro(jerry_add_define01)
|
||||
|
||||
# Checks the optional features
|
||||
# Enable 32 bit cpointers
|
||||
jerry_add_define01(JERRY_CPOINTER_32_BIT)
|
||||
|
||||
# Fill error messages for builtin error objects
|
||||
jerry_add_define01(JERRY_ERROR_MESSAGES)
|
||||
|
||||
# Use external context instead of static one
|
||||
jerry_add_define01(JERRY_EXTERNAL_CONTEXT)
|
||||
|
||||
# JS-Parser
|
||||
jerry_add_define01(JERRY_PARSER)
|
||||
|
||||
# JS line info
|
||||
jerry_add_define01(JERRY_LINE_INFO)
|
||||
|
||||
# Logging
|
||||
jerry_add_define01(JERRY_LOGGING)
|
||||
|
||||
# Memory statistics
|
||||
jerry_add_define01(JERRY_MEM_STATS)
|
||||
|
||||
# Enable debugger
|
||||
jerry_add_define01(JERRY_DEBUGGER)
|
||||
|
||||
# Memory management stress-test mode
|
||||
jerry_add_define01(JERRY_MEM_GC_BEFORE_EACH_ALLOC)
|
||||
|
||||
# Parser byte-code dumps
|
||||
jerry_add_define01(JERRY_PARSER_DUMP_BYTE_CODE)
|
||||
|
||||
# Profile
|
||||
if (${JERRY_PROFILE} STREQUAL "es2015-subset")
|
||||
message(DEPRECATION "'es2015-subset' profile is deprecated, please use 'es.next' instead.")
|
||||
endif()
|
||||
|
||||
if (NOT IS_ABSOLUTE ${JERRY_PROFILE})
|
||||
set(JERRY_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/profiles/${JERRY_PROFILE}.profile")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${JERRY_PROFILE})
|
||||
file(READ "${JERRY_PROFILE}" PROFILE_SETTINGS)
|
||||
string(REGEX REPLACE "[ \t]*#[^\n]*" "" PROFILE_SETTINGS "${PROFILE_SETTINGS}")
|
||||
string(REGEX REPLACE "[\r\n]" ";" PROFILE_SETTINGS "${PROFILE_SETTINGS}")
|
||||
|
||||
# Process entries and save them as CMake variables.
|
||||
# This is required to correctly generate the jerryscript-config.h file.
|
||||
foreach(PROFILE_ENTRY ${PROFILE_SETTINGS})
|
||||
string(REPLACE "=" ";" PROFILE_ENTRY "${PROFILE_ENTRY}")
|
||||
list(GET PROFILE_ENTRY 0 PROFILE_KEY)
|
||||
list(GET PROFILE_ENTRY 1 PROFILE_VALUE)
|
||||
set(${PROFILE_KEY} ${PROFILE_VALUE})
|
||||
endforeach()
|
||||
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} ${PROFILE_SETTINGS})
|
||||
else()
|
||||
message(FATAL_ERROR "Profile file: '${JERRY_PROFILE}' doesn't exist!")
|
||||
endif()
|
||||
|
||||
# RegExp strict mode
|
||||
jerry_add_define01(JERRY_REGEXP_STRICT_MODE)
|
||||
|
||||
# RegExp byte-code dumps
|
||||
jerry_add_define01(JERRY_REGEXP_DUMP_BYTE_CODE)
|
||||
|
||||
# Snapshot exec
|
||||
jerry_add_define01(JERRY_SNAPSHOT_EXEC)
|
||||
|
||||
# Snapshot save
|
||||
jerry_add_define01(JERRY_SNAPSHOT_SAVE)
|
||||
|
||||
# Enable system allocator
|
||||
jerry_add_define01(JERRY_SYSTEM_ALLOCATOR)
|
||||
|
||||
# Valgrind
|
||||
jerry_add_define01(JERRY_VALGRIND)
|
||||
if(JERRY_VALGRIND)
|
||||
set(INCLUDE_CORE_PRIVATE ${INCLUDE_CORE_PRIVATE} ${INCLUDE_THIRD_PARTY_VALGRIND})
|
||||
endif()
|
||||
|
||||
# Enable VM execution stopping
|
||||
jerry_add_define01(JERRY_VM_EXEC_STOP)
|
||||
|
||||
# Size of heap
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_GLOBAL_HEAP_SIZE=${JERRY_GLOBAL_HEAP_SIZE})
|
||||
|
||||
# Maximum size of stack memory usage
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_STACK_LIMIT=${JERRY_STACK_LIMIT})
|
||||
|
||||
# Maximum depth of recursion during GC mark phase
|
||||
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_GC_MARK_LIMIT=${JERRY_GC_MARK_LIMIT})
|
||||
|
||||
## This function is to read "config.h" for default values
|
||||
function(read_set_defines FILE PREFIX OUTPUTVAR)
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}" INPUT_FILE_CONTENTS)
|
||||
|
||||
# match all "#define <PREFIX>\n" lines
|
||||
# notes:
|
||||
# * before the "#" there must be a newline and any number of spaces.
|
||||
# * after the "#" there can be any number of spaces.
|
||||
string(REGEX MATCHALL "\r?\n[ ]*#[ ]*define ${PREFIX}[^\n]*"
|
||||
RAW_DEFINES "${INPUT_FILE_CONTENTS}")
|
||||
|
||||
set(SELECTED_VARS )
|
||||
|
||||
# Transform the defines to a list of (<name>; <value>; <name 2>; <value 2>; ...) list
|
||||
foreach(DEFINE_ENTRY ${RAW_DEFINES})
|
||||
# by default every define value is empty
|
||||
set(DEFINE_VALUE " ")
|
||||
|
||||
# split up the define at the space between the define name and value (if there is any)
|
||||
|
||||
# first remove "#define" part of the string
|
||||
string(REGEX REPLACE "\r?\n[ ]*#[ ]*define[ ]+" "" DEFINE_KEY_VALUE "${DEFINE_ENTRY}")
|
||||
string(FIND "${DEFINE_KEY_VALUE}" " " DEFINE_KEY_IDX)
|
||||
string(LENGTH "${DEFINE_KEY_VALUE}" DEFINE_LENGTH)
|
||||
|
||||
if (DEFINE_KEY_IDX EQUAL "-1")
|
||||
set(DEFINE_KEY ${DEFINE_KEY_VALUE})
|
||||
else()
|
||||
string(SUBSTRING "${DEFINE_KEY_VALUE}" 0 ${DEFINE_KEY_IDX} DEFINE_KEY)
|
||||
string(SUBSTRING "${DEFINE_KEY_VALUE}" ${DEFINE_KEY_IDX} -1 DEFINE_VALUE)
|
||||
string(STRIP "${DEFINE_VALUE}" DEFINE_VALUE)
|
||||
endif()
|
||||
|
||||
list(APPEND SELECTED_VARS ${DEFINE_KEY} ${DEFINE_VALUE})
|
||||
endforeach()
|
||||
|
||||
set(${OUTPUTVAR} ${SELECTED_VARS} PARENT_SCOPE)
|
||||
endfunction(read_set_defines)
|
||||
|
||||
# CONFIG_DEFAULTS contains define name and values which have the JERRY_ prefix
|
||||
# as a list of (<name>; <value>; <name 2>; <value 2>; ...)
|
||||
read_set_defines("config.h" JERRY_ CONFIG_DEFAULTS)
|
||||
|
||||
|
||||
## Process the default values and build options to generate build config defines
|
||||
list(LENGTH CONFIG_DEFAULTS CONFIG_DEFAULT_LENGTH)
|
||||
math(EXPR CONFIG_DEFAULT_LENGTH "${CONFIG_DEFAULT_LENGTH} - 1")
|
||||
|
||||
set(JERRY_MODIFIED_OPTIONS)
|
||||
foreach(CONFIG_IDX RANGE 0 ${CONFIG_DEFAULT_LENGTH} 2)
|
||||
list(GET CONFIG_DEFAULTS ${CONFIG_IDX} KEY)
|
||||
math(EXPR VALUE_IDX "${CONFIG_IDX} + 1")
|
||||
list(GET CONFIG_DEFAULTS ${VALUE_IDX} VALUE)
|
||||
|
||||
# ${KEY} is the value for the given variable (aka define)
|
||||
# normalize ON/OFF cmake values to 1/0 for easier processing.
|
||||
if(${KEY} STREQUAL "ON")
|
||||
set(${KEY} 1)
|
||||
elseif(${KEY} STREQUAL "OFF")
|
||||
set(${KEY} 0)
|
||||
endif()
|
||||
|
||||
# Generate "#define JERRY_<CONFIG> <CONFIG_VALUE>" entries if it is different from
|
||||
# the config default.
|
||||
|
||||
# If the define loaded from the config file have a different value than the
|
||||
# relevant option passed for the CMake means that it does not have a default value.
|
||||
if(DEFINED ${KEY} AND NOT (${KEY} STREQUAL ${VALUE}))
|
||||
set(JERRY_MODIFIED_OPTIONS "${JERRY_MODIFIED_OPTIONS}#define ${KEY} ${${KEY}}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Generate the jerryscript-config.h file into the build directory
|
||||
# This file will contain the options different from the default (aka it's the build config).
|
||||
if(JERRY_MODIFIED_OPTIONS)
|
||||
set(JERRY_BUILD_CFG
|
||||
"Generated differences from default by CMake based on build options:\n${JERRY_MODIFIED_OPTIONS}")
|
||||
else()
|
||||
set(JERRY_BUILD_CFG "JerryScript configuration")
|
||||
endif()
|
||||
configure_file(config.h jerryscript-config.h @ONLY)
|
||||
|
||||
add_library(${JERRY_CORE_NAME} ${SOURCE_CORE_FILES})
|
||||
|
||||
target_compile_definitions(${JERRY_CORE_NAME} PUBLIC ${DEFINES_JERRY})
|
||||
target_include_directories(${JERRY_CORE_NAME} PUBLIC ${INCLUDE_CORE_PUBLIC})
|
||||
target_include_directories(${JERRY_CORE_NAME} PRIVATE ${INCLUDE_CORE_PRIVATE})
|
||||
|
||||
set(JERRY_CORE_PKGCONFIG_REQUIRES)
|
||||
set(JERRY_CORE_PKGCONFIG_LIBS)
|
||||
set(JERRY_CORE_PKGCONFIG_CFLAGS)
|
||||
|
||||
if(ENABLE_LTO)
|
||||
set(JERRY_CORE_PKGCONFIG_CFLAGS "${JERRY_CORE_PKGCONFIG_CFLAGS} -flto")
|
||||
endif()
|
||||
|
||||
if(JERRY_MATH)
|
||||
target_link_libraries(${JERRY_CORE_NAME} jerry-math)
|
||||
set(JERRY_CORE_PKGCONFIG_REQUIRES libjerry-math)
|
||||
else()
|
||||
if(USING_GCC OR USING_CLANG)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wno-error -Wno-error=strict-prototypes")
|
||||
endif()
|
||||
check_library_exists(m sin "" HAVE_M_LIB)
|
||||
if(HAVE_M_LIB)
|
||||
target_link_libraries(${JERRY_CORE_NAME} m)
|
||||
set(JERRY_CORE_PKGCONFIG_LIBS "${JERRY_CORE_PKGCONFIG_LIBS} -lm")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
separate_arguments(EXTERNAL_LINK_LIBS)
|
||||
foreach(EXT_LIB ${EXTERNAL_LINK_LIBS})
|
||||
target_link_libraries(${JERRY_CORE_NAME} ${EXT_LIB})
|
||||
set(JERRY_CORE_PKGCONFIG_LIBS "${JERRY_CORE_PKGCONFIG_LIBS} -l${EXT_LIB}")
|
||||
endforeach()
|
||||
|
||||
configure_file(libjerry-core.pc.in libjerry-core.pc @ONLY)
|
||||
|
||||
install(TARGETS ${JERRY_CORE_NAME} DESTINATION lib)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libjerry-core.pc DESTINATION lib/pkgconfig)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jerryscript-config.h DESTINATION include)
|
||||
install(DIRECTORY ${INCLUDE_CORE_PUBLIC}/ DESTINATION include)
|
|
@ -0,0 +1,250 @@
|
|||
/* 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 "debugger.h"
|
||||
#include "jcontext.h"
|
||||
#include "jerryscript.h"
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
|
||||
/**
|
||||
* Minimum number of bytes transmitted or received.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE 64
|
||||
|
||||
/**
|
||||
* Sleep time in milliseconds between each jerry_debugger_receive call
|
||||
*/
|
||||
#define JERRY_DEBUGGER_TRANSPORT_TIMEOUT 100
|
||||
|
||||
/**
|
||||
* Add a new transport layer.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_transport_add (jerry_debugger_transport_header_t *header_p, /**< transport implementation */
|
||||
size_t send_message_header_size, /**< header bytes reserved for outgoing messages */
|
||||
size_t max_send_message_size, /**< maximum number of bytes transmitted in a message */
|
||||
size_t receive_message_header_size, /**< header bytes reserved for incoming messages */
|
||||
size_t max_receive_message_size) /**< maximum number of bytes received in a message */
|
||||
{
|
||||
JERRY_ASSERT (max_send_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE
|
||||
&& max_receive_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE);
|
||||
|
||||
header_p->next_p = JERRY_CONTEXT (debugger_transport_header_p);
|
||||
JERRY_CONTEXT (debugger_transport_header_p) = header_p;
|
||||
|
||||
uint8_t *payload_p;
|
||||
size_t max_send_size;
|
||||
size_t max_receive_size;
|
||||
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
{
|
||||
payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
|
||||
max_send_size = JERRY_CONTEXT (debugger_max_send_size);
|
||||
max_receive_size = JERRY_CONTEXT (debugger_max_receive_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_CONNECTED);
|
||||
payload_p = JERRY_CONTEXT (debugger_send_buffer);
|
||||
max_send_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
|
||||
max_receive_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (max_send_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + send_message_header_size);
|
||||
JERRY_ASSERT (max_receive_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + receive_message_header_size);
|
||||
|
||||
JERRY_CONTEXT (debugger_send_buffer_payload_p) = payload_p + send_message_header_size;
|
||||
|
||||
max_send_size = max_send_size - send_message_header_size;
|
||||
max_receive_size = max_receive_size - receive_message_header_size;
|
||||
|
||||
if (max_send_size > max_send_message_size)
|
||||
{
|
||||
max_send_size = max_send_message_size;
|
||||
}
|
||||
|
||||
if (max_receive_size > max_receive_message_size)
|
||||
{
|
||||
max_receive_size = max_receive_message_size;
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (debugger_max_send_size) = (uint8_t) max_send_size;
|
||||
JERRY_CONTEXT (debugger_max_receive_size) = (uint8_t) max_receive_size;
|
||||
} /* jerry_debugger_transport_add */
|
||||
|
||||
/**
|
||||
* Starts the communication to the debugger client.
|
||||
* Must be called after the connection is successfully established.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_transport_start (void)
|
||||
{
|
||||
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
|
||||
|
||||
if (jerry_debugger_send_configuration (JERRY_CONTEXT (debugger_max_receive_size)))
|
||||
{
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
|
||||
JERRY_CONTEXT (debugger_stop_context) = NULL;
|
||||
}
|
||||
} /* jerry_debugger_transport_start */
|
||||
|
||||
/**
|
||||
* Returns true if a debugger client is connected.
|
||||
*
|
||||
* @return true - a debugger client is connected,
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
jerry_debugger_transport_is_connected (void)
|
||||
{
|
||||
return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0;
|
||||
} /* jerry_debugger_transport_is_connected */
|
||||
|
||||
/**
|
||||
* Notifies the debugger server that the connection is closed.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_transport_close (void)
|
||||
{
|
||||
if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (debugger_flags) = JERRY_DEBUGGER_VM_IGNORE;
|
||||
|
||||
jerry_debugger_transport_header_t *current_p = JERRY_CONTEXT (debugger_transport_header_p);
|
||||
|
||||
JERRY_ASSERT (current_p != NULL);
|
||||
|
||||
do
|
||||
{
|
||||
jerry_debugger_transport_header_t *next_p = current_p->next_p;
|
||||
|
||||
current_p->close (current_p);
|
||||
|
||||
current_p = next_p;
|
||||
}
|
||||
while (current_p != NULL);
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Debugger client connection closed.\n");
|
||||
|
||||
jerry_debugger_free_unreferenced_byte_code ();
|
||||
} /* jerry_debugger_transport_close */
|
||||
|
||||
/**
|
||||
* Send data over the current connection
|
||||
*
|
||||
* @return true - data sent successfully,
|
||||
* false - connection closed
|
||||
*/
|
||||
bool
|
||||
jerry_debugger_transport_send (const uint8_t *message_p, /**< message to be sent */
|
||||
size_t message_length) /**< message length in bytes */
|
||||
{
|
||||
JERRY_ASSERT (jerry_debugger_transport_is_connected ());
|
||||
JERRY_ASSERT (message_length > 0);
|
||||
|
||||
jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
|
||||
uint8_t *payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
|
||||
size_t max_send_size = JERRY_CONTEXT (debugger_max_send_size);
|
||||
|
||||
do
|
||||
{
|
||||
size_t fragment_length = (message_length <= max_send_size ? message_length
|
||||
: max_send_size);
|
||||
|
||||
memcpy (payload_p, message_p, fragment_length);
|
||||
|
||||
if (!header_p->send (header_p, payload_p, fragment_length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
message_p += fragment_length;
|
||||
message_length -= fragment_length;
|
||||
}
|
||||
while (message_length > 0);
|
||||
|
||||
return true;
|
||||
} /* jerry_debugger_transport_send */
|
||||
|
||||
/**
|
||||
* Receive data from the current connection
|
||||
*
|
||||
* Note:
|
||||
* A message is received if message_start_p is not NULL
|
||||
*
|
||||
* @return true - function successfully completed,
|
||||
* false - connection closed
|
||||
*/
|
||||
bool
|
||||
jerry_debugger_transport_receive (jerry_debugger_transport_receive_context_t *context_p) /**< [out] receive
|
||||
* context */
|
||||
{
|
||||
JERRY_ASSERT (jerry_debugger_transport_is_connected ());
|
||||
|
||||
context_p->buffer_p = JERRY_CONTEXT (debugger_receive_buffer);
|
||||
context_p->received_length = JERRY_CONTEXT (debugger_received_length);
|
||||
context_p->message_p = NULL;
|
||||
context_p->message_length = 0;
|
||||
context_p->message_total_length = 0;
|
||||
|
||||
jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
|
||||
|
||||
return header_p->receive (header_p, context_p);
|
||||
} /* jerry_debugger_transport_receive */
|
||||
|
||||
/**
|
||||
* Clear the message buffer after the message is processed
|
||||
*/
|
||||
void
|
||||
jerry_debugger_transport_receive_completed (jerry_debugger_transport_receive_context_t *context_p) /**< receive
|
||||
* context */
|
||||
{
|
||||
JERRY_ASSERT (context_p->message_p != NULL);
|
||||
JERRY_ASSERT (context_p->buffer_p == JERRY_CONTEXT (debugger_receive_buffer));
|
||||
|
||||
size_t message_total_length = context_p->message_total_length;
|
||||
size_t received_length = context_p->received_length;
|
||||
|
||||
JERRY_ASSERT (message_total_length <= received_length);
|
||||
|
||||
if (message_total_length == 0 || message_total_length == received_length)
|
||||
{
|
||||
/* All received data is processed. */
|
||||
JERRY_CONTEXT (debugger_received_length) = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *buffer_p = context_p->buffer_p;
|
||||
received_length -= message_total_length;
|
||||
|
||||
memmove (buffer_p, buffer_p + message_total_length, received_length);
|
||||
|
||||
JERRY_CONTEXT (debugger_received_length) = (uint16_t) received_length;
|
||||
} /* jerry_debugger_transport_receive_completed */
|
||||
|
||||
/**
|
||||
* Suspend execution for a predefined time (JERRY_DEBUGGER_TRANSPORT_TIMEOUT ms).
|
||||
*/
|
||||
void
|
||||
jerry_debugger_transport_sleep (void)
|
||||
{
|
||||
jerry_port_sleep (JERRY_DEBUGGER_TRANSPORT_TIMEOUT);
|
||||
} /* jerry_debugger_transport_sleep */
|
||||
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
|
@ -0,0 +1,230 @@
|
|||
/* 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 "debugger.h"
|
||||
#include "jcontext.h"
|
||||
#include "jerryscript.h"
|
||||
|
||||
/**
|
||||
* Checks whether the debugger is connected.
|
||||
*
|
||||
* @return true - if the debugger is connected
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
jerry_debugger_is_connected (void)
|
||||
{
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
return JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED;
|
||||
#else /* !ENABLED (JERRY_DEBUGGER) */
|
||||
return false;
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_is_connected */
|
||||
|
||||
/**
|
||||
* Stop execution at the next available breakpoint.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_stop (void)
|
||||
{
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
&& !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE))
|
||||
{
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
|
||||
JERRY_CONTEXT (debugger_stop_context) = NULL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_stop */
|
||||
|
||||
/**
|
||||
* Continue execution.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_continue (void)
|
||||
{
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
&& !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE))
|
||||
{
|
||||
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP);
|
||||
JERRY_CONTEXT (debugger_stop_context) = NULL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_continue */
|
||||
|
||||
/**
|
||||
* Sets whether the engine should stop at breakpoints.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_stop_at_breakpoint (bool enable_stop_at_breakpoint) /**< enable/disable stop at breakpoint */
|
||||
{
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED
|
||||
&& !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE))
|
||||
{
|
||||
if (enable_stop_at_breakpoint)
|
||||
{
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE);
|
||||
}
|
||||
}
|
||||
#else /* !ENABLED (JERRY_DEBUGGER) */
|
||||
JERRY_UNUSED (enable_stop_at_breakpoint);
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_stop_at_breakpoint */
|
||||
|
||||
/**
|
||||
* Sets whether the engine should wait and run a source.
|
||||
*
|
||||
* @return enum JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED - if the source is not received
|
||||
* JERRY_DEBUGGER_SOURCE_RECEIVED - if a source code received
|
||||
* JERRY_DEBUGGER_SOURCE_END - the end of the source codes
|
||||
* JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED - the end of the context
|
||||
*/
|
||||
jerry_debugger_wait_for_source_status_t
|
||||
jerry_debugger_wait_for_client_source (jerry_debugger_wait_for_source_callback_t callback_p, /**< callback function */
|
||||
void *user_p, /**< user pointer passed to the callback */
|
||||
jerry_value_t *return_value) /**< [out] parse and run return value */
|
||||
{
|
||||
*return_value = jerry_create_undefined ();
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
&& !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE))
|
||||
{
|
||||
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE);
|
||||
jerry_debugger_uint8_data_t *client_source_data_p = NULL;
|
||||
jerry_debugger_wait_for_source_status_t ret_type = JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED;
|
||||
|
||||
/* Notify the client about that the engine is waiting for a source. */
|
||||
jerry_debugger_send_type (JERRY_DEBUGGER_WAIT_FOR_SOURCE);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (jerry_debugger_receive (&client_source_data_p))
|
||||
{
|
||||
if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Stop executing the current context. */
|
||||
if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONTEXT_RESET_MODE))
|
||||
{
|
||||
ret_type = JERRY_DEBUGGER_CONTEXT_RESET_RECEIVED;
|
||||
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CONTEXT_RESET_MODE);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Stop waiting for a new source file. */
|
||||
if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_NO_SOURCE))
|
||||
{
|
||||
ret_type = JERRY_DEBUGGER_SOURCE_END;
|
||||
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE);
|
||||
break;
|
||||
}
|
||||
|
||||
/* The source arrived. */
|
||||
if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE))
|
||||
{
|
||||
JERRY_ASSERT (client_source_data_p != NULL);
|
||||
|
||||
jerry_char_t *resource_name_p = (jerry_char_t *) (client_source_data_p + 1);
|
||||
size_t resource_name_size = strlen ((const char *) resource_name_p);
|
||||
|
||||
*return_value = callback_p (resource_name_p,
|
||||
resource_name_size,
|
||||
resource_name_p + resource_name_size + 1,
|
||||
client_source_data_p->uint8_size - resource_name_size - 1,
|
||||
user_p);
|
||||
|
||||
ret_type = JERRY_DEBUGGER_SOURCE_RECEIVED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jerry_debugger_transport_sleep ();
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)
|
||||
|| !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED));
|
||||
|
||||
if (client_source_data_p != NULL)
|
||||
{
|
||||
/* The data may partly arrived. */
|
||||
jmem_heap_free_block (client_source_data_p,
|
||||
client_source_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t));
|
||||
}
|
||||
|
||||
return ret_type;
|
||||
}
|
||||
|
||||
return JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED;
|
||||
#else /* !ENABLED (JERRY_DEBUGGER) */
|
||||
JERRY_UNUSED (callback_p);
|
||||
JERRY_UNUSED (user_p);
|
||||
|
||||
return JERRY_DEBUGGER_SOURCE_RECEIVE_FAILED;
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_wait_for_client_source */
|
||||
|
||||
/**
|
||||
* Send the output of the program to the debugger client.
|
||||
* Currently only sends print output.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_send_output (const jerry_char_t *buffer, /**< buffer */
|
||||
jerry_size_t str_size) /**< string size */
|
||||
{
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
{
|
||||
jerry_debugger_send_string (JERRY_DEBUGGER_OUTPUT_RESULT,
|
||||
JERRY_DEBUGGER_OUTPUT_OK,
|
||||
(const uint8_t *) buffer,
|
||||
sizeof (uint8_t) * str_size);
|
||||
}
|
||||
#else /* !ENABLED (JERRY_DEBUGGER) */
|
||||
JERRY_UNUSED (buffer);
|
||||
JERRY_UNUSED (str_size);
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_send_output */
|
||||
|
||||
/**
|
||||
* Send the log of the program to the debugger client.
|
||||
*/
|
||||
void
|
||||
jerry_debugger_send_log (jerry_log_level_t level, /**< level of the diagnostics message */
|
||||
const jerry_char_t *buffer, /**< buffer */
|
||||
jerry_size_t str_size) /**< string size */
|
||||
{
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
{
|
||||
jerry_debugger_send_string (JERRY_DEBUGGER_OUTPUT_RESULT,
|
||||
(uint8_t) (level + 2),
|
||||
(const uint8_t *) buffer,
|
||||
sizeof (uint8_t) * str_size);
|
||||
}
|
||||
#else /* !ENABLED (JERRY_DEBUGGER) */
|
||||
JERRY_UNUSED (level);
|
||||
JERRY_UNUSED (buffer);
|
||||
JERRY_UNUSED (str_size);
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
} /* jerry_debugger_send_log */
|
|
@ -0,0 +1,54 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef JERRY_SNAPSHOT_H
|
||||
#define JERRY_SNAPSHOT_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
/**
|
||||
* Snapshot header
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* The size of this structure is recommended to be divisible by
|
||||
* uint32_t alignment. Otherwise some bytes after the header are wasted. */
|
||||
uint32_t magic; /**< four byte magic number */
|
||||
uint32_t version; /**< version number */
|
||||
uint32_t global_flags; /**< global configuration and feature flags */
|
||||
uint32_t lit_table_offset; /**< byte offset of the literal table */
|
||||
uint32_t number_of_funcs; /**< number of primary ECMAScript functions */
|
||||
uint32_t func_offsets[1]; /**< function offsets (lowest bit: global(0) or eval(1) context) */
|
||||
} jerry_snapshot_header_t;
|
||||
|
||||
/**
|
||||
* Jerry snapshot magic marker.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_MAGIC (0x5952524Au)
|
||||
|
||||
/**
|
||||
* Snapshot configuration flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* 8 bits are reserved for dynamic features */
|
||||
JERRY_SNAPSHOT_HAS_REGEX_LITERAL = (1u << 0), /**< byte code has regex literal */
|
||||
JERRY_SNAPSHOT_HAS_REALM_VALUE = (1u << 1), /**< byte code has realm value */
|
||||
JERRY_SNAPSHOT_HAS_CLASS_LITERAL = (1u << 2), /**< byte code has class literal */
|
||||
/* 24 bits are reserved for compile time features */
|
||||
JERRY_SNAPSHOT_FOUR_BYTE_CPOINTER = (1u << 8) /**< deprecated, an unused placeholder now */
|
||||
} jerry_snapshot_global_flags_t;
|
||||
|
||||
#endif /* !JERRY_SNAPSHOT_H */
|
|
@ -0,0 +1,727 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef JERRYSCRIPT_CONFIG_H
|
||||
#define JERRYSCRIPT_CONFIG_H
|
||||
|
||||
// @JERRY_BUILD_CFG@
|
||||
|
||||
/**
|
||||
* Built-in configurations
|
||||
*
|
||||
* Allowed values for built-in defines:
|
||||
* 0: Disable the given built-in.
|
||||
* 1: Enable the given built-in.
|
||||
*/
|
||||
/*
|
||||
* By default all built-ins are enabled if they are not defined.
|
||||
*/
|
||||
#ifndef JERRY_BUILTINS
|
||||
# define JERRY_BUILTINS 1
|
||||
#endif /* !defined (JERRY_BUILTINS) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_ANNEXB
|
||||
# define JERRY_BUILTIN_ANNEXB JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_ANNEXB) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_ARRAY
|
||||
# define JERRY_BUILTIN_ARRAY JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_ARRAY) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_BOOLEAN
|
||||
# define JERRY_BUILTIN_BOOLEAN JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_BOOLEAN) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_DATE
|
||||
# define JERRY_BUILTIN_DATE JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_DATE) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_ERRORS
|
||||
# define JERRY_BUILTIN_ERRORS JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_ERRORS) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_JSON
|
||||
# define JERRY_BUILTIN_JSON JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_JSON) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_MATH
|
||||
# define JERRY_BUILTIN_MATH JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_MATH) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_NUMBER
|
||||
# define JERRY_BUILTIN_NUMBER JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_NUMBER) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_REGEXP
|
||||
# define JERRY_BUILTIN_REGEXP JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_REGEXP) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_STRING
|
||||
# define JERRY_BUILTIN_STRING JERRY_BUILTINS
|
||||
#endif /* !defined (JERRY_BUILTIN_STRING) */
|
||||
|
||||
/**
|
||||
* ES2015+ related features, by default all of them are enabled.
|
||||
*/
|
||||
#ifndef JERRY_ESNEXT
|
||||
# define JERRY_ESNEXT 1
|
||||
#endif /* !defined (JERRY_ESNEXT) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_BIGINT
|
||||
# define JERRY_BUILTIN_BIGINT JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_DATAVIEW
|
||||
# define JERRY_BUILTIN_DATAVIEW JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_DATAVIEW) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_MAP
|
||||
# define JERRY_BUILTIN_MAP JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_MAP) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_PROMISE
|
||||
# define JERRY_BUILTIN_PROMISE JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_PROMISE) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_PROXY
|
||||
# define JERRY_BUILTIN_PROXY JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_PROXY) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_REALMS
|
||||
# define JERRY_BUILTIN_REALMS JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_REFLECT
|
||||
# define JERRY_BUILTIN_REFLECT JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_REFLECT) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_SET
|
||||
# define JERRY_BUILTIN_SET JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_SET) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_TYPEDARRAY
|
||||
# define JERRY_BUILTIN_TYPEDARRAY JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_TYPEDARRAY) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_WEAKMAP
|
||||
# define JERRY_BUILTIN_WEAKMAP JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_WEAKMAP) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_WEAKSET
|
||||
# define JERRY_BUILTIN_WEAKSET JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_WEAKSET) */
|
||||
|
||||
#ifndef JERRY_MODULE_SYSTEM
|
||||
# define JERRY_MODULE_SYSTEM JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_MODULE_SYSTEM) */
|
||||
|
||||
/**
|
||||
* Engine internal and misc configurations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specifies the compressed pointer representation
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: use 16 bit representation
|
||||
* 1: use 32 bit representation
|
||||
*
|
||||
* Default value: 0
|
||||
* For more details see: jmem/jmem.h
|
||||
*/
|
||||
#ifndef JERRY_CPOINTER_32_BIT
|
||||
# define JERRY_CPOINTER_32_BIT 0
|
||||
#endif /* !defined (JERRY_CPOINTER_32_BIT) */
|
||||
|
||||
/**
|
||||
* Enable/Disable the engine's JavaScript debugger interface
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable the debugger parts.
|
||||
* 1: Enable the debugger.
|
||||
*/
|
||||
#ifndef JERRY_DEBUGGER
|
||||
# define JERRY_DEBUGGER 0
|
||||
#endif /* !defined (JERRY_DEBUGGER) */
|
||||
|
||||
/**
|
||||
* Enable/Disable built-in error messages for error objects.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable error messages.
|
||||
* 1: Enable error message.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_ERROR_MESSAGES
|
||||
# define JERRY_ERROR_MESSAGES 0
|
||||
#endif /* !defined (JERRY_ERROR_MESSAGES) */
|
||||
|
||||
/**
|
||||
* Enable/Disable external context.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable external context.
|
||||
* 1: Enable external context support.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_EXTERNAL_CONTEXT
|
||||
# define JERRY_EXTERNAL_CONTEXT 0
|
||||
#endif /* !defined (JERRY_EXTERNAL_CONTEXT) */
|
||||
|
||||
/**
|
||||
* Maximum size of heap in kilobytes
|
||||
*
|
||||
* Default value: 512 KiB
|
||||
*/
|
||||
#ifndef JERRY_GLOBAL_HEAP_SIZE
|
||||
# define JERRY_GLOBAL_HEAP_SIZE (512)
|
||||
#endif /* !defined (JERRY_GLOBAL_HEAP_SIZE) */
|
||||
|
||||
/**
|
||||
* The allowed heap usage limit until next garbage collection, in bytes.
|
||||
*
|
||||
* If value is 0, the default is 1/32 of JERRY_HEAP_SIZE
|
||||
*/
|
||||
#ifndef JERRY_GC_LIMIT
|
||||
# define JERRY_GC_LIMIT 0
|
||||
#endif /* !defined (JERRY_GC_LIMIT) */
|
||||
|
||||
/**
|
||||
* Maximum stack usage size in kilobytes
|
||||
*
|
||||
* Note: This feature cannot be used when 'detect_stack_use_after_return=1' ASAN option is enabled.
|
||||
* For more detailed description:
|
||||
* - https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn#compatibility
|
||||
*
|
||||
* Default value: 0, unlimited
|
||||
*/
|
||||
#ifndef JERRY_STACK_LIMIT
|
||||
# define JERRY_STACK_LIMIT (0)
|
||||
#endif /* !defined (JERRY_STACK_LIMIT) */
|
||||
|
||||
/**
|
||||
* Maximum depth of recursion during GC mark phase
|
||||
*
|
||||
* Default value: 8
|
||||
*/
|
||||
#ifndef JERRY_GC_MARK_LIMIT
|
||||
# define JERRY_GC_MARK_LIMIT (8)
|
||||
#endif /* !defined (JERRY_GC_MARK_LIMIT) */
|
||||
|
||||
/**
|
||||
* Enable/Disable property lookup cache.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable lookup cache.
|
||||
* 1: Enable lookup cache.
|
||||
*
|
||||
* Default value: 1
|
||||
*/
|
||||
#ifndef JERRY_LCACHE
|
||||
# define JERRY_LCACHE 1
|
||||
#endif /* !defined (JERRY_LCACHE) */
|
||||
|
||||
/**
|
||||
* Enable/Disable line-info management inside the engine.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable line-info in the engine.
|
||||
* 1: Enable line-info management.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_LINE_INFO
|
||||
# define JERRY_LINE_INFO 0
|
||||
#endif /* !defined (JERRY_LINE_INFO) */
|
||||
|
||||
/**
|
||||
* Enable/Disable logging inside the engine.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable internal logging.
|
||||
* 1: Enable internal logging.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_LOGGING
|
||||
# define JERRY_LOGGING 0
|
||||
#endif /* !defined (JERRY_LOGGING) */
|
||||
|
||||
/**
|
||||
* Enable/Disable gc call before every allocation.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable gc call before each allocation.
|
||||
* 1: Enable and force gc call before each allocation.
|
||||
*
|
||||
* Default value: 0
|
||||
* Warning!: This is an advanced option and will slow down the engine!
|
||||
* Only enable it for debugging purposes.
|
||||
*/
|
||||
#ifndef JERRY_MEM_GC_BEFORE_EACH_ALLOC
|
||||
# define JERRY_MEM_GC_BEFORE_EACH_ALLOC 0
|
||||
#endif /* !defined (JERRY_MEM_GC_BEFORE_EACH_ALLOC) */
|
||||
|
||||
/**
|
||||
* Enable/Disable the collection if run-time memory statistics.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable run-time memory information collection.
|
||||
* 1: Enable run-time memory statistics collection.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_MEM_STATS
|
||||
# define JERRY_MEM_STATS 0
|
||||
#endif /* !defined (JERRY_MEM_STATS) */
|
||||
|
||||
/**
|
||||
* Use 32-bit/64-bit float for ecma-numbers
|
||||
* This option is for expert use only!
|
||||
*
|
||||
* Allowed values:
|
||||
* 1: use 64-bit floating point number mode
|
||||
* 0: use 32-bit floating point number mode
|
||||
*
|
||||
* Default value: 1
|
||||
*/
|
||||
#ifndef JERRY_NUMBER_TYPE_FLOAT64
|
||||
# define JERRY_NUMBER_TYPE_FLOAT64 1
|
||||
#endif /* !defined (JERRY_NUMBER_TYPE_FLOAT64 */
|
||||
|
||||
/**
|
||||
* Enable/Disable the JavaScript parser.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable the JavaScript parser and all related functionallity.
|
||||
* 1: Enable the JavaScript parser.
|
||||
*
|
||||
* Default value: 1
|
||||
*/
|
||||
#ifndef JERRY_PARSER
|
||||
# define JERRY_PARSER 1
|
||||
#endif /* !defined (JERRY_PARSER) */
|
||||
|
||||
/**
|
||||
* Enable/Disable JerryScript byte code dump functions during parsing.
|
||||
* To dump the JerryScript byte code the engine must be initialized with opcodes
|
||||
* display flag. This option does not influence RegExp byte code dumps.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable all bytecode dump functions.
|
||||
* 1: Enable bytecode dump functions.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_PARSER_DUMP_BYTE_CODE
|
||||
# define JERRY_PARSER_DUMP_BYTE_CODE 0
|
||||
#endif /* defined (JERRY_PARSER_DUMP_BYTE_CODE) */
|
||||
|
||||
/**
|
||||
* Enable/Disable ECMA property hashmap.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable property hasmap.
|
||||
* 1: Enable property hashmap.
|
||||
*
|
||||
* Default value: 1
|
||||
*/
|
||||
#ifndef JERRY_PROPRETY_HASHMAP
|
||||
# define JERRY_PROPRETY_HASHMAP 1
|
||||
#endif /* !defined (JERRY_PROPRETY_HASHMAP) */
|
||||
|
||||
/**
|
||||
* Enable/Disable byte code dump functions for RegExp objects.
|
||||
* To dump the RegExp byte code the engine must be initialized with
|
||||
* regexp opcodes display flag. This option does not influence the
|
||||
* JerryScript byte code dumps.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable all bytecode dump functions.
|
||||
* 1: Enable bytecode dump functions.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_REGEXP_DUMP_BYTE_CODE
|
||||
# define JERRY_REGEXP_DUMP_BYTE_CODE 0
|
||||
#endif /* !defined (JERRY_REGEXP_DUMP_BYTE_CODE) */
|
||||
|
||||
/**
|
||||
* Enables/disables the RegExp strict mode
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_REGEXP_STRICT_MODE
|
||||
# define JERRY_REGEXP_STRICT_MODE 0
|
||||
#endif /* !defined (JERRY_REGEXP_STRICT_MODE) */
|
||||
|
||||
/**
|
||||
* Enable/Disable the snapshot execution functions.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable snapshot execution.
|
||||
* 1: Enable snapshot execution.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_SNAPSHOT_EXEC
|
||||
# define JERRY_SNAPSHOT_EXEC 0
|
||||
#endif /* !defined (JERRY_SNAPSHOT_EXEC) */
|
||||
|
||||
/**
|
||||
* Enable/Disable the snapshot save functions.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable snapshot save functions.
|
||||
* 1: Enable snapshot save functions.
|
||||
*/
|
||||
#ifndef JERRY_SNAPSHOT_SAVE
|
||||
# define JERRY_SNAPSHOT_SAVE 0
|
||||
#endif /* !defined (JERRY_SNAPSHOT_SAVE) */
|
||||
|
||||
/**
|
||||
* Enable/Disable usage of system allocator.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable usage of system allocator.
|
||||
* 1: Enable usage of system allocator.
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_SYSTEM_ALLOCATOR
|
||||
# define JERRY_SYSTEM_ALLOCATOR 0
|
||||
#endif /* !defined (JERRY_SYSTEM_ALLOCATOR) */
|
||||
|
||||
/**
|
||||
* Enables/disables the unicode case conversion in the engine.
|
||||
* By default Unicode case conversion is enabled.
|
||||
*/
|
||||
#ifndef JERRY_UNICODE_CASE_CONVERSION
|
||||
# define JERRY_UNICODE_CASE_CONVERSION 1
|
||||
#endif /* !defined (JERRY_UNICODE_CASE_CONVERSION) */
|
||||
|
||||
/**
|
||||
* Configures if the internal memory allocations are exposed to Valgrind or not.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable the Valgrind specific memory allocation notifications.
|
||||
* 1: Enable the Valgrind specific allocation notifications.
|
||||
*/
|
||||
#ifndef JERRY_VALGRIND
|
||||
# define JERRY_VALGRIND 0
|
||||
#endif /* !defined (JERRY_VALGRIND) */
|
||||
|
||||
/**
|
||||
* Enable/Disable the vm execution stop callback function.
|
||||
*
|
||||
* Allowed values:
|
||||
* 0: Disable vm exec stop callbacks.
|
||||
* 1: Enable vm exec stop callback functionality.
|
||||
*/
|
||||
#ifndef JERRY_VM_EXEC_STOP
|
||||
# define JERRY_VM_EXEC_STOP 0
|
||||
#endif /* !defined (JERRY_VM_EXEC_STOP) */
|
||||
|
||||
/**
|
||||
* Advanced section configurations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allow configuring attributes on a few constant data inside the engine.
|
||||
*
|
||||
* One of the main usages:
|
||||
* Normally compilers store const(ant)s in ROM. Thus saving RAM.
|
||||
* But if your compiler does not support it then the directive below can force it.
|
||||
*
|
||||
* For the moment it is mainly meant for the following targets:
|
||||
* - ESP8266
|
||||
*
|
||||
* Example configuration for moving (some) constatns into a given section:
|
||||
* # define JERRY_ATTR_CONST_DATA __attribute__((section(".rodata.const")))
|
||||
*/
|
||||
#ifndef JERRY_ATTR_CONST_DATA
|
||||
# define JERRY_ATTR_CONST_DATA
|
||||
#endif /* !defined (JERRY_ATTR_CONST_DATA) */
|
||||
|
||||
/**
|
||||
* The JERRY_ATTR_GLOBAL_HEAP allows adding extra attributes for the Jerry global heap.
|
||||
*
|
||||
* Example on how to move the global heap into it's own section:
|
||||
* #define JERRY_ATTR_GLOBAL_HEAP __attribute__((section(".text.globalheap")))
|
||||
*/
|
||||
#ifndef JERRY_ATTR_GLOBAL_HEAP
|
||||
# define JERRY_ATTR_GLOBAL_HEAP
|
||||
#endif /* !defined (JERRY_ATTR_GLOBAL_HEAP) */
|
||||
|
||||
/**
|
||||
* Sanity check for macros to see if the values are 0 or 1
|
||||
*
|
||||
* If a new feature is added this should be updated.
|
||||
*/
|
||||
/**
|
||||
* Check base builtins.
|
||||
*/
|
||||
#if !defined (JERRY_BUILTIN_ANNEXB) \
|
||||
|| ((JERRY_BUILTIN_ANNEXB != 0) && (JERRY_BUILTIN_ANNEXB != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_ANNEXB macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_ARRAY) \
|
||||
|| ((JERRY_BUILTIN_ARRAY != 0) && (JERRY_BUILTIN_ARRAY != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_ARRAY macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_BOOLEAN) \
|
||||
|| ((JERRY_BUILTIN_BOOLEAN != 0) && (JERRY_BUILTIN_BOOLEAN != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_BOOLEAN macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_DATE) \
|
||||
|| ((JERRY_BUILTIN_DATE != 0) && (JERRY_BUILTIN_DATE != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_DATE macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_ERRORS) \
|
||||
|| ((JERRY_BUILTIN_ERRORS != 0) && (JERRY_BUILTIN_ERRORS != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_ERRORS macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_JSON) \
|
||||
|| ((JERRY_BUILTIN_JSON != 0) && (JERRY_BUILTIN_JSON != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_JSON macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_MATH) \
|
||||
|| ((JERRY_BUILTIN_MATH != 0) && (JERRY_BUILTIN_MATH != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_MATH macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_NUMBER) \
|
||||
|| ((JERRY_BUILTIN_NUMBER != 0) && (JERRY_BUILTIN_NUMBER != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_NUMBER macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_REGEXP) \
|
||||
|| ((JERRY_BUILTIN_REGEXP != 0) && (JERRY_BUILTIN_REGEXP != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_REGEXP macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_STRING) \
|
||||
|| ((JERRY_BUILTIN_STRING != 0) && (JERRY_BUILTIN_STRING != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_STRING macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTINS) \
|
||||
|| ((JERRY_BUILTINS != 0) && (JERRY_BUILTINS != 1))
|
||||
# error "Invalid value for JERRY_BUILTINS macro."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check ES2015+ features
|
||||
*/
|
||||
#if !defined (JERRY_ESNEXT) \
|
||||
|| ((JERRY_ESNEXT != 0) && (JERRY_ESNEXT != 1))
|
||||
# error "Invalid value for JERRY_ESNEXT macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_REALMS) \
|
||||
|| ((JERRY_BUILTIN_REALMS != 0) && (JERRY_BUILTIN_REALMS != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_REALMS macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_DATAVIEW) \
|
||||
|| ((JERRY_BUILTIN_DATAVIEW != 0) && (JERRY_BUILTIN_DATAVIEW != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_DATAVIEW macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_MAP) \
|
||||
|| ((JERRY_BUILTIN_MAP != 0) && (JERRY_BUILTIN_MAP != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_MAP macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_REFLECT) \
|
||||
|| ((JERRY_BUILTIN_REFLECT != 0) && (JERRY_BUILTIN_REFLECT != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_REFLECT macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_SET) \
|
||||
|| ((JERRY_BUILTIN_SET != 0) && (JERRY_BUILTIN_SET != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_SET macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_WEAKMAP) \
|
||||
|| ((JERRY_BUILTIN_WEAKMAP != 0) && (JERRY_BUILTIN_WEAKMAP != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_WEAKMAP macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_WEAKSET) \
|
||||
|| ((JERRY_BUILTIN_WEAKSET != 0) && (JERRY_BUILTIN_WEAKSET != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_WEAKSET macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_PROMISE) \
|
||||
|| ((JERRY_BUILTIN_PROMISE != 0) && (JERRY_BUILTIN_PROMISE != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_PROMISE macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_PROXY) \
|
||||
|| ((JERRY_BUILTIN_PROXY != 0) && (JERRY_BUILTIN_PROXY != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_PROXY macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_TYPEDARRAY) \
|
||||
|| ((JERRY_BUILTIN_TYPEDARRAY != 0) && (JERRY_BUILTIN_TYPEDARRAY != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_TYPEDARRAY macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_BIGINT) \
|
||||
|| ((JERRY_BUILTIN_BIGINT != 0) && (JERRY_BUILTIN_BIGINT != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_BIGINT macro."
|
||||
#endif
|
||||
#if !defined (JERRY_MODULE_SYSTEM) \
|
||||
|| ((JERRY_MODULE_SYSTEM != 0) && (JERRY_MODULE_SYSTEM != 1))
|
||||
# error "Invalid value for JERRY_MODULE_SYSTEM macro."
|
||||
#endif
|
||||
#if (JERRY_ESNEXT == 0) \
|
||||
&& ((JERRY_BUILTIN_DATAVIEW == 1) \
|
||||
|| (JERRY_BUILTIN_MAP == 1) \
|
||||
|| (JERRY_BUILTIN_SET == 1) \
|
||||
|| (JERRY_BUILTIN_WEAKMAP == 1) \
|
||||
|| (JERRY_BUILTIN_WEAKSET == 1) \
|
||||
|| (JERRY_BUILTIN_PROMISE == 1) \
|
||||
|| (JERRY_BUILTIN_PROXY == 1) \
|
||||
|| (JERRY_BUILTIN_REFLECT == 1) \
|
||||
|| (JERRY_BUILTIN_TYPEDARRAY == 1))
|
||||
# error "JERRY_ESNEXT should be enabled too to enable JERRY_BUILTIN_xxxxx macro."
|
||||
#endif
|
||||
#if (JERRY_ESNEXT == 0) && (JERRY_MODULE_SYSTEM == 1)
|
||||
# error "JERRY_ESNEXT should be enabled too to enable JERRY_MODULE_SYSTEM macro."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Internal options.
|
||||
*/
|
||||
#if !defined (JERRY_CPOINTER_32_BIT) \
|
||||
|| ((JERRY_CPOINTER_32_BIT != 0) && (JERRY_CPOINTER_32_BIT != 1))
|
||||
# error "Invalid value for 'JERRY_CPOINTER_32_BIT' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_DEBUGGER) \
|
||||
|| ((JERRY_DEBUGGER != 0) && (JERRY_DEBUGGER != 1))
|
||||
# error "Invalid value for 'JERRY_DEBUGGER' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_ERROR_MESSAGES) \
|
||||
|| ((JERRY_ERROR_MESSAGES != 0) && (JERRY_ERROR_MESSAGES != 1))
|
||||
# error "Invalid value for 'JERRY_ERROR_MESSAGES' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_EXTERNAL_CONTEXT) \
|
||||
|| ((JERRY_EXTERNAL_CONTEXT != 0) && (JERRY_EXTERNAL_CONTEXT != 1))
|
||||
# error "Invalid value for 'JERRY_EXTERNAL_CONTEXT' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_GLOBAL_HEAP_SIZE) || (JERRY_GLOBAL_HEAP_SIZE <= 0)
|
||||
# error "Invalid value for 'JERRY_GLOBAL_HEAP_SIZE' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_GC_LIMIT) || (JERRY_GC_LIMIT < 0)
|
||||
# error "Invalid value for 'JERRY_GC_LIMIT' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_STACK_LIMIT) || (JERRY_STACK_LIMIT < 0)
|
||||
# error "Invalid value for 'JERRY_STACK_LIMIT' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_GC_MARK_LIMIT) || (JERRY_GC_MARK_LIMIT < 0)
|
||||
# error "Invalid value for 'JERRY_GC_MARK_LIMIT' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_LCACHE) \
|
||||
|| ((JERRY_LCACHE != 0) && (JERRY_LCACHE != 1))
|
||||
# error "Invalid value for 'JERRY_LCACHE' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_LINE_INFO) \
|
||||
|| ((JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1))
|
||||
# error "Invalid value for 'JERRY_LINE_INFO' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_LOGGING) \
|
||||
|| ((JERRY_LOGGING != 0) && (JERRY_LOGGING != 1))
|
||||
# error "Invalid value for 'JERRY_LOGGING' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_MEM_GC_BEFORE_EACH_ALLOC) \
|
||||
|| ((JERRY_MEM_GC_BEFORE_EACH_ALLOC != 0) && (JERRY_MEM_GC_BEFORE_EACH_ALLOC != 1))
|
||||
# error "Invalid value for 'JERRY_MEM_GC_BEFORE_EACH_ALLOC' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_MEM_STATS) \
|
||||
|| ((JERRY_MEM_STATS != 0) && (JERRY_MEM_STATS != 1))
|
||||
# error "Invalid value for 'JERRY_MEM_STATS' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_NUMBER_TYPE_FLOAT64) \
|
||||
|| ((JERRY_NUMBER_TYPE_FLOAT64 != 0) && (JERRY_NUMBER_TYPE_FLOAT64 != 1))
|
||||
# error "Invalid value for 'JERRY_NUMBER_TYPE_FLOAT64' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_PARSER) \
|
||||
|| ((JERRY_PARSER != 0) && (JERRY_PARSER != 1))
|
||||
# error "Invalid value for 'JERRY_PARSER' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_PARSER_DUMP_BYTE_CODE) \
|
||||
|| ((JERRY_PARSER_DUMP_BYTE_CODE != 0) && (JERRY_PARSER_DUMP_BYTE_CODE != 1))
|
||||
# error "Invalid value for 'JERRY_PARSER_DUMP_BYTE_CODE' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_PROPRETY_HASHMAP) \
|
||||
|| ((JERRY_PROPRETY_HASHMAP != 0) && (JERRY_PROPRETY_HASHMAP != 1))
|
||||
# error "Invalid value for 'JERRY_PROPRETY_HASHMAP' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_REGEXP_DUMP_BYTE_CODE) \
|
||||
|| ((JERRY_REGEXP_DUMP_BYTE_CODE != 0) && (JERRY_REGEXP_DUMP_BYTE_CODE != 1))
|
||||
# error "Invalid value for 'JERRY_REGEXP_DUMP_BYTE_CODE' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_REGEXP_STRICT_MODE) \
|
||||
|| ((JERRY_REGEXP_STRICT_MODE != 0) && (JERRY_REGEXP_STRICT_MODE != 1))
|
||||
# error "Invalid value for 'JERRY_REGEXP_STRICT_MODE' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_SNAPSHOT_EXEC) \
|
||||
|| ((JERRY_SNAPSHOT_EXEC != 0) && (JERRY_SNAPSHOT_EXEC != 1))
|
||||
# error "Invalid value for 'JERRY_SNAPSHOT_EXEC' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_SNAPSHOT_SAVE) \
|
||||
|| ((JERRY_SNAPSHOT_SAVE != 0) && (JERRY_SNAPSHOT_SAVE != 1))
|
||||
# error "Invalid value for 'JERRY_SNAPSHOT_SAVE' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_SYSTEM_ALLOCATOR) \
|
||||
|| ((JERRY_SYSTEM_ALLOCATOR != 0) && (JERRY_SYSTEM_ALLOCATOR != 1))
|
||||
# error "Invalid value for 'JERRY_SYSTEM_ALLOCATOR' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_UNICODE_CASE_CONVERSION) \
|
||||
|| ((JERRY_UNICODE_CASE_CONVERSION != 0) && (JERRY_UNICODE_CASE_CONVERSION != 1))
|
||||
# error "Invalid value for 'JERRY_UNICODE_CASE_CONVERSION' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_VALGRIND) \
|
||||
|| ((JERRY_VALGRIND != 0) && (JERRY_VALGRIND != 1))
|
||||
# error "Invalid value for 'JERRY_VALGRIND' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_VM_EXEC_STOP) \
|
||||
|| ((JERRY_VM_EXEC_STOP != 0) && (JERRY_VM_EXEC_STOP != 1))
|
||||
# error "Invalid value for 'JERRY_VM_EXEC_STOP' macro."
|
||||
#endif
|
||||
|
||||
#define ENABLED(FEATURE) ((FEATURE) == 1)
|
||||
#define DISABLED(FEATURE) ((FEATURE) != 1)
|
||||
|
||||
/**
|
||||
* Cross component requirements check.
|
||||
*/
|
||||
/**
|
||||
* The date module can only use the float 64 number types.
|
||||
* Do a check for this.
|
||||
*/
|
||||
#if ENABLED (JERRY_BUILTIN_DATE) && !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
|
||||
# error "Date does not support float32"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Wrap container types into a single guard
|
||||
*/
|
||||
#if ENABLED (JERRY_BUILTIN_MAP) || ENABLED (JERRY_BUILTIN_SET) \
|
||||
|| ENABLED (JERRY_BUILTIN_WEAKMAP) || ENABLED (JERRY_BUILTIN_WEAKSET)
|
||||
# define JERRY_BUILTIN_CONTAINER 1
|
||||
#else
|
||||
# define JERRY_BUILTIN_CONTAINER 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Resource name related types into a single guard
|
||||
*/
|
||||
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_MODULE_SYSTEM)
|
||||
# define JERRY_RESOURCE_NAME 1
|
||||
#else
|
||||
# define JERRY_RESOURCE_NAME 0
|
||||
#endif
|
||||
|
||||
#endif /* !JERRYSCRIPT_CONFIG_H */
|
|
@ -0,0 +1,491 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef DEBUGGER_H
|
||||
#define DEBUGGER_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jerryscript-debugger-transport.h"
|
||||
|
||||
#if ENABLED (JERRY_DEBUGGER)
|
||||
|
||||
/* JerryScript debugger protocol is a simplified version of RFC-6455 (WebSockets). */
|
||||
|
||||
/**
|
||||
* Frequency of calling jerry_debugger_receive() by the VM.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_MESSAGE_FREQUENCY 5
|
||||
|
||||
/**
|
||||
* This constant represents that the string to be sent has no subtype.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_NO_SUBTYPE 0
|
||||
|
||||
/**
|
||||
* Limited resources available for the engine, so it is important to
|
||||
* check the maximum buffer size. It needs to be between 64 and 256 bytes.
|
||||
*/
|
||||
#if JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE < 64 || JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE > 256
|
||||
#error Please define the MAX_BUFFER_SIZE between 64 and 256 bytes.
|
||||
#endif /* JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE < 64 || JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE > 256 */
|
||||
|
||||
/**
|
||||
* Calculate the maximum number of items for a given type
|
||||
* which can be transmitted in one message.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_SEND_MAX(type) \
|
||||
((size_t) ((JERRY_CONTEXT (debugger_max_send_size) - sizeof (jerry_debugger_send_type_t)) / sizeof (type)))
|
||||
|
||||
/**
|
||||
* Calculate the size of a message when a count number of items transmitted.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_SEND_SIZE(count, type) \
|
||||
((size_t) ((count * sizeof (type)) + sizeof (jerry_debugger_send_type_t)))
|
||||
|
||||
/**
|
||||
* Debugger operation modes:
|
||||
*
|
||||
* The debugger has two operation modes: run mode and breakpoint mode.
|
||||
*
|
||||
* In run mode the debugger server accepts only a limited number of message
|
||||
* types from the debugger client (e.g. stop execution, set breakpoint).
|
||||
*
|
||||
* In breakpoint mode the JavaScript execution is stopped at a breakpoint and
|
||||
* more message types are accepted (e.g. get backtrace, evaluate expression).
|
||||
*
|
||||
* Switching between modes:
|
||||
*
|
||||
* When the JavaScript execution stops at a breakpoint the server sends a
|
||||
* JERRY_DEBUGGER_BREAKPOINT_HIT message to the client. The client can only
|
||||
* issue breakpoint mode commands after this message is received.
|
||||
*
|
||||
* Certain breakpoint mode commands (e.g. continue) resumes the JavaScript
|
||||
* execution and the client must not send any breakpoint mode messages
|
||||
* until the JERRY_DEBUGGER_BREAKPOINT_HIT is received again.
|
||||
*
|
||||
* The debugger server starts in run mode but stops at the first available
|
||||
* breakpoint.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Debugger option flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_CONNECTED = 1u << 0, /**< debugger is connected */
|
||||
JERRY_DEBUGGER_BREAKPOINT_MODE = 1u << 1, /**< debugger waiting at a breakpoint */
|
||||
JERRY_DEBUGGER_VM_STOP = 1u << 2, /**< stop at the next breakpoint even if disabled */
|
||||
JERRY_DEBUGGER_VM_IGNORE = 1u << 3, /**< ignore all breakpoints */
|
||||
JERRY_DEBUGGER_VM_IGNORE_EXCEPTION = 1u << 4, /**< debugger doesn't stop at any exception */
|
||||
JERRY_DEBUGGER_VM_EXCEPTION_THROWN = 1u << 5, /**< no need to stop for this exception */
|
||||
JERRY_DEBUGGER_PARSER_WAIT = 1u << 6, /**< debugger should wait after parsing is completed */
|
||||
JERRY_DEBUGGER_PARSER_WAIT_MODE = 1u << 7, /**< debugger is waiting after parsing is completed */
|
||||
JERRY_DEBUGGER_CLIENT_SOURCE_MODE = 1u << 8, /**< debugger waiting for client code */
|
||||
JERRY_DEBUGGER_CLIENT_NO_SOURCE = 1u << 9, /**< debugger leaving the client source loop */
|
||||
JERRY_DEBUGGER_CONTEXT_RESET_MODE = 1u << 10, /**< debugger and engine reinitialization mode */
|
||||
} jerry_debugger_flags_t;
|
||||
|
||||
/**
|
||||
* Set debugger flags.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_SET_FLAGS(flags) \
|
||||
JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags))
|
||||
|
||||
/**
|
||||
* Clear debugger flags.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_CLEAR_FLAGS(flags) \
|
||||
JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) & (uint32_t) ~(flags))
|
||||
|
||||
/**
|
||||
* Set and clear debugger flags.
|
||||
*/
|
||||
#define JERRY_DEBUGGER_UPDATE_FLAGS(flags_to_set, flags_to_clear) \
|
||||
JERRY_CONTEXT (debugger_flags) = ((JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags_to_set)) \
|
||||
& (uint32_t) ~(flags_to_clear))
|
||||
|
||||
/**
|
||||
* Types for the package.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* Messages sent by the server to client. */
|
||||
/* This is a handshake message, sent once during initialization. */
|
||||
JERRY_DEBUGGER_CONFIGURATION = 1, /**< debugger configuration */
|
||||
/* These messages are sent by the parser. */
|
||||
JERRY_DEBUGGER_PARSE_ERROR = 2, /**< parse error */
|
||||
JERRY_DEBUGGER_BYTE_CODE_CP = 3, /**< byte code compressed pointer */
|
||||
JERRY_DEBUGGER_PARSE_FUNCTION = 4, /**< parsing a new function */
|
||||
JERRY_DEBUGGER_BREAKPOINT_LIST = 5, /**< list of line offsets */
|
||||
JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST = 6, /**< list of byte code offsets */
|
||||
JERRY_DEBUGGER_SOURCE_CODE = 7, /**< source code fragment */
|
||||
JERRY_DEBUGGER_SOURCE_CODE_END = 8, /**< source code last fragment */
|
||||
JERRY_DEBUGGER_SOURCE_CODE_NAME = 9, /**< source code name fragment */
|
||||
JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10, /**< source code name last fragment */
|
||||
JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */
|
||||
JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */
|
||||
JERRY_DEBUGGER_WAITING_AFTER_PARSE = 13, /**< engine waiting for a parser resume */
|
||||
/* These messages are generic messages. */
|
||||
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 14, /**< invalidate byte code compressed pointer */
|
||||
JERRY_DEBUGGER_MEMSTATS_RECEIVE = 15, /**< memstats sent to the client */
|
||||
JERRY_DEBUGGER_BREAKPOINT_HIT = 16, /**< notify breakpoint hit */
|
||||
JERRY_DEBUGGER_EXCEPTION_HIT = 17, /**< notify exception hit */
|
||||
JERRY_DEBUGGER_EXCEPTION_STR = 18, /**< exception string fragment */
|
||||
JERRY_DEBUGGER_EXCEPTION_STR_END = 19, /**< exception string last fragment */
|
||||
JERRY_DEBUGGER_BACKTRACE_TOTAL = 20, /**< number of total frames */
|
||||
JERRY_DEBUGGER_BACKTRACE = 21, /**< backtrace data */
|
||||
JERRY_DEBUGGER_BACKTRACE_END = 22, /**< last backtrace data */
|
||||
JERRY_DEBUGGER_EVAL_RESULT = 23, /**< eval result */
|
||||
JERRY_DEBUGGER_EVAL_RESULT_END = 24, /**< last part of eval result */
|
||||
JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25, /**< engine waiting for source code */
|
||||
JERRY_DEBUGGER_OUTPUT_RESULT = 26, /**< output sent by the program to the debugger */
|
||||
JERRY_DEBUGGER_OUTPUT_RESULT_END = 27, /**< last output result data */
|
||||
JERRY_DEBUGGER_SCOPE_CHAIN = 28, /**< scope chain */
|
||||
JERRY_DEBUGGER_SCOPE_CHAIN_END = 29, /**< last output of scope chain */
|
||||
JERRY_DEBUGGER_SCOPE_VARIABLES = 30, /**< scope variables */
|
||||
JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31, /**< last output of scope variables */
|
||||
JERRY_DEBUGGER_CLOSE_CONNECTION = 32, /**< close connection with the client */
|
||||
JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT, /**< number of different type of output messages by the debugger */
|
||||
|
||||
/* Messages sent by the client to server. */
|
||||
|
||||
/* The following messages are accepted in both run and breakpoint modes. */
|
||||
JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */
|
||||
JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */
|
||||
JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */
|
||||
JERRY_DEBUGGER_PARSER_CONFIG = 4, /**< parser config */
|
||||
JERRY_DEBUGGER_MEMSTATS = 5, /**< list memory statistics */
|
||||
JERRY_DEBUGGER_STOP = 6, /**< stop execution */
|
||||
/* The following message is only available in waiting after parse mode. */
|
||||
JERRY_DEBUGGER_PARSER_RESUME = 7, /**< stop waiting after parse */
|
||||
/* The following four messages are only available in client switch mode. */
|
||||
JERRY_DEBUGGER_CLIENT_SOURCE = 8, /**< first message of client source */
|
||||
JERRY_DEBUGGER_CLIENT_SOURCE_PART = 9, /**< next message of client source */
|
||||
JERRY_DEBUGGER_NO_MORE_SOURCES = 10, /**< no more sources notification */
|
||||
JERRY_DEBUGGER_CONTEXT_RESET = 11, /**< context reset request */
|
||||
/* The following messages are only available in breakpoint
|
||||
* mode and they switch the engine to run mode. */
|
||||
JERRY_DEBUGGER_CONTINUE = 12, /**< continue execution */
|
||||
JERRY_DEBUGGER_STEP = 13, /**< next breakpoint, step into functions */
|
||||
JERRY_DEBUGGER_NEXT = 14, /**< next breakpoint in the same context */
|
||||
JERRY_DEBUGGER_FINISH = 15, /**< Continue running just after the function in the current stack frame returns */
|
||||
/* The following messages are only available in breakpoint
|
||||
* mode and this mode is kept after the message is processed. */
|
||||
JERRY_DEBUGGER_GET_BACKTRACE = 16, /**< get backtrace */
|
||||
JERRY_DEBUGGER_EVAL = 17, /**< first message of evaluating a string */
|
||||
JERRY_DEBUGGER_EVAL_PART = 18, /**< next message of evaluating a string */
|
||||
JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19, /**< get type names of the scope chain */
|
||||
JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20, /**< get variables of a scope */
|
||||
JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */
|
||||
} jerry_debugger_header_type_t;
|
||||
|
||||
/**
|
||||
* Debugger option flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_LITTLE_ENDIAN = 1u << 0, /**< little endian */
|
||||
} jerry_debugger_configuration_flags_t;
|
||||
|
||||
/**
|
||||
* Subtypes of eval.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_EVAL_EVAL = 0, /**< evaluate expression */
|
||||
JERRY_DEBUGGER_EVAL_THROW = 1, /**< evaluate expression and throw the result */
|
||||
JERRY_DEBUGGER_EVAL_ABORT = 2, /**< evaluate expression and abrot with the result */
|
||||
} jerry_debugger_eval_type_t;
|
||||
|
||||
/**
|
||||
* Subtypes of eval_result.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_EVAL_OK = 1, /**< eval result, no error */
|
||||
JERRY_DEBUGGER_EVAL_ERROR = 2, /**< eval result when an error has occurred */
|
||||
} jerry_debugger_eval_result_type_t;
|
||||
|
||||
/**
|
||||
* Subtypes of output_result.
|
||||
*
|
||||
* Note:
|
||||
* This enum has to be kept in sync with jerry_log_level_t with an offset
|
||||
* of +2.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_OUTPUT_OK = 1, /**< output result, no error */
|
||||
JERRY_DEBUGGER_OUTPUT_ERROR = 2, /**< output result, error */
|
||||
JERRY_DEBUGGER_OUTPUT_WARNING = 3, /**< output result, warning */
|
||||
JERRY_DEBUGGER_OUTPUT_DEBUG = 4, /**< output result, debug */
|
||||
JERRY_DEBUGGER_OUTPUT_TRACE = 5, /**< output result, trace */
|
||||
} jerry_debugger_output_subtype_t;
|
||||
|
||||
/**
|
||||
* Types of scopes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_SCOPE_WITH = 1, /**< with */
|
||||
JERRY_DEBUGGER_SCOPE_LOCAL = 2, /**< local */
|
||||
JERRY_DEBUGGER_SCOPE_CLOSURE = 3, /**< closure */
|
||||
JERRY_DEBUGGER_SCOPE_GLOBAL = 4, /**< global */
|
||||
JERRY_DEBUGGER_SCOPE_NON_CLOSURE = 5 /**< non closure */
|
||||
} jerry_debugger_scope_chain_type_t;
|
||||
|
||||
/**
|
||||
* Type of scope variables.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_DEBUGGER_VALUE_NONE = 1,
|
||||
JERRY_DEBUGGER_VALUE_UNDEFINED = 2,
|
||||
JERRY_DEBUGGER_VALUE_NULL = 3,
|
||||
JERRY_DEBUGGER_VALUE_BOOLEAN = 4,
|
||||
JERRY_DEBUGGER_VALUE_NUMBER = 5,
|
||||
JERRY_DEBUGGER_VALUE_STRING = 6,
|
||||
JERRY_DEBUGGER_VALUE_FUNCTION = 7,
|
||||
JERRY_DEBUGGER_VALUE_ARRAY = 8,
|
||||
JERRY_DEBUGGER_VALUE_OBJECT = 9
|
||||
} jerry_debugger_scope_variable_type_t;
|
||||
|
||||
/**
|
||||
* Byte data for evaluating expressions and receiving client source.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t uint8_size; /**< total size of the client source */
|
||||
uint32_t uint8_offset; /**< current offset in the client source */
|
||||
} jerry_debugger_uint8_data_t;
|
||||
|
||||
/**
|
||||
* Delayed free of byte code data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t size; /**< size of the byte code header divided by JMEM_ALIGNMENT */
|
||||
jmem_cpointer_t prev_cp; /**< previous byte code data to be freed */
|
||||
} jerry_debugger_byte_code_free_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: JerryScript configuration.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t configuration; /**< configuration option bits */
|
||||
uint8_t version[sizeof (uint32_t)]; /**< debugger version */
|
||||
uint8_t max_message_size; /**< maximum incoming message size */
|
||||
uint8_t cpointer_size; /**< size of compressed pointers */
|
||||
} jerry_debugger_send_configuration_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: message without arguments.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
} jerry_debugger_send_type_t;
|
||||
|
||||
/**
|
||||
* Incoming message: message without arguments.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
} jerry_debugger_receive_type_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: string (Source file name or function name).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t string[]; /**< string data */
|
||||
} jerry_debugger_send_string_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: uint32 value.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t line[sizeof (uint32_t)]; /**< value data */
|
||||
uint8_t column[sizeof (uint32_t)]; /**< value data */
|
||||
} jerry_debugger_send_parse_function_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: byte code compressed pointer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
|
||||
} jerry_debugger_send_byte_code_cp_t;
|
||||
|
||||
/**
|
||||
* Incoming message: byte code compressed pointer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
|
||||
} jerry_debugger_receive_byte_code_cp_t;
|
||||
|
||||
/**
|
||||
* Incoming message: update (enable/disable) breakpoint status.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t is_set_breakpoint; /**< set or clear breakpoint */
|
||||
uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
|
||||
uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
|
||||
} jerry_debugger_receive_update_breakpoint_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: send memory statistics
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t allocated_bytes[sizeof (uint32_t)]; /**< allocated bytes */
|
||||
uint8_t byte_code_bytes[sizeof (uint32_t)]; /**< byte code bytes */
|
||||
uint8_t string_bytes[sizeof (uint32_t)]; /**< string bytes */
|
||||
uint8_t object_bytes[sizeof (uint32_t)]; /**< object bytes */
|
||||
uint8_t property_bytes[sizeof (uint32_t)]; /**< property bytes */
|
||||
} jerry_debugger_send_memstats_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: notify breakpoint hit.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
|
||||
uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
|
||||
} jerry_debugger_send_breakpoint_hit_t;
|
||||
|
||||
/**
|
||||
* Stack frame descriptor for sending backtrace information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
|
||||
uint8_t offset[sizeof (uint32_t)]; /**< last breakpoint offset */
|
||||
} jerry_debugger_frame_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: backtrace information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
jerry_debugger_frame_t frames[]; /**< frames */
|
||||
} jerry_debugger_send_backtrace_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: scope chain.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t scope_types[]; /**< scope types */
|
||||
} jerry_debugger_send_scope_chain_t;
|
||||
|
||||
/**
|
||||
* Outgoing message: number of total frames in backtrace.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t frame_count[sizeof (uint32_t)]; /**< total number of frames */
|
||||
} jerry_debugger_send_backtrace_total_t;
|
||||
|
||||
/**
|
||||
* Incoming message: set behaviour when exception occures.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t enable; /**< non-zero: enable stop at exception */
|
||||
} jerry_debugger_receive_exception_config_t;
|
||||
|
||||
/**
|
||||
* Incoming message: set parser configuration.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t enable_wait; /**< non-zero: wait after parsing is completed */
|
||||
} jerry_debugger_receive_parser_config_t;
|
||||
|
||||
/**
|
||||
* Incoming message: get backtrace.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t min_depth[sizeof (uint32_t)]; /**< minimum depth*/
|
||||
uint8_t max_depth[sizeof (uint32_t)]; /**< maximum depth (0 - unlimited) */
|
||||
uint8_t get_total_frame_count; /**< non-zero: if total frame count is also requested */
|
||||
} jerry_debugger_receive_get_backtrace_t;
|
||||
|
||||
/**
|
||||
* Incoming message: first message of evaluating expression.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t eval_size[sizeof (uint32_t)]; /**< total size of the message */
|
||||
} jerry_debugger_receive_eval_first_t;
|
||||
|
||||
/**
|
||||
* Incoming message: get scope variables
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t chain_index[sizeof (uint32_t)]; /**< index element of the scope */
|
||||
} jerry_debugger_receive_get_scope_variables_t;
|
||||
|
||||
/**
|
||||
* Incoming message: first message of client source.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< type of the message */
|
||||
uint8_t code_size[sizeof (uint32_t)]; /**< total size of the message */
|
||||
} jerry_debugger_receive_client_source_first_t;
|
||||
|
||||
void jerry_debugger_free_unreferenced_byte_code (void);
|
||||
|
||||
bool jerry_debugger_receive (jerry_debugger_uint8_data_t **message_data_p);
|
||||
|
||||
void jerry_debugger_breakpoint_hit (uint8_t message_type);
|
||||
|
||||
void jerry_debugger_send_type (jerry_debugger_header_type_t type);
|
||||
bool jerry_debugger_send_configuration (uint8_t max_message_size);
|
||||
void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *data, size_t size);
|
||||
bool jerry_debugger_send_string (uint8_t message_type, uint8_t sub_type, const uint8_t *string_p, size_t string_length);
|
||||
bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
|
||||
bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
|
||||
void jerry_debugger_send_memstats (void);
|
||||
bool jerry_debugger_send_exception_string (ecma_value_t exception_value);
|
||||
|
||||
#endif /* ENABLED (JERRY_DEBUGGER) */
|
||||
|
||||
#endif /* !DEBUGGER_H */
|
|
@ -0,0 +1,270 @@
|
|||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "jrt.h"
|
||||
#include "jmem.h"
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_property_value_t) == sizeof (ecma_value_t),
|
||||
size_of_ecma_property_value_t_must_be_equal_to_size_of_ecma_value_t);
|
||||
JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0,
|
||||
size_of_ecma_property_value_t_must_be_power_of_2);
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_extended_object_t) - sizeof (ecma_object_t) <= sizeof (uint64_t),
|
||||
size_of_ecma_extended_object_part_must_be_less_than_or_equal_to_8_bytes);
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of routines for allocation/freeing memory for ECMA data types.
|
||||
*
|
||||
* All allocation routines from this module have the same structure:
|
||||
* 1. Try to allocate memory.
|
||||
* 2. If allocation was successful, return pointer to the allocated block.
|
||||
* 3. Run garbage collection.
|
||||
* 4. Try to allocate memory.
|
||||
* 5. If allocation was successful, return pointer to the allocated block;
|
||||
* else - shutdown engine.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-number
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_number_t *
|
||||
ecma_alloc_number (void)
|
||||
{
|
||||
return (ecma_number_t *) jmem_pools_alloc (sizeof (ecma_number_t));
|
||||
} /* ecma_alloc_number */
|
||||
|
||||
/**
|
||||
* Dealloc memory from an ecma-number
|
||||
*/
|
||||
void
|
||||
ecma_dealloc_number (ecma_number_t *number_p) /**< number to be freed */
|
||||
{
|
||||
jmem_pools_free ((uint8_t *) number_p, sizeof (ecma_number_t));
|
||||
} /* ecma_dealloc_number */
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-object
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_object (void)
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_object_bytes (sizeof (ecma_object_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return (ecma_object_t *) jmem_pools_alloc (sizeof (ecma_object_t));
|
||||
} /* ecma_alloc_object */
|
||||
|
||||
/**
|
||||
* Dealloc memory from an ecma-object
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_object (ecma_object_t *object_p) /**< object to be freed */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_object_bytes (sizeof (ecma_object_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_pools_free (object_p, sizeof (ecma_object_t));
|
||||
} /* ecma_dealloc_object */
|
||||
|
||||
/**
|
||||
* Allocate memory for extended object
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_extended_object_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_extended_object (size_t size) /**< size of object */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_object_bytes (size);
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return jmem_heap_alloc_block (size);
|
||||
} /* ecma_alloc_extended_object */
|
||||
|
||||
/**
|
||||
* Dealloc memory of an extended object
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_extended_object (ecma_object_t *object_p, /**< extended object */
|
||||
size_t size) /**< size of object */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_object_bytes (size);
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_heap_free_block (object_p, size);
|
||||
} /* ecma_dealloc_extended_object */
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-string descriptor
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_string_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_string (void)
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_string_bytes (sizeof (ecma_string_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return (ecma_string_t *) jmem_pools_alloc (sizeof (ecma_string_t));
|
||||
} /* ecma_alloc_string */
|
||||
|
||||
/**
|
||||
* Dealloc memory from ecma-string descriptor
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_string (ecma_string_t *string_p) /**< string to be freed */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_string_bytes (sizeof (ecma_string_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_pools_free (string_p, sizeof (ecma_string_t));
|
||||
} /* ecma_dealloc_string */
|
||||
|
||||
/**
|
||||
* Allocate memory for extended ecma-string descriptor
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_extended_string_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_extended_string (void)
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_string_bytes (sizeof (ecma_extended_string_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return (ecma_extended_string_t *) jmem_heap_alloc_block (sizeof (ecma_extended_string_t));
|
||||
} /* ecma_alloc_extended_string */
|
||||
|
||||
/**
|
||||
* Dealloc memory from extended ecma-string descriptor
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_extended_string (ecma_extended_string_t *ext_string_p) /**< extended string to be freed */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_string_bytes (sizeof (ecma_extended_string_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_heap_free_block (ext_string_p, sizeof (ecma_extended_string_t));
|
||||
} /* ecma_dealloc_extended_string */
|
||||
|
||||
/**
|
||||
* Allocate memory for external ecma-string descriptor
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_external_string_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_external_string (void)
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_string_bytes (sizeof (ecma_external_string_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return (ecma_external_string_t *) jmem_heap_alloc_block (sizeof (ecma_external_string_t));
|
||||
} /* ecma_alloc_external_string */
|
||||
|
||||
/**
|
||||
* Dealloc memory from external ecma-string descriptor
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_external_string (ecma_external_string_t *ext_string_p) /**< external string to be freed */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_string_bytes (sizeof (ecma_external_string_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_heap_free_block (ext_string_p, sizeof (ecma_external_string_t));
|
||||
} /* ecma_dealloc_external_string */
|
||||
|
||||
/**
|
||||
* Allocate memory for an string with character data
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_string_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_string_buffer (size_t size) /**< size of string */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_string_bytes (size);
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return jmem_heap_alloc_block (size);
|
||||
} /* ecma_alloc_string_buffer */
|
||||
|
||||
/**
|
||||
* Dealloc memory of a string with character data
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_string_buffer (ecma_string_t *string_p, /**< string with data */
|
||||
size_t size) /**< size of string */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_string_bytes (size);
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_heap_free_block (string_p, size);
|
||||
} /* ecma_dealloc_string_buffer */
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-property pair
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
extern inline ecma_property_pair_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_alloc_property_pair (void)
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_allocate_property_bytes (sizeof (ecma_property_pair_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
return jmem_heap_alloc_block (sizeof (ecma_property_pair_t));
|
||||
} /* ecma_alloc_property_pair */
|
||||
|
||||
/**
|
||||
* Dealloc memory of an ecma-property
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p) /**< property pair to be freed */
|
||||
{
|
||||
#if ENABLED (JERRY_MEM_STATS)
|
||||
jmem_stats_free_property_bytes (sizeof (ecma_property_pair_t));
|
||||
#endif /* ENABLED (JERRY_MEM_STATS) */
|
||||
|
||||
jmem_heap_free_block (property_pair_p, sizeof (ecma_property_pair_t));
|
||||
} /* ecma_dealloc_property_pair */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,129 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_ALLOC_H
|
||||
#define ECMA_ALLOC_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-object
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_object_t *ecma_alloc_object (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from an ecma-object
|
||||
*/
|
||||
void ecma_dealloc_object (ecma_object_t *object_p);
|
||||
|
||||
/**
|
||||
* Allocate memory for extended object
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_extended_object_t *ecma_alloc_extended_object (size_t size);
|
||||
|
||||
/**
|
||||
* Dealloc memory of an extended object
|
||||
*/
|
||||
void ecma_dealloc_extended_object (ecma_object_t *object_p, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-number
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_number_t *ecma_alloc_number (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from an ecma-number
|
||||
*/
|
||||
void ecma_dealloc_number (ecma_number_t *number_p);
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-string descriptor
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_string_t *ecma_alloc_string (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from ecma-string descriptor
|
||||
*/
|
||||
void ecma_dealloc_string (ecma_string_t *string_p);
|
||||
|
||||
/**
|
||||
* Allocate memory for extended ecma-string descriptor
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_extended_string_t *ecma_alloc_extended_string (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from extended ecma-string descriptor
|
||||
*/
|
||||
void ecma_dealloc_extended_string (ecma_extended_string_t *string_p);
|
||||
|
||||
/**
|
||||
* Allocate memory for external ecma-string descriptor
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_external_string_t *ecma_alloc_external_string (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from external ecma-string descriptor
|
||||
*/
|
||||
void ecma_dealloc_external_string (ecma_external_string_t *string_p);
|
||||
|
||||
/**
|
||||
* Allocate memory for string with character data
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_string_t *ecma_alloc_string_buffer (size_t size);
|
||||
|
||||
/**
|
||||
* Dealloc memory of a string with character data
|
||||
*/
|
||||
void ecma_dealloc_string_buffer (ecma_string_t *string_p, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate memory for ecma-property pair
|
||||
*
|
||||
* @return pointer to allocated memory
|
||||
*/
|
||||
ecma_property_pair_t *ecma_alloc_property_pair (void);
|
||||
|
||||
/**
|
||||
* Dealloc memory from an ecma-property pair
|
||||
*/
|
||||
void ecma_dealloc_property_pair (ecma_property_pair_t *property_pair_p);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_ALLOC_H */
|
|
@ -0,0 +1,41 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_GC_H
|
||||
#define ECMA_GC_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmagc Garbage collector
|
||||
* @{
|
||||
*/
|
||||
|
||||
void ecma_init_gc_info (ecma_object_t *object_p);
|
||||
void ecma_ref_object (ecma_object_t *object_p);
|
||||
void ecma_deref_object (ecma_object_t *object_p);
|
||||
void ecma_gc_free_properties (ecma_object_t *object_p);
|
||||
void ecma_gc_run (void);
|
||||
void ecma_free_unused_memory (jmem_pressure_t pressure);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_GC_H */
|
|
@ -0,0 +1,422 @@
|
|||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jrt.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocate a collection of ecma values.
|
||||
*
|
||||
* @return pointer to the collection
|
||||
*/
|
||||
ecma_collection_t *
|
||||
ecma_new_collection (void)
|
||||
{
|
||||
ecma_collection_t *collection_p;
|
||||
collection_p = (ecma_collection_t *) jmem_heap_alloc_block (sizeof (ecma_collection_t));
|
||||
|
||||
collection_p->item_count = 0;
|
||||
collection_p->capacity = ECMA_COLLECTION_INITIAL_CAPACITY;
|
||||
const uint32_t size = ECMA_COLLECTION_ALLOCATED_SIZE (ECMA_COLLECTION_INITIAL_CAPACITY);
|
||||
collection_p->buffer_p = (ecma_value_t *) jmem_heap_alloc_block (size);
|
||||
|
||||
return collection_p;
|
||||
} /* ecma_new_collection */
|
||||
|
||||
/**
|
||||
* Deallocate a collection of ecma values without freeing it's values
|
||||
*/
|
||||
extern inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_collection_destroy (ecma_collection_t *collection_p) /**< value collection */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
|
||||
jmem_heap_free_block (collection_p->buffer_p, ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity));
|
||||
jmem_heap_free_block (collection_p, sizeof (ecma_collection_t));
|
||||
} /* ecma_collection_destroy */
|
||||
|
||||
/**
|
||||
* Free the object collection elements and deallocate the collection
|
||||
*/
|
||||
void
|
||||
ecma_collection_free_objects (ecma_collection_t *collection_p) /**< value collection */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
|
||||
for (uint32_t i = 0; i < collection_p->item_count; i++)
|
||||
{
|
||||
if (ecma_is_value_object (buffer_p[i]))
|
||||
{
|
||||
ecma_deref_object (ecma_get_object_from_value (buffer_p[i]));
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_destroy (collection_p);
|
||||
} /* ecma_collection_free_objects */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Free the template literal objects and deallocate the collection
|
||||
*/
|
||||
void
|
||||
ecma_collection_free_template_literal (ecma_collection_t *collection_p) /**< value collection */
|
||||
{
|
||||
for (uint32_t i = 0; i < collection_p->item_count; i++)
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (collection_p->buffer_p[i]);
|
||||
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL);
|
||||
array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_ARRAY_TEMPLATE_LITERAL;
|
||||
|
||||
ecma_property_value_t *property_value_p;
|
||||
|
||||
property_value_p = ecma_get_named_data_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_RAW));
|
||||
ecma_object_t *raw_object_p = ecma_get_object_from_value (property_value_p->value);
|
||||
|
||||
JERRY_ASSERT (ecma_get_object_type (raw_object_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
array_object_p = (ecma_extended_object_t *) raw_object_p;
|
||||
|
||||
JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL);
|
||||
array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_ARRAY_TEMPLATE_LITERAL;
|
||||
|
||||
ecma_deref_object (raw_object_p);
|
||||
ecma_deref_object (object_p);
|
||||
}
|
||||
|
||||
ecma_collection_destroy (collection_p);
|
||||
} /* ecma_collection_free_template_literal */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Free the non-object collection elements and deallocate the collection
|
||||
*/
|
||||
void
|
||||
ecma_collection_free_if_not_object (ecma_collection_t *collection_p) /**< value collection */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
|
||||
for (uint32_t i = 0; i < collection_p->item_count; i++)
|
||||
{
|
||||
ecma_free_value_if_not_object (buffer_p[i]);
|
||||
}
|
||||
|
||||
ecma_collection_destroy (collection_p);
|
||||
} /* ecma_collection_free_if_not_object */
|
||||
|
||||
/**
|
||||
* Free the collection elements and deallocate the collection
|
||||
*/
|
||||
void
|
||||
ecma_collection_free (ecma_collection_t *collection_p) /**< value collection */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
|
||||
for (uint32_t i = 0; i < collection_p->item_count; i++)
|
||||
{
|
||||
ecma_free_value (buffer_p[i]);
|
||||
}
|
||||
|
||||
ecma_collection_destroy (collection_p);
|
||||
} /* ecma_collection_free */
|
||||
|
||||
/**
|
||||
* Append new value to ecma values collection
|
||||
*
|
||||
* Note: The reference count of the values are not increased
|
||||
*/
|
||||
void
|
||||
ecma_collection_push_back (ecma_collection_t *collection_p, /**< value collection */
|
||||
ecma_value_t value) /**< ecma value to append */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
|
||||
if (JERRY_LIKELY (collection_p->item_count < collection_p->capacity))
|
||||
{
|
||||
buffer_p[collection_p->item_count++] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t new_capacity = collection_p->capacity + ECMA_COLLECTION_GROW_FACTOR;
|
||||
const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity);
|
||||
const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity);
|
||||
|
||||
buffer_p = jmem_heap_realloc_block (buffer_p, old_size, new_size);
|
||||
buffer_p[collection_p->item_count++] = value;
|
||||
collection_p->capacity = new_capacity;
|
||||
|
||||
collection_p->buffer_p = buffer_p;
|
||||
} /* ecma_collection_push_back */
|
||||
|
||||
/**
|
||||
* Reserve space for the given amount of ecma_values in the collection
|
||||
*/
|
||||
void
|
||||
ecma_collection_reserve (ecma_collection_t *collection_p, /**< value collection */
|
||||
uint32_t count) /**< number of ecma values to reserve */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
JERRY_ASSERT (UINT32_MAX - count > collection_p->capacity);
|
||||
|
||||
const uint32_t new_capacity = collection_p->capacity + count;
|
||||
const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity);
|
||||
const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity);
|
||||
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
buffer_p = jmem_heap_realloc_block (buffer_p, old_size, new_size);
|
||||
|
||||
collection_p->capacity = new_capacity;
|
||||
collection_p->buffer_p = buffer_p;
|
||||
} /* ecma_collection_reserve */
|
||||
|
||||
/**
|
||||
* Append a list of values to the end of the collection
|
||||
*/
|
||||
void
|
||||
ecma_collection_append (ecma_collection_t *collection_p, /**< value collection */
|
||||
const ecma_value_t *buffer_p, /**< values to append */
|
||||
uint32_t count) /**< number of ecma values to append */
|
||||
{
|
||||
JERRY_ASSERT (collection_p != NULL);
|
||||
JERRY_ASSERT (collection_p->capacity >= collection_p->item_count);
|
||||
|
||||
uint32_t free_count = collection_p->capacity - collection_p->item_count;
|
||||
|
||||
if (free_count < count)
|
||||
{
|
||||
ecma_collection_reserve (collection_p, count - free_count);
|
||||
}
|
||||
|
||||
memcpy (collection_p->buffer_p + collection_p->item_count, buffer_p, count * sizeof (ecma_value_t));
|
||||
collection_p->item_count += count;
|
||||
} /* ecma_collection_append */
|
||||
|
||||
/**
|
||||
* Helper function to check if a given collection have duplicated properties or not
|
||||
*
|
||||
* @return true - if there are duplicated properties in the collection
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p) /**< prop name collection */
|
||||
{
|
||||
if (collection_p->item_count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
|
||||
for (uint32_t i = 0; i < collection_p->item_count - 1; i++)
|
||||
{
|
||||
ecma_string_t *current_name_p = ecma_get_prop_name_from_value (buffer_p[i]);
|
||||
|
||||
for (uint32_t j = i + 1; j < collection_p->item_count; j++)
|
||||
{
|
||||
if (ecma_compare_ecma_strings (current_name_p, ecma_get_prop_name_from_value (buffer_p[j])))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_collection_check_duplicated_entries */
|
||||
|
||||
/**
|
||||
* Check the string value existance in the collection.
|
||||
*
|
||||
* Used by:
|
||||
* - ecma_builtin_json_stringify step 4.b.ii.5
|
||||
* - ecma_op_object_enumerate
|
||||
*
|
||||
* @return true, if the string is already in the collection.
|
||||
*/
|
||||
bool
|
||||
ecma_collection_has_string_value (ecma_collection_t *collection_p, /**< collection */
|
||||
ecma_string_t *string_p) /**< string */
|
||||
{
|
||||
ecma_value_t *buffer_p = collection_p->buffer_p;
|
||||
|
||||
for (uint32_t i = 0; i < collection_p->item_count; i++)
|
||||
{
|
||||
ecma_string_t *current_p = ecma_get_string_from_value (buffer_p[i]);
|
||||
|
||||
if (ecma_compare_ecma_strings (current_p, string_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_collection_has_string_value */
|
||||
|
||||
/**
|
||||
* Initial capacity of an ecma-collection
|
||||
*/
|
||||
#define ECMA_COMPACT_COLLECTION_GROWTH 8
|
||||
|
||||
/**
|
||||
* Set the size of the compact collection
|
||||
*/
|
||||
#define ECMA_COMPACT_COLLECTION_SET_SIZE(compact_collection_p, item_count, unused_items) \
|
||||
((compact_collection_p)[0] = (((item_count) << ECMA_COMPACT_COLLECTION_SIZE_SHIFT) | (unused_items)))
|
||||
|
||||
/**
|
||||
* Set the size of the compact collection
|
||||
*/
|
||||
#define ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT(compact_collection_p) \
|
||||
((compact_collection_p)[0] & ((1 << ECMA_COMPACT_COLLECTION_SIZE_SHIFT) - 1))
|
||||
|
||||
/**
|
||||
* Allocate a compact collection of ecma values
|
||||
*
|
||||
* @return pointer to the compact collection
|
||||
*/
|
||||
ecma_value_t *
|
||||
ecma_new_compact_collection (void)
|
||||
{
|
||||
size_t size = (ECMA_COMPACT_COLLECTION_GROWTH / 2) * sizeof (ecma_value_t);
|
||||
ecma_value_t *compact_collection_p = (ecma_value_t *) jmem_heap_alloc_block (size);
|
||||
|
||||
ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p,
|
||||
ECMA_COMPACT_COLLECTION_GROWTH / 2,
|
||||
(ECMA_COMPACT_COLLECTION_GROWTH / 2) - 1);
|
||||
return compact_collection_p;
|
||||
} /* ecma_new_compact_collection */
|
||||
|
||||
/**
|
||||
* Append a value to the compact collection
|
||||
*
|
||||
* @return updated pointer to the compact collection
|
||||
*/
|
||||
ecma_value_t *
|
||||
ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, /**< compact collection */
|
||||
ecma_value_t value) /**< ecma value to append */
|
||||
{
|
||||
ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p);
|
||||
ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p);
|
||||
|
||||
if (unused_items > 0)
|
||||
{
|
||||
compact_collection_p[size - unused_items] = value;
|
||||
(*compact_collection_p)--;
|
||||
return compact_collection_p;
|
||||
}
|
||||
|
||||
if (size == ECMA_COMPACT_COLLECTION_GROWTH / 2)
|
||||
{
|
||||
size_t old_size = (ECMA_COMPACT_COLLECTION_GROWTH / 2) * sizeof (ecma_value_t);
|
||||
size_t new_size = ECMA_COMPACT_COLLECTION_GROWTH * sizeof (ecma_value_t);
|
||||
compact_collection_p = jmem_heap_realloc_block (compact_collection_p, old_size, new_size);
|
||||
|
||||
compact_collection_p[ECMA_COMPACT_COLLECTION_GROWTH / 2] = value;
|
||||
|
||||
ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p,
|
||||
ECMA_COMPACT_COLLECTION_GROWTH,
|
||||
(ECMA_COMPACT_COLLECTION_GROWTH / 2) - 1);
|
||||
return compact_collection_p;
|
||||
}
|
||||
|
||||
size_t old_size = size * sizeof (ecma_value_t);
|
||||
size_t new_size = old_size + (ECMA_COMPACT_COLLECTION_GROWTH * sizeof (ecma_value_t));
|
||||
|
||||
compact_collection_p = jmem_heap_realloc_block (compact_collection_p, old_size, new_size);
|
||||
compact_collection_p[size] = value;
|
||||
|
||||
ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p,
|
||||
size + ECMA_COMPACT_COLLECTION_GROWTH,
|
||||
ECMA_COMPACT_COLLECTION_GROWTH - 1);
|
||||
return compact_collection_p;
|
||||
} /* ecma_compact_collection_push_back */
|
||||
|
||||
/**
|
||||
* Discard the unused elements of a compact collection
|
||||
*
|
||||
* Note:
|
||||
* further items should not be added after this call
|
||||
*
|
||||
* @return updated pointer to the compact collection
|
||||
*/
|
||||
ecma_value_t *
|
||||
ecma_compact_collection_shrink (ecma_value_t *compact_collection_p) /**< compact collection */
|
||||
{
|
||||
ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p);
|
||||
|
||||
if (unused_items == 0)
|
||||
{
|
||||
return compact_collection_p;
|
||||
}
|
||||
|
||||
ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p);
|
||||
|
||||
size_t old_size = size * sizeof (ecma_value_t);
|
||||
size_t new_size = (size - unused_items) * sizeof (ecma_value_t);
|
||||
|
||||
compact_collection_p = jmem_heap_realloc_block (compact_collection_p, old_size, new_size);
|
||||
|
||||
ECMA_COMPACT_COLLECTION_SET_SIZE (compact_collection_p, size - unused_items, 0);
|
||||
return compact_collection_p;
|
||||
} /* ecma_compact_collection_shrink */
|
||||
|
||||
/**
|
||||
* Free a compact collection
|
||||
*/
|
||||
void
|
||||
ecma_compact_collection_free (ecma_value_t *compact_collection_p) /**< compact collection */
|
||||
{
|
||||
ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p);
|
||||
ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p);
|
||||
|
||||
ecma_value_t *end_p = compact_collection_p + size - unused_items;
|
||||
ecma_value_t *current_p = compact_collection_p + 1;
|
||||
|
||||
while (current_p < end_p)
|
||||
{
|
||||
ecma_free_value (*current_p++);
|
||||
}
|
||||
|
||||
jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t));
|
||||
} /* ecma_compact_collection_free */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,241 @@
|
|||
/* 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.
|
||||
*
|
||||
* This file is based on work under the following copyright and permission
|
||||
* notice:
|
||||
*
|
||||
* Copyright (c) 2016 Marc Andrysco
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Printing Floating-Point Numbers
|
||||
*
|
||||
* available at http://cseweb.ucsd.edu/~mandrysc/pub/dtoa.pdf
|
||||
*/
|
||||
|
||||
/**
|
||||
* Floating point format definitions (next float value)
|
||||
*/
|
||||
#define ECMA_NEXT_FLOAT(value) (nextafter ((value), INFINITY))
|
||||
/**
|
||||
* Floating point format definitions (previous float value)
|
||||
*/
|
||||
#define ECMA_PREV_FLOAT(value) (nextafter ((value), -INFINITY))
|
||||
|
||||
/**
|
||||
* Value of epsilon
|
||||
*/
|
||||
#define ERROL0_EPSILON 0.0000001
|
||||
|
||||
/**
|
||||
* High-precision data structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double value; /**< value */
|
||||
double offset; /**< offset */
|
||||
} ecma_high_prec_t;
|
||||
|
||||
/**
|
||||
* Normalize the number by factoring in the error.
|
||||
*/
|
||||
static inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_normalize_high_prec_data (ecma_high_prec_t *hp_data_p) /**< [in, out] float pair */
|
||||
{
|
||||
double val = hp_data_p->value;
|
||||
|
||||
hp_data_p->value += hp_data_p->offset;
|
||||
hp_data_p->offset += val - hp_data_p->value;
|
||||
} /* ecma_normalize_high_prec_data */
|
||||
|
||||
/**
|
||||
* Multiply the high-precision number by ten.
|
||||
*/
|
||||
static inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_multiply_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */
|
||||
{
|
||||
double value = hp_data_p->value;
|
||||
|
||||
hp_data_p->value *= 10.0;
|
||||
hp_data_p->offset *= 10.0;
|
||||
|
||||
double offset = hp_data_p->value;
|
||||
|
||||
offset -= value * 8.0;
|
||||
offset -= value * 2.0;
|
||||
|
||||
hp_data_p->offset -= offset;
|
||||
|
||||
ecma_normalize_high_prec_data (hp_data_p);
|
||||
} /* ecma_multiply_high_prec_by_10 */
|
||||
|
||||
/**
|
||||
* Divide the high-precision number by ten.
|
||||
*/
|
||||
static void
|
||||
ecma_divide_high_prec_by_10 (ecma_high_prec_t *hp_data_p) /**< [in, out] high-precision number */
|
||||
{
|
||||
double value = hp_data_p->value;
|
||||
|
||||
hp_data_p->value /= 10.0;
|
||||
hp_data_p->offset /= 10.0;
|
||||
|
||||
value -= hp_data_p->value * 8.0;
|
||||
value -= hp_data_p->value * 2.0;
|
||||
|
||||
hp_data_p->offset += value / 10.0;
|
||||
|
||||
ecma_normalize_high_prec_data (hp_data_p);
|
||||
} /* ecma_divide_high_prec_by_10 */
|
||||
|
||||
/**
|
||||
* Errol0 double to ASCII conversion, guaranteed correct but possibly not optimal.
|
||||
*
|
||||
* @return number of generated digits
|
||||
*/
|
||||
extern inline lit_utf8_size_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_errol0_dtoa (double val, /**< ecma number */
|
||||
lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */
|
||||
int32_t *exp_p) /**< [out] exponent */
|
||||
{
|
||||
double power_of_10 = 1.0;
|
||||
int32_t exp = 1;
|
||||
|
||||
/* normalize the midpoint */
|
||||
ecma_high_prec_t mid;
|
||||
|
||||
mid.value = val;
|
||||
mid.offset = 0.0;
|
||||
|
||||
while (((mid.value > 10.0) || ((mid.value == 10.0) && (mid.offset >= 0.0))) && (exp < 308))
|
||||
{
|
||||
exp++;
|
||||
ecma_divide_high_prec_by_10 (&mid);
|
||||
power_of_10 /= 10.0;
|
||||
}
|
||||
|
||||
while (((mid.value < 1.0) || ((mid.value == 1.0) && (mid.offset < 0.0))) && (exp > -307))
|
||||
{
|
||||
exp--;
|
||||
ecma_multiply_high_prec_by_10 (&mid);
|
||||
power_of_10 *= 10.0;
|
||||
}
|
||||
|
||||
ecma_high_prec_t high_bound, low_bound;
|
||||
|
||||
high_bound.value = mid.value;
|
||||
high_bound.offset = mid.offset;
|
||||
|
||||
if (ECMA_NEXT_FLOAT (val) != INFINITY)
|
||||
{
|
||||
high_bound.offset += (ECMA_NEXT_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON);
|
||||
}
|
||||
|
||||
low_bound.value = mid.value;
|
||||
low_bound.offset = mid.offset + (ECMA_PREV_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON);
|
||||
|
||||
ecma_normalize_high_prec_data (&high_bound);
|
||||
ecma_normalize_high_prec_data (&low_bound);
|
||||
|
||||
/* normalized boundaries */
|
||||
|
||||
while (high_bound.value > 10.0 || (high_bound.value == 10.0 && (high_bound.offset >= 0.0)))
|
||||
{
|
||||
exp++;
|
||||
ecma_divide_high_prec_by_10 (&high_bound);
|
||||
ecma_divide_high_prec_by_10 (&low_bound);
|
||||
}
|
||||
|
||||
while (high_bound.value < 1.0 || (high_bound.value == 1.0 && (high_bound.offset < 0.0)))
|
||||
{
|
||||
exp--;
|
||||
ecma_multiply_high_prec_by_10 (&high_bound);
|
||||
ecma_multiply_high_prec_by_10 (&low_bound);
|
||||
}
|
||||
|
||||
/* digit generation */
|
||||
|
||||
lit_utf8_byte_t *dst_p = buffer_p;
|
||||
|
||||
while (high_bound.value != 0.0 || high_bound.offset != 0.0)
|
||||
{
|
||||
uint8_t high_digit = (uint8_t) high_bound.value;
|
||||
|
||||
if ((high_bound.value == high_digit) && (high_bound.offset < 0))
|
||||
{
|
||||
high_digit = (uint8_t) (high_digit - 1u);
|
||||
}
|
||||
|
||||
uint8_t low_digit = (uint8_t) low_bound.value;
|
||||
|
||||
if ((low_bound.value == low_digit) && (low_bound.offset < 0))
|
||||
{
|
||||
low_digit = (uint8_t) (low_digit - 1u);
|
||||
}
|
||||
|
||||
if (low_digit != high_digit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*dst_p++ = (lit_utf8_byte_t) ('0' + high_digit);
|
||||
|
||||
high_bound.value -= high_digit;
|
||||
ecma_multiply_high_prec_by_10 (&high_bound);
|
||||
|
||||
low_bound.value -= low_digit;
|
||||
ecma_multiply_high_prec_by_10 (&low_bound);
|
||||
}
|
||||
|
||||
double mdig = (high_bound.value + low_bound.value) / 2.0 + 0.5;
|
||||
*dst_p++ = (lit_utf8_byte_t) ('0' + (uint8_t) mdig);
|
||||
|
||||
*exp_p = exp;
|
||||
|
||||
return (lit_utf8_size_t) (dst_p - buffer_p);
|
||||
} /* ecma_errol0_dtoa */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,229 @@
|
|||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a native pointer property to store the native pointer and its type info.
|
||||
*
|
||||
* @return true - if property was just created with specified value,
|
||||
* false - otherwise, if property existed before the call, it's value was updated
|
||||
*/
|
||||
bool
|
||||
ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
|
||||
void *native_p, /**< native pointer */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
ecma_fast_array_convert_to_normal (obj_p);
|
||||
}
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
|
||||
|
||||
bool is_new = (property_p == NULL);
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p;
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
ecma_property_value_t *value_p;
|
||||
ECMA_CREATE_INTERNAL_PROPERTY (obj_p, name_p, property_p, value_p);
|
||||
|
||||
native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t));
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
ecma_native_pointer_t *iter_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value);
|
||||
|
||||
/* There should be at least 1 native pointer in the chain */
|
||||
JERRY_ASSERT (iter_p != NULL);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (iter_p->info_p == info_p)
|
||||
{
|
||||
/* The native info already exists -> update the corresponding data */
|
||||
iter_p->data_p = native_p;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iter_p->next_p == NULL)
|
||||
{
|
||||
/* The native info does not exist -> append a new element to the chain */
|
||||
break;
|
||||
}
|
||||
|
||||
iter_p = iter_p->next_p;
|
||||
}
|
||||
|
||||
native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t));
|
||||
|
||||
iter_p->next_p = native_pointer_p;
|
||||
}
|
||||
|
||||
native_pointer_p->data_p = native_p;
|
||||
native_pointer_p->info_p = info_p;
|
||||
native_pointer_p->next_p = NULL;
|
||||
|
||||
return is_new;
|
||||
} /* ecma_create_native_pointer_property */
|
||||
|
||||
/**
|
||||
* Get value of native package stored in the object's property with specified identifier
|
||||
*
|
||||
* Note:
|
||||
* property identifier should be one of the following:
|
||||
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
|
||||
*
|
||||
* @return native pointer data if property exists
|
||||
* NULL otherwise
|
||||
*/
|
||||
ecma_native_pointer_t *
|
||||
ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
/* Fast access mode array can not have native pointer properties */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||
value_p->value);
|
||||
|
||||
JERRY_ASSERT (native_pointer_p != NULL);
|
||||
|
||||
while (native_pointer_p != NULL)
|
||||
{
|
||||
if (native_pointer_p->info_p == info_p)
|
||||
{
|
||||
return native_pointer_p;
|
||||
}
|
||||
|
||||
native_pointer_p = native_pointer_p->next_p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* ecma_get_native_pointer_value */
|
||||
|
||||
/**
|
||||
* Delete the previously set native pointer by the native type info from the specified object.
|
||||
*
|
||||
* Note:
|
||||
* If the specified object has no matching native pointer for the given native type info
|
||||
* the function has no effect.
|
||||
*
|
||||
* @return true - if the native pointer has been deleted succesfully
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */
|
||||
void *info_p) /**< native pointer's type info */
|
||||
{
|
||||
if (ecma_op_object_is_fast_array (obj_p))
|
||||
{
|
||||
/* Fast access mode array can not have native pointer properties */
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||
value_p->value);
|
||||
ecma_native_pointer_t *prev_p = NULL;
|
||||
|
||||
JERRY_ASSERT (native_pointer_p != NULL);
|
||||
|
||||
while (native_pointer_p != NULL)
|
||||
{
|
||||
if (native_pointer_p->info_p == info_p)
|
||||
{
|
||||
if (prev_p == NULL)
|
||||
{
|
||||
if (native_pointer_p->next_p == NULL)
|
||||
{
|
||||
/* Only one native pointer property exists, so the property can be deleted as well. */
|
||||
ecma_op_general_object_delete (obj_p, name_p, false);
|
||||
|
||||
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are at least two native pointers and the first one should be deleted.
|
||||
In this case the second element's data is copied to the head of the chain, and freed as well. */
|
||||
ecma_native_pointer_t *next_p = native_pointer_p->next_p;
|
||||
memcpy (native_pointer_p, next_p, sizeof (ecma_native_pointer_t));
|
||||
jmem_heap_free_block (next_p, sizeof (ecma_native_pointer_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are at least two native pointers and not the first element should be deleted.
|
||||
In this case the current element's next element reference is copied to the previous element. */
|
||||
prev_p->next_p = native_pointer_p->next_p;
|
||||
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
prev_p = native_pointer_p;
|
||||
native_pointer_p = native_pointer_p->next_p;
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_delete_native_pointer_property */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,554 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_HELPERS_H
|
||||
#define ECMA_HELPERS_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem.h"
|
||||
#include "lit-strings.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmahelpers Helpers for operations with ECMA data types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get value of pointer from specified non-null compressed pointer.
|
||||
*/
|
||||
#define ECMA_GET_NON_NULL_POINTER(type, field) JMEM_CP_GET_NON_NULL_POINTER (type, field)
|
||||
|
||||
/**
|
||||
* Extract value of pointer from specified pointer-tag value
|
||||
*/
|
||||
#define ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG(type, field) \
|
||||
JMEM_CP_GET_NON_NULL_POINTER_FROM_POINTER_TAG (type, field)
|
||||
|
||||
/**
|
||||
* Get value of pointer from specified compressed pointer.
|
||||
*/
|
||||
#define ECMA_GET_POINTER(type, field) JMEM_CP_GET_POINTER (type, field)
|
||||
|
||||
/**
|
||||
* Set value of non-null compressed pointer so that it will correspond
|
||||
* to specified non_compressed_pointer.
|
||||
*/
|
||||
#define ECMA_SET_NON_NULL_POINTER(field, non_compressed_pointer) JMEM_CP_SET_NON_NULL_POINTER (field, \
|
||||
non_compressed_pointer)
|
||||
|
||||
/**
|
||||
* Set value of pointer-tag value so that it will correspond
|
||||
* to specified non_compressed_pointer along with tag
|
||||
*/
|
||||
#define ECMA_SET_NON_NULL_POINTER_TAG(field, non_compressed_pointer, tag) \
|
||||
JMEM_CP_SET_NON_NULL_POINTER_TAG (field, non_compressed_pointer, tag)
|
||||
|
||||
/**
|
||||
* Set value of compressed pointer so that it will correspond
|
||||
* to specified non_compressed_pointer.
|
||||
*/
|
||||
#define ECMA_SET_POINTER(field, non_compressed_pointer) JMEM_CP_SET_POINTER (field, non_compressed_pointer)
|
||||
|
||||
/**
|
||||
* Get value of each tag bit from specified pointer-tag value
|
||||
*/
|
||||
#define ECMA_GET_FIRST_BIT_FROM_POINTER_TAG(field) \
|
||||
JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (field) /**< get first tag bit from jmem_cpointer_tag_t **/
|
||||
#define ECMA_GET_SECOND_BIT_FROM_POINTER_TAG(field) \
|
||||
JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (field) /**< get second tag bit from jmem_cpointer_tag_t **/
|
||||
#define ECMA_GET_THIRD_BIT_FROM_POINTER_TAG(field) \
|
||||
JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (field) /**< get third tag bit from jmem_cpointer_tag_t **/
|
||||
|
||||
/**
|
||||
* Set value of each tag bit to specified pointer-tag value
|
||||
*/
|
||||
#define ECMA_SET_FIRST_BIT_TO_POINTER_TAG(field) \
|
||||
JMEM_CP_SET_FIRST_BIT_TO_POINTER_TAG (field) /**< set first tag bit to jmem_cpointer_tag_t **/
|
||||
#define ECMA_SET_SECOND_BIT_TO_POINTER_TAG(field) \
|
||||
JMEM_CP_SET_SECOND_BIT_TO_POINTER_TAG (field) /**< set second tag bit to jmem_cpointer_tag_t **/
|
||||
#define ECMA_SET_THIRD_BIT_TO_POINTER_TAG(field) \
|
||||
JMEM_CP_SET_THIRD_BIT_TO_POINTER_TAG (field) /**< set third tag bit to jmem_cpointer_tag_t **/
|
||||
|
||||
/**
|
||||
* Status flags for ecma_string_get_chars function
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_STRING_FLAG_EMPTY = 0, /**< No options are provided. */
|
||||
ECMA_STRING_FLAG_IS_ASCII = (1 << 0), /**< The string contains only ASCII characters. */
|
||||
ECMA_STRING_FLAG_REHASH_NEEDED = (1 << 1), /**< The hash of the string must be recalculated.
|
||||
* For more details see ecma_append_chars_to_string */
|
||||
ECMA_STRING_FLAG_IS_UINT32 = (1 << 2), /**< The string repesents an UINT32 number */
|
||||
ECMA_STRING_FLAG_MUST_BE_FREED = (1 << 3), /**< The returned buffer must be freed */
|
||||
} ecma_string_flag_t;
|
||||
|
||||
/**
|
||||
* Underscore is ignored when this option is passed.
|
||||
*/
|
||||
#define ECMA_CONVERSION_ALLOW_UNDERSCORE 0x1
|
||||
|
||||
/**
|
||||
* Convert ecma-string's contents to a cesu-8 string and put it into a buffer.
|
||||
*/
|
||||
#define ECMA_STRING_TO_UTF8_STRING(ecma_str_ptr, /**< ecma string pointer */ \
|
||||
utf8_ptr, /**< [out] output buffer pointer */ \
|
||||
utf8_str_size) /**< [out] output buffer size */ \
|
||||
lit_utf8_size_t utf8_str_size; \
|
||||
uint8_t utf8_ptr ## flags = ECMA_STRING_FLAG_EMPTY; \
|
||||
const lit_utf8_byte_t *utf8_ptr = ecma_string_get_chars (ecma_str_ptr, \
|
||||
&utf8_str_size, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
&utf8_ptr ## flags);
|
||||
|
||||
/**
|
||||
* Free the cesu-8 string buffer allocated by 'ECMA_STRING_TO_UTF8_STRING'
|
||||
*/
|
||||
#define ECMA_FINALIZE_UTF8_STRING(utf8_ptr, /**< pointer to character buffer */ \
|
||||
utf8_str_size) /**< buffer size */ \
|
||||
if (utf8_ptr ## flags & ECMA_STRING_FLAG_MUST_BE_FREED) \
|
||||
{ \
|
||||
JERRY_ASSERT (utf8_ptr != NULL); \
|
||||
jmem_heap_free_block ((void *) utf8_ptr, utf8_str_size); \
|
||||
}
|
||||
|
||||
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
|
||||
|
||||
/**
|
||||
* Set an internal property value from pointer.
|
||||
*/
|
||||
#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) \
|
||||
((field) = ((ecma_value_t) pointer))
|
||||
|
||||
/**
|
||||
* Set an internal property value from pointer. Pointer can be NULL.
|
||||
*/
|
||||
#define ECMA_SET_INTERNAL_VALUE_ANY_POINTER(field, pointer) \
|
||||
((field) = ((ecma_value_t) pointer))
|
||||
|
||||
/**
|
||||
* Convert an internal property value to pointer.
|
||||
*/
|
||||
#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) \
|
||||
((type *) field)
|
||||
|
||||
/**
|
||||
* Convert an internal property value to pointer. Result can be NULL.
|
||||
*/
|
||||
#define ECMA_GET_INTERNAL_VALUE_ANY_POINTER(type, field) \
|
||||
((type *) field)
|
||||
|
||||
/**
|
||||
* Checks whether an internal property is NULL.
|
||||
*/
|
||||
#define ECMA_IS_INTERNAL_VALUE_NULL(field) \
|
||||
((field) == ((ecma_value_t) NULL))
|
||||
|
||||
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
/**
|
||||
* Set an internal property value from pointer.
|
||||
*/
|
||||
#define ECMA_SET_INTERNAL_VALUE_POINTER(field, pointer) \
|
||||
ECMA_SET_NON_NULL_POINTER (field, pointer)
|
||||
|
||||
/**
|
||||
* Set an internal property value from pointer. Pointer can be NULL.
|
||||
*/
|
||||
#define ECMA_SET_INTERNAL_VALUE_ANY_POINTER(field, pointer) \
|
||||
ECMA_SET_POINTER (field, pointer)
|
||||
|
||||
/**
|
||||
* Convert an internal property value to pointer.
|
||||
*/
|
||||
#define ECMA_GET_INTERNAL_VALUE_POINTER(type, field) \
|
||||
ECMA_GET_NON_NULL_POINTER (type, field)
|
||||
|
||||
/**
|
||||
* Convert an internal property value to pointer. Result can be NULL.
|
||||
*/
|
||||
#define ECMA_GET_INTERNAL_VALUE_ANY_POINTER(type, field) \
|
||||
ECMA_GET_POINTER (type, field)
|
||||
|
||||
/**
|
||||
* Checks whether an internal property is NULL.
|
||||
*/
|
||||
#define ECMA_IS_INTERNAL_VALUE_NULL(field) \
|
||||
((field) == ((ecma_value_t) JMEM_CP_NULL))
|
||||
|
||||
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
|
||||
|
||||
/**
|
||||
* Convert boolean to bitfield value.
|
||||
*/
|
||||
#define ECMA_BOOL_TO_BITFIELD(x) ((x) ? 1 : 0)
|
||||
|
||||
/**
|
||||
* Check whether the given type is ECMA_OBJECT_TYPE_PROXY
|
||||
*
|
||||
* @param type object type
|
||||
*/
|
||||
#define ECMA_OBJECT_TYPE_IS_PROXY(type) (JERRY_UNLIKELY ((type) == ECMA_OBJECT_TYPE_PROXY))
|
||||
|
||||
/**
|
||||
* Check whether the given object has [[ProxyHandler]] and [[ProxyTarger]] internal slots
|
||||
*
|
||||
* @param obj_p ecma-object
|
||||
*/
|
||||
#if ENABLED (JERRY_BUILTIN_PROXY)
|
||||
#define ECMA_OBJECT_IS_PROXY(obj_p) (ECMA_OBJECT_TYPE_IS_PROXY (ecma_get_object_type ((obj_p))))
|
||||
#else /* !ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
#define ECMA_OBJECT_IS_PROXY(obj_p) (false)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
|
||||
/* ecma-helpers-value.c */
|
||||
ecma_type_t JERRY_ATTR_CONST ecma_get_value_type_field (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_direct (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_simple (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_empty (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_undefined (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_null (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_boolean (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_true (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_false (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_found (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_array_hole (ecma_value_t value);
|
||||
|
||||
bool JERRY_ATTR_CONST ecma_is_value_integer_number (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_are_values_integer_numbers (ecma_value_t first_value, ecma_value_t second_value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_float_number (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_number (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_string (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_symbol (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_magic_string (ecma_value_t value, lit_magic_string_id_t id);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_bigint (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_prop_name (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_direct_string (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_non_direct_string (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_object (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_error_reference (ecma_value_t value);
|
||||
ecma_value_t ecma_is_value_array (ecma_value_t arg);
|
||||
|
||||
void ecma_check_value_type_is_spec_defined (ecma_value_t value);
|
||||
|
||||
ecma_value_t JERRY_ATTR_CONST ecma_make_boolean_value (bool boolean_value);
|
||||
ecma_value_t JERRY_ATTR_CONST ecma_make_integer_value (ecma_integer_value_t integer_value);
|
||||
ecma_value_t ecma_make_nan_value (void);
|
||||
ecma_value_t ecma_make_float_value (ecma_number_t *ecma_num_p);
|
||||
ecma_value_t ecma_make_length_value (ecma_length_t length);
|
||||
ecma_value_t ecma_make_number_value (ecma_number_t ecma_number);
|
||||
ecma_value_t ecma_make_int32_value (int32_t int32_number);
|
||||
ecma_value_t ecma_make_uint32_value (uint32_t uint32_number);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_string_value (const ecma_string_t *ecma_string_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_magic_string_value (lit_magic_string_id_t id);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_object_value (const ecma_object_t *object_p);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p,
|
||||
uint32_t type);
|
||||
ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t value);
|
||||
ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value);
|
||||
ecma_number_t * ecma_get_pointer_from_float_value (ecma_value_t value);
|
||||
ecma_number_t JERRY_ATTR_PURE ecma_get_number_from_value (ecma_value_t value);
|
||||
ecma_string_t JERRY_ATTR_PURE *ecma_get_string_from_value (ecma_value_t value);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_string_t JERRY_ATTR_PURE *ecma_get_symbol_from_value (ecma_value_t value);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_string_t JERRY_ATTR_PURE *ecma_get_prop_name_from_value (ecma_value_t value);
|
||||
ecma_object_t JERRY_ATTR_PURE *ecma_get_object_from_value (ecma_value_t value);
|
||||
ecma_extended_primitive_t JERRY_ATTR_PURE *ecma_get_extended_primitive_from_value (ecma_value_t value);
|
||||
ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value);
|
||||
ecma_value_t ecma_copy_value (ecma_value_t value);
|
||||
ecma_value_t ecma_fast_copy_value (ecma_value_t value);
|
||||
ecma_value_t ecma_copy_value_if_not_object (ecma_value_t value);
|
||||
void ecma_ref_if_object (ecma_value_t value);
|
||||
void ecma_deref_if_object (ecma_value_t value);
|
||||
ecma_value_t ecma_update_float_number (ecma_value_t float_value, ecma_number_t new_number);
|
||||
void ecma_value_assign_value (ecma_value_t *value_p, ecma_value_t ecma_value);
|
||||
void ecma_value_assign_number (ecma_value_t *value_p, ecma_number_t ecma_number);
|
||||
void ecma_free_value (ecma_value_t value);
|
||||
void ecma_fast_free_value (ecma_value_t value);
|
||||
void ecma_free_value_if_not_object (ecma_value_t value);
|
||||
void ecma_free_object (ecma_value_t value);
|
||||
void ecma_free_number (ecma_value_t value);
|
||||
lit_magic_string_id_t ecma_get_typeof_lit_id (ecma_value_t value);
|
||||
|
||||
/* ecma-helpers-string.c */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_string_t *ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc);
|
||||
bool ecma_prop_name_is_symbol (ecma_string_t *string_p);
|
||||
ecma_length_t ecma_op_advance_string_index (ecma_string_t *str_p, ecma_length_t index_num, bool is_unicode);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_MAP) || ENABLED (JERRY_BUILTIN_SET)
|
||||
ecma_string_t *ecma_new_map_key_string (ecma_value_t value);
|
||||
bool ecma_prop_name_is_map_key (ecma_string_t *string_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_MAP) || ENABLED (JERRY_BUILTIN_SET) */
|
||||
ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size);
|
||||
ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p,
|
||||
lit_utf8_size_t string_size);
|
||||
ecma_string_t *ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size,
|
||||
ecma_object_native_free_callback_t free_cb);
|
||||
ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_string_t *ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, ecma_char_t second_code_unit);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_string_t *ecma_new_ecma_string_from_length (ecma_length_t index);
|
||||
ecma_string_t *ecma_new_ecma_string_from_uint32 (uint32_t uint32_number);
|
||||
ecma_string_t *ecma_new_non_direct_string_from_uint32 (uint32_t uint32_number);
|
||||
ecma_string_t *ecma_get_ecma_string_from_uint32 (uint32_t uint32_number);
|
||||
ecma_string_t *ecma_new_ecma_string_from_number (ecma_number_t num);
|
||||
ecma_string_t *ecma_get_magic_string (lit_magic_string_id_t id);
|
||||
ecma_string_t *ecma_get_internal_string (lit_magic_string_id_t id);
|
||||
ecma_string_t *ecma_append_chars_to_string (ecma_string_t *string1_p,
|
||||
const lit_utf8_byte_t *cesu8_string2_p,
|
||||
lit_utf8_size_t cesu8_string2_size,
|
||||
lit_utf8_size_t cesu8_string2_length);
|
||||
ecma_string_t *ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t *string2_p);
|
||||
void ecma_ref_ecma_string (ecma_string_t *string_p);
|
||||
void ecma_deref_ecma_string (ecma_string_t *string_p);
|
||||
void ecma_destroy_ecma_string (ecma_string_t *string_p);
|
||||
ecma_number_t ecma_string_to_number (const ecma_string_t *str_p);
|
||||
uint32_t ecma_string_get_array_index (const ecma_string_t *str_p);
|
||||
|
||||
lit_utf8_size_t JERRY_ATTR_WARN_UNUSED_RESULT
|
||||
ecma_string_copy_to_cesu8_buffer (const ecma_string_t *string_desc_p,
|
||||
lit_utf8_byte_t *buffer_p,
|
||||
lit_utf8_size_t buffer_size);
|
||||
lit_utf8_size_t JERRY_ATTR_WARN_UNUSED_RESULT
|
||||
ecma_string_copy_to_utf8_buffer (const ecma_string_t *string_desc_p,
|
||||
lit_utf8_byte_t *buffer_p,
|
||||
lit_utf8_size_t buffer_size);
|
||||
lit_utf8_size_t
|
||||
ecma_substring_copy_to_cesu8_buffer (const ecma_string_t *string_desc_p,
|
||||
lit_utf8_size_t start_pos,
|
||||
lit_utf8_size_t end_pos,
|
||||
lit_utf8_byte_t *buffer_p,
|
||||
lit_utf8_size_t buffer_size);
|
||||
lit_utf8_size_t
|
||||
ecma_substring_copy_to_utf8_buffer (const ecma_string_t *string_desc_p,
|
||||
lit_utf8_size_t start_pos,
|
||||
lit_utf8_size_t end_pos,
|
||||
lit_utf8_byte_t *buffer_p,
|
||||
lit_utf8_size_t buffer_size);
|
||||
void ecma_string_to_utf8_bytes (const ecma_string_t *string_desc_p, lit_utf8_byte_t *buffer_p,
|
||||
lit_utf8_size_t buffer_size);
|
||||
const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p,
|
||||
lit_utf8_size_t *size_p,
|
||||
lit_utf8_size_t *length_p,
|
||||
lit_utf8_byte_t *uint32_buff_p,
|
||||
uint8_t *flags_p);
|
||||
bool ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, lit_magic_string_id_t id);
|
||||
bool ecma_string_is_empty (const ecma_string_t *string_p);
|
||||
bool ecma_string_is_length (const ecma_string_t *string_p);
|
||||
|
||||
jmem_cpointer_t ecma_string_to_property_name (ecma_string_t *prop_name_p, ecma_property_t *name_type_p);
|
||||
ecma_string_t *ecma_string_from_property_name (ecma_property_t property, jmem_cpointer_t prop_name_cp);
|
||||
lit_string_hash_t ecma_string_get_property_name_hash (ecma_property_t property, jmem_cpointer_t prop_name_cp);
|
||||
uint32_t ecma_string_get_property_index (ecma_property_t property, jmem_cpointer_t prop_name_cp);
|
||||
bool ecma_string_compare_to_property_name (ecma_property_t property, jmem_cpointer_t prop_name_cp,
|
||||
const ecma_string_t *string_p);
|
||||
|
||||
bool ecma_compare_ecma_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p);
|
||||
bool ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p);
|
||||
bool ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, const ecma_string_t *string2_p);
|
||||
lit_utf8_size_t ecma_string_get_length (const ecma_string_t *string_p);
|
||||
lit_utf8_size_t ecma_string_get_utf8_length (const ecma_string_t *string_p);
|
||||
lit_utf8_size_t ecma_string_get_size (const ecma_string_t *string_p);
|
||||
lit_utf8_size_t ecma_string_get_utf8_size (const ecma_string_t *string_p);
|
||||
ecma_char_t ecma_string_get_char_at_pos (const ecma_string_t *string_p, lit_utf8_size_t index);
|
||||
|
||||
lit_magic_string_id_t ecma_get_string_magic (const ecma_string_t *string_p);
|
||||
|
||||
lit_string_hash_t ecma_string_hash (const ecma_string_t *string_p);
|
||||
ecma_string_t *ecma_string_substr (const ecma_string_t *string_p, lit_utf8_size_t start_pos, lit_utf8_size_t end_pos);
|
||||
const lit_utf8_byte_t *ecma_string_trim_front (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p);
|
||||
const lit_utf8_byte_t *ecma_string_trim_back (const lit_utf8_byte_t *start_p, const lit_utf8_byte_t *end_p);
|
||||
void ecma_string_trim_helper (const lit_utf8_byte_t **utf8_str_p,
|
||||
lit_utf8_size_t *utf8_str_size);
|
||||
ecma_string_t *ecma_string_trim (const ecma_string_t *string_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_value_t ecma_string_pad (ecma_value_t original_string_p,
|
||||
ecma_value_t max_length,
|
||||
ecma_value_t fill_string,
|
||||
bool pad_on_start);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_stringbuilder_t ecma_stringbuilder_create (void);
|
||||
ecma_stringbuilder_t ecma_stringbuilder_create_from (ecma_string_t *string_p);
|
||||
ecma_stringbuilder_t ecma_stringbuilder_create_raw (const lit_utf8_byte_t *data_p,
|
||||
const lit_utf8_size_t data_size);
|
||||
lit_utf8_size_t ecma_stringbuilder_get_size (ecma_stringbuilder_t *builder_p);
|
||||
lit_utf8_byte_t *ecma_stringbuilder_get_data (ecma_stringbuilder_t *builder_p);
|
||||
void ecma_stringbuilder_revert (ecma_stringbuilder_t *builder_p, const lit_utf8_size_t size);
|
||||
void ecma_stringbuilder_append (ecma_stringbuilder_t *builder_p, const ecma_string_t *string_p);
|
||||
void ecma_stringbuilder_append_magic (ecma_stringbuilder_t *builder_p, const lit_magic_string_id_t id);
|
||||
void ecma_stringbuilder_append_raw (ecma_stringbuilder_t *builder_p,
|
||||
const lit_utf8_byte_t *data_p,
|
||||
const lit_utf8_size_t data_size);
|
||||
void ecma_stringbuilder_append_codepoint (ecma_stringbuilder_t *builder_p, lit_code_point_t cp);
|
||||
void ecma_stringbuilder_append_char (ecma_stringbuilder_t *builder_p, const ecma_char_t c);
|
||||
void ecma_stringbuilder_append_byte (ecma_stringbuilder_t *builder_p, const lit_utf8_byte_t);
|
||||
ecma_string_t *ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p);
|
||||
void ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p);
|
||||
|
||||
/* ecma-helpers-number.c */
|
||||
ecma_number_t ecma_number_pack (bool sign, uint32_t biased_exp, uint64_t fraction);
|
||||
void ecma_number_unpack (ecma_number_t num, bool *sign_p, uint32_t *biased_exp_p, uint64_t *fraction_p);
|
||||
ecma_number_t ecma_number_make_nan (void);
|
||||
ecma_number_t ecma_number_make_infinity (bool sign);
|
||||
bool ecma_number_is_nan (ecma_number_t num);
|
||||
bool ecma_number_is_negative (ecma_number_t num);
|
||||
bool ecma_number_is_zero (ecma_number_t num);
|
||||
bool ecma_number_is_infinity (ecma_number_t num);
|
||||
bool ecma_number_is_finite (ecma_number_t num);
|
||||
ecma_number_t
|
||||
ecma_number_make_from_sign_mantissa_and_exponent (bool sign, uint64_t mantissa, int32_t exponent);
|
||||
ecma_number_t ecma_number_get_prev (ecma_number_t num);
|
||||
ecma_number_t ecma_number_get_next (ecma_number_t num);
|
||||
ecma_number_t ecma_number_trunc (ecma_number_t num);
|
||||
ecma_number_t ecma_number_calc_remainder (ecma_number_t left_num, ecma_number_t right_num);
|
||||
ecma_number_t ecma_number_pow (ecma_number_t x, ecma_number_t y);
|
||||
ecma_value_t ecma_number_parse_int (const lit_utf8_byte_t *string_buff,
|
||||
lit_utf8_size_t string_buff_size,
|
||||
ecma_value_t radix);
|
||||
ecma_value_t ecma_number_parse_float (const lit_utf8_byte_t *string_buff,
|
||||
lit_utf8_size_t string_buff_size);
|
||||
ecma_value_t ecma_integer_multiply (ecma_integer_value_t left_integer, ecma_integer_value_t right_integer);
|
||||
lit_utf8_size_t ecma_number_to_decimal (ecma_number_t num, lit_utf8_byte_t *out_digits_p, int32_t *out_decimal_exp_p);
|
||||
|
||||
/* ecma-helpers-collection.c */
|
||||
ecma_collection_t *ecma_new_collection (void);
|
||||
void ecma_collection_push_back (ecma_collection_t *collection_p, ecma_value_t value);
|
||||
void ecma_collection_reserve (ecma_collection_t *collection_p, uint32_t count);
|
||||
void ecma_collection_append (ecma_collection_t *collection_p, const ecma_value_t *buffer_p, uint32_t count);
|
||||
void ecma_collection_destroy (ecma_collection_t *collection_p);
|
||||
void ecma_collection_free (ecma_collection_t *collection_p);
|
||||
void ecma_collection_free_if_not_object (ecma_collection_t *collection_p);
|
||||
void ecma_collection_free_objects (ecma_collection_t *collection_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
void ecma_collection_free_template_literal (ecma_collection_t *collection_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
bool ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p);
|
||||
bool ecma_collection_has_string_value (ecma_collection_t *collection_p, ecma_string_t *string_p);
|
||||
|
||||
ecma_value_t *ecma_new_compact_collection (void);
|
||||
ecma_value_t *ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, ecma_value_t value);
|
||||
ecma_value_t *ecma_compact_collection_shrink (ecma_value_t *compact_collection_p);
|
||||
void ecma_compact_collection_free (ecma_value_t *compact_collection_p);
|
||||
|
||||
/* ecma-helpers.c */
|
||||
ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type);
|
||||
ecma_object_t *ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p);
|
||||
ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p,
|
||||
ecma_lexical_environment_type_t type);
|
||||
bool JERRY_ATTR_PURE ecma_is_lexical_environment (const ecma_object_t *object_p);
|
||||
void ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p);
|
||||
ecma_object_type_t JERRY_ATTR_PURE ecma_get_object_type (const ecma_object_t *object_p);
|
||||
bool JERRY_ATTR_PURE ecma_get_object_is_builtin (const ecma_object_t *object_p);
|
||||
void ecma_set_object_is_builtin (ecma_object_t *object_p);
|
||||
uint8_t ecma_get_object_builtin_id (ecma_object_t *object_p);
|
||||
ecma_lexical_environment_type_t JERRY_ATTR_PURE ecma_get_lex_env_type (const ecma_object_t *object_p);
|
||||
ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_binding_object (const ecma_object_t *object_p);
|
||||
ecma_object_t *ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, bool copy_values);
|
||||
|
||||
ecma_property_value_t *
|
||||
ecma_create_named_data_property (ecma_object_t *object_p, ecma_string_t *name_p, uint8_t prop_attributes,
|
||||
ecma_property_t **out_prop_p);
|
||||
ecma_property_value_t *
|
||||
ecma_create_named_accessor_property (ecma_object_t *object_p, ecma_string_t *name_p, ecma_object_t *get_p,
|
||||
ecma_object_t *set_p, uint8_t prop_attributes, ecma_property_t **out_prop_p);
|
||||
ecma_property_t *
|
||||
ecma_find_named_property (ecma_object_t *obj_p, ecma_string_t *name_p);
|
||||
ecma_property_value_t *
|
||||
ecma_get_named_data_property (ecma_object_t *obj_p, ecma_string_t *name_p);
|
||||
|
||||
void ecma_free_property (ecma_object_t *object_p, jmem_cpointer_t name_cp, ecma_property_t *property_p);
|
||||
|
||||
void ecma_delete_property (ecma_object_t *object_p, ecma_property_value_t *prop_value_p);
|
||||
|
||||
void ecma_named_data_property_assign_value (ecma_object_t *obj_p, ecma_property_value_t *prop_value_p,
|
||||
ecma_value_t value);
|
||||
|
||||
ecma_getter_setter_pointers_t *
|
||||
ecma_get_named_accessor_property (const ecma_property_value_t *prop_value_p);
|
||||
void ecma_set_named_accessor_property_getter (ecma_object_t *object_p, ecma_property_value_t *prop_value_p,
|
||||
ecma_object_t *getter_p);
|
||||
void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, ecma_property_value_t *prop_value_p,
|
||||
ecma_object_t *setter_p);
|
||||
bool ecma_is_property_writable (ecma_property_t property);
|
||||
void ecma_set_property_writable_attr (ecma_property_t *property_p, bool is_writable);
|
||||
bool ecma_is_property_enumerable (ecma_property_t property);
|
||||
void ecma_set_property_enumerable_attr (ecma_property_t *property_p, bool is_enumerable);
|
||||
bool ecma_is_property_configurable (ecma_property_t property);
|
||||
void ecma_set_property_configurable_attr (ecma_property_t *property_p, bool is_configurable);
|
||||
|
||||
#if ENABLED (JERRY_LCACHE)
|
||||
bool ecma_is_property_lcached (ecma_property_t *property_p);
|
||||
void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached);
|
||||
#endif /* ENABLED (JERRY_LCACHE) */
|
||||
|
||||
ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
|
||||
void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p);
|
||||
|
||||
void ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p);
|
||||
void ecma_deref_error_reference (ecma_extended_primitive_t *error_ref_p);
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
void ecma_deref_bigint (ecma_extended_primitive_t *bigint_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
ecma_value_t ecma_create_error_reference (ecma_value_t value, bool is_exception);
|
||||
ecma_value_t ecma_create_error_reference_from_context (void);
|
||||
ecma_value_t ecma_create_error_object_reference (ecma_object_t *object_p);
|
||||
void ecma_raise_error_from_error_reference (ecma_value_t value);
|
||||
|
||||
void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
|
||||
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
|
||||
ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p);
|
||||
uint32_t ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p);
|
||||
ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_value_t ecma_get_resource_name (const ecma_compiled_code_t *bytecode_p);
|
||||
#if (JERRY_STACK_LIMIT != 0)
|
||||
uintptr_t ecma_get_current_stack_usage (void);
|
||||
#endif /* (JERRY_STACK_LIMIT != 0) */
|
||||
|
||||
/* ecma-helpers-external-pointers.c */
|
||||
bool ecma_create_native_pointer_property (ecma_object_t *obj_p, void *native_p, void *info_p);
|
||||
ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p, void *info_p);
|
||||
bool ecma_delete_native_pointer_property (ecma_object_t *obj_p, void *info_p);
|
||||
|
||||
/* ecma-helpers-conversion.c */
|
||||
ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size,
|
||||
uint32_t option);
|
||||
lit_utf8_size_t ecma_uint32_to_utf8_string (uint32_t value, lit_utf8_byte_t *out_buffer_p, lit_utf8_size_t buffer_size);
|
||||
uint32_t ecma_number_to_uint32 (ecma_number_t num);
|
||||
int32_t ecma_number_to_int32 (ecma_number_t num);
|
||||
lit_utf8_size_t ecma_number_to_utf8_string (ecma_number_t num, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size);
|
||||
|
||||
/* ecma-helpers-errol.c */
|
||||
lit_utf8_size_t ecma_errol0_dtoa (double val, lit_utf8_byte_t *buffer_p, int32_t *exp_p);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_HELPERS_H */
|
|
@ -0,0 +1,109 @@
|
|||
/* 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 "ecma-builtins.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-init-finalize.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "jmem.h"
|
||||
#include "jcontext.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmainitfinalize Initialization and finalization of ECMA components
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maximum number of GC loops on cleanup.
|
||||
*/
|
||||
#define JERRY_GC_LOOP_LIMIT 100
|
||||
|
||||
/**
|
||||
* Initialize ECMA components
|
||||
*/
|
||||
void
|
||||
ecma_init (void)
|
||||
{
|
||||
#if (JERRY_GC_MARK_LIMIT != 0)
|
||||
JERRY_CONTEXT (ecma_gc_mark_recursion_limit) = JERRY_GC_MARK_LIMIT;
|
||||
#endif /* (JERRY_GC_MARK_LIMIT != 0) */
|
||||
|
||||
ecma_init_global_environment ();
|
||||
|
||||
#if ENABLED (JERRY_PROPRETY_HASHMAP)
|
||||
JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) = ECMA_PROP_HASHMAP_ALLOC_ON;
|
||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_HIGH_PRESSURE_GC;
|
||||
#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
|
||||
|
||||
#if (JERRY_STACK_LIMIT != 0)
|
||||
volatile int sp;
|
||||
JERRY_CONTEXT (stack_base) = (uintptr_t) &sp;
|
||||
#endif /* (JERRY_STACK_LIMIT != 0) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_PROMISE)
|
||||
ecma_job_queue_init ();
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_CONTEXT (current_new_target_p) = NULL;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} /* ecma_init */
|
||||
|
||||
/**
|
||||
* Finalize ECMA components
|
||||
*/
|
||||
void
|
||||
ecma_finalize (void)
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) == NULL);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_finalize_global_environment ();
|
||||
uint8_t runs = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ecma_gc_run ();
|
||||
if (++runs >= JERRY_GC_LOOP_LIMIT)
|
||||
{
|
||||
jerry_fatal (ERR_UNTERMINATED_GC_LOOPS);
|
||||
}
|
||||
}
|
||||
while (JERRY_CONTEXT (ecma_gc_new_objects) != 0);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
jmem_cpointer_t *global_symbols_cp = JERRY_CONTEXT (global_symbols_cp);
|
||||
|
||||
for (uint32_t i = 0; i < ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT; i++)
|
||||
{
|
||||
if (global_symbols_cp[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, global_symbols_cp[i]));
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_finalize_lit_storage ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,34 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_INIT_FINALIZE_H
|
||||
#define ECMA_INIT_FINALIZE_H
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmainitfinalize Initialization and finalization of ECMA components
|
||||
* @{
|
||||
*/
|
||||
|
||||
void ecma_init (void);
|
||||
void ecma_finalize (void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_INIT_FINALIZE_H */
|
|
@ -0,0 +1,221 @@
|
|||
/* 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 "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "jcontext.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalcache Property lookup cache
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_LCACHE)
|
||||
|
||||
/**
|
||||
* Bitshift index for calculating hash.
|
||||
*/
|
||||
#if ENABLED (JERRY_CPOINTER_32_BIT)
|
||||
#define ECMA_LCACHE_HASH_BITSHIFT_INDEX (2 * JMEM_ALIGNMENT_LOG)
|
||||
#else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
#define ECMA_LCACHE_HASH_BITSHIFT_INDEX 0
|
||||
#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
|
||||
/**
|
||||
* Mask for hash bits
|
||||
*/
|
||||
#define ECMA_LCACHE_HASH_MASK ((ECMA_LCACHE_HASH_ROWS_COUNT - 1) << ECMA_LCACHE_HASH_BITSHIFT_INDEX)
|
||||
|
||||
/**
|
||||
* Bitshift index for creating property identifier
|
||||
*/
|
||||
#define ECMA_LCACHE_HASH_ENTRY_ID_SHIFT (8 * sizeof (jmem_cpointer_t))
|
||||
|
||||
/**
|
||||
* Create property identifier
|
||||
*/
|
||||
#define ECMA_LCACHE_CREATE_ID(object_cp, name_cp) \
|
||||
(((ecma_lcache_hash_entry_id_t) (object_cp) << ECMA_LCACHE_HASH_ENTRY_ID_SHIFT) | (name_cp))
|
||||
|
||||
/**
|
||||
* Invalidate specified LCache entry
|
||||
*/
|
||||
static inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to invalidate */
|
||||
{
|
||||
JERRY_ASSERT (entry_p != NULL);
|
||||
JERRY_ASSERT (entry_p->id != 0);
|
||||
JERRY_ASSERT (entry_p->prop_p != NULL);
|
||||
|
||||
entry_p->id = 0;
|
||||
ecma_set_property_lcached (entry_p->prop_p, false);
|
||||
} /* ecma_lcache_invalidate_entry */
|
||||
|
||||
/**
|
||||
* Compute the row index of object / property name pair
|
||||
*
|
||||
* @return row index
|
||||
*/
|
||||
static inline size_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to object */
|
||||
jmem_cpointer_t name_cp) /**< compressed pointer to property name */
|
||||
{
|
||||
/* Randomize the property name with the object pointer using a xor operation,
|
||||
* so properties of different objects with the same name can be cached effectively. */
|
||||
return (size_t) (((name_cp ^ object_cp) & ECMA_LCACHE_HASH_MASK) >> ECMA_LCACHE_HASH_BITSHIFT_INDEX);
|
||||
} /* ecma_lcache_row_index */
|
||||
|
||||
/**
|
||||
* Insert an entry into LCache
|
||||
*/
|
||||
void
|
||||
ecma_lcache_insert (const ecma_object_t *object_p, /**< object */
|
||||
const jmem_cpointer_t name_cp, /**< property name */
|
||||
ecma_property_t *prop_p) /**< property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_p != NULL && !ecma_is_property_lcached (prop_p));
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*prop_p));
|
||||
|
||||
jmem_cpointer_t object_cp;
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
size_t row_index = ecma_lcache_row_index (object_cp, name_cp);
|
||||
ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache) [row_index];
|
||||
ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH;
|
||||
|
||||
do
|
||||
{
|
||||
if (entry_p->id == 0)
|
||||
{
|
||||
goto insert;
|
||||
}
|
||||
|
||||
entry_p++;
|
||||
}
|
||||
while (entry_p < entry_end_p);
|
||||
|
||||
/* Invalidate the last entry. */
|
||||
ecma_lcache_invalidate_entry (--entry_p);
|
||||
|
||||
/* Shift other entries towards the end. */
|
||||
for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH - 1; i++)
|
||||
{
|
||||
entry_p->id = entry_p[-1].id;
|
||||
entry_p->prop_p = entry_p[-1].prop_p;
|
||||
entry_p--;
|
||||
}
|
||||
|
||||
insert:
|
||||
entry_p->prop_p = prop_p;
|
||||
entry_p->id = ECMA_LCACHE_CREATE_ID (object_cp, name_cp);
|
||||
|
||||
ecma_set_property_lcached (entry_p->prop_p, true);
|
||||
} /* ecma_lcache_insert */
|
||||
|
||||
/**
|
||||
* Lookup property in the LCache
|
||||
*
|
||||
* @return a pointer to an ecma_property_t if the lookup is successful
|
||||
* NULL otherwise
|
||||
*/
|
||||
extern inline ecma_property_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_lcache_lookup (const ecma_object_t *object_p, /**< object */
|
||||
const ecma_string_t *prop_name_p) /**< property's name */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_name_p != NULL);
|
||||
|
||||
jmem_cpointer_t object_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
ecma_property_t prop_name_type = ECMA_DIRECT_STRING_PTR;
|
||||
jmem_cpointer_t prop_name_cp;
|
||||
|
||||
if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (prop_name_p)))
|
||||
{
|
||||
prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (prop_name_p);
|
||||
prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p);
|
||||
}
|
||||
|
||||
size_t row_index = ecma_lcache_row_index (object_cp, prop_name_cp);
|
||||
|
||||
ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache) [row_index];
|
||||
ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH;
|
||||
ecma_lcache_hash_entry_id_t id = ECMA_LCACHE_CREATE_ID (object_cp, prop_name_cp);
|
||||
|
||||
do
|
||||
{
|
||||
if (entry_p->id == id && JERRY_LIKELY (ECMA_PROPERTY_GET_NAME_TYPE (*entry_p->prop_p) == prop_name_type))
|
||||
{
|
||||
JERRY_ASSERT (entry_p->prop_p != NULL && ecma_is_property_lcached (entry_p->prop_p));
|
||||
return entry_p->prop_p;
|
||||
}
|
||||
entry_p++;
|
||||
}
|
||||
while (entry_p < entry_end_p);
|
||||
|
||||
return NULL;
|
||||
} /* ecma_lcache_lookup */
|
||||
|
||||
/**
|
||||
* Invalidate LCache entries associated with given object and property name / property
|
||||
*/
|
||||
void
|
||||
ecma_lcache_invalidate (const ecma_object_t *object_p, /**< object */
|
||||
const jmem_cpointer_t name_cp, /**< property name */
|
||||
ecma_property_t *prop_p) /**< property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*prop_p));
|
||||
|
||||
jmem_cpointer_t object_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
size_t row_index = ecma_lcache_row_index (object_cp, name_cp);
|
||||
ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache) [row_index];
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* The property must be present. */
|
||||
JERRY_ASSERT (entry_p - JERRY_CONTEXT (lcache) [row_index] < ECMA_LCACHE_HASH_ROW_LENGTH);
|
||||
|
||||
if (entry_p->id != 0 && entry_p->prop_p == prop_p)
|
||||
{
|
||||
JERRY_ASSERT (entry_p->id == ECMA_LCACHE_CREATE_ID (object_cp, name_cp));
|
||||
|
||||
ecma_lcache_invalidate_entry (entry_p);
|
||||
return;
|
||||
}
|
||||
entry_p++;
|
||||
}
|
||||
} /* ecma_lcache_invalidate */
|
||||
|
||||
#endif /* ENABLED (JERRY_LCACHE) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,38 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_LCACHE_H
|
||||
#define ECMA_LCACHE_H
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalcache Property lookup cache
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_LCACHE)
|
||||
void ecma_lcache_insert (const ecma_object_t *object_p, const jmem_cpointer_t name_cp, ecma_property_t *prop_p);
|
||||
ecma_property_t *ecma_lcache_lookup (const ecma_object_t *object_p, const ecma_string_t *prop_name_p);
|
||||
void ecma_lcache_invalidate (const ecma_object_t *object_p, const jmem_cpointer_t name_cp, ecma_property_t *prop_p);
|
||||
|
||||
#endif /* ENABLED (JERRY_LCACHE) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_LCACHE_H */
|
|
@ -0,0 +1,752 @@
|
|||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-big-uint.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jcontext.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalitstorage Literal storage
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/**
|
||||
* Free symbol list
|
||||
*/
|
||||
static void
|
||||
ecma_free_symbol_list (jmem_cpointer_t symbol_list_cp) /**< symbol list */
|
||||
{
|
||||
while (symbol_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, symbol_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (symbol_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
symbol_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p));
|
||||
ecma_deref_ecma_string (string_p);
|
||||
}
|
||||
}
|
||||
|
||||
jmem_cpointer_t next_item_cp = symbol_list_p->next_cp;
|
||||
jmem_pools_free (symbol_list_p, sizeof (ecma_lit_storage_item_t));
|
||||
symbol_list_cp = next_item_cp;
|
||||
}
|
||||
} /* ecma_free_symbol_list */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Free string list
|
||||
*/
|
||||
static void
|
||||
ecma_free_string_list (jmem_cpointer_t string_list_cp) /**< string list */
|
||||
{
|
||||
while (string_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p));
|
||||
ecma_destroy_ecma_string (string_p);
|
||||
}
|
||||
}
|
||||
|
||||
jmem_cpointer_t next_item_cp = string_list_p->next_cp;
|
||||
jmem_pools_free (string_list_p, sizeof (ecma_lit_storage_item_t));
|
||||
string_list_cp = next_item_cp;
|
||||
}
|
||||
} /* ecma_free_string_list */
|
||||
|
||||
/**
|
||||
* Free number list
|
||||
*/
|
||||
static void
|
||||
ecma_free_number_list (jmem_cpointer_t number_list_cp) /**< number list */
|
||||
{
|
||||
while (number_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t,
|
||||
number_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_dealloc_number (JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, number_list_p->values[i]));
|
||||
}
|
||||
}
|
||||
|
||||
jmem_cpointer_t next_item_cp = number_list_p->next_cp;
|
||||
jmem_pools_free (number_list_p, sizeof (ecma_lit_storage_item_t));
|
||||
number_list_cp = next_item_cp;
|
||||
}
|
||||
} /* ecma_free_number_list */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Free bigint list
|
||||
*/
|
||||
static void
|
||||
ecma_free_bigint_list (jmem_cpointer_t bigint_list_cp) /**< bigint list */
|
||||
{
|
||||
while (bigint_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *bigint_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t,
|
||||
bigint_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (bigint_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_extended_primitive_t *bigint_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_extended_primitive_t,
|
||||
bigint_list_p->values[i]);
|
||||
JERRY_ASSERT (ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE (bigint_p));
|
||||
ecma_deref_bigint (bigint_p);
|
||||
}
|
||||
}
|
||||
|
||||
jmem_cpointer_t next_item_cp = bigint_list_p->next_cp;
|
||||
jmem_pools_free (bigint_list_p, sizeof (ecma_lit_storage_item_t));
|
||||
bigint_list_cp = next_item_cp;
|
||||
}
|
||||
} /* ecma_free_bigint_list */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
/**
|
||||
* Finalize literal storage
|
||||
*/
|
||||
void
|
||||
ecma_finalize_lit_storage (void)
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_free_symbol_list (JERRY_CONTEXT (symbol_list_first_cp));
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_free_string_list (JERRY_CONTEXT (string_list_first_cp));
|
||||
ecma_free_number_list (JERRY_CONTEXT (number_list_first_cp));
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
ecma_free_bigint_list (JERRY_CONTEXT (bigint_list_first_cp));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
} /* ecma_finalize_lit_storage */
|
||||
|
||||
/**
|
||||
* Find or create a literal string.
|
||||
*
|
||||
* @return ecma_string_t compressed pointer
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string to be searched */
|
||||
lit_utf8_size_t size) /**< size of the string */
|
||||
{
|
||||
ecma_string_t *string_p = ecma_new_ecma_string_from_utf8 (chars_p, size);
|
||||
|
||||
if (ECMA_IS_DIRECT_STRING (string_p))
|
||||
{
|
||||
return ecma_make_string_value (string_p);
|
||||
}
|
||||
|
||||
jmem_cpointer_t string_list_cp = JERRY_CONTEXT (string_list_first_cp);
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (string_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = string_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
if (ecma_compare_ecma_strings (string_p, value_p))
|
||||
{
|
||||
/* Return with string if found in the list. */
|
||||
ecma_deref_ecma_string (string_p);
|
||||
return ecma_make_string_value (value_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_list_cp = string_list_p->next_cp;
|
||||
}
|
||||
|
||||
ECMA_SET_STRING_AS_STATIC (string_p);
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, string_p);
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return ecma_make_string_value (string_p);
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p;
|
||||
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
new_item_p->next_cp = JERRY_CONTEXT (string_list_first_cp);
|
||||
JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (string_list_first_cp), new_item_p);
|
||||
|
||||
return ecma_make_string_value (string_p);
|
||||
} /* ecma_find_or_create_literal_string */
|
||||
|
||||
/**
|
||||
* Find or create a literal number.
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be searched */
|
||||
{
|
||||
ecma_value_t num = ecma_make_number_value (number_arg);
|
||||
|
||||
if (ecma_is_value_integer_number (num))
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_float_number (num));
|
||||
|
||||
jmem_cpointer_t number_list_cp = JERRY_CONTEXT (number_list_first_cp);
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (number_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t,
|
||||
number_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = number_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_number_t *number_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t,
|
||||
number_list_p->values[i]);
|
||||
|
||||
if (*number_p == number_arg)
|
||||
{
|
||||
ecma_free_value (num);
|
||||
return ecma_make_float_value (number_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
number_list_cp = number_list_p->next_cp;
|
||||
}
|
||||
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, ecma_get_pointer_from_float_value (num));
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return num;
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p;
|
||||
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
new_item_p->next_cp = JERRY_CONTEXT (number_list_first_cp);
|
||||
JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (number_list_first_cp), new_item_p);
|
||||
|
||||
return num;
|
||||
} /* ecma_find_or_create_literal_number */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Find or create a literal BigInt.
|
||||
*
|
||||
* @return BigInt value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_find_or_create_literal_bigint (ecma_value_t bigint) /**< bigint to be searched */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_bigint (bigint));
|
||||
|
||||
if (bigint == ECMA_BIGINT_ZERO)
|
||||
{
|
||||
return bigint;
|
||||
}
|
||||
|
||||
jmem_cpointer_t bigint_list_cp = JERRY_CONTEXT (bigint_list_first_cp);
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (bigint_list_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_lit_storage_item_t *bigint_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t,
|
||||
bigint_list_cp);
|
||||
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (bigint_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = bigint_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_extended_primitive_t *other_bigint_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_extended_primitive_t,
|
||||
bigint_list_p->values[i]);
|
||||
ecma_value_t other_bigint = ecma_make_extended_primitive_value (other_bigint_p, ECMA_TYPE_BIGINT);
|
||||
|
||||
if (ecma_bigint_is_equal_to_bigint (bigint, other_bigint))
|
||||
{
|
||||
ecma_free_value (bigint);
|
||||
return other_bigint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bigint_list_cp = bigint_list_p->next_cp;
|
||||
}
|
||||
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, ecma_get_extended_primitive_from_value (bigint));
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return bigint;
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p;
|
||||
new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
new_item_p->next_cp = JERRY_CONTEXT (bigint_list_first_cp);
|
||||
JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (bigint_list_first_cp), new_item_p);
|
||||
|
||||
return bigint;
|
||||
} /* ecma_find_or_create_literal_bigint */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
/**
|
||||
* Log2 of snapshot literal alignment.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 1
|
||||
|
||||
/**
|
||||
* Snapshot literal alignment.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT (1u << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG)
|
||||
|
||||
/**
|
||||
* Literal offset shift.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_SHIFT (ECMA_VALUE_SHIFT + 2)
|
||||
|
||||
/**
|
||||
* Literal value is number.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_IS_NUMBER (1u << ECMA_VALUE_SHIFT)
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
/**
|
||||
* Literal value is BigInt.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_IS_BIGINT (2u << ECMA_VALUE_SHIFT)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_SAVE)
|
||||
|
||||
/**
|
||||
* Append the value at the end of the appropriate list if it is not present there.
|
||||
*/
|
||||
void ecma_save_literals_append_value (ecma_value_t value, /**< value to be appended */
|
||||
ecma_collection_t *lit_pool_p) /**< list of known values */
|
||||
{
|
||||
/* Unlike direct numbers, direct strings are converted to character literals. */
|
||||
if (!ecma_is_value_string (value)
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
&& (!ecma_is_value_bigint (value) || value == ECMA_BIGINT_ZERO)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
&& !ecma_is_value_float_number (value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_value_t *buffer_p = lit_pool_p->buffer_p;
|
||||
|
||||
for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
|
||||
{
|
||||
/* Strings / numbers are direct strings or stored in the literal storage.
|
||||
* Therefore direct comparison is enough to find the same strings / numbers. */
|
||||
if (buffer_p[i] == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_push_back (lit_pool_p, value);
|
||||
} /* ecma_save_literals_append_value */
|
||||
|
||||
/**
|
||||
* Add names from a byte-code data to a list.
|
||||
*/
|
||||
void
|
||||
ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< byte-code data */
|
||||
ecma_collection_t *lit_pool_p) /**< list of known values */
|
||||
{
|
||||
ecma_value_t *literal_p;
|
||||
uint32_t argument_end;
|
||||
uint32_t register_end;
|
||||
uint32_t const_literal_end;
|
||||
uint32_t literal_end;
|
||||
|
||||
JERRY_ASSERT (CBC_IS_FUNCTION (compiled_code_p->status_flags));
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p;
|
||||
uint8_t *byte_p = (uint8_t *) compiled_code_p;
|
||||
|
||||
literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint16_arguments_t));
|
||||
register_end = args_p->register_end;
|
||||
const_literal_end = args_p->const_literal_end - register_end;
|
||||
literal_end = args_p->literal_end - register_end;
|
||||
argument_end = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p;
|
||||
uint8_t *byte_p = (uint8_t *) compiled_code_p;
|
||||
|
||||
literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint8_arguments_t));
|
||||
register_end = args_p->register_end;
|
||||
const_literal_end = args_p->const_literal_end - register_end;
|
||||
literal_end = args_p->literal_end - register_end;
|
||||
argument_end = args_p->argument_end;
|
||||
}
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
for (uint32_t i = 0; i < argument_end; i++)
|
||||
{
|
||||
ecma_save_literals_append_value (literal_p[i], lit_pool_p);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < const_literal_end; i++)
|
||||
{
|
||||
ecma_save_literals_append_value (literal_p[i], lit_pool_p);
|
||||
}
|
||||
|
||||
for (uint32_t i = const_literal_end; i < literal_end; i++)
|
||||
{
|
||||
ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
literal_p[i]);
|
||||
|
||||
if (CBC_IS_FUNCTION (bytecode_p->status_flags)
|
||||
&& bytecode_p != compiled_code_p)
|
||||
{
|
||||
ecma_save_literals_add_compiled_code (bytecode_p, lit_pool_p);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *byte_p = ((uint8_t *) compiled_code_p) + (((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG);
|
||||
literal_p = ecma_snapshot_resolve_serializable_values ((ecma_compiled_code_t *) compiled_code_p, byte_p);
|
||||
|
||||
while (literal_p < (ecma_value_t *) byte_p)
|
||||
{
|
||||
ecma_save_literals_append_value (*literal_p, lit_pool_p);
|
||||
literal_p++;
|
||||
}
|
||||
} /* ecma_save_literals_add_compiled_code */
|
||||
|
||||
/**
|
||||
* Save literals to specified snapshot buffer.
|
||||
*
|
||||
* Note:
|
||||
* Frees 'lit_pool_p' regardless of success.
|
||||
*
|
||||
* @return true - if save was performed successfully (i.e. buffer size is sufficient),
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, /**< list of known values */
|
||||
uint32_t *buffer_p, /**< [out] output snapshot buffer */
|
||||
size_t buffer_size, /**< size of the buffer */
|
||||
size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */
|
||||
lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers
|
||||
* to the literal offsets
|
||||
* in snapshot */
|
||||
uint32_t *out_map_len_p) /**< [out] number of literals */
|
||||
{
|
||||
if (lit_pool_p->item_count == 0)
|
||||
{
|
||||
*out_map_p = NULL;
|
||||
*out_map_len_p = 0;
|
||||
}
|
||||
|
||||
uint32_t lit_table_size = 0;
|
||||
size_t max_lit_table_size = buffer_size - *in_out_buffer_offset_p;
|
||||
|
||||
if (max_lit_table_size > (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT))
|
||||
{
|
||||
max_lit_table_size = (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT);
|
||||
}
|
||||
|
||||
ecma_value_t *lit_buffer_p = lit_pool_p->buffer_p;
|
||||
|
||||
/* Compute the size of the literal pool. */
|
||||
for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
|
||||
{
|
||||
if (ecma_is_value_float_number (lit_buffer_p[i]))
|
||||
{
|
||||
lit_table_size += (uint32_t) sizeof (ecma_number_t);
|
||||
}
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
else if (ecma_is_value_bigint (lit_buffer_p[i]))
|
||||
{
|
||||
ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]);
|
||||
|
||||
lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint32_t) + ECMA_BIGINT_GET_SIZE (bigint_p),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
else
|
||||
{
|
||||
ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]);
|
||||
|
||||
lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
}
|
||||
|
||||
/* Check whether enough space is available and the maximum size is not reached. */
|
||||
if (lit_table_size > max_lit_table_size)
|
||||
{
|
||||
ecma_collection_destroy (lit_pool_p);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p;
|
||||
uint32_t total_count = lit_pool_p->item_count;
|
||||
|
||||
map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
|
||||
/* Set return values (no error is possible from here). */
|
||||
JERRY_ASSERT ((*in_out_buffer_offset_p % sizeof (uint32_t)) == 0);
|
||||
|
||||
uint8_t *destination_p = (uint8_t *) (buffer_p + (*in_out_buffer_offset_p / sizeof (uint32_t)));
|
||||
uint32_t literal_offset = 0;
|
||||
|
||||
*in_out_buffer_offset_p += lit_table_size;
|
||||
*out_map_p = map_p;
|
||||
*out_map_len_p = total_count;
|
||||
|
||||
lit_buffer_p = lit_pool_p->buffer_p;
|
||||
|
||||
/* Generate literal pool data. */
|
||||
for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
|
||||
{
|
||||
map_p->literal_id = lit_buffer_p[i];
|
||||
map_p->literal_offset = (literal_offset << JERRY_SNAPSHOT_LITERAL_SHIFT) | ECMA_TYPE_SNAPSHOT_OFFSET;
|
||||
|
||||
lit_utf8_size_t length;
|
||||
|
||||
if (ecma_is_value_float_number (lit_buffer_p[i]))
|
||||
{
|
||||
map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_NUMBER;
|
||||
|
||||
ecma_number_t num = ecma_get_float_from_value (lit_buffer_p[i]);
|
||||
memcpy (destination_p, &num, sizeof (ecma_number_t));
|
||||
|
||||
length = JERRY_ALIGNUP (sizeof (ecma_number_t), JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
}
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
else if (ecma_is_value_bigint (lit_buffer_p[i]))
|
||||
{
|
||||
map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_BIGINT;
|
||||
|
||||
ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]);
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p);
|
||||
|
||||
memcpy (destination_p, &bigint_p->u.bigint_sign_and_size, sizeof (uint32_t));
|
||||
memcpy (destination_p + sizeof (uint32_t), ECMA_BIGINT_GET_DIGITS (bigint_p, 0), size);
|
||||
|
||||
length = JERRY_ALIGNUP (sizeof (uint32_t) + size, JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
else
|
||||
{
|
||||
ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]);
|
||||
length = ecma_string_get_size (string_p);
|
||||
|
||||
*(uint16_t *) destination_p = (uint16_t) length;
|
||||
|
||||
ecma_string_to_utf8_bytes (string_p, destination_p + sizeof (uint16_t), length);
|
||||
|
||||
length = JERRY_ALIGNUP (sizeof (uint16_t) + length, JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
}
|
||||
|
||||
JERRY_ASSERT ((length % sizeof (uint16_t)) == 0);
|
||||
destination_p += length;
|
||||
literal_offset += length;
|
||||
|
||||
map_p++;
|
||||
}
|
||||
|
||||
ecma_collection_destroy (lit_pool_p);
|
||||
return true;
|
||||
} /* ecma_save_literals_for_snapshot */
|
||||
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE)
|
||||
|
||||
/**
|
||||
* Get the compressed pointer of a given literal.
|
||||
*
|
||||
* @return literal compressed pointer
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_snapshot_get_literal (const uint8_t *literal_base_p, /**< literal start */
|
||||
ecma_value_t literal_value) /**< string / number offset */
|
||||
{
|
||||
JERRY_ASSERT ((literal_value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET);
|
||||
|
||||
const uint8_t *literal_p = literal_base_p + (literal_value >> JERRY_SNAPSHOT_LITERAL_SHIFT);
|
||||
|
||||
if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_NUMBER)
|
||||
{
|
||||
ecma_number_t num;
|
||||
memcpy (&num, literal_p, sizeof (ecma_number_t));
|
||||
return ecma_find_or_create_literal_number (num);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_BIGINT)
|
||||
{
|
||||
uint32_t bigint_sign_and_size = *(uint32_t *) literal_p;
|
||||
uint32_t size = bigint_sign_and_size & ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1);
|
||||
|
||||
ecma_extended_primitive_t *bigint_p = ecma_bigint_create (size);
|
||||
|
||||
if (bigint_p == NULL)
|
||||
{
|
||||
jerry_fatal (ERR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
/* Only the sign bit can differ. */
|
||||
JERRY_ASSERT (bigint_p->u.bigint_sign_and_size == (bigint_sign_and_size & ~(uint32_t) ECMA_BIGINT_SIGN));
|
||||
|
||||
bigint_p->u.bigint_sign_and_size = bigint_sign_and_size;
|
||||
memcpy (ECMA_BIGINT_GET_DIGITS (bigint_p, 0), literal_p + sizeof (uint32_t), size);
|
||||
return ecma_find_or_create_literal_bigint (ecma_make_extended_primitive_value (bigint_p, ECMA_TYPE_BIGINT));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
uint16_t length = *(const uint16_t *) literal_p;
|
||||
|
||||
return ecma_find_or_create_literal_string (literal_p + sizeof (uint16_t), length);
|
||||
} /* ecma_snapshot_get_literal */
|
||||
|
||||
/**
|
||||
* Compute the start of the serializable ecma-values of the bytecode
|
||||
* Related values:
|
||||
* - function argument names, if CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is present
|
||||
* - function name, if CBC_CODE_FLAGS_CLASS_CONSTRUCTOR is not present and ES.next profile is enabled
|
||||
*
|
||||
* @return pointer to the beginning of the serializable ecma-values
|
||||
*/
|
||||
ecma_value_t *
|
||||
ecma_snapshot_resolve_serializable_values (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
|
||||
uint8_t *bytecode_end_p) /**< end of the bytecode */
|
||||
{
|
||||
ecma_value_t *base_p = (ecma_value_t *) bytecode_end_p;
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
|
||||
{
|
||||
uint32_t argument_end;
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
argument_end = ((cbc_uint16_arguments_t *) compiled_code_p)->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
argument_end = ((cbc_uint8_arguments_t *) compiled_code_p)->argument_end;
|
||||
}
|
||||
|
||||
base_p -= argument_end;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/* function name */
|
||||
if (CBC_FUNCTION_GET_TYPE (compiled_code_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR)
|
||||
{
|
||||
base_p--;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
return base_p;
|
||||
} /* ecma_snapshot_resolve_serializable_values */
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,70 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_LIT_STORAGE_H
|
||||
#define ECMA_LIT_STORAGE_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem.h"
|
||||
#include "lit-globals.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalitstorage Literal storage
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_SAVE)
|
||||
/**
|
||||
* Snapshot literal - offset map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_value_t literal_id; /**< literal id */
|
||||
ecma_value_t literal_offset; /**< literal offset */
|
||||
} lit_mem_to_snapshot_id_map_entry_t;
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
|
||||
|
||||
void ecma_finalize_lit_storage (void);
|
||||
|
||||
ecma_value_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, lit_utf8_size_t size);
|
||||
ecma_value_t ecma_find_or_create_literal_number (ecma_number_t number_arg);
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
ecma_value_t ecma_find_or_create_literal_bigint (ecma_value_t bigint);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_SAVE)
|
||||
void ecma_save_literals_append_value (ecma_value_t value, ecma_collection_t *lit_pool_p);
|
||||
void ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p,
|
||||
ecma_collection_t *lit_pool_p);
|
||||
bool ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, uint32_t *buffer_p, size_t buffer_size,
|
||||
size_t *in_out_buffer_offset_p, lit_mem_to_snapshot_id_map_entry_t **out_map_p,
|
||||
uint32_t *out_map_len_p);
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE)
|
||||
ecma_value_t
|
||||
ecma_snapshot_get_literal (const uint8_t *literal_base_p, ecma_value_t literal_value);
|
||||
ecma_value_t *
|
||||
ecma_snapshot_resolve_serializable_values (ecma_compiled_code_t *compiled_code_p, uint8_t *byte_code_end_p);
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_LIT_STORAGE_H */
|
|
@ -0,0 +1,136 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_MODULE_H
|
||||
#define ECMA_MODULE_H
|
||||
|
||||
#include "common.h"
|
||||
#include "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_MODULE_SYSTEM)
|
||||
|
||||
#define ECMA_MODULE_MAX_PATH 255u
|
||||
|
||||
/**
|
||||
* Imported or exported names, such as "a as b"
|
||||
* Note: See https://www.ecma-international.org/ecma-262/6.0/#table-39
|
||||
* and https://www.ecma-international.org/ecma-262/6.0/#table-41
|
||||
*/
|
||||
typedef struct ecma_module_names
|
||||
{
|
||||
struct ecma_module_names *next_p; /**< next linked list node */
|
||||
ecma_string_t *imex_name_p; /**< Import/export name of the item */
|
||||
ecma_string_t *local_name_p; /**< Local name of the item */
|
||||
} ecma_module_names_t;
|
||||
|
||||
/**
|
||||
* An enum identifing the current state of the module
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_MODULE_STATE_INIT = 0, /**< module is initialized */
|
||||
ECMA_MODULE_STATE_PARSING = 1, /**< module is currently being parsed */
|
||||
ECMA_MODULE_STATE_PARSED = 2, /**< module has been parsed */
|
||||
ECMA_MODULE_STATE_EVALUATING = 3, /**< module is currently being evaluated */
|
||||
ECMA_MODULE_STATE_EVALUATED = 4, /**< module has been evaluated */
|
||||
ECMA_MODULE_STATE_NATIVE = 5, /**< module is native */
|
||||
ECMA_MODULE_STATE_ROOT = 6, /**< module is a root module */
|
||||
} ecma_module_state_t;
|
||||
|
||||
/**
|
||||
* Module structure storing an instance of a module
|
||||
*/
|
||||
typedef struct ecma_module
|
||||
{
|
||||
/* TODO(dbatyai): These could be compressed pointers */
|
||||
struct ecma_module *next_p; /**< next module in the list */
|
||||
struct ecma_module_node *imports_p; /**< import requests of the module */
|
||||
struct ecma_module_node *local_exports_p; /**< local exports of the module */
|
||||
struct ecma_module_node *indirect_exports_p; /**< indirect exports of the module */
|
||||
struct ecma_module_node *star_exports_p; /**< star exports of the module*/
|
||||
ecma_string_t *path_p; /**< path of the module */
|
||||
ecma_compiled_code_t *compiled_code_p; /**< compiled code for the module */
|
||||
ecma_object_t *scope_p; /**< lexical lenvironment of the module */
|
||||
ecma_object_t *namespace_object_p; /**< namespace object of the module */
|
||||
ecma_module_state_t state; /**< evaluation state of the module */
|
||||
} ecma_module_t;
|
||||
|
||||
/**
|
||||
* Module node to store imports / exports.
|
||||
*/
|
||||
typedef struct ecma_module_node
|
||||
{
|
||||
struct ecma_module_node *next_p; /**< next linked list node */
|
||||
ecma_module_names_t *module_names_p; /**< names of the requested import/export node */
|
||||
ecma_module_t *module_request_p; /**< module structure of the requested module */
|
||||
} ecma_module_node_t;
|
||||
|
||||
/**
|
||||
* A record that can be used to store {module, identifier} pairs
|
||||
*/
|
||||
typedef struct ecma_module_record
|
||||
{
|
||||
ecma_module_t *module_p; /**< module */
|
||||
ecma_string_t *name_p; /**< identifier name */
|
||||
} ecma_module_record_t;
|
||||
|
||||
/**
|
||||
* A list of module records that can be used to identify circular imports during resolution
|
||||
*/
|
||||
typedef struct ecma_module_resolve_set
|
||||
{
|
||||
struct ecma_module_resolve_set *next_p; /**< next in linked list */
|
||||
ecma_module_record_t record; /**< module record */
|
||||
} ecma_module_resolve_set_t;
|
||||
|
||||
/**
|
||||
* A list that is used like a stack to drive the resolution process, instead of recursion.
|
||||
*/
|
||||
typedef struct ecma_module_resolve_stack
|
||||
{
|
||||
struct ecma_module_resolve_stack *next_p; /**< next in linked list */
|
||||
ecma_module_t *module_p; /**< module request */
|
||||
ecma_string_t *export_name_p; /**< export identifier name */
|
||||
bool resolving; /**< flag storing wether the current frame started resolving */
|
||||
} ecma_module_resolve_stack_t;
|
||||
|
||||
bool ecma_module_resolve_set_insert (ecma_module_resolve_set_t **set_p,
|
||||
ecma_module_t *const module_p,
|
||||
ecma_string_t *const export_name_p);
|
||||
void ecma_module_resolve_set_cleanup (ecma_module_resolve_set_t *set_p);
|
||||
|
||||
void ecma_module_resolve_stack_push (ecma_module_resolve_stack_t **stack_p,
|
||||
ecma_module_t *const module_p,
|
||||
ecma_string_t *const export_name_p);
|
||||
void ecma_module_resolve_stack_pop (ecma_module_resolve_stack_t **stack_p);
|
||||
|
||||
ecma_string_t *ecma_module_create_normalized_path (const lit_utf8_byte_t *char_p,
|
||||
lit_utf8_size_t size,
|
||||
ecma_string_t *const base_path_p);
|
||||
|
||||
ecma_module_t *ecma_module_find_module (ecma_string_t *const path_p);
|
||||
ecma_module_t *ecma_module_find_native_module (ecma_string_t *const path_p);
|
||||
|
||||
ecma_value_t ecma_module_parse_referenced_modules (void);
|
||||
ecma_value_t ecma_module_initialize (ecma_module_t *module_p);
|
||||
|
||||
void ecma_module_initialize_context (ecma_string_t *root_path_p);
|
||||
void ecma_module_cleanup_context (void);
|
||||
|
||||
void ecma_module_release_module_nodes (ecma_module_node_t *module_node_p);
|
||||
void ecma_module_cleanup (ecma_module_t *head_p);
|
||||
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
|
||||
|
||||
#endif /* !ECMA_MODULE_H */
|
|
@ -0,0 +1,536 @@
|
|||
/* 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 "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-property-hashmap.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
#include "jcontext.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmapropertyhashmap Property hashmap
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_PROPRETY_HASHMAP)
|
||||
|
||||
/**
|
||||
* Compute the total size of the property hashmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE(max_property_count) \
|
||||
(sizeof (ecma_property_hashmap_t) + (max_property_count * sizeof (jmem_cpointer_t)) + (max_property_count >> 3))
|
||||
|
||||
/**
|
||||
* Number of items in the stepping table.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS 8
|
||||
|
||||
/**
|
||||
* Stepping values for searching items in the hashmap.
|
||||
*/
|
||||
static const uint8_t ecma_property_hashmap_steps[ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS] JERRY_ATTR_CONST_DATA =
|
||||
{
|
||||
3, 5, 7, 11, 13, 17, 19, 23
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the value of a bit in a bitmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_GET_BIT(byte_p, index) \
|
||||
((byte_p)[(index) >> 3] & (1 << ((index) & 0x7)))
|
||||
|
||||
/**
|
||||
* Clear the value of a bit in a bitmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_CLEAR_BIT(byte_p, index) \
|
||||
((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] & ~(1 << ((index) & 0x7))))
|
||||
|
||||
/**
|
||||
* Set the value of a bit in a bitmap.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASHMAP_SET_BIT(byte_p, index) \
|
||||
((byte_p)[(index) >> 3] = (uint8_t) ((byte_p)[(index) >> 3] | (1 << ((index) & 0x7))))
|
||||
|
||||
/**
|
||||
* Create a new property hashmap for the object.
|
||||
* The object must not have a property hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
if (JERRY_CONTEXT (ecma_prop_hashmap_alloc_state) != ECMA_PROP_HASHMAP_ALLOC_ON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp;
|
||||
|
||||
if (prop_iter_cp == JMEM_CP_NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t named_property_count = 0;
|
||||
|
||||
while (prop_iter_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i]));
|
||||
named_property_count++;
|
||||
}
|
||||
}
|
||||
prop_iter_cp = prop_iter_p->next_property_cp;
|
||||
}
|
||||
|
||||
if (named_property_count < (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* The max_property_count must be power of 2. */
|
||||
uint32_t max_property_count = ECMA_PROPERTY_HASMAP_MINIMUM_SIZE;
|
||||
|
||||
/* At least 1/3 items must be NULL. */
|
||||
while (max_property_count < (named_property_count + (named_property_count >> 1)))
|
||||
{
|
||||
max_property_count <<= 1;
|
||||
}
|
||||
|
||||
size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count);
|
||||
|
||||
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size);
|
||||
|
||||
if (hashmap_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset (hashmap_p, 0, total_size);
|
||||
|
||||
hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP;
|
||||
hashmap_p->header.next_property_cp = object_p->u1.property_list_cp;
|
||||
hashmap_p->max_property_count = max_property_count;
|
||||
hashmap_p->null_count = max_property_count - named_property_count;
|
||||
hashmap_p->unused_count = max_property_count - named_property_count;
|
||||
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + max_property_count);
|
||||
uint32_t mask = max_property_count - 1;
|
||||
|
||||
prop_iter_cp = object_p->u1.property_list_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, hashmap_p);
|
||||
|
||||
while (prop_iter_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if (prop_iter_p->types[i] == ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i]));
|
||||
|
||||
ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
|
||||
uint32_t entry_index = ecma_string_get_property_name_hash (prop_iter_p->types[i],
|
||||
property_pair_p->names_cp[i]);
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
|
||||
entry_index &= mask;
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* Because max_property_count (power of 2) and step (a prime
|
||||
* number) are relative primes, all entries of the hasmap are
|
||||
* visited exactly once before the start entry index is reached
|
||||
* again. Furthermore because at least one NULL is present in
|
||||
* the hashmap, the while loop must be terminated before the
|
||||
* the starting index is reached again. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
while (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p);
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index);
|
||||
}
|
||||
}
|
||||
|
||||
prop_iter_cp = prop_iter_p->next_property_cp;
|
||||
}
|
||||
} /* ecma_property_hashmap_create */
|
||||
|
||||
/**
|
||||
* Free the hashmap of the object.
|
||||
* The object must have a property hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_free (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
/* Property hash must be exists and must be the first property. */
|
||||
JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL);
|
||||
|
||||
ecma_property_header_t *property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
|
||||
object_p->u1.property_list_cp);
|
||||
|
||||
JERRY_ASSERT (property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) property_p;
|
||||
|
||||
object_p->u1.property_list_cp = property_p->next_property_cp;
|
||||
|
||||
jmem_heap_free_block (hashmap_p,
|
||||
ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (hashmap_p->max_property_count));
|
||||
} /* ecma_property_hashmap_free */
|
||||
|
||||
/**
|
||||
* Insert named property into the hashmap.
|
||||
*/
|
||||
void
|
||||
ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *name_p, /**< name of the property */
|
||||
ecma_property_pair_t *property_pair_p, /**< property pair */
|
||||
int property_index) /**< property index in the pair (0 or 1) */
|
||||
{
|
||||
JERRY_ASSERT (property_pair_p != NULL);
|
||||
|
||||
ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t,
|
||||
object_p->u1.property_list_cp);
|
||||
|
||||
JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
/* The NULLs are reduced below 1/8 of the hashmap. */
|
||||
if (hashmap_p->null_count < (hashmap_p->max_property_count >> 3))
|
||||
{
|
||||
ecma_property_hashmap_free (object_p);
|
||||
ecma_property_hashmap_create (object_p);
|
||||
return;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_index < ECMA_PROPERTY_PAIR_ITEM_COUNT);
|
||||
|
||||
uint32_t entry_index = ecma_string_hash (name_p);
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
uint32_t mask = hashmap_p->max_property_count - 1;
|
||||
entry_index &= mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* See the comment for this variable in ecma_property_hashmap_create. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
|
||||
while (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (pair_list_p[entry_index], property_pair_p);
|
||||
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count);
|
||||
bits_p += (entry_index >> 3);
|
||||
mask = (uint32_t) (1 << (entry_index & 0x7));
|
||||
|
||||
if (!(*bits_p & mask))
|
||||
{
|
||||
/* Deleted entries also has ECMA_NULL_POINTER
|
||||
* value, but they are not NULL values. */
|
||||
hashmap_p->null_count--;
|
||||
JERRY_ASSERT (hashmap_p->null_count > 0);
|
||||
}
|
||||
|
||||
hashmap_p->unused_count--;
|
||||
JERRY_ASSERT (hashmap_p->unused_count > 0);
|
||||
|
||||
if (property_index == 0)
|
||||
{
|
||||
*bits_p = (uint8_t) ((*bits_p) & ~mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
*bits_p = (uint8_t) ((*bits_p) | mask);
|
||||
}
|
||||
} /* ecma_property_hashmap_insert */
|
||||
|
||||
/**
|
||||
* Delete named property from the hashmap.
|
||||
*
|
||||
* @return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP if hashmap should be recreated
|
||||
* ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP otherwise
|
||||
*/
|
||||
ecma_property_hashmap_delete_status
|
||||
ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */
|
||||
jmem_cpointer_t name_cp, /**< property name */
|
||||
ecma_property_t *property_p) /**< property */
|
||||
{
|
||||
ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t,
|
||||
object_p->u1.property_list_cp);
|
||||
|
||||
JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
hashmap_p->unused_count++;
|
||||
|
||||
/* The NULLs are above 3/4 of the hashmap. */
|
||||
if (hashmap_p->unused_count > ((hashmap_p->max_property_count * 3) >> 2))
|
||||
{
|
||||
return ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP;
|
||||
}
|
||||
|
||||
uint32_t entry_index = ecma_string_get_property_name_hash (*property_p, name_cp);
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
uint32_t mask = hashmap_p->max_property_count - 1;
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count);
|
||||
|
||||
entry_index &= mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* See the comment for this variable in ecma_property_hashmap_create. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
size_t offset = 0;
|
||||
|
||||
if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t,
|
||||
pair_list_p[entry_index]);
|
||||
|
||||
if ((property_pair_p->header.types + offset) == property_p)
|
||||
{
|
||||
JERRY_ASSERT (property_pair_p->names_cp[offset] == name_cp);
|
||||
|
||||
pair_list_p[entry_index] = ECMA_NULL_POINTER;
|
||||
ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index);
|
||||
return ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Must be a deleted entry. */
|
||||
JERRY_ASSERT (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index));
|
||||
}
|
||||
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
} /* ecma_property_hashmap_delete */
|
||||
|
||||
/**
|
||||
* Find a named property.
|
||||
*
|
||||
* @return pointer to the property if found or NULL otherwise
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */
|
||||
ecma_string_t *name_p, /**< property name */
|
||||
jmem_cpointer_t *property_real_name_cp) /**< [out] property real name */
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* A sanity check in debug mode: a named property must be present
|
||||
* in both the property hashmap and in the property chain, or missing
|
||||
* from both data collection. The following code checks the property
|
||||
* chain, and sets the property_found variable. */
|
||||
bool property_found = false;
|
||||
|
||||
jmem_cpointer_t prop_iter_cp = hashmap_p->header.next_property_cp;
|
||||
|
||||
while (prop_iter_cp != JMEM_CP_NULL && !property_found)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i]))
|
||||
{
|
||||
if (ecma_string_compare_to_property_name (prop_iter_p->types[i],
|
||||
prop_pair_p->names_cp[i],
|
||||
name_p))
|
||||
{
|
||||
/* Property is found */
|
||||
property_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prop_iter_cp = prop_iter_p->next_property_cp;
|
||||
}
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
uint32_t entry_index = ecma_string_hash (name_p);
|
||||
uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)];
|
||||
uint32_t mask = hashmap_p->max_property_count - 1;
|
||||
jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1);
|
||||
uint8_t *bits_p = (uint8_t *) (pair_list_p + hashmap_p->max_property_count);
|
||||
entry_index &= mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/* See the comment for this variable in ecma_property_hashmap_create. */
|
||||
uint32_t start_entry_index = entry_index;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
if (ECMA_IS_DIRECT_STRING (name_p))
|
||||
{
|
||||
ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p);
|
||||
jmem_cpointer_t property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p);
|
||||
|
||||
JERRY_ASSERT (prop_name_type > 0);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
size_t offset = 0;
|
||||
if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t,
|
||||
pair_list_p[entry_index]);
|
||||
|
||||
ecma_property_t *property_p = property_pair_p->header.types + offset;
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p));
|
||||
|
||||
if (property_pair_p->names_cp[offset] == property_name_cp
|
||||
&& ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == prop_name_type)
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (property_found);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
*property_real_name_cp = property_name_cp;
|
||||
return property_p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (!property_found);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* Otherwise it is a deleted entry. */
|
||||
}
|
||||
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (pair_list_p[entry_index] != ECMA_NULL_POINTER)
|
||||
{
|
||||
size_t offset = 0;
|
||||
if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t,
|
||||
pair_list_p[entry_index]);
|
||||
|
||||
ecma_property_t *property_p = property_pair_p->header.types + offset;
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p));
|
||||
|
||||
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR)
|
||||
{
|
||||
ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_pair_p->names_cp[offset]);
|
||||
|
||||
if (ecma_compare_ecma_non_direct_strings (prop_name_p, name_p))
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (property_found);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
*property_real_name_cp = property_pair_p->names_cp[offset];
|
||||
return property_p;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index))
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (!property_found);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* Otherwise it is a deleted entry. */
|
||||
}
|
||||
|
||||
entry_index = (entry_index + step) & mask;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (entry_index != start_entry_index);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
} /* ecma_property_hashmap_find */
|
||||
#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -0,0 +1,84 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_PROPERTY_HASHMAP_H
|
||||
#define ECMA_PROPERTY_HASHMAP_H
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmapropertyhashmap Property hashmap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Recommended minimum number of items in a property cache.
|
||||
*/
|
||||
#define ECMA_PROPERTY_HASMAP_MINIMUM_SIZE 32
|
||||
|
||||
/**
|
||||
* Property hash.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_property_header_t header; /**< header of the property */
|
||||
uint32_t max_property_count; /**< maximum property count (power of 2) */
|
||||
uint32_t null_count; /**< number of NULLs in the map */
|
||||
uint32_t unused_count; /**< number of unused entires in the map */
|
||||
|
||||
/*
|
||||
* The hash is followed by max_property_count ecma_cpointer_t
|
||||
* compressed pointers and (max_property_count + 7) / 8 bytes
|
||||
* which stores a flag for each compressed pointer.
|
||||
*
|
||||
* If the compressed pointer is equal to ECMA_NULL_POINTER
|
||||
* - flag is cleared if the entry is NULL
|
||||
* - flag is set if the entry is deleted
|
||||
*
|
||||
* If the compressed pointer is not equal to ECMA_NULL_POINTER
|
||||
* - flag is cleared if the first entry of a property pair is referenced
|
||||
* - flag is set if the second entry of a property pair is referenced
|
||||
*/
|
||||
} ecma_property_hashmap_t;
|
||||
|
||||
#if ENABLED (JERRY_PROPRETY_HASHMAP)
|
||||
|
||||
/**
|
||||
* Simple ecma values
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP, /**< object has no hashmap */
|
||||
ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP, /**< object has hashmap */
|
||||
ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP, /**< hashmap should be recreated */
|
||||
} ecma_property_hashmap_delete_status;
|
||||
|
||||
void ecma_property_hashmap_create (ecma_object_t *object_p);
|
||||
void ecma_property_hashmap_free (ecma_object_t *object_p);
|
||||
void ecma_property_hashmap_insert (ecma_object_t *object_p, ecma_string_t *name_p,
|
||||
ecma_property_pair_t *property_pair_p, int property_index);
|
||||
ecma_property_hashmap_delete_status ecma_property_hashmap_delete (ecma_object_t *object_p, jmem_cpointer_t name_cp,
|
||||
ecma_property_t *property_p);
|
||||
|
||||
ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, ecma_string_t *name_p,
|
||||
jmem_cpointer_t *property_real_name_cp);
|
||||
#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_PROPERTY_HASHMAP_H */
|
|
@ -0,0 +1,191 @@
|
|||
/* 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 "ecma-builtin-helpers.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-iterator-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "ecma-arraybuffer-object.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-iterator-prototype.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID array_iterator_prototype
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup %arrayiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The %ArrayIteratorPrototype% object's 'next' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 22.1.5.2.1
|
||||
*
|
||||
* Note:
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*
|
||||
* @return iterator result object, if success
|
||||
* error - otherwise
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */
|
||||
{
|
||||
/* 1 - 2. */
|
||||
if (!ecma_is_value_object (this_val))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an object."));
|
||||
}
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (this_val);
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
/* 3. */
|
||||
if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_PSEUDO_ARRAY
|
||||
|| ext_obj_p->u.pseudo_array.type != ECMA_PSEUDO_ARRAY_ITERATOR)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an iterator."));
|
||||
}
|
||||
|
||||
ecma_value_t iterated_value = ext_obj_p->u.pseudo_array.u2.iterated_value;
|
||||
|
||||
/* 4 - 5 */
|
||||
if (ecma_is_value_empty (iterated_value))
|
||||
{
|
||||
return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
|
||||
}
|
||||
|
||||
ecma_object_t *array_object_p = ecma_get_object_from_value (iterated_value);
|
||||
|
||||
/* 8. */
|
||||
ecma_length_t length;
|
||||
if (ecma_object_is_typedarray (array_object_p))
|
||||
{
|
||||
/* a. */
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_object_p);
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
|
||||
}
|
||||
|
||||
/* b. */
|
||||
length = ecma_typedarray_get_length (array_object_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_value_t len_value = ecma_op_object_get_length (array_object_p, &length);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (len_value))
|
||||
{
|
||||
return len_value;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_length_t index = ext_obj_p->u.pseudo_array.u1.iterator_index;
|
||||
|
||||
if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT))
|
||||
{
|
||||
/* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]]
|
||||
property is stored as an internal property */
|
||||
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX);
|
||||
ecma_value_t index_value = ecma_op_object_get (obj_p, prop_name_p);
|
||||
|
||||
if (!ecma_is_value_undefined (index_value))
|
||||
{
|
||||
index = (ecma_length_t) (ecma_get_number_from_value (index_value) + 1);
|
||||
}
|
||||
|
||||
ecma_value_t put_result = ecma_op_object_put (obj_p,
|
||||
prop_name_p,
|
||||
ecma_make_length_value (index),
|
||||
true);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (put_result));
|
||||
|
||||
ecma_free_value (index_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 11. */
|
||||
ext_obj_p->u.pseudo_array.u1.iterator_index++;
|
||||
}
|
||||
|
||||
if (index >= length)
|
||||
{
|
||||
ext_obj_p->u.pseudo_array.u2.iterated_value = ECMA_VALUE_EMPTY;
|
||||
return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
|
||||
}
|
||||
|
||||
/* 7. */
|
||||
uint8_t iterator_kind = ext_obj_p->u.pseudo_array.extra_info;
|
||||
|
||||
if (iterator_kind == ECMA_ITERATOR_KEYS)
|
||||
{
|
||||
/* 12. */
|
||||
return ecma_create_iter_result_object (ecma_make_length_value (index), ECMA_VALUE_FALSE);
|
||||
}
|
||||
|
||||
/* 14. */
|
||||
ecma_value_t get_value = ecma_op_object_get_by_index (array_object_p, index);
|
||||
|
||||
/* 15. */
|
||||
if (ECMA_IS_VALUE_ERROR (get_value))
|
||||
{
|
||||
return get_value;
|
||||
}
|
||||
|
||||
ecma_value_t result;
|
||||
|
||||
/* 16. */
|
||||
if (iterator_kind == ECMA_ITERATOR_VALUES)
|
||||
{
|
||||
result = ecma_create_iter_result_object (get_value, ECMA_VALUE_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 17.a */
|
||||
JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_ENTRIES);
|
||||
|
||||
/* 17.b */
|
||||
ecma_value_t entry_array_value;
|
||||
entry_array_value = ecma_create_array_from_iter_element (get_value,
|
||||
ecma_make_length_value (index));
|
||||
|
||||
result = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE);
|
||||
ecma_free_value (entry_array_value);
|
||||
}
|
||||
|
||||
ecma_free_value (get_value);
|
||||
|
||||
return result;
|
||||
} /* ecma_builtin_array_iterator_prototype_object_next */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
@ -0,0 +1,34 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* %ArrayIteratorPrototype% built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
|
||||
LIT_MAGIC_STRING_ARRAY_ITERATOR_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
ROUTINE (LIT_MAGIC_STRING_NEXT, ecma_builtin_array_iterator_prototype_object_next, 0, 0)
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,28 @@
|
|||
/* 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 "ecma-builtin-helpers.h"
|
||||
#include "ecma-builtins.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype-unscopables.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID array_prototype_unscopables
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
@ -0,0 +1,66 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Array.prototype[@@unscopables] built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_COPY_WITHIN,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_ENTRIES,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_FILL,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_FIND,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_FIND_INDEX,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_FLAT,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_FLATMAP,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_INCLUDES,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_KEYS,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
SIMPLE_VALUE (LIT_MAGIC_STRING_VALUES,
|
||||
ECMA_VALUE_TRUE,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,94 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Array.prototype built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_ARRAY)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
/* ECMA-262 v5, 15.4.4.1 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
|
||||
ECMA_BUILTIN_ID_ARRAY,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/* ECMA-262 v6, 22.1.3.31 */
|
||||
OBJECT_VALUE (LIT_GLOBAL_SYMBOL_UNSCOPABLES,
|
||||
ECMA_BUILTIN_ID_ARRAY_PROTOTYPE_UNSCOPABLES,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* Number properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
/* ECMA-262 v5, 15.4.4 */
|
||||
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||
0,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE)
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, 0, 0)
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_ARRAY_PROTOTYPE_TO_STRING, 0, 0)
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_ARRAY_PROTOTYPE_CONCAT, NON_FIXED, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_ARRAY_PROTOTYPE_JOIN, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_POP, ECMA_ARRAY_PROTOTYPE_POP, 0, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_PUSH, ECMA_ARRAY_PROTOTYPE_PUSH, NON_FIXED, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_ARRAY_PROTOTYPE_REVERSE, 0, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_SHIFT, ECMA_ARRAY_PROTOTYPE_SHIFT, 0, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_ARRAY_PROTOTYPE_SLICE, 2, 2)
|
||||
ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_ARRAY_PROTOTYPE_SORT, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_SPLICE, ECMA_ARRAY_PROTOTYPE_SPLICE, NON_FIXED, 2)
|
||||
ROUTINE (LIT_MAGIC_STRING_UNSHIFT, ECMA_ARRAY_PROTOTYPE_UNSHIFT, NON_FIXED, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_INDEX_OF, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, NON_FIXED, 1)
|
||||
/* Note these 3 routines must be in this order */
|
||||
ROUTINE (LIT_MAGIC_STRING_EVERY, ECMA_ARRAY_PROTOTYPE_EVERY, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_SOME, ECMA_ARRAY_PROTOTYPE_SOME, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_ARRAY_PROTOTYPE_FOR_EACH, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_MAP, ECMA_ARRAY_PROTOTYPE_MAP, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_FILTER, ECMA_ARRAY_PROTOTYPE_FILTER, 2, 1)
|
||||
/* Note these 2 routines must be in this order */
|
||||
ROUTINE (LIT_MAGIC_STRING_REDUCE, ECMA_ARRAY_PROTOTYPE_REDUCE, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, 2, 1)
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_ARRAY_PROTOTYPE_FIND, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_ARRAY_PROTOTYPE_FIND_INDEX, 2, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_FILL, ECMA_ARRAY_PROTOTYPE_FILL, 3, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_ARRAY_PROTOTYPE_COPY_WITHIN, NON_FIXED, 2)
|
||||
ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_ARRAY_PROTOTYPE_ENTRIES, 0, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_ARRAY_PROTOTYPE_KEYS, 0, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_ARRAY_PROTOTYPE_INCLUDES, NON_FIXED, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_FLAT, ECMA_ARRAY_PROTOTYPE_FLAT, 1, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_FLATMAP, ECMA_ARRAY_PROTOTYPE_FLATMAP, 2, 1)
|
||||
INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_STRING_UL, LIT_MAGIC_STRING_TO_STRING_UL,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,588 @@
|
|||
/* 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 "ecma-alloc.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-iterator-object.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "jcontext.h"
|
||||
#include "jrt.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_ARRAY)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
/**
|
||||
* This object has a custom dispatch function.
|
||||
*/
|
||||
#define BUILTIN_CUSTOM_DISPATCH
|
||||
|
||||
/**
|
||||
* List of built-in routine identifiers.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
ECMA_ARRAY_ROUTINE_START = 0,
|
||||
ECMA_ARRAY_ROUTINE_IS_ARRAY,
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ECMA_ARRAY_ROUTINE_FROM,
|
||||
ECMA_ARRAY_ROUTINE_OF,
|
||||
ECMA_ARRAY_ROUTINE_SPECIES_GET
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
};
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID array
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup array ECMA Array object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/**
|
||||
* The Array object's 'from' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 22.1.2.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
|
||||
const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
/* 1. */
|
||||
ecma_value_t constructor = this_arg;
|
||||
ecma_value_t call_this_arg = ECMA_VALUE_UNDEFINED;
|
||||
ecma_value_t items = arguments_list_p[0];
|
||||
ecma_value_t mapfn = (arguments_list_len > 1) ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED;
|
||||
|
||||
/* 2. */
|
||||
ecma_object_t *mapfn_obj_p = NULL;
|
||||
|
||||
/* 3. */
|
||||
if (!ecma_is_value_undefined (mapfn))
|
||||
{
|
||||
/* 3.a */
|
||||
if (!ecma_op_is_callable (mapfn))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable."));
|
||||
}
|
||||
|
||||
/* 3.b */
|
||||
if (arguments_list_len > 2)
|
||||
{
|
||||
call_this_arg = arguments_list_p[2];
|
||||
}
|
||||
|
||||
/* 3.c */
|
||||
mapfn_obj_p = ecma_get_object_from_value (mapfn);
|
||||
}
|
||||
|
||||
/* 4. */
|
||||
ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items, LIT_GLOBAL_SYMBOL_ITERATOR);
|
||||
|
||||
/* 5. */
|
||||
if (ECMA_IS_VALUE_ERROR (using_iterator))
|
||||
{
|
||||
return using_iterator;
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ECMA_VALUE_ERROR;
|
||||
|
||||
/* 6. */
|
||||
if (!ecma_is_value_undefined (using_iterator))
|
||||
{
|
||||
ecma_object_t *array_obj_p;
|
||||
|
||||
/* 6.a */
|
||||
if (ecma_is_constructor (constructor))
|
||||
{
|
||||
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
|
||||
|
||||
ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, NULL, 0);
|
||||
|
||||
if (ecma_is_value_undefined (array) || ecma_is_value_null (array))
|
||||
{
|
||||
ecma_free_value (using_iterator);
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert undefined or null to object"));
|
||||
}
|
||||
|
||||
/* 6.c */
|
||||
if (ECMA_IS_VALUE_ERROR (array))
|
||||
{
|
||||
ecma_free_value (using_iterator);
|
||||
return array;
|
||||
}
|
||||
|
||||
array_obj_p = ecma_get_object_from_value (array);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 6.b */
|
||||
array_obj_p = ecma_op_new_array_object (0);
|
||||
}
|
||||
|
||||
/* 6.d */
|
||||
ecma_value_t next_method;
|
||||
ecma_value_t iterator = ecma_op_get_iterator (items, using_iterator, &next_method);
|
||||
ecma_free_value (using_iterator);
|
||||
|
||||
/* 6.e */
|
||||
if (ECMA_IS_VALUE_ERROR (iterator))
|
||||
{
|
||||
ecma_deref_object (array_obj_p);
|
||||
return iterator;
|
||||
}
|
||||
|
||||
/* 6.f */
|
||||
uint32_t k = 0;
|
||||
|
||||
/* 6.g */
|
||||
while (true)
|
||||
{
|
||||
/* 6.g.ii */
|
||||
ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
|
||||
|
||||
/* 6.g.iii */
|
||||
if (ECMA_IS_VALUE_ERROR (next))
|
||||
{
|
||||
goto iterator_cleanup;
|
||||
}
|
||||
|
||||
/* 6.g.iii */
|
||||
if (ecma_is_value_false (next))
|
||||
{
|
||||
/* 6.g.iv.1 */
|
||||
ecma_value_t len_value = ecma_make_uint32_value (k);
|
||||
ecma_value_t set_status = ecma_op_object_put (array_obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
|
||||
len_value,
|
||||
true);
|
||||
ecma_free_value (len_value);
|
||||
|
||||
/* 6.g.iv.2 */
|
||||
if (ECMA_IS_VALUE_ERROR (set_status))
|
||||
{
|
||||
goto iterator_cleanup;
|
||||
}
|
||||
|
||||
ecma_free_value (iterator);
|
||||
ecma_free_value (next_method);
|
||||
/* 6.g.iv.3 */
|
||||
return ecma_make_object_value (array_obj_p);
|
||||
}
|
||||
|
||||
/* 6.g.v */
|
||||
ecma_value_t next_value = ecma_op_iterator_value (next);
|
||||
|
||||
ecma_free_value (next);
|
||||
|
||||
/* 6.g.vi */
|
||||
if (ECMA_IS_VALUE_ERROR (next_value))
|
||||
{
|
||||
goto iterator_cleanup;
|
||||
}
|
||||
|
||||
ecma_value_t mapped_value;
|
||||
/* 6.g.vii */
|
||||
if (mapfn_obj_p != NULL)
|
||||
{
|
||||
/* 6.g.vii.1 */
|
||||
ecma_value_t args_p[2] = { next_value, ecma_make_uint32_value (k) };
|
||||
/* 6.g.vii.3 */
|
||||
mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2);
|
||||
ecma_free_value (args_p[1]);
|
||||
ecma_free_value (next_value);
|
||||
|
||||
/* 6.g.vii.2 */
|
||||
if (ECMA_IS_VALUE_ERROR (mapped_value))
|
||||
{
|
||||
ecma_op_iterator_close (iterator);
|
||||
goto iterator_cleanup;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 6.g.viii */
|
||||
mapped_value = next_value;
|
||||
}
|
||||
|
||||
/* 6.g.ix */
|
||||
const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_IS_THROW;
|
||||
ecma_value_t set_status = ecma_builtin_helper_def_prop_by_index (array_obj_p, k, mapped_value, flags);
|
||||
|
||||
ecma_free_value (mapped_value);
|
||||
|
||||
/* 6.g.x */
|
||||
if (ECMA_IS_VALUE_ERROR (set_status))
|
||||
{
|
||||
ecma_op_iterator_close (iterator);
|
||||
goto iterator_cleanup;
|
||||
}
|
||||
|
||||
/* 6.g.xi */
|
||||
k++;
|
||||
}
|
||||
|
||||
iterator_cleanup:
|
||||
ecma_free_value (iterator);
|
||||
ecma_free_value (next_method);
|
||||
ecma_deref_object (array_obj_p);
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
/* 8. */
|
||||
ecma_value_t array_like = ecma_op_to_object (items);
|
||||
|
||||
/* 9. */
|
||||
if (ECMA_IS_VALUE_ERROR (array_like))
|
||||
{
|
||||
return array_like;
|
||||
}
|
||||
|
||||
ecma_object_t *array_like_obj_p = ecma_get_object_from_value (array_like);
|
||||
|
||||
/* 10. */
|
||||
ecma_length_t len;
|
||||
ecma_value_t len_value = ecma_op_object_get_length (array_like_obj_p, &len);
|
||||
|
||||
/* 11. */
|
||||
if (ECMA_IS_VALUE_ERROR (len_value))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* 12. */
|
||||
ecma_object_t *array_obj_p;
|
||||
|
||||
/* 12.a */
|
||||
if (ecma_is_constructor (constructor))
|
||||
{
|
||||
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
|
||||
|
||||
len_value = ecma_make_length_value (len);
|
||||
ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &len_value, 1);
|
||||
ecma_free_value (len_value);
|
||||
|
||||
if (ecma_is_value_undefined (array) || ecma_is_value_null (array))
|
||||
{
|
||||
ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert undefined or null to object"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* 14. */
|
||||
if (ECMA_IS_VALUE_ERROR (array))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
array_obj_p = ecma_get_object_from_value (array);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 13.a */
|
||||
array_obj_p = ecma_op_new_array_object_from_length (len);
|
||||
|
||||
if (JERRY_UNLIKELY (array_obj_p == NULL))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* 15. */
|
||||
ecma_length_t k = 0;
|
||||
|
||||
/* 16. */
|
||||
while (k < len)
|
||||
{
|
||||
/* 16.b */
|
||||
ecma_value_t k_value = ecma_op_object_get_by_index (array_like_obj_p, k);
|
||||
|
||||
/* 16.c */
|
||||
if (ECMA_IS_VALUE_ERROR (k_value))
|
||||
{
|
||||
goto construct_cleanup;
|
||||
}
|
||||
|
||||
ecma_value_t mapped_value;
|
||||
/* 16.d */
|
||||
if (mapfn_obj_p != NULL)
|
||||
{
|
||||
/* 16.d.i */
|
||||
ecma_value_t args_p[2] = { k_value, ecma_make_length_value (k) };
|
||||
mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2);
|
||||
ecma_free_value (args_p[1]);
|
||||
ecma_free_value (k_value);
|
||||
|
||||
/* 16.d.ii */
|
||||
if (ECMA_IS_VALUE_ERROR (mapped_value))
|
||||
{
|
||||
goto construct_cleanup;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 16.e */
|
||||
mapped_value = k_value;
|
||||
}
|
||||
|
||||
/* 16.f */
|
||||
const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_IS_THROW;
|
||||
ecma_value_t set_status = ecma_builtin_helper_def_prop_by_index (array_obj_p, k, mapped_value, flags);
|
||||
|
||||
ecma_free_value (mapped_value);
|
||||
|
||||
/* 16.g */
|
||||
if (ECMA_IS_VALUE_ERROR (set_status))
|
||||
{
|
||||
goto construct_cleanup;
|
||||
}
|
||||
|
||||
/* 16.h */
|
||||
k++;
|
||||
}
|
||||
|
||||
/* 17. */
|
||||
len_value = ecma_make_length_value (k);
|
||||
ecma_value_t set_status = ecma_op_object_put (array_obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
|
||||
len_value,
|
||||
true);
|
||||
ecma_free_value (len_value);
|
||||
|
||||
/* 18. */
|
||||
if (ECMA_IS_VALUE_ERROR (set_status))
|
||||
{
|
||||
goto construct_cleanup;
|
||||
}
|
||||
|
||||
/* 19. */
|
||||
ecma_deref_object (array_like_obj_p);
|
||||
return ecma_make_object_value (array_obj_p);
|
||||
|
||||
construct_cleanup:
|
||||
ecma_deref_object (array_obj_p);
|
||||
cleanup:
|
||||
ecma_deref_object (array_like_obj_p);
|
||||
return ret_value;
|
||||
} /* ecma_builtin_array_object_from */
|
||||
|
||||
/**
|
||||
* The Array object's 'of' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 22.1.2.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */
|
||||
const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
if (!ecma_is_constructor (this_arg))
|
||||
{
|
||||
return ecma_op_new_array_object_from_buffer (arguments_list_p, arguments_list_len);
|
||||
}
|
||||
|
||||
ecma_value_t len = ecma_make_uint32_value (arguments_list_len);
|
||||
|
||||
ecma_value_t ret_val = ecma_op_function_construct (ecma_get_object_from_value (this_arg),
|
||||
ecma_get_object_from_value (this_arg),
|
||||
&len,
|
||||
1);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_val))
|
||||
{
|
||||
ecma_free_value (len);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
uint32_t k = 0;
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (ret_val);
|
||||
const uint32_t prop_status_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_IS_THROW;
|
||||
|
||||
while (k < arguments_list_len)
|
||||
{
|
||||
ecma_value_t define_status = ecma_builtin_helper_def_prop_by_index (obj_p,
|
||||
k,
|
||||
arguments_list_p[k],
|
||||
prop_status_flags);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (define_status))
|
||||
{
|
||||
ecma_free_value (len);
|
||||
ecma_deref_object (obj_p);
|
||||
return define_status;
|
||||
}
|
||||
|
||||
k++;
|
||||
}
|
||||
|
||||
ret_val = ecma_op_object_put (obj_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
|
||||
len,
|
||||
true);
|
||||
|
||||
ecma_free_value (len);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_val))
|
||||
{
|
||||
ecma_deref_object (obj_p);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
return ecma_make_object_value (obj_p);
|
||||
} /* ecma_builtin_array_object_of */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Handle calling [[Call]] of built-in Array object
|
||||
*
|
||||
* @return ECMA_VALUE_ERROR - if the array construction fails
|
||||
* constructed array object - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_array_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
if (arguments_list_len != 1
|
||||
|| !ecma_is_value_number (arguments_list_p[0]))
|
||||
{
|
||||
return ecma_op_new_array_object_from_buffer (arguments_list_p, arguments_list_len);
|
||||
}
|
||||
|
||||
ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]);
|
||||
uint32_t num_uint32 = ecma_number_to_uint32 (num);
|
||||
|
||||
if (num != ((ecma_number_t) num_uint32))
|
||||
{
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length."));
|
||||
}
|
||||
|
||||
return ecma_make_object_value (ecma_op_new_array_object (num_uint32));
|
||||
} /* ecma_builtin_array_dispatch_call */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in Array object
|
||||
*
|
||||
* @return ECMA_VALUE_ERROR - if the array construction fails
|
||||
* constructed array object - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_array_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
#if !ENABLED (JERRY_ESNEXT)
|
||||
return ecma_builtin_array_dispatch_call (arguments_list_p, arguments_list_len);
|
||||
#else /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p),
|
||||
ECMA_BUILTIN_ID_ARRAY_PROTOTYPE);
|
||||
|
||||
if (proto_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_value_t result = ecma_builtin_array_dispatch_call (arguments_list_p, arguments_list_len);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
ecma_deref_object (proto_p);
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (result);
|
||||
ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, proto_p);
|
||||
ecma_deref_object (proto_p);
|
||||
return result;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} /* ecma_builtin_array_dispatch_construct */
|
||||
|
||||
/**
|
||||
* Dispatcher of the built-in's routines
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_array_dispatch_routine (uint8_t builtin_routine_id, /**< built-in wide routine identifier */
|
||||
ecma_value_t this_arg, /**< 'this' argument value */
|
||||
const ecma_value_t arguments_list_p[], /**< list of arguments
|
||||
* passed to routine */
|
||||
uint32_t arguments_number) /**< length of arguments' list */
|
||||
{
|
||||
switch (builtin_routine_id)
|
||||
{
|
||||
case ECMA_ARRAY_ROUTINE_IS_ARRAY:
|
||||
{
|
||||
JERRY_UNUSED (this_arg);
|
||||
|
||||
return arguments_number > 0 ? ecma_is_value_array (arguments_list_p[0]) : ECMA_VALUE_FALSE;
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case ECMA_ARRAY_ROUTINE_FROM:
|
||||
{
|
||||
return ecma_builtin_array_object_from (this_arg, arguments_list_p, arguments_number);
|
||||
}
|
||||
case ECMA_ARRAY_ROUTINE_OF:
|
||||
{
|
||||
return ecma_builtin_array_object_of (this_arg, arguments_list_p, arguments_number);
|
||||
}
|
||||
case ECMA_ARRAY_ROUTINE_SPECIES_GET:
|
||||
{
|
||||
return ecma_copy_value (this_arg);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
} /* ecma_builtin_array_dispatch_routine */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
|
|
@ -0,0 +1,60 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Array description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_ARRAY)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
/* ECMA-262 v5, 15.4.3.1 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
|
||||
ECMA_BUILTIN_ID_ARRAY_PROTOTYPE,
|
||||
ECMA_PROPERTY_FIXED)
|
||||
|
||||
/* Number properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||
1,
|
||||
ECMA_PROPERTY_FLAG_DEFAULT_LENGTH)
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
STRING_VALUE (LIT_MAGIC_STRING_NAME,
|
||||
LIT_MAGIC_STRING_ARRAY_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
ROUTINE (LIT_MAGIC_STRING_IS_ARRAY_UL, ECMA_ARRAY_ROUTINE_IS_ARRAY, 1, 1)
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ROUTINE (LIT_MAGIC_STRING_FROM, ECMA_ARRAY_ROUTINE_FROM, NON_FIXED, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_OF, ECMA_ARRAY_ROUTINE_OF, NON_FIXED, 0)
|
||||
|
||||
/* ECMA-262 v6, 22.1.2.5 */
|
||||
ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES,
|
||||
ECMA_ARRAY_ROUTINE_SPECIES_GET,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#endif /* !(ENABLED (JERRY_BUILTIN_ARRAY)) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,236 @@
|
|||
/* 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 "ecma-builtin-helpers.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-arraybuffer-object.h"
|
||||
#include "jrt.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-arraybuffer-prototype.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID arraybuffer_prototype
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup arraybufferprototype ECMA ArrayBuffer.prototype object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The ArrayBuffer.prototype.bytelength accessor
|
||||
*
|
||||
* See also:
|
||||
* ES2015, 24.1.4.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /**< this argument */
|
||||
{
|
||||
if (ecma_is_value_object (this_arg))
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
|
||||
|
||||
if (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL))
|
||||
{
|
||||
if (ecma_arraybuffer_is_detached (object_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
|
||||
}
|
||||
uint32_t len = ecma_arraybuffer_get_length (object_p);
|
||||
|
||||
return ecma_make_uint32_value (len);
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a ArrayBuffer object."));
|
||||
} /* ecma_builtin_arraybuffer_prototype_bytelength_getter */
|
||||
|
||||
/**
|
||||
* The ArrayBuffer.prototype object's 'slice' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v11, 24.1.4.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< this argument */
|
||||
const ecma_value_t *argument_list_p, /**< arguments list */
|
||||
uint32_t arguments_number) /**< number of arguments */
|
||||
{
|
||||
if (!ecma_is_value_object (this_arg))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not object."));
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
|
||||
|
||||
/* 2. */
|
||||
if (!ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an ArrayBuffer object."));
|
||||
}
|
||||
|
||||
/* TODO: step 3. if SharedArrayBuffer will be implemented */
|
||||
|
||||
/* 4. */
|
||||
if (ecma_arraybuffer_is_detached (object_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
uint32_t len = ecma_arraybuffer_get_length (object_p);
|
||||
|
||||
uint32_t start = 0;
|
||||
uint32_t end = len;
|
||||
|
||||
if (arguments_number > 0)
|
||||
{
|
||||
/* 6-7. */
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[0],
|
||||
len,
|
||||
&start)))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (arguments_number > 1 && !ecma_is_value_undefined (argument_list_p[1]))
|
||||
{
|
||||
/* 8-9 .*/
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[1],
|
||||
len,
|
||||
&end)))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 10. */
|
||||
uint32_t new_len = (end >= start) ? (end - start) : 0;
|
||||
|
||||
/* 11. */
|
||||
ecma_value_t ctor = ecma_op_species_constructor (object_p, ECMA_BUILTIN_ID_ARRAYBUFFER);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ctor))
|
||||
{
|
||||
return ctor;
|
||||
}
|
||||
|
||||
/* 12. */
|
||||
ecma_object_t *ctor_obj_p = ecma_get_object_from_value (ctor);
|
||||
ecma_value_t new_len_value = ecma_make_uint32_value (new_len);
|
||||
|
||||
ecma_value_t new_arraybuffer = ecma_op_function_construct (ctor_obj_p, ctor_obj_p, &new_len_value, 1);
|
||||
|
||||
ecma_deref_object (ctor_obj_p);
|
||||
ecma_free_value (new_len_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (new_arraybuffer))
|
||||
{
|
||||
return new_arraybuffer;
|
||||
}
|
||||
|
||||
ecma_object_t *new_arraybuffer_p = ecma_get_object_from_value (new_arraybuffer);
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
/* 13. */
|
||||
if (!ecma_object_class_is (new_arraybuffer_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL))
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Return value is not an ArrayBuffer object."));
|
||||
goto free_new_arraybuffer;
|
||||
}
|
||||
|
||||
/* TODO: step 14. if SharedArrayBuffer will be implemented */
|
||||
|
||||
/* 15. */
|
||||
if (ecma_arraybuffer_is_detached (new_arraybuffer_p))
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Return ArrayBuffer has been detached."));
|
||||
goto free_new_arraybuffer;
|
||||
}
|
||||
|
||||
/* 16. */
|
||||
if (ecma_op_same_value (new_arraybuffer, this_arg))
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer subclass returned this from species constructor"));
|
||||
goto free_new_arraybuffer;
|
||||
}
|
||||
|
||||
/* 17. */
|
||||
if (ecma_arraybuffer_get_length (new_arraybuffer_p) < new_len)
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Derived ArrayBuffer constructor created a too small buffer."));
|
||||
goto free_new_arraybuffer;
|
||||
}
|
||||
|
||||
/* 19. */
|
||||
if (ecma_arraybuffer_is_detached (object_p))
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Original ArrayBuffer has been detached."));
|
||||
goto free_new_arraybuffer;
|
||||
}
|
||||
|
||||
/* 20. */
|
||||
lit_utf8_byte_t *old_buf = ecma_arraybuffer_get_buffer (object_p);
|
||||
|
||||
/* 21. */
|
||||
lit_utf8_byte_t *new_buf = ecma_arraybuffer_get_buffer (new_arraybuffer_p);
|
||||
|
||||
/* 22. */
|
||||
memcpy (new_buf, old_buf + start, new_len);
|
||||
|
||||
free_new_arraybuffer:
|
||||
if (ret_value != ECMA_VALUE_EMPTY)
|
||||
{
|
||||
ecma_deref_object (new_arraybuffer_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 23. */
|
||||
ret_value = ecma_make_object_value (new_arraybuffer_p);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_arraybuffer_prototype_object_slice */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
|
@ -0,0 +1,47 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ArrayBuffer.prototype built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
|
||||
ECMA_BUILTIN_ID_ARRAYBUFFER,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
|
||||
/* Readonly accessor properties */
|
||||
ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL,
|
||||
ecma_builtin_arraybuffer_prototype_bytelength_getter,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* ECMA-262 v6, 24.1.4.4 */
|
||||
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
|
||||
LIT_MAGIC_STRING_ARRAY_BUFFER_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_arraybuffer_prototype_object_slice, NON_FIXED, 2)
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,113 @@
|
|||
/* 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 "ecma-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-arraybuffer-object.h"
|
||||
#include "ecma-dataview-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "jrt.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-arraybuffer.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID arraybuffer
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup arraybuffer ECMA ArrayBuffer object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The ArrayBuffer object's 'isView' routine
|
||||
*
|
||||
* See also:
|
||||
* ES2015 24.1.3.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_arraybuffer_object_is_view (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t arg) /**< argument 1 */
|
||||
{
|
||||
JERRY_UNUSED (this_arg);
|
||||
|
||||
return ecma_make_boolean_value (ecma_is_typedarray (arg) || ecma_is_dataview (arg));
|
||||
} /* ecma_builtin_arraybuffer_object_is_view */
|
||||
|
||||
/**
|
||||
* Handle calling [[Call]] of built-in ArrayBuffer object
|
||||
*
|
||||
* ES2015 24.1.2 ArrayBuffer is not intended to be called as
|
||||
* a function and will throw an exception when called in
|
||||
* that manner.
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_arraybuffer_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Constructor ArrayBuffer requires 'new'"));
|
||||
} /* ecma_builtin_arraybuffer_dispatch_call */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in ArrayBuffer object
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_arraybuffer_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
return ecma_op_create_arraybuffer_object (arguments_list_p, arguments_list_len);
|
||||
} /* ecma_builtin_arraybuffer_dispatch_construct */
|
||||
|
||||
/**
|
||||
* 24.1.3.3 get ArrayBuffer [ @@species ] accessor
|
||||
*
|
||||
* @return ecma_value
|
||||
* returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_arraybuffer_species_get (ecma_value_t this_value) /**< This Value */
|
||||
{
|
||||
return ecma_copy_value (this_value);
|
||||
} /* ecma_builtin_arraybuffer_species_get */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
|
@ -0,0 +1,55 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ArrayBuffer built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
|
||||
/* Number properties:
|
||||
* (property name, number value, writable, enumerable, configurable) */
|
||||
|
||||
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||
1,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
|
||||
ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE,
|
||||
ECMA_PROPERTY_FIXED)
|
||||
|
||||
STRING_VALUE (LIT_MAGIC_STRING_NAME,
|
||||
LIT_MAGIC_STRING_ARRAY_BUFFER_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
|
||||
/* ES2015 24.1.3.1 */
|
||||
ROUTINE (LIT_MAGIC_STRING_IS_VIEW_UL, ecma_builtin_arraybuffer_object_is_view, 1, 1)
|
||||
|
||||
/* ES2015 24.1.3.3 */
|
||||
ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES,
|
||||
ecma_builtin_arraybuffer_species_get,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,43 @@
|
|||
/* 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 "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-function-prototype.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID async_function_prototype
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup asyncfunctionprototype ECMA AsyncFunction.prototype object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
@ -0,0 +1,36 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* %AsyncFunctionPrototype% built-in description (AsyncFunction.prototype)
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/* ECMA-262 v11, 25.7.3.1 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
|
||||
ECMA_BUILTIN_ID_ASYNC_FUNCTION,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* ECMA-262 v11, 25.7.3.2 */
|
||||
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
|
||||
LIT_MAGIC_STRING_ASYNC_FUNCTION_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,74 @@
|
|||
/* 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 "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
#include "ecma-function-object.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-function.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID async_function
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup asyncfunction ECMA AsyncFunction object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle calling [[Call]] of built-in AsyncFunction object
|
||||
*
|
||||
* @return constructed async function object - if success
|
||||
* raised error otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_async_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
return ecma_op_create_dynamic_function (arguments_list_p,
|
||||
arguments_list_len,
|
||||
ECMA_PARSE_ASYNC_FUNCTION);
|
||||
} /* ecma_builtin_async_function_dispatch_call */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in AsyncFunction object
|
||||
*
|
||||
* @return constructed async function object - if success
|
||||
* raised error otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_async_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
return ecma_builtin_async_function_dispatch_call (arguments_list_p, arguments_list_len);
|
||||
} /* ecma_builtin_async_function_dispatch_construct */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
|
@ -0,0 +1,41 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* %AsyncFunction% built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/* ECMA-262 v11, 25.7.2 */
|
||||
STRING_VALUE (LIT_MAGIC_STRING_NAME,
|
||||
LIT_MAGIC_STRING_ASYNC_FUNCTION_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* ECMA-262 v11, 25.7.2.1 */
|
||||
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||
1,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* ECMA-262 v10, 25.7.2.2 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
|
||||
ECMA_BUILTIN_ID_ASYNC_FUNCTION,
|
||||
ECMA_PROPERTY_FIXED)
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
|
@ -0,0 +1,74 @@
|
|||
/* 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 "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
#include "ecma-function-object.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-async-generator-function.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID async_generator_function
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup asyncgenerator ECMA AsyncGeneratorFunction object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle calling [[Call]] of built-in AsyncGeneratorFunction object
|
||||
*
|
||||
* @return constructed async generator function object - if success
|
||||
* raised error otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_async_generator_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
return ecma_op_create_dynamic_function (arguments_list_p,
|
||||
arguments_list_len,
|
||||
ECMA_PARSE_GENERATOR_FUNCTION | ECMA_PARSE_ASYNC_FUNCTION);
|
||||
} /* ecma_builtin_async_generator_function_dispatch_call */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in AsyncGeneratorFunction object
|
||||
*
|
||||
* @return constructed async generator function object - if success
|
||||
* raised error otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_async_generator_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
return ecma_builtin_async_generator_function_dispatch_call (arguments_list_p, arguments_list_len);
|
||||
} /* ecma_builtin_async_generator_function_dispatch_construct */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|