From d121168fb0228ca6ff76841d34c0d56e6277fa80 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 17 Aug 2020 21:15:57 +0800 Subject: [PATCH] interpreters/quickjs: Initial QuickJS support Signed-off-by: Huang Qi Change-Id: Ie6cb7a37c34ef3bd63390eed905b6fb76c31a3d9 --- interpreters/quickjs/.gitignore | 2 + interpreters/quickjs/Kconfig | 24 +++ interpreters/quickjs/Make.defs | 30 +++ interpreters/quickjs/Makefile | 74 +++++++ interpreters/quickjs/quickjs.patch | 302 +++++++++++++++++++++++++++++ 5 files changed, 432 insertions(+) create mode 100644 interpreters/quickjs/.gitignore create mode 100644 interpreters/quickjs/Kconfig create mode 100644 interpreters/quickjs/Make.defs create mode 100644 interpreters/quickjs/Makefile create mode 100644 interpreters/quickjs/quickjs.patch diff --git a/interpreters/quickjs/.gitignore b/interpreters/quickjs/.gitignore new file mode 100644 index 000000000..30534d8e1 --- /dev/null +++ b/interpreters/quickjs/.gitignore @@ -0,0 +1,2 @@ +quickjs* +*.tar.gz diff --git a/interpreters/quickjs/Kconfig b/interpreters/quickjs/Kconfig new file mode 100644 index 000000000..7e29d66e2 --- /dev/null +++ b/interpreters/quickjs/Kconfig @@ -0,0 +1,24 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config INTERPRETERS_QUICKJS + tristate "QuickJS JavaScript interpreter" + default n + +if INTERPRETERS_QUICKJS + +config INTERPRETERS_QUICKJS_BIGNUM + bool "Bignum support" + default false + +config INTERPRETERS_QUICKJS_PRIORITY + int "QuickJS interpreter priority" + default 100 + +config INTERPRETERS_QUICKJS_STACKSIZE + int "QuickJS interpreter stack size" + default 8192 + +endif diff --git a/interpreters/quickjs/Make.defs b/interpreters/quickjs/Make.defs new file mode 100644 index 000000000..0c0304088 --- /dev/null +++ b/interpreters/quickjs/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# interpreters/quickjs/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you 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. +# +############################################################################ + +ifneq ($(CONFIG_INTERPRETERS_QUICKJS),) +CONFIGURED_APPS += $(APPDIR)/interpreters/quickjs + +# It allows `` import. +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \ + $(APPDIR)/interpreters/quickjs} +CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \ + $(APPDIR)/interpreters/quickjs} + +endif diff --git a/interpreters/quickjs/Makefile b/interpreters/quickjs/Makefile new file mode 100644 index 000000000..eab440a2b --- /dev/null +++ b/interpreters/quickjs/Makefile @@ -0,0 +1,74 @@ +############################################################################ +# interpreters/quickjs/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you 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 $(APPDIR)/Make.defs + +QUICKJS_VERSION = 20200705 +QUICKJS_UNPACK = quickjs +QUICKJS_TARBALL = $(QUICKJS_VERSION).tar.gz +QUICKJS_URL_BASE = https://github.com/horhof/quickjs/archive +QUICKJS_URL = $(QUICKJS_URL_BASE)/$(QUICKJS_TARBALL) + +CSRCS = quickjs.c libregexp.c jscompress.c libbf.c libunicode.c +CSRCS += cutils.c quickjs-libc.c repl.c + +MAINSRC = qjs.c + +VERSION=\"$(shell cat $(QUICKJS_UNPACK)/VERSION)\" + +CFLAGS += -DCONFIG_VERSION=$(VERSION) -Wno-shadow -D__NuttX__ +CFLAGS += -Wno-array-bounds -I$(QUICKJS_UNPACK) +ifneq ($(CONFIG_INTERPRETERS_QUICKJS_BIGNUM),) +CFLAGS += -DCONFIG_BIGNUM +CSRCS += qjscalc.c +endif + +VPATH += $(QUICKJS_UNPACK) + +PROGNAME = qjs +PRIORITY = $(CONFIG_INTERPRETERS_QUICKJS_PRIORITY) +STACKSIZE = $(CONFIG_INTERPRETERS_QUICKJS_STACKSIZE) +MODULE = $(CONFIG_INTERPRETERS_QUICKJS) + +$(QUICKJS_TARBALL): + $(Q) echo "Downloading $(QUICKJS_TARBALL)" + $(Q) wget $(QUICKJS_URL) + +$(QUICKJS_UNPACK): $(QUICKJS_TARBALL) + $(Q) echo "Unpacking $(QUICKJS_TARBALL) to $(QUICKJS_UNPACK)" + $(Q) tar xzvf $(QUICKJS_TARBALL) + $(Q) mv quickjs-$(QUICKJS_VERSION) $(QUICKJS_UNPACK) + $(Q) patch -p0 < quickjs.patch + +$(QUICKJS_UNPACK)/.patch: $(QUICKJS_UNPACK) + $(Q) make -C $(QUICKJS_UNPACK) \ + CONFIG_BIGNUM=$(CONFIG_INTERPRETERS_QUICKJS_BIGNUM) + $(Q) touch $(QUICKJS_UNPACK)/.patch + +context:: $(QUICKJS_UNPACK)/.patch + +clean:: + $(Q) test ! -d $(QUICKJS_UNPACK) || make -C $(QUICKJS_UNPACK) clean + +distclean:: + $(call DELDIR, $(QUICKJS_UNPACK)) + $(call DELFILE, $(QUICKJS_TARBALL)) + +include $(APPDIR)/Application.mk diff --git a/interpreters/quickjs/quickjs.patch b/interpreters/quickjs/quickjs.patch new file mode 100644 index 000000000..d3242b411 --- /dev/null +++ b/interpreters/quickjs/quickjs.patch @@ -0,0 +1,302 @@ +diff --color -upr quickjs/libregexp.c quickjs-20200705-modified/libregexp.c +--- quickjs/libregexp.c 2020-07-25 05:25:41.000000000 +0800 ++++ quickjs-20200705-modified/libregexp.c 2020-08-27 16:04:41.440000000 +0800 +@@ -21,6 +21,7 @@ + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ ++#include + #include + #include + #include +diff --color -upr quickjs/qjs.c quickjs-20200705-modified/qjs.c +--- quickjs/qjs.c 2020-07-25 05:25:41.000000000 +0800 ++++ quickjs-20200705-modified/qjs.c 2020-08-27 16:23:55.750000000 +0800 +@@ -34,7 +34,7 @@ + #include + #if defined(__APPLE__) + #include +-#elif defined(__linux__) ++#elif defined(__linux__) || defined(__NuttX__) + #include + #endif + +@@ -242,7 +242,7 @@ static const JSMallocFunctions trace_mf + (size_t (*)(const void *))_msize, + #elif defined(EMSCRIPTEN) + NULL, +-#elif defined(__linux__) ++#elif defined(__linux__) || defined(__NuttX__) + (size_t (*)(const void *))malloc_usable_size, + #else + /* change this to `NULL,` if compilation fails */ +diff --color -upr quickjs/quickjs-libc.c quickjs-20200705-modified/quickjs-libc.c +--- quickjs/quickjs-libc.c 2020-07-25 05:25:41.000000000 +0800 ++++ quickjs-20200705-modified/quickjs-libc.c 2020-08-27 17:10:06.890000000 +0800 +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + #if defined(__APPLE__) + typedef sig_t sighandler_t; +@@ -71,6 +72,42 @@ typedef sig_t sighandler_t; + #include "list.h" + #include "quickjs-libc.h" + ++#ifndef SIGQUIT ++# define SIGQUIT 3 ++#endif ++ ++#ifndef SIGILL ++# define SIGILL 4 ++#endif ++ ++#ifndef SIGABRT ++# define SIGABRT 6 ++#endif ++ ++#ifndef SIGFPE ++# define SIGFPE 8 ++#endif ++ ++#ifndef SIGSEGV ++# define SIGSEGV 13 ++#endif ++ ++#ifndef SIGTERM ++# define SIGTERM 15 ++#endif ++ ++#ifndef SIGTSTP ++# define SIGTSTP 18 ++#endif ++ ++#ifndef SIGTTIN ++# define SIGTTIN 21 ++#endif ++ ++#ifndef SIGTTOU ++# define SIGTTOU 22 ++#endif ++ + /* TODO: + - add socket calls + */ +@@ -2622,62 +2651,6 @@ static char **build_envp(JSContext *ctx, + goto done; + } + +-/* execvpe is not available on non GNU systems */ +-static int my_execvpe(const char *filename, char **argv, char **envp) +-{ +- char *path, *p, *p_next, *p1; +- char buf[PATH_MAX]; +- size_t filename_len, path_len; +- BOOL eacces_error; +- +- filename_len = strlen(filename); +- if (filename_len == 0) { +- errno = ENOENT; +- return -1; +- } +- if (strchr(filename, '/')) +- return execve(filename, argv, envp); +- +- path = getenv("PATH"); +- if (!path) +- path = (char *)"/bin:/usr/bin"; +- eacces_error = FALSE; +- p = path; +- for(p = path; p != NULL; p = p_next) { +- p1 = strchr(p, ':'); +- if (!p1) { +- p_next = NULL; +- path_len = strlen(p); +- } else { +- p_next = p1 + 1; +- path_len = p1 - p; +- } +- /* path too long */ +- if ((path_len + 1 + filename_len + 1) > PATH_MAX) +- continue; +- memcpy(buf, p, path_len); +- buf[path_len] = '/'; +- memcpy(buf + path_len + 1, filename, filename_len); +- buf[path_len + 1 + filename_len] = '\0'; +- +- execve(buf, argv, envp); +- +- switch(errno) { +- case EACCES: +- eacces_error = TRUE; +- break; +- case ENOENT: +- case ENOTDIR: +- break; +- default: +- return -1; +- } +- } +- if (eacces_error) +- errno = EACCES; +- return -1; +-} +- + /* exec(args[, options]) -> exitcode */ + static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +@@ -2687,12 +2660,13 @@ static JSValue js_os_exec(JSContext *ctx + const char **exec_argv, *file = NULL, *str, *cwd = NULL; + char **envp = environ; + uint32_t exec_argc, i; +- int ret, pid, status; ++ int ret, status; ++ pid_t pid; + BOOL block_flag = TRUE, use_path = TRUE; + static const char *std_name[3] = { "stdin", "stdout", "stderr" }; +- int std_fds[3]; + uint32_t uid = -1, gid = -1; +- ++ posix_spawn_file_actions_t action; ++ + val = JS_GetPropertyStr(ctx, args, "length"); + if (JS_IsException(val)) + return JS_EXCEPTION; +@@ -2718,10 +2692,8 @@ static JSValue js_os_exec(JSContext *ctx + exec_argv[i] = str; + } + exec_argv[exec_argc] = NULL; ++ posix_spawn_file_actions_init(&action); + +- for(i = 0; i < 3; i++) +- std_fds[i] = i; +- + /* get the options, if any */ + if (argc >= 2) { + options = argv[1]; +@@ -2762,7 +2734,9 @@ static JSValue js_os_exec(JSContext *ctx + JS_FreeValue(ctx, val); + if (ret) + goto exception; +- std_fds[i] = fd; ++ if (fd != i) { ++ posix_spawn_file_actions_adddup2(&action, fd, i); ++ } + } + } + +@@ -2797,46 +2771,17 @@ static JSValue js_os_exec(JSContext *ctx + } + } + +- pid = fork(); +- if (pid < 0) { +- JS_ThrowTypeError(ctx, "fork error"); ++ if (!file) ++ file = exec_argv[0]; ++ if (use_path) ++ ret = posix_spawnp(&pid, file, &action, NULL, (char **)exec_argv, envp); ++ else ++ ret = posix_spawn(&pid, file, &action, NULL, (char **)exec_argv, envp); ++ ++ if (ret < 0) { + goto exception; + } +- if (pid == 0) { +- /* child */ +- int fd_max = sysconf(_SC_OPEN_MAX); + +- /* remap the stdin/stdout/stderr handles if necessary */ +- for(i = 0; i < 3; i++) { +- if (std_fds[i] != i) { +- if (dup2(std_fds[i], i) < 0) +- _exit(127); +- } +- } +- +- for(i = 3; i < fd_max; i++) +- close(i); +- if (cwd) { +- if (chdir(cwd) < 0) +- _exit(127); +- } +- if (uid != -1) { +- if (setuid(uid) < 0) +- _exit(127); +- } +- if (gid != -1) { +- if (setgid(gid) < 0) +- _exit(127); +- } +- +- if (!file) +- file = exec_argv[0]; +- if (use_path) +- ret = my_execvpe(file, (char **)exec_argv, envp); +- else +- ret = execve(file, (char **)exec_argv, envp); +- _exit(127); +- } + /* parent */ + if (block_flag) { + for(;;) { +@@ -2856,6 +2801,7 @@ static JSValue js_os_exec(JSContext *ctx + } + ret_val = JS_NewInt32(ctx, ret); + done: ++ posix_spawn_file_actions_destroy(&action); + JS_FreeCString(ctx, file); + JS_FreeCString(ctx, cwd); + for(i = 0; i < exec_argc; i++) +diff --color -upr quickjs/quickjs.c quickjs-20200705-modified/quickjs.c +--- quickjs/quickjs.c 2020-07-25 05:25:41.000000000 +0800 ++++ quickjs-20200705-modified/quickjs.c 2020-08-27 17:10:33.520000000 +0800 +@@ -22,6 +22,7 @@ + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ ++#include + #include + #include + #include +@@ -34,7 +35,7 @@ + #include + #if defined(__APPLE__) + #include +-#elif defined(__linux__) ++#elif defined(__linux__) || defined(__NuttX__) + #include + #endif + +@@ -104,6 +105,20 @@ + //#define DUMP_PROMISE + //#define DUMP_READ_OBJECT + ++#ifndef FE_TONEAREST ++# define FE_TONEAREST 0x00000000 ++#endif ++#ifndef FE_UPWARD ++# define FE_UPWARD 0x00400000 ++#endif ++#ifndef FE_DOWNWARD ++# define FE_DOWNWARD 0x00800000 ++#endif ++#ifndef FE_TOWARDZERO ++# define FE_TOWARDZERO 0x00c00000 ++#endif ++ ++ + /* test the GC by forcing it before each object allocation */ + //#define FORCE_GC_AT_MALLOC + +@@ -1736,7 +1751,7 @@ static const JSMallocFunctions def_mallo + (size_t (*)(const void *))_msize, + #elif defined(EMSCRIPTEN) + NULL, +-#elif defined(__linux__) ++#elif defined(__linux__) || defined(__NuttX__) + (size_t (*)(const void *))malloc_usable_size, + #else + /* change this to `NULL,` if compilation fails */