Browse Source

2019-09-18

- added os.exec and other system calls
- exported JS_ValueToAtom()
- qjsc: added 'qjsc_' prefix to the generated C identifiers
- added cross-compilation support
- misc bug fixes
pull/11/head 20190918
Horunabu Hofutenho 2 years ago
parent
commit
37925d8d5b
No known key found for this signature in database GPG Key ID: 7EB80FA93BC3054C
21 changed files with 868 additions and 349 deletions
  1. +8
    -0
      Changelog
  2. +66
    -36
      Makefile
  3. +3
    -3
      TODO
  4. +1
    -1
      VERSION
  5. +1
    -0
      cutils.h
  6. +73
    -4
      doc/quickjs.html
  7. BIN
      doc/quickjs.pdf
  8. +59
    -4
      doc/quickjs.texi
  9. +2
    -3
      libbf.c
  10. +1
    -1
      libregexp.c
  11. +1
    -1
      libunicode.c
  12. +8
    -8
      qjs.c
  13. +40
    -14
      qjsc.c
  14. +335
    -16
      quickjs-libc.c
  15. +3
    -1
      quickjs-opcode.h
  16. +186
    -100
      quickjs.c
  17. +1
    -0
      quickjs.h
  18. +0
    -153
      tests/test262.patch
  19. +18
    -0
      tests/test_builtin.js
  20. +30
    -4
      tests/test_op.js
  21. +32
    -0
      tests/test_std.js

+ 8
- 0
Changelog View File

@ -1,3 +1,11 @@
2019-09-18:
- added os.exec and other system calls
- exported JS_ValueToAtom()
- qjsc: added 'qjsc_' prefix to the generated C identifiers
- added cross-compilation support
- misc bug fixes
2019-09-01:
- added globalThis


+ 66
- 36
Makefile View File

@ -31,11 +31,9 @@ endif
CONFIG_LTO=y
# consider warnings as errors (for development)
#CONFIG_WERROR=y
ifndef CONFIG_WIN32
# force 32 bit build for some utilities
CONFIG_M32=y
endif
#CONFIG_M32=y
ifdef CONFIG_DARWIN
# use clang instead of gcc
CONFIG_CLANG=y
@ -60,6 +58,7 @@ else
EXE=
endif
ifdef CONFIG_CLANG
HOST_CC=clang
CC=$(CROSS_PREFIX)clang
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wextra
@ -80,15 +79,17 @@ ifdef CONFIG_CLANG
endif
endif
else
HOST_CC=gcc
CC=$(CROSS_PREFIX)gcc
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wno-array-bounds
CFLAGS += -Wno-array-bounds -Wno-format-truncation
ifdef CONFIG_LTO
AR=$(CROSS_PREFIX)gcc-ar
else
AR=$(CROSS_PREFIX)ar
endif
endif
STRIP=$(CROSS_PREFIX)strip
ifdef CONFIG_WERROR
CFLAGS+=-Werror
endif
@ -118,7 +119,17 @@ else
LDEXPORT=-rdynamic
endif
PROGS=qjs$(EXE) qjsbn$(EXE) qjsc qjsbnc run-test262 run-test262-bn
PROGS=qjs$(EXE) qjsbn$(EXE) qjsc$(EXE) qjsbnc$(EXE) run-test262 run-test262-bn
ifneq ($(CROSS_PREFIX),)
QJSC_CC=gcc
QJSC=./host-qjsc
QJSBNC=./host-qjsbnc
PROGS+=$(QJSC) $(QJSBNC)
else
QJSC_CC=$(CC)
QJSC=./qjsc$(EXE)
QJSBNC=./qjsbnc$(EXE)
endif
ifndef CONFIG_WIN32
PROGS+=qjscalc
endif
@ -129,14 +140,15 @@ PROGS+=libquickjs.a libquickjs.bn.a
ifdef CONFIG_LTO
PROGS+=libquickjs.lto.a libquickjs.bn.lto.a
endif
# examples
ifeq ($(CROSS_PREFIX),)
ifdef CONFIG_ASAN
PROGS+=
else ifdef CONFIG_WIN32
PROGS+=
else
PROGS+=examples/hello examples/hello_module examples/c_module
endif
endif
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
@ -162,20 +174,32 @@ qjs$(EXE): $(QJS_OBJS)
qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS))
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
qjsc: $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS)
qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
qjsbnc: $(OBJDIR)/qjsc.bn.o $(QJSBN_LIB_OBJS)
qjsbnc$(EXE): $(OBJDIR)/qjsc.bn.o $(QJSBN_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
ifneq ($(CROSS_PREFIX),)
$(QJSC): $(OBJDIR)/qjsc.host.o \
$(patsubst %.o, %.host.o, $(QJS_LIB_OBJS))
$(HOST_CC) $(LDFLAGS) -o $@ $^ $(LIBS)
$(QJSBNC): $(OBJDIR)/qjsc.bn.host.o \
$(patsubst %.o, %.host.o, $(QJSBN_LIB_OBJS))
$(HOST_CC) $(LDFLAGS) -o $@ $^ $(LIBS)
endif #CROSS_PREFIX
QJSC_DEFINES:=-DCONFIG_CC=\"$(CC)\"
QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(prefix)\"
ifdef CONFIG_LTO
QJSC_DEFINES+=-DCONFIG_LTO
endif
QJSC_DEFINES+=-DCONFIG_PREFIX=\"$(prefix)\"
QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(prefix)\"
$(OBJDIR)/qjsc.o $(OBJDIR)/qjsc.bn.o: CFLAGS+=$(QJSC_DEFINES)
$(OBJDIR)/qjsc.host.o $(OBJDIR)/qjsc.bn.host.o: CFLAGS+=$(QJSC_HOST_DEFINES)
qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS))
$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
@ -216,14 +240,14 @@ libquickjs.bn.a: $(patsubst %.o, %.nolto.o, $(QJSBN_LIB_OBJS))
$(AR) rcs $@ $^
endif # CONFIG_LTO
repl.c: qjsc repl.js
./qjsc -c -o $@ -m repl.js
repl.c: $(QJSC) repl.js
$(QJSC) -c -o $@ -m repl.js
repl-bn.c: qjsbnc repl.js
./qjsbnc -c -o $@ -m repl.js
repl-bn.c: $(QJSBNC) repl.js
$(QJSBNC) -c -o $@ -m repl.js
qjscalc.c: qjsbnc qjscalc.js
./qjsbnc -c -o $@ qjscalc.js
qjscalc.c: $(QJSBNC) qjscalc.js
$(QJSBNC) -c -o $@ qjscalc.js
ifneq ($(wildcard unicode/UnicodeData.txt),)
$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o $(OBJDIR)/libunicode.bn.o $(OBJDIR)/libunicode.bn.m32.o \
@ -253,12 +277,18 @@ run-test262-bn32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.bn.o $(QJSBN_LI
$(OBJDIR)/%.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.host.o: %.c | $(OBJDIR)
$(HOST_CC) $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.pic.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $<
$(OBJDIR)/%.bn.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $<
$(OBJDIR)/%.bn.host.o: %.c | $(OBJDIR)
$(HOST_CC) $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $<
$(OBJDIR)/%.nolto.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_NOLTO) -c -o $@ $<
@ -289,8 +319,8 @@ regexp_test: libregexp.c libunicode.c cutils.c
jscompress: jscompress.c
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c
unicode_gen: unicode_gen.c cutils.c libunicode.c unicode_gen_def.h
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ unicode_gen.c cutils.c
unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
clean:
rm -f repl.c repl-bn.c qjscalc.c out.c
@ -300,17 +330,17 @@ clean:
rm -rf run-test262-debug run-test262-32 run-test262-bn32
install: all
mkdir -p "$(prefix)/bin"
install -m755 -s qjs qjsc qjsbn qjsbnc "$(prefix)/bin"
ln -sf qjsbn "$(prefix)/bin/qjscalc"
mkdir -p "$(prefix)/lib/quickjs"
install -m755 libquickjs.a libquickjs.bn.a "$(prefix)/lib/quickjs"
mkdir -p "$(DESTDIR)$(prefix)/bin"
$(STRIP) qjs qjsbn qjsc qjsbnc
install -m755 qjs qjsbn qjsc qjsbnc "$(DESTDIR)$(prefix)/bin"
ln -sf qjsbn "$(DESTDIR)$(prefix)/bin/qjscalc"
mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
install -m644 libquickjs.a libquickjs.bn.a "$(DESTDIR)$(prefix)/lib/quickjs"
ifdef CONFIG_LTO
install -m755 libquickjs.lto.a libquickjs.bn.lto.a "$(prefix)/lib/quickjs"
install -m644 libquickjs.lto.a libquickjs.bn.lto.a "$(DESTDIR)$(prefix)/lib/quickjs"
endif
mkdir -p "$(prefix)/include/quickjs"
install -m755 quickjs.h quickjs-libc.h "$(prefix)/include/quickjs"
mkdir -p "$(DESTDIR)$(prefix)/include/quickjs"
install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(prefix)/include/quickjs"
###############################################################################
# examples
@ -319,10 +349,10 @@ endif
HELLO_SRCS=examples/hello.js
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
-fno-date
-fno-date -fno-module-loader
hello.c: qjsc $(HELLO_SRCS)
./qjsc -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
hello.c: $(QJSC) $(HELLO_SRCS)
$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
ifdef CONFIG_M32
examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
@ -337,13 +367,13 @@ HELLO_MODULE_SRCS=examples/hello_module.js
HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
-fno-date -m
examples/hello_module: qjsc libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS)
./qjsc $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS)
examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS)
$(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS)
# use of an external C module (static compilation)
c_module.c: qjsc examples/c_module.js
./qjsc -e -M examples/fib.so,fib -m -o $@ examples/c_module.js
c_module.c: $(QJSC) examples/c_module.js
$(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/c_module.js
examples/c_module: $(OBJDIR)/c_module.o $(OBJDIR)/fib.o libquickjs$(LTOEXT).a
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)


+ 3
- 3
TODO View File

@ -75,6 +75,6 @@ REPL:
Test262o: 0/11262 errors, 463 excluded
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
Test262: 2/67303 errors, 839 excluded, 1390 skipped
Test262bn: 2/69404 errors, 772 excluded, 403 skipped
test262 commit: b63cdfd4f4a00f5fdb732778244d3456725f46c9
Test262: 2/67351 errors, 839 excluded, 1370 skipped
Test262bn: 2/69452 errors, 772 excluded, 383 skipped
test262 commit: d65b9b35be091147edf31ec527a47cb95a327217

+ 1
- 1
VERSION View File

@ -1 +1 @@
2019-09-01
2019-09-18

+ 1
- 0
cutils.h View File

@ -35,6 +35,7 @@
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
#define __maybe_unused __attribute__((unused))
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)


+ 73
- 4
doc/quickjs.html View File

@ -548,6 +548,11 @@ and <samp>stdio.h</samp> and a few other utilities.
<code>std.Error</code> in case of I/O error.
</p>
</dd>
<dt><code>fdopen(fd, flags)</code></dt>
<dd><p>Open a file from a file handle (wrapper to the libc
<code>fdopen()</code>). Throws <code>std.Error</code> in case of I/O error.
</p>
</dd>
<dt><code>tmpfile()</code></dt>
<dd><p>Open a temporary file. Throws <code>std.Error</code> in case of I/O error.
</p>
@ -834,6 +839,69 @@ the signal.
<dd><p>POSIX signal numbers.
</p>
</dd>
<dt><code>kill(pid, sig)</code></dt>
<dd><p>Send the signal <code>sig</code> to the process <code>pid</code>.
</p>
</dd>
<dt><code>exec(args[, options])</code></dt>
<dd><p>Execute a process with the arguments <code>args</code>. <code>options</code> is an
object containing optional parameters:
</p>
<dl compact="compact">
<dt><code>block</code></dt>
<dd><p>Boolean (default = true). If true, wait until the process is
termined. In this case, <code>exec</code> return the exit code if positive
or the negated signal number if the process was interrupted by a
signal. If false, do not block and return the process id of the child.
</p>
</dd>
<dt><code>usePath</code></dt>
<dd><p>Boolean (default = true). If true, the file is searched in the
<code>PATH</code> environment variable.
</p>
</dd>
<dt><code>file</code></dt>
<dd><p>String (default = <code>args[0]</code>). Set the file to be executed.
</p>
</dd>
<dt><code>cwd</code></dt>
<dd><p>String. If present, set the working directory of the new process.
</p>
</dd>
<dt><code>stdin</code></dt>
<dt><code>stdout</code></dt>
<dt><code>stderr</code></dt>
<dd><p>If present, set the handle in the child for stdin, stdout or stderr.
</p>
</dd>
</dl>
</dd>
<dt><code>waitpid(pid, options)</code></dt>
<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret, status]</code>.
</p>
</dd>
<dt><code>WNOHANG</code></dt>
<dd><p>Constant for the <code>options</code> argument of <code>waitpid</code>.
</p>
</dd>
<dt><code>dup(fd)</code></dt>
<dd><p><code>dup</code> Unix system call.
</p>
</dd>
<dt><code>dup2(oldfd, newfd)</code></dt>
<dd><p><code>dup2</code> Unix system call.
</p>
</dd>
<dt><code>pipe()</code></dt>
<dd><p><code>pipe</code> Unix system call. Return two handles as <code>[read_fd,
write_fd]</code> or null in case of error.
</p>
</dd>
<dt><code>sleep(delay_ms)</code></dt>
<dd><p>Sleep during <code>delay_ms</code> milliseconds.
</p>
</dd>
<dt><code>setTimeout(func, delay)</code></dt>
<dd><p>Call the function <code>func</code> after <code>delay</code> ms. Return a handle
to the timer.
@ -907,10 +975,11 @@ occured. The actual exception object is stored in the
<p>Use <code>JS_Eval()</code> to evaluate a script or module source.
</p>
<p>If the script or module was compiled to bytecode with <code>qjsc</code>,
<code>JS_EvalBinary()</code> achieves the same result. The advantage is that
no compilation is needed so it is faster and smaller because the compiler
can be removed from the executable if no <code>eval</code> is required.
<p>If the script or module was compiled to bytecode with <code>qjsc</code>, it
can be evaluated by calling <code>js_std_eval_binary()</code>. The advantage
is that no compilation is needed so it is faster and smaller because
the compiler can be removed from the executable if no <code>eval</code> is
required.
</p>
<p>Note: the bytecode format is linked to a given QuickJS
version. Moreover, no security check is done before its


BIN
doc/quickjs.pdf View File


+ 59
- 4
doc/quickjs.texi View File

@ -402,6 +402,10 @@ Open a file (wrapper to the libc @code{fopen()}). Throws
Open a process by creating a pipe (wrapper to the libc @code{popen()}). Throws
@code{std.Error} in case of I/O error.
@item fdopen(fd, flags)
Open a file from a file handle (wrapper to the libc
@code{fdopen()}). Throws @code{std.Error} in case of I/O error.
@item tmpfile()
Open a temporary file. Throws @code{std.Error} in case of I/O error.
@ -638,6 +642,56 @@ the signal.
@item SIGTERM
POSIX signal numbers.
@item kill(pid, sig)
Send the signal @code{sig} to the process @code{pid}.
@item exec(args[, options])
Execute a process with the arguments @code{args}. @code{options} is an
object containing optional parameters:
@table @code
@item block
Boolean (default = true). If true, wait until the process is
termined. In this case, @code{exec} return the exit code if positive
or the negated signal number if the process was interrupted by a
signal. If false, do not block and return the process id of the child.
@item usePath
Boolean (default = true). If true, the file is searched in the
@code{PATH} environment variable.
@item file
String (default = @code{args[0]}). Set the file to be executed.
@item cwd
String. If present, set the working directory of the new process.
@item stdin
@item stdout
@item stderr
If present, set the handle in the child for stdin, stdout or stderr.
@end table
@item waitpid(pid, options)
@code{waitpid} Unix system call. Return the array @code{[ret, status]}.
@item WNOHANG
Constant for the @code{options} argument of @code{waitpid}.
@item dup(fd)
@code{dup} Unix system call.
@item dup2(oldfd, newfd)
@code{dup2} Unix system call.
@item pipe()
@code{pipe} Unix system call. Return two handles as @code{[read_fd,
write_fd]} or null in case of error.
@item sleep(delay_ms)
Sleep during @code{delay_ms} milliseconds.
@item setTimeout(func, delay)
Call the function @code{func} after @code{delay} ms. Return a handle
to the timer.
@ -702,10 +756,11 @@ occured. The actual exception object is stored in the
Use @code{JS_Eval()} to evaluate a script or module source.
If the script or module was compiled to bytecode with @code{qjsc},
@code{JS_EvalBinary()} achieves the same result. The advantage is that
no compilation is needed so it is faster and smaller because the compiler
can be removed from the executable if no @code{eval} is required.
If the script or module was compiled to bytecode with @code{qjsc}, it
can be evaluated by calling @code{js_std_eval_binary()}. The advantage
is that no compilation is needed so it is faster and smaller because
the compiler can be removed from the executable if no @code{eval} is
required.
Note: the bytecode format is linked to a given QuickJS
version. Moreover, no security check is done before its


+ 2
- 3
libbf.c View File

@ -41,7 +41,6 @@
#define USE_FFT_MUL
//#define inline __attribute__((always_inline))
#define unused __attribute__((unused))
#ifdef __AVX2__
#define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */
@ -613,7 +612,7 @@ int bf_round(bf_t *r, limb_t prec, bf_flags_t flags)
}
/* for debugging */
static unused void dump_limbs(const char *str, const limb_t *tab, limb_t n)
static __maybe_unused void dump_limbs(const char *str, const limb_t *tab, limb_t n)
{
limb_t i;
printf("%s: len=%" PRId_LIMB "\n", str, n);
@ -1570,7 +1569,7 @@ int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
return ret;
}
static unused inline limb_t mul_mod(limb_t a, limb_t b, limb_t m)
static __maybe_unused inline limb_t mul_mod(limb_t a, limb_t b, limb_t m)
{
dlimb_t t;
t = (dlimb_t)a * (dlimb_t)b;


+ 1
- 1
libregexp.c View File

@ -269,7 +269,7 @@ static int cr_canonicalize(CharRange *cr)
}
#ifdef DUMP_REOP
static __attribute__((unused)) void lre_dump_bytecode(const uint8_t *buf,
static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
int buf_len)
{
int pos, len, opcode, bc_len, re_flags, i;


+ 1
- 1
libunicode.c View File

@ -271,7 +271,7 @@ BOOL lre_is_case_ignorable(uint32_t c)
/* character range */
static __attribute__((unused)) void cr_dump(CharRange *cr)
static __maybe_unused void cr_dump(CharRange *cr)
{
int i;
for(i = 0; i < cr->len; i++)


+ 8
- 8
qjs.c View File

@ -41,11 +41,11 @@
#include "cutils.h"
#include "quickjs-libc.h"
extern const uint8_t repl[];
extern const uint32_t repl_size;
extern const uint8_t qjsc_repl[];
extern const uint32_t qjsc_repl_size;
#ifdef CONFIG_BIGNUM
extern const uint8_t qjscalc[];
extern const uint32_t qjscalc_size;
extern const uint8_t qjsc_qjscalc[];
extern const uint32_t qjsc_qjscalc_size;
#endif
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
@ -406,7 +406,7 @@ int main(int argc, char **argv)
if (!empty_run) {
#ifdef CONFIG_BIGNUM
if (load_jscalc) {
js_std_eval_binary(ctx, qjscalc, qjscalc_size, 0);
js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0);
}
#endif
js_std_add_helpers(ctx, argc - optind, argv + optind);
@ -419,8 +419,8 @@ int main(int argc, char **argv)
if (load_std) {
const char *str = "import * as std from 'std';\n"
"import * as os from 'os';\n"
"std.global.std = std;\n"
"std.global.os = os;\n";
"globalThis.std = std;\n"
"globalThis.os = os;\n";
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
}
@ -438,7 +438,7 @@ int main(int argc, char **argv)
goto fail;
}
if (interactive) {
js_std_eval_binary(ctx, repl, repl_size, 0);
js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0);
}
js_std_loop(ctx);
}


+ 40
- 14
qjsc.c View File

@ -53,14 +53,16 @@ typedef struct {
const char *init_name;
} FeatureEntry;
#define FE_ALL (-1)
static namelist_t cname_list;
static namelist_t cmodule_list;
static namelist_t init_module_list;
static uint64_t feature_bitmap;
static FILE *outfile;
static BOOL byte_swap;
static BOOL dynamic_export;
static const char *c_ident_prefix = "qjsc_";
#define FE_ALL (-1)
static const FeatureEntry feature_list[] = {
{ "date", "Date" },
@ -72,6 +74,8 @@ static const FeatureEntry feature_list[] = {
{ "map", "MapSet" },
{ "typedarray", "TypedArrays" },
{ "promise", "Promise" },
#define FE_MODULE_LOADER 9
{ "module-loader", NULL },
};
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
@ -122,6 +126,8 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
{
const char *p, *r;
size_t len, i;
int c;
char *q;
p = strrchr(file, '/');
if (!p)
@ -130,17 +136,22 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
p++;
r = strrchr(p, '.');
if (!r)
r = p + strlen(p);
len = r - p;
if (len > buf_size - 1)
len = buf_size - 1;
memcpy(buf, p, len);
len = strlen(p);
else
len = r - p;
pstrcpy(buf, buf_size, c_ident_prefix);
q = buf + strlen(buf);
for(i = 0; i < len; i++) {
if (buf[i] == '-')
buf[i] = '_';
c = p[i];
if (!((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z'))) {
c = '_';
}
if ((q - buf) < buf_size - 1)
*q++ = c;
}
buf[len] = '\0';
/* Note: could also try to avoid using C keywords */
*q = '\0';
}
static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
@ -228,9 +239,12 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
/* create a dummy module */
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
} else if (has_suffix(module_name, ".so")) {
fprintf(stderr, "Warning: binary module '%s' is not compiled\n", module_name);
fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name);
/* create a dummy module */
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
/* the resulting executable will export its symbols for the
dynamic library */
dynamic_export = TRUE;
} else {
size_t buf_len;
uint8_t *buf;
@ -337,6 +351,7 @@ void help(void)
"-m compile as Javascript module (default=autodetect)\n"
"-M module_name[,cname] add initialization code for an external C module\n"
"-x byte swapped output\n"
"-p prefix set the prefix of the generated C names\n"
);
#ifdef CONFIG_LTO
{
@ -428,6 +443,8 @@ static int output_executable(const char *out_filename, const char *cfilename,
*arg++ = inc_dir;
*arg++ = "-o";
*arg++ = out_filename;
if (dynamic_export)
*arg++ = "-rdynamic";
*arg++ = cfilename;
snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a",
lib_dir, bn_suffix, lto_suffix);
@ -489,7 +506,7 @@ int main(int argc, char **argv)
namelist_add(&cmodule_list, "os", "os", 0);
for(;;) {
c = getopt(argc, argv, "ho:cN:f:mxevM:");
c = getopt(argc, argv, "ho:cN:f:mxevM:p:");
if (c == -1)
break;
switch(c) {
@ -555,6 +572,9 @@ int main(int argc, char **argv)
case 'v':
verbose++;
break;
case 'p':
c_ident_prefix = optarg;
break;
default:
break;
}
@ -620,12 +640,18 @@ int main(int argc, char **argv)
if (output_type != OUTPUT_C) {
fputs(main_c_template1, fo);
fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");
/* add the module loader if necessary */
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
}
/* add the basic objects */
fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
for(i = 0; i < countof(feature_list); i++) {
if (feature_bitmap & ((uint64_t)1 << i)) {
if ((feature_bitmap & ((uint64_t)1 << i)) &&
feature_list[i].init_name) {
fprintf(fo, " JS_AddIntrinsic%s(ctx);\n",
feature_list[i].init_name);
}


+ 335
- 16
quickjs-libc.c View File

@ -44,6 +44,7 @@
#include <dlfcn.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#if defined(__APPLE__)
typedef sig_t sighandler_t;
#endif
@ -59,7 +60,7 @@ static void js_std_dbuf_init(JSContext *ctx, DynBuf *s)
}
/* TODO:
- add exec() wrapper
- add worker
- add minimal VT100 emulation for win32
- add socket calls
*/
@ -434,7 +435,7 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
JS_BOOL use_realpath, JS_BOOL is_main)
{
JSModuleDef *m;
char buf[PATH_MAX + 16], *res;
char buf[PATH_MAX + 16];
JSValue meta_obj;
JSAtom module_name_atom;
const char *module_name;
@ -449,17 +450,20 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
return -1;
if (!strchr(module_name, ':')) {
strcpy(buf, "file://");
#if !defined(_WIN32)
/* realpath() cannot be used with modules compiled with qjsc
because the corresponding module source code is not
necessarily present */
if (use_realpath) {
res = realpath(module_name, buf + strlen(buf));
char *res = realpath(module_name, buf + strlen(buf));
if (!res) {
JS_ThrowTypeError(ctx, "realpath failure");
JS_FreeCString(ctx, module_name);
return -1;
}
} else {
} else
#endif
{
pstrcat(buf, sizeof(buf), module_name);
}
} else {
@ -720,6 +724,33 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
const char *mode;
FILE *f;
int fd;
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
mode = JS_ToCString(ctx, argv[1]);
if (!mode)
goto fail;
if (mode[strspn(mode, "rwa+")] != '\0') {
js_std_throw_errno(ctx, EINVAL);
goto fail;
}
f = fdopen(fd, mode);
JS_FreeCString(ctx, mode);
if (!f)
return js_std_throw_errno(ctx, errno);
return js_new_std_file(ctx, f, TRUE, FALSE);
fail:
JS_FreeCString(ctx, mode);
return JS_EXCEPTION;
}
static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@ -1036,6 +1067,21 @@ static int http_get_status(const char *buf)
return atoi(p);
}
static int get_bool_option(JSContext *ctx, BOOL *pbool,
JSValueConst obj,
const char *option)
{
JSValue val;
val = JS_GetPropertyStr(ctx, obj, option);
if (JS_IsException(val))
return -1;
if (!JS_IsUndefined(val)) {
*pbool = JS_ToBool(ctx, val);
}
JS_FreeValue(ctx, val);
return 0;
}
static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@ -1046,7 +1092,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
char *buf;
size_t i, len;
int c, status;
JSValue val, response = JS_UNDEFINED, ret_obj;
JSValue response = JS_UNDEFINED, ret_obj;
JSValueConst options_obj;
FILE *f;
BOOL binary_flag, full_flag;
@ -1061,23 +1107,16 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val,
if (argc >= 2) {
options_obj = argv[1];
val = JS_GetPropertyStr(ctx, options_obj, "binary");
if (JS_IsException(val))
goto fail_opt;
binary_flag = JS_ToBool(ctx, val);
JS_FreeValue(ctx, val);
if (get_bool_option(ctx, &binary_flag, options_obj, "binary"))
goto fail_obj;
val = JS_GetPropertyStr(ctx, options_obj, "full");
if (JS_IsException(val)) {
fail_opt:
if (get_bool_option(ctx, &full_flag, options_obj, "full")) {
fail_obj:
JS_FreeCString(ctx, url);
return JS_EXCEPTION;
}
full_flag = JS_ToBool(ctx, val);
JS_FreeValue(ctx, val);
}
js_std_dbuf_init(ctx, &cmd_buf);
dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM);
len = strlen(url);
@ -1203,6 +1242,7 @@ static const JSCFunctionListEntry js_std_funcs[] = {
/* FILE I/O */
JS_CFUNC_DEF("open", 2, js_std_open ),
JS_CFUNC_DEF("popen", 2, js_std_popen ),
JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ),
JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ),
JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ),
JS_CFUNC_DEF("printf", 1, js_std_printf ),
@ -1971,6 +2011,8 @@ static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val,
return make_string_error(ctx, buf, err);
}
#if !defined(_WIN32)
/* return [path, errorcode] */
static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
@ -2210,6 +2252,260 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
return js_os_return(ctx, ret);
}
/* exec(args[, options]) -> exitcode */
static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSValueConst options, args = argv[0];
JSValue val, ret_val;
const char **exec_argv, *file = NULL, *str, *cwd = NULL;
uint32_t exec_argc, i;
int ret, pid, status;
BOOL block_flag = TRUE, use_path = TRUE;
static const char *std_name[3] = { "stdin", "stdout", "stderr" };
int std_fds[3];
val = JS_GetPropertyStr(ctx, args, "length");
if (JS_IsException(val))
return JS_EXCEPTION;
ret = JS_ToUint32(ctx, &exec_argc, val);
JS_FreeValue(ctx, val);
if (ret)
return JS_EXCEPTION;
/* arbitrary limit to avoid overflow */
if (exec_argc < 1 || exec_argc > 65535) {
return JS_ThrowTypeError(ctx, "invalid number of arguments");
}
exec_argv = js_mallocz(ctx, sizeof(exec_argv[0]) * (exec_argc + 1));
if (!exec_argv)
return JS_EXCEPTION;
for(i = 0; i < exec_argc; i++) {
val = JS_GetPropertyUint32(ctx, args, i);
if (JS_IsException(val))
goto exception;
str = JS_ToCString(ctx, val);
JS_FreeValue(ctx, val);
if (!str)
goto exception;
exec_argv[i] = str;
}
exec_argv[exec_argc] = NULL;
for(i = 0; i < 3; i++)
std_fds[i] = i;
/* get the options, if any */
if (argc >= 2) {
options = argv[1];
if (get_bool_option(ctx, &block_flag, options, "block"))
goto exception;
if (get_bool_option(ctx, &use_path, options, "usePath"))
goto exception;
val = JS_GetPropertyStr(ctx, options, "file");
if (JS_IsException(val))
goto exception;
if (!JS_IsUndefined(val)) {
file = JS_ToCString(ctx, val);
JS_FreeValue(ctx, val);
if (!file)
goto exception;
}
val = JS_GetPropertyStr(ctx, options, "cwd");
if (JS_IsException(val))
goto exception;
if (!JS_IsUndefined(val)) {
cwd = JS_ToCString(ctx, val);
JS_FreeValue(ctx, val);
if (!cwd)
goto exception;
}
/* stdin/stdout/stderr handles */
for(i = 0; i < 3; i++) {
val = JS_GetPropertyStr(ctx, options, std_name[i]);
if (JS_IsException(val))
goto exception;
if (!JS_IsUndefined(val)) {
int fd;
ret = JS_ToInt32(ctx, &fd, val);
JS_FreeValue(ctx, val);
if (ret)
goto exception;
std_fds[i] = fd;
}
}
}
pid = fork();
if (pid < 0) {
JS_ThrowTypeError(ctx, "fork error");
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 (!file)
file = exec_argv[0];
if (use_path)
ret = execvp(file, (char **)exec_argv);
else
ret = execv(file, (char **)exec_argv);
_exit(127);
}
/* parent */
if (block_flag) {
for(;;) {
ret = waitpid(pid, &status, 0);
if (ret == pid) {
if (WIFEXITED(status)) {
ret = WEXITSTATUS(status);
break;
} else if (WIFSIGNALED(status)) {
ret = -WTERMSIG(status);
break;
}
}
}
} else {
ret = pid;
}
ret_val = JS_NewInt32(ctx, ret);
done:
JS_FreeCString(ctx, file);
JS_FreeCString(ctx, cwd);
for(i = 0; i < exec_argc; i++)
JS_FreeCString(ctx, exec_argv[i]);
js_free(ctx, exec_argv);
return ret_val;
exception:
ret_val = JS_EXCEPTION;
goto done;
}
/* waitpid(pid, block) -> [pid, status] */
static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int pid, status, options, ret;
JSValue obj;
if (JS_ToInt32(ctx, &pid, argv[0]))
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &options, argv[1]))
return JS_EXCEPTION;
ret = waitpid(pid, &status, options);
if (ret < 0) {
ret = -errno;
status = 0;
}
obj = JS_NewArray(ctx);
if (JS_IsException(obj))
return obj;
JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, ret),
JS_PROP_C_W_E);
JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, status),
JS_PROP_C_W_E);
return obj;
}
/* pipe() -> [read_fd, write_fd] or null if error */
static JSValue js_os_pipe(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int pipe_fds[2], ret;
JSValue obj;
ret = pipe(pipe_fds);
if (ret < 0)
return JS_NULL;
obj = JS_NewArray(ctx);
if (JS_IsException(obj))
return obj;
JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, pipe_fds[0]),
JS_PROP_C_W_E);
JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, pipe_fds[1]),
JS_PROP_C_W_E);
return obj;
}
/* kill(pid, sig) */
static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int pid, sig, ret;
if (JS_ToInt32(ctx, &pid, argv[0]))
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &sig, argv[1]))
return JS_EXCEPTION;
ret = kill(pid, sig);
return js_os_return(ctx, ret);
}
/* sleep(delay_ms) */
static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int64_t delay;
struct timespec ts;
int ret;
if (JS_ToInt64(ctx, &delay, argv[0]))
return JS_EXCEPTION;
ts.tv_sec = delay / 1000;
ts.tv_nsec = (delay % 1000) * 1000000;
ret = nanosleep(&ts, NULL);
return js_os_return(ctx, ret);
}
/* dup(fd) */
static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int fd, ret;
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
ret = dup(fd);
return js_os_return(ctx, ret);
}
/* dup2(fd) */
static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int fd, fd2, ret;
if (JS_ToInt32(ctx, &fd, argv[0]))
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &fd2, argv[1]))
return JS_EXCEPTION;
ret = dup2(fd, fd2);
return js_os_return(ctx, ret);
}
#endif /* !_WIN32 */
#if defined(_WIN32)
#define OS_PLATFORM "win32"
#elif defined(__APPLE__)
@ -2253,10 +2549,24 @@ static const JSCFunctionListEntry js_os_funcs[] = {
OS_FLAG(SIGILL),
OS_FLAG(SIGSEGV),
OS_FLAG(SIGTERM),
#if !defined(_WIN32)
OS_FLAG(SIGQUIT),
OS_FLAG(SIGPIPE),
OS_FLAG(SIGALRM),
OS_FLAG(SIGUSR1),
OS_FLAG(SIGUSR2),
OS_FLAG(SIGCHLD),
OS_FLAG(SIGCONT),
OS_FLAG(SIGSTOP),
OS_FLAG(SIGTSTP),
OS_FLAG(SIGTTIN),
OS_FLAG(SIGTTOU),
#endif
JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ),
JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ),
JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ),
JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ),
#if !defined(_WIN32)
JS_CFUNC_DEF("realpath", 1, js_os_realpath ),
JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ),
JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ),
@ -2276,6 +2586,15 @@ static const JSCFunctionListEntry js_os_funcs[] = {
JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
JS_CFUNC_DEF("readdir", 1, js_os_readdir ),
JS_CFUNC_DEF("utimes", 3, js_os_utimes ),
JS_CFUNC_DEF("exec", 1, js_os_exec ),
JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),
OS_FLAG(WNOHANG),
JS_CFUNC_DEF("pipe", 0, js_os_pipe ),
JS_CFUNC_DEF("kill", 2, js_os_kill ),
JS_CFUNC_DEF("sleep", 1, js_os_sleep ),
JS_CFUNC_DEF("dup", 1, js_os_dup ),
JS_CFUNC_DEF("dup2", 2, js_os_dup2 ),
#endif
};
static int js_os_init(JSContext *ctx, JSModuleDef *m)


+ 3
- 1
quickjs-opcode.h View File

@ -39,6 +39,7 @@ FMT(i16)
FMT(label16)
FMT(npop)
FMT(npopx)
FMT(npop_u16)
FMT(loc)
FMT(arg)
FMT(var_ref)
@ -114,7 +115,8 @@ DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
DEF( return_async, 1, 1, 0, none)
DEF( throw, 1, 1, 0, none)
DEF( throw_var, 6, 0, 0, atom_u8)
DEF( eval, 3, 1, 1, u16)
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
bytecode string */
DEF( get_super_ctor, 1, 1, 1, none)


+ 186
- 100
quickjs.c View File

@ -343,6 +343,7 @@ struct JSContext {
JSValue async_iterator_proto;
JSValue array_proto_values;
JSValue throw_type_error;
JSValue eval_obj;
JSValue global_obj; /* global object */
JSValue global_var_obj; /* contains the global let/const definitions */
@ -854,18 +855,18 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
JSValueConst val, int flags, int scope_idx);
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
static __attribute__((unused)) void JS_DumpAtoms(JSRuntime *rt);
static __attribute__((unused)) void JS_DumpString(JSRuntime *rt,
static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
static __maybe_unused void JS_DumpString(JSRuntime *rt,
const JSString *p);
static __attribute__((unused)) void JS_DumpObjectHeader(JSRuntime *rt);
static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p);
static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt,
static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
JSValueConst val);
static __attribute__((unused)) void JS_DumpValue(JSContext *ctx, JSValueConst val);
static __attribute__((unused)) void JS_PrintValue(JSContext *ctx,
static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
static __maybe_unused void JS_PrintValue(JSContext *ctx,
const char *str,
JSValueConst val);
static __attribute__((unused)) void JS_DumpShapes(JSRuntime *rt);
static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic);
static void js_array_finalizer(JSRuntime *rt, JSValue val);
@ -1023,6 +1024,9 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
JSValueConst obj);
static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
JSValueConst obj);
static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len);
static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
JSValueConst array_arg);
static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
JSValue **arrpp, uint32_t *countp);
static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,
@ -1033,7 +1037,6 @@ static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,
static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,
JSValueConst this_val,
int argc, JSValueConst *argv);
static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val);
static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
static const JSClassExoticMethods js_arguments_exotic_methods;
@ -1945,6 +1948,7 @@ void JS_FreeContext(JSContext *ctx)
JS_FreeValue(ctx, ctx->global_var_obj);
JS_FreeValue(ctx, ctx->throw_type_error);
JS_FreeValue(ctx, ctx->eval_obj);
JS_FreeValue(ctx, ctx->array_proto_values);
for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
@ -2133,7 +2137,7 @@ static uint32_t hash_string(const JSString *str, uint32_t h)
return h;
}
static __attribute__((unused)) void JS_DumpString(JSRuntime *rt,
static __maybe_unused void JS_DumpString(JSRuntime *rt,
const JSString *p)
{
int i, c, sep;
@ -2165,7 +2169,7 @@ static __attribute__((unused)) void JS_DumpString(JSRuntime *rt,
putchar(sep);
}
static __attribute__((unused)) void JS_DumpAtoms(JSRuntime *rt)
static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)
{
JSAtomStruct *p;
int h, i;
@ -2918,7 +2922,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
!(p->len == 0 && p->is_wide_char != 0));
}
static __attribute__((unused)) void print_atom(JSContext *ctx, JSAtom atom)
static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
{
char buf[ATOM_GET_STR_BUF_SIZE];
const char *p;
@ -4234,7 +4238,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,
return NULL;
}
static __attribute__((unused)) void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
{
char atom_buf[ATOM_GET_STR_BUF_SIZE];
int j;
@ -4250,7 +4254,7 @@ static __attribute__((unused)) void JS_DumpShape(JSRuntime *rt, int i, JSShape *
printf("\n");
}
static __attribute__((unused)) void JS_DumpShapes(JSRuntime *rt)
static __maybe_unused void JS_DumpShapes(JSRuntime *rt)
{
int i;
JSShape *sh;
@ -5163,6 +5167,7 @@ static void mark_context(JSRuntime *rt, JSContext *ctx)
JS_MarkValue(rt, ctx->native_error_proto[i]);
JS_MarkValue(rt, ctx->throw_type_error);
JS_MarkValue(rt, ctx->eval_obj);
JS_MarkValue(rt, ctx->global_obj);
JS_MarkValue(rt, ctx->global_var_obj);
}
@ -7214,7 +7219,7 @@ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val)
}
/* return JS_ATOM_NULL in case of exception */
static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val)
JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
{
JSAtom atom;
uint32_t tag;
@ -7288,7 +7293,7 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
}
} else {
slow_path:
atom = js_value_to_atom(ctx, prop);
atom = JS_ValueToAtom(ctx, prop);
JS_FreeValue(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
@ -8121,7 +8126,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
JSAtom atom;
int ret;
slow_path:
atom = js_value_to_atom(ctx, prop);
atom = JS_ValueToAtom(ctx, prop);
JS_FreeValue(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL)) {
JS_FreeValue(ctx, val);
@ -8680,7 +8685,7 @@ int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj,
{
JSAtom atom;
int ret;
atom = js_value_to_atom(ctx, prop);
atom = JS_ValueToAtom(ctx, prop);
JS_FreeValue(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL)) {
JS_FreeValue(ctx, val);
@ -8778,7 +8783,7 @@ static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj,
!js_object_has_name(ctx, obj)) {
JSAtom prop;
JSValue name_str;
prop = js_value_to_atom(ctx, str);
prop = JS_ValueToAtom(ctx, str);
if (prop == JS_ATOM_NULL)
return -1;
name_str = js_get_function_name(ctx, prop);
@ -9020,12 +9025,18 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */
int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)
{
if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(obj);
int res = delete_property(ctx, p, prop);
if (res != FALSE)
return res;
}
JSValue obj1;
JSObject *p;
int res;
obj1 = JS_ToObject(ctx, obj);
if (JS_IsException(obj1))
return -1;
p = JS_VALUE_GET_OBJ(obj1);
res = delete_property(ctx, p, prop);
JS_FreeValue(ctx, obj1);
if (res != FALSE)
return res;
if ((flags & JS_PROP_THROW) ||
((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {
JS_ThrowTypeError(ctx, "could not delete property");
@ -9752,7 +9763,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)
return JS_ToNumberFree(ctx, JS_DupValue(ctx, val));
}
static __attribute__((unused)) JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
{
uint32_t tag;
JSValue ret;
@ -10821,14 +10832,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
return JS_EXCEPTION;
}
static __attribute__((unused)) void JS_DumpObjectHeader(JSRuntime *rt)
static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
{
printf("%14s %4s %4s %14s %10s %s\n",
"ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
}
/* for debug only: dump an object without side effect */
static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p)
static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
{
uint32_t i;
char atom_buf[ATOM_GET_STR_BUF_SIZE];
@ -10920,7 +10931,7 @@ static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p)
printf("\n");
}
static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt,
static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
JSValueConst val)
{
uint32_t tag = JS_VALUE_GET_NORM_TAG(val)<