зеркало из https://github.com/microsoft/CCF.git
Update `quickjs` from `2021-03-27` to `2024-01-14` (#6025)
This commit is contained in:
Родитель
2c739c6559
Коммит
e65b4dc843
|
@ -1,3 +1,30 @@
|
||||||
|
2024-01-13:
|
||||||
|
|
||||||
|
- top-level-await support in modules
|
||||||
|
- allow 'await' in the REPL
|
||||||
|
- added Array.prototype.{with,toReversed,toSpliced,toSorted} and
|
||||||
|
TypedArray.prototype.{with,toReversed,toSorted}
|
||||||
|
- added String.prototype.isWellFormed and String.prototype.toWellFormed
|
||||||
|
- added Object.groupBy and Map.groupBy
|
||||||
|
- added Promise.withResolvers
|
||||||
|
- class static block
|
||||||
|
- 'in' operator support for private fields
|
||||||
|
- optional chaining fixes
|
||||||
|
- added RegExp 'd' flag
|
||||||
|
- fixed RegExp zero length match logic
|
||||||
|
- fixed RegExp case insensitive flag
|
||||||
|
- added os.getpid() and os.now()
|
||||||
|
- added cosmopolitan build
|
||||||
|
- misc bug fixes
|
||||||
|
|
||||||
|
2023-12-09:
|
||||||
|
|
||||||
|
- added Object.hasOwn, {String|Array|TypedArray}.prototype.at,
|
||||||
|
{Array|TypedArray}.prototype.findLast{Index}
|
||||||
|
- BigInt support is enabled even if CONFIG_BIGNUM disabled
|
||||||
|
- updated to Unicode 15.0.0
|
||||||
|
- misc bug fixes
|
||||||
|
|
||||||
2021-03-27:
|
2021-03-27:
|
||||||
|
|
||||||
- faster Array.prototype.push and Array.prototype.unshift
|
- faster Array.prototype.push and Array.prototype.unshift
|
||||||
|
|
|
@ -33,6 +33,20 @@ CONFIG_LTO=y
|
||||||
#CONFIG_WERROR=y
|
#CONFIG_WERROR=y
|
||||||
# force 32 bit build for some utilities
|
# force 32 bit build for some utilities
|
||||||
#CONFIG_M32=y
|
#CONFIG_M32=y
|
||||||
|
# cosmopolitan build (see https://github.com/jart/cosmopolitan)
|
||||||
|
#CONFIG_COSMO=y
|
||||||
|
|
||||||
|
# installation directory
|
||||||
|
PREFIX?=/usr/local
|
||||||
|
|
||||||
|
# use the gprof profiler
|
||||||
|
#CONFIG_PROFILE=y
|
||||||
|
# use address sanitizer
|
||||||
|
#CONFIG_ASAN=y
|
||||||
|
# include the code for BigFloat/BigDecimal, math mode and faster large integers
|
||||||
|
CONFIG_BIGNUM=y
|
||||||
|
|
||||||
|
OBJDIR=.obj
|
||||||
|
|
||||||
ifdef CONFIG_DARWIN
|
ifdef CONFIG_DARWIN
|
||||||
# use clang instead of gcc
|
# use clang instead of gcc
|
||||||
|
@ -40,33 +54,22 @@ CONFIG_CLANG=y
|
||||||
CONFIG_DEFAULT_AR=y
|
CONFIG_DEFAULT_AR=y
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# installation directory
|
|
||||||
prefix=/usr/local
|
|
||||||
|
|
||||||
# use the gprof profiler
|
|
||||||
#CONFIG_PROFILE=y
|
|
||||||
# use address sanitizer
|
|
||||||
#CONFIG_ASAN=y
|
|
||||||
# include the code for BigInt/BigFloat/BigDecimal and math mode
|
|
||||||
CONFIG_BIGNUM=y
|
|
||||||
|
|
||||||
OBJDIR=.obj
|
|
||||||
|
|
||||||
ifdef CONFIG_WIN32
|
ifdef CONFIG_WIN32
|
||||||
ifdef CONFIG_M32
|
ifdef CONFIG_M32
|
||||||
CROSS_PREFIX=i686-w64-mingw32-
|
CROSS_PREFIX?=i686-w64-mingw32-
|
||||||
else
|
else
|
||||||
CROSS_PREFIX=x86_64-w64-mingw32-
|
CROSS_PREFIX?=x86_64-w64-mingw32-
|
||||||
endif
|
endif
|
||||||
EXE=.exe
|
EXE=.exe
|
||||||
else
|
else
|
||||||
CROSS_PREFIX=
|
CROSS_PREFIX?=
|
||||||
EXE=
|
EXE=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_CLANG
|
ifdef CONFIG_CLANG
|
||||||
HOST_CC=clang
|
HOST_CC=clang
|
||||||
CC=$(CROSS_PREFIX)clang
|
CC=$(CROSS_PREFIX)clang
|
||||||
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
CFLAGS += -Wextra
|
CFLAGS += -Wextra
|
||||||
CFLAGS += -Wno-sign-compare
|
CFLAGS += -Wno-sign-compare
|
||||||
CFLAGS += -Wno-missing-field-initializers
|
CFLAGS += -Wno-missing-field-initializers
|
||||||
|
@ -84,10 +87,18 @@ ifdef CONFIG_CLANG
|
||||||
AR=$(CROSS_PREFIX)ar
|
AR=$(CROSS_PREFIX)ar
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
else ifdef CONFIG_COSMO
|
||||||
|
CONFIG_LTO=
|
||||||
|
HOST_CC=gcc
|
||||||
|
CC=cosmocc
|
||||||
|
# cosmocc does not correct support -MF
|
||||||
|
CFLAGS=-g -Wall #-MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
CFLAGS += -Wno-array-bounds -Wno-format-truncation
|
||||||
|
AR=cosmoar
|
||||||
else
|
else
|
||||||
HOST_CC=gcc
|
HOST_CC=gcc
|
||||||
CC=$(CROSS_PREFIX)gcc
|
CC=$(CROSS_PREFIX)gcc
|
||||||
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
CFLAGS += -Wno-array-bounds -Wno-format-truncation
|
CFLAGS += -Wno-array-bounds -Wno-format-truncation
|
||||||
ifdef CONFIG_LTO
|
ifdef CONFIG_LTO
|
||||||
AR=$(CROSS_PREFIX)gcc-ar
|
AR=$(CROSS_PREFIX)gcc-ar
|
||||||
|
@ -96,6 +107,7 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
STRIP=$(CROSS_PREFIX)strip
|
STRIP=$(CROSS_PREFIX)strip
|
||||||
|
CFLAGS+=-fwrapv # ensure that signed overflows behave as expected
|
||||||
ifdef CONFIG_WERROR
|
ifdef CONFIG_WERROR
|
||||||
CFLAGS+=-Werror
|
CFLAGS+=-Werror
|
||||||
endif
|
endif
|
||||||
|
@ -112,7 +124,11 @@ CFLAGS_DEBUG=$(CFLAGS) -O0
|
||||||
CFLAGS_SMALL=$(CFLAGS) -Os
|
CFLAGS_SMALL=$(CFLAGS) -Os
|
||||||
CFLAGS_OPT=$(CFLAGS) -O2
|
CFLAGS_OPT=$(CFLAGS) -O2
|
||||||
CFLAGS_NOLTO:=$(CFLAGS_OPT)
|
CFLAGS_NOLTO:=$(CFLAGS_OPT)
|
||||||
LDFLAGS=-g
|
ifdef CONFIG_COSMO
|
||||||
|
LDFLAGS+=-s # better to strip by default
|
||||||
|
else
|
||||||
|
LDFLAGS+=-g
|
||||||
|
endif
|
||||||
ifdef CONFIG_LTO
|
ifdef CONFIG_LTO
|
||||||
CFLAGS_SMALL+=-flto
|
CFLAGS_SMALL+=-flto
|
||||||
CFLAGS_OPT+=-flto
|
CFLAGS_OPT+=-flto
|
||||||
|
@ -132,6 +148,12 @@ else
|
||||||
LDEXPORT=-rdynamic
|
LDEXPORT=-rdynamic
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifndef CONFIG_COSMO
|
||||||
|
ifndef CONFIG_DARWIN
|
||||||
|
CONFIG_SHARED_LIBS=y # building shared libraries is supported
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
PROGS=qjs$(EXE) qjsc$(EXE) run-test262
|
PROGS=qjs$(EXE) qjsc$(EXE) run-test262
|
||||||
ifneq ($(CROSS_PREFIX),)
|
ifneq ($(CROSS_PREFIX),)
|
||||||
QJSC_CC=gcc
|
QJSC_CC=gcc
|
||||||
|
@ -154,23 +176,21 @@ endif
|
||||||
|
|
||||||
# examples
|
# examples
|
||||||
ifeq ($(CROSS_PREFIX),)
|
ifeq ($(CROSS_PREFIX),)
|
||||||
ifdef CONFIG_ASAN
|
PROGS+=examples/hello
|
||||||
PROGS+=
|
ifndef CONFIG_ASAN
|
||||||
else
|
PROGS+=examples/hello_module
|
||||||
PROGS+=examples/hello examples/hello_module examples/test_fib
|
|
||||||
ifndef CONFIG_DARWIN
|
|
||||||
PROGS+=examples/fib.so examples/point.so
|
|
||||||
endif
|
endif
|
||||||
|
ifdef CONFIG_SHARED_LIBS
|
||||||
|
PROGS+=examples/test_fib examples/fib.so examples/point.so
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
|
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
|
||||||
|
|
||||||
QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
|
QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
|
||||||
|
|
||||||
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
|
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
|
||||||
ifdef CONFIG_BIGNUM
|
ifdef CONFIG_BIGNUM
|
||||||
QJS_LIB_OBJS+=$(OBJDIR)/libbf.o
|
|
||||||
QJS_OBJS+=$(OBJDIR)/qjscalc.o
|
QJS_OBJS+=$(OBJDIR)/qjscalc.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -201,11 +221,11 @@ $(QJSC): $(OBJDIR)/qjsc.host.o \
|
||||||
|
|
||||||
endif #CROSS_PREFIX
|
endif #CROSS_PREFIX
|
||||||
|
|
||||||
QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(prefix)\"
|
QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(PREFIX)\"
|
||||||
ifdef CONFIG_LTO
|
ifdef CONFIG_LTO
|
||||||
QJSC_DEFINES+=-DCONFIG_LTO
|
QJSC_DEFINES+=-DCONFIG_LTO
|
||||||
endif
|
endif
|
||||||
QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(prefix)\"
|
QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(PREFIX)\"
|
||||||
|
|
||||||
$(OBJDIR)/qjsc.o: CFLAGS+=$(QJSC_DEFINES)
|
$(OBJDIR)/qjsc.o: CFLAGS+=$(QJSC_DEFINES)
|
||||||
$(OBJDIR)/qjsc.host.o: CFLAGS+=$(QJSC_HOST_DEFINES)
|
$(OBJDIR)/qjsc.host.o: CFLAGS+=$(QJSC_HOST_DEFINES)
|
||||||
|
@ -298,17 +318,17 @@ clean:
|
||||||
rm -rf run-test262-debug run-test262-32
|
rm -rf run-test262-debug run-test262-32
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
mkdir -p "$(DESTDIR)$(prefix)/bin"
|
mkdir -p "$(DESTDIR)$(PREFIX)/bin"
|
||||||
$(STRIP) qjs qjsc
|
$(STRIP) qjs qjsc
|
||||||
install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
|
install -m755 qjs qjsc "$(DESTDIR)$(PREFIX)/bin"
|
||||||
ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
|
ln -sf qjs "$(DESTDIR)$(PREFIX)/bin/qjscalc"
|
||||||
mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
|
mkdir -p "$(DESTDIR)$(PREFIX)/lib/quickjs"
|
||||||
install -m644 libquickjs.a "$(DESTDIR)$(prefix)/lib/quickjs"
|
install -m644 libquickjs.a "$(DESTDIR)$(PREFIX)/lib/quickjs"
|
||||||
ifdef CONFIG_LTO
|
ifdef CONFIG_LTO
|
||||||
install -m644 libquickjs.lto.a "$(DESTDIR)$(prefix)/lib/quickjs"
|
install -m644 libquickjs.lto.a "$(DESTDIR)$(PREFIX)/lib/quickjs"
|
||||||
endif
|
endif
|
||||||
mkdir -p "$(DESTDIR)$(prefix)/include/quickjs"
|
mkdir -p "$(DESTDIR)$(PREFIX)/include/quickjs"
|
||||||
install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(prefix)/include/quickjs"
|
install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(PREFIX)/include/quickjs"
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# examples
|
# examples
|
||||||
|
@ -317,10 +337,7 @@ endif
|
||||||
HELLO_SRCS=examples/hello.js
|
HELLO_SRCS=examples/hello.js
|
||||||
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
|
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
|
||||||
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
|
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
|
||||||
-fno-date -fno-module-loader
|
-fno-date -fno-module-loader -fno-bigint
|
||||||
ifdef CONFIG_BIGNUM
|
|
||||||
HELLO_OPTS+=-fno-bigint
|
|
||||||
endif
|
|
||||||
|
|
||||||
hello.c: $(QJSC) $(HELLO_SRCS)
|
hello.c: $(QJSC) $(HELLO_SRCS)
|
||||||
$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
|
$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
|
||||||
|
@ -377,7 +394,7 @@ doc/%.html: doc/%.html.pre
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# tests
|
# tests
|
||||||
|
|
||||||
ifndef CONFIG_DARWIN
|
ifdef CONFIG_SHARED_LIBS
|
||||||
test: tests/bjson.so examples/point.so
|
test: tests/bjson.so examples/point.so
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_M32
|
ifdef CONFIG_M32
|
||||||
|
@ -391,7 +408,7 @@ test: qjs
|
||||||
./qjs tests/test_loop.js
|
./qjs tests/test_loop.js
|
||||||
./qjs tests/test_std.js
|
./qjs tests/test_std.js
|
||||||
./qjs tests/test_worker.js
|
./qjs tests/test_worker.js
|
||||||
ifndef CONFIG_DARWIN
|
ifdef CONFIG_SHARED_LIBS
|
||||||
ifdef CONFIG_BIGNUM
|
ifdef CONFIG_BIGNUM
|
||||||
./qjs --bignum tests/test_bjson.js
|
./qjs --bignum tests/test_bjson.js
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
Bugs:
|
|
||||||
- modules: better error handling with cyclic module references
|
|
||||||
|
|
||||||
Misc ideas:
|
Misc ideas:
|
||||||
- use custom printf to avoid compatibility issues with floating point numbers
|
- use custom printf to avoid compatibility issues with floating point numbers
|
||||||
- consistent naming for preprocessor defines
|
- consistent naming for preprocessor defines
|
||||||
|
@ -66,5 +63,5 @@ Optimization ideas:
|
||||||
Test262o: 0/11262 errors, 463 excluded
|
Test262o: 0/11262 errors, 463 excluded
|
||||||
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||||
|
|
||||||
Result: 35/75280 errors, 909 excluded, 585 skipped
|
Result: 10/76947 errors, 1497 excluded, 8117 skipped
|
||||||
Test262 commit: 31126581e7290f9233c29cefd93f66c6ac78f1c9
|
Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
2021-03-27
|
2024-01-13
|
||||||
|
|
|
@ -49,6 +49,9 @@
|
||||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
|
||||||
|
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
|
||||||
|
|
||||||
typedef int BOOL;
|
typedef int BOOL;
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
|
|
|
@ -72,7 +72,7 @@ ul.no-bullet {list-style: none}
|
||||||
<ul class="no-bullet">
|
<ul class="no-bullet">
|
||||||
<li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
|
<li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
|
||||||
<ul class="no-bullet">
|
<ul class="no-bullet">
|
||||||
<li><a name="toc-ES2020-support" href="#ES2020-support">3.1.1 ES2020 support</a></li>
|
<li><a name="toc-ES2023-support" href="#ES2023-support">3.1.1 ES2023 support</a></li>
|
||||||
<li><a name="toc-ECMA402" href="#ECMA402">3.1.2 ECMA402</a></li>
|
<li><a name="toc-ECMA402" href="#ECMA402">3.1.2 ECMA402</a></li>
|
||||||
<li><a name="toc-Extensions" href="#Extensions">3.1.3 Extensions</a></li>
|
<li><a name="toc-Extensions" href="#Extensions">3.1.3 Extensions</a></li>
|
||||||
<li><a name="toc-Mathematical-extensions" href="#Mathematical-extensions">3.1.4 Mathematical extensions</a></li>
|
<li><a name="toc-Mathematical-extensions" href="#Mathematical-extensions">3.1.4 Mathematical extensions</a></li>
|
||||||
|
@ -128,8 +128,8 @@ ul.no-bullet {list-style: none}
|
||||||
<a name="Introduction"></a>
|
<a name="Introduction"></a>
|
||||||
<h2 class="chapter">1 Introduction</h2>
|
<h2 class="chapter">1 Introduction</h2>
|
||||||
|
|
||||||
<p>QuickJS is a small and embeddable Javascript engine. It supports the
|
<p>QuickJS is a small and embeddable Javascript engine. It supports most of the
|
||||||
ES2020 specification
|
ES2023 specification
|
||||||
<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
|
<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
|
||||||
including modules, asynchronous generators, proxies and BigInt.
|
including modules, asynchronous generators, proxies and BigInt.
|
||||||
</p>
|
</p>
|
||||||
|
@ -143,14 +143,14 @@ and operator overloading.
|
||||||
<ul>
|
<ul>
|
||||||
<li> Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple “hello world” program.
|
<li> Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple “hello world” program.
|
||||||
|
|
||||||
</li><li> Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
</li><li> Fast interpreter with very low startup time: runs the 77000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in less than 2 minutes on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
||||||
|
|
||||||
</li><li> Almost complete ES2020 support including modules, asynchronous
|
</li><li> Almost complete ES2023 support including modules, asynchronous
|
||||||
generators and full Annex B support (legacy web compatibility). Many
|
generators and full Annex B support (legacy web compatibility). Some
|
||||||
features from the upcoming ES2021 specification
|
features from the upcoming ES2024 specification
|
||||||
<a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
|
<a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
|
||||||
|
|
||||||
</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
|
</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2023 features.
|
||||||
|
|
||||||
</li><li> Compile Javascript sources to executables with no external dependency.
|
</li><li> Compile Javascript sources to executables with no external dependency.
|
||||||
|
|
||||||
|
@ -180,6 +180,11 @@ options then run <code>make</code>.
|
||||||
<p>You can type <code>make install</code> as root if you wish to install the binaries and support files to
|
<p>You can type <code>make install</code> as root if you wish to install the binaries and support files to
|
||||||
<code>/usr/local</code> (this is not necessary to use QuickJS).
|
<code>/usr/local</code> (this is not necessary to use QuickJS).
|
||||||
</p>
|
</p>
|
||||||
|
<p>Note: On some OSes atomic operations are not available or need a
|
||||||
|
specific library. If you get related errors, you should either add
|
||||||
|
<code>-latomics</code> in the Makefile <code>LIBS</code> variable or disable
|
||||||
|
<code>CONFIG_ATOMICS</code> in <samp>quickjs.c</samp>.
|
||||||
|
</p>
|
||||||
<a name="Quick-start"></a>
|
<a name="Quick-start"></a>
|
||||||
<h3 class="section">2.2 Quick start</h3>
|
<h3 class="section">2.2 Quick start</h3>
|
||||||
|
|
||||||
|
@ -400,10 +405,10 @@ about 100 seconds).
|
||||||
<a name="Language-support"></a>
|
<a name="Language-support"></a>
|
||||||
<h3 class="section">3.1 Language support</h3>
|
<h3 class="section">3.1 Language support</h3>
|
||||||
|
|
||||||
<a name="ES2020-support"></a>
|
<a name="ES2023-support"></a>
|
||||||
<h4 class="subsection">3.1.1 ES2020 support</h4>
|
<h4 class="subsection">3.1.1 ES2023 support</h4>
|
||||||
|
|
||||||
<p>The ES2020 specification is almost fully supported including the Annex
|
<p>The ES2023 specification is almost fully supported including the Annex
|
||||||
B (legacy web compatibility) and the Unicode related features.
|
B (legacy web compatibility) and the Unicode related features.
|
||||||
</p>
|
</p>
|
||||||
<p>The following features are not supported yet:
|
<p>The following features are not supported yet:
|
||||||
|
@ -411,6 +416,10 @@ B (legacy web compatibility) and the Unicode related features.
|
||||||
<ul>
|
<ul>
|
||||||
<li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
|
<li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
|
||||||
|
|
||||||
|
</li><li> WeakRef and FinalizationRegistry objects
|
||||||
|
|
||||||
|
</li><li> Symbols as WeakMap keys
|
||||||
|
|
||||||
</li></ul>
|
</li></ul>
|
||||||
|
|
||||||
<a name="ECMA402"></a>
|
<a name="ECMA402"></a>
|
||||||
|
@ -511,6 +520,10 @@ optional properties:
|
||||||
<dd><p>Boolean (default = false). If true, error backtraces do not list the
|
<dd><p>Boolean (default = false). If true, error backtraces do not list the
|
||||||
stack frames below the evalScript.
|
stack frames below the evalScript.
|
||||||
</p></dd>
|
</p></dd>
|
||||||
|
<dt><code>async</code></dt>
|
||||||
|
<dd><p>Boolean (default = false). If true, <code>await</code> is accepted in the
|
||||||
|
script and a promise is returned.
|
||||||
|
</p></dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -611,6 +624,19 @@ useful in case of specific memory constraints or for testing.
|
||||||
<code>undefined</code> if it is not defined.
|
<code>undefined</code> if it is not defined.
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>setenv(name, value)</code></dt>
|
||||||
|
<dd><p>Set the value of the environment variable <code>name</code> to the string
|
||||||
|
<code>value</code>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
<dt><code>unsetenv(name)</code></dt>
|
||||||
|
<dd><p>Delete the environment variable <code>name</code>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
<dt><code>getenviron()</code></dt>
|
||||||
|
<dd><p>Return an object containing the environment variables as key-value pairs.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
<dt><code>urlGet(url, options = undefined)</code></dt>
|
<dt><code>urlGet(url, options = undefined)</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p>Download <code>url</code> using the <samp>curl</samp> command line
|
<p>Download <code>url</code> using the <samp>curl</samp> command line
|
||||||
|
@ -707,7 +733,7 @@ position <code>position</code> (wrapper to the libc <code>fread</code>).
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>write(buffer, position, length)</code></dt>
|
<dt><code>write(buffer, position, length)</code></dt>
|
||||||
<dd><p>Write <code>length</code> bytes to the file from the ArrayBuffer <code>buffer</code> at byte
|
<dd><p>Write <code>length</code> bytes to the file from the ArrayBuffer <code>buffer</code> at byte
|
||||||
position <code>position</code> (wrapper to the libc <code>fread</code>).
|
position <code>position</code> (wrapper to the libc <code>fwrite</code>).
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>getline()</code></dt>
|
<dt><code>getline()</code></dt>
|
||||||
|
@ -955,6 +981,10 @@ object containing optional parameters:
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt><code>getpid()</code></dt>
|
||||||
|
<dd><p>Return the current process ID.
|
||||||
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>waitpid(pid, options)</code></dt>
|
<dt><code>waitpid(pid, options)</code></dt>
|
||||||
<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret,
|
<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret,
|
||||||
|
@ -982,6 +1012,19 @@ write_fd]</code> or null in case of error.
|
||||||
<dd><p>Sleep during <code>delay_ms</code> milliseconds.
|
<dd><p>Sleep during <code>delay_ms</code> milliseconds.
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>sleepAsync(delay_ms)</code></dt>
|
||||||
|
<dd><p>Asynchronouse sleep during <code>delay_ms</code> milliseconds. Returns a promise. Example:
|
||||||
|
</p><div class="example">
|
||||||
|
<pre class="example">await os.sleepAsync(500);
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt><code>now()</code></dt>
|
||||||
|
<dd><p>Return a timestamp in milliseconds with more precision than
|
||||||
|
<code>Date.now()</code>. The time origin is unspecified and is normally not
|
||||||
|
impacted by system clock adjustments.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
<dt><code>setTimeout(func, delay)</code></dt>
|
<dt><code>setTimeout(func, delay)</code></dt>
|
||||||
<dd><p>Call the function <code>func</code> after <code>delay</code> ms. Return a handle
|
<dd><p>Call the function <code>func</code> after <code>delay</code> ms. Return a handle
|
||||||
to the timer.
|
to the timer.
|
||||||
|
@ -1123,10 +1166,11 @@ set the C opaque point with
|
||||||
<code>JS_GetOpaque()</code>/<code>JS_SetOpaque()</code>.
|
<code>JS_GetOpaque()</code>/<code>JS_SetOpaque()</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>When defining a new JS class, it is possible to declare a finalizer
|
<p>When defining a new JS class, it is possible to declare a finalizer
|
||||||
which is called when the object is destroyed. A <code>gc_mark</code> method
|
which is called when the object is destroyed. The finalizer should be
|
||||||
can be provided so that the cycle removal algorithm can find the other
|
used to release C resources. It is invalid to execute JS code from
|
||||||
objects referenced by this object. Other methods are available to
|
it. A <code>gc_mark</code> method can be provided so that the cycle removal
|
||||||
define exotic object behaviors.
|
algorithm can find the other objects referenced by this object. Other
|
||||||
|
methods are available to define exotic object behaviors.
|
||||||
</p>
|
</p>
|
||||||
<p>The Class ID are globally allocated (i.e. for all runtimes). The
|
<p>The Class ID are globally allocated (i.e. for all runtimes). The
|
||||||
JSClass are allocated per <code>JSRuntime</code>. <code>JS_SetClassProto()</code>
|
JSClass are allocated per <code>JSRuntime</code>. <code>JS_SetClassProto()</code>
|
||||||
|
@ -1296,7 +1340,7 @@ stack holds the Javascript parameters and local variables.
|
||||||
<h3 class="section">4.4 RegExp</h3>
|
<h3 class="section">4.4 RegExp</h3>
|
||||||
|
|
||||||
<p>A specific regular expression engine was developed. It is both small
|
<p>A specific regular expression engine was developed. It is both small
|
||||||
and efficient and supports all the ES2020 features including the
|
and efficient and supports all the ES2023 features including the
|
||||||
Unicode properties. As the Javascript compiler, it directly generates
|
Unicode properties. As the Javascript compiler, it directly generates
|
||||||
bytecode without a parse tree.
|
bytecode without a parse tree.
|
||||||
</p>
|
</p>
|
||||||
|
@ -1304,9 +1348,6 @@ bytecode without a parse tree.
|
||||||
recursion on the system stack. Simple quantifiers are specifically
|
recursion on the system stack. Simple quantifiers are specifically
|
||||||
optimized to avoid recursions.
|
optimized to avoid recursions.
|
||||||
</p>
|
</p>
|
||||||
<p>Infinite recursions coming from quantifiers with empty terms are
|
|
||||||
avoided.
|
|
||||||
</p>
|
|
||||||
<p>The full regexp library weights about 15 KiB (x86 code), excluding the
|
<p>The full regexp library weights about 15 KiB (x86 code), excluding the
|
||||||
Unicode library.
|
Unicode library.
|
||||||
</p>
|
</p>
|
||||||
|
@ -1345,11 +1386,11 @@ Bellard and Charlie Gordon.
|
||||||
<h4 class="footnotes-heading">Footnotes</h4>
|
<h4 class="footnotes-heading">Footnotes</h4>
|
||||||
|
|
||||||
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
|
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
|
||||||
<p><a href="https://tc39.es/ecma262/">https://tc39.es/ecma262/</a></p>
|
<p><a href="https://tc39.es/ecma262/2023">https://tc39.es/ecma262/2023</a></p>
|
||||||
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
|
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
|
||||||
<p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
|
<p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
|
||||||
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
|
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
|
||||||
<p><a href="https://tc39.github.io/ecma262/">https://tc39.github.io/ecma262/</a></p>
|
<p><a href="https://tc39.es/ecma262/">https://tc39.es/ecma262/</a></p>
|
||||||
<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
|
<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
|
||||||
<p>The old
|
<p>The old
|
||||||
ES5.1 tests can be extracted with <code>git clone --single-branch
|
ES5.1 tests can be extracted with <code>git clone --single-branch
|
||||||
|
|
Двоичный файл не отображается.
|
@ -19,9 +19,9 @@
|
||||||
|
|
||||||
@chapter Introduction
|
@chapter Introduction
|
||||||
|
|
||||||
QuickJS is a small and embeddable Javascript engine. It supports the
|
QuickJS is a small and embeddable Javascript engine. It supports most of the
|
||||||
ES2020 specification
|
ES2023 specification
|
||||||
@footnote{@url{https://tc39.es/ecma262/}}
|
@footnote{@url{https://tc39.es/ecma262/2023 }}
|
||||||
including modules, asynchronous generators, proxies and BigInt.
|
including modules, asynchronous generators, proxies and BigInt.
|
||||||
|
|
||||||
It supports mathematical extensions such as big decimal float float
|
It supports mathematical extensions such as big decimal float float
|
||||||
|
@ -34,14 +34,14 @@ and operator overloading.
|
||||||
|
|
||||||
@item Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple ``hello world'' program.
|
@item Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple ``hello world'' program.
|
||||||
|
|
||||||
@item Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
@item Fast interpreter with very low startup time: runs the 77000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in less than 2 minutes on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
|
||||||
|
|
||||||
@item Almost complete ES2020 support including modules, asynchronous
|
@item Almost complete ES2023 support including modules, asynchronous
|
||||||
generators and full Annex B support (legacy web compatibility). Many
|
generators and full Annex B support (legacy web compatibility). Some
|
||||||
features from the upcoming ES2021 specification
|
features from the upcoming ES2024 specification
|
||||||
@footnote{@url{https://tc39.github.io/ecma262/}} are also supported.
|
@footnote{@url{https://tc39.es/ecma262/}} are also supported.
|
||||||
|
|
||||||
@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
|
@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2023 features.
|
||||||
|
|
||||||
@item Compile Javascript sources to executables with no external dependency.
|
@item Compile Javascript sources to executables with no external dependency.
|
||||||
|
|
||||||
|
@ -69,6 +69,11 @@ options then run @code{make}.
|
||||||
You can type @code{make install} as root if you wish to install the binaries and support files to
|
You can type @code{make install} as root if you wish to install the binaries and support files to
|
||||||
@code{/usr/local} (this is not necessary to use QuickJS).
|
@code{/usr/local} (this is not necessary to use QuickJS).
|
||||||
|
|
||||||
|
Note: On some OSes atomic operations are not available or need a
|
||||||
|
specific library. If you get related errors, you should either add
|
||||||
|
@code{-latomics} in the Makefile @code{LIBS} variable or disable
|
||||||
|
@code{CONFIG_ATOMICS} in @file{quickjs.c}.
|
||||||
|
|
||||||
@section Quick start
|
@section Quick start
|
||||||
|
|
||||||
@code{qjs} is the command line interpreter (Read-Eval-Print Loop). You can pass
|
@code{qjs} is the command line interpreter (Read-Eval-Print Loop). You can pass
|
||||||
|
@ -265,9 +270,9 @@ about 100 seconds).
|
||||||
|
|
||||||
@section Language support
|
@section Language support
|
||||||
|
|
||||||
@subsection ES2020 support
|
@subsection ES2023 support
|
||||||
|
|
||||||
The ES2020 specification is almost fully supported including the Annex
|
The ES2023 specification is almost fully supported including the Annex
|
||||||
B (legacy web compatibility) and the Unicode related features.
|
B (legacy web compatibility) and the Unicode related features.
|
||||||
|
|
||||||
The following features are not supported yet:
|
The following features are not supported yet:
|
||||||
|
@ -276,6 +281,10 @@ The following features are not supported yet:
|
||||||
|
|
||||||
@item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.}
|
@item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.}
|
||||||
|
|
||||||
|
@item WeakRef and FinalizationRegistry objects
|
||||||
|
|
||||||
|
@item Symbols as WeakMap keys
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@subsection ECMA402
|
@subsection ECMA402
|
||||||
|
@ -368,6 +377,9 @@ optional properties:
|
||||||
@item backtrace_barrier
|
@item backtrace_barrier
|
||||||
Boolean (default = false). If true, error backtraces do not list the
|
Boolean (default = false). If true, error backtraces do not list the
|
||||||
stack frames below the evalScript.
|
stack frames below the evalScript.
|
||||||
|
@item async
|
||||||
|
Boolean (default = false). If true, @code{await} is accepted in the
|
||||||
|
script and a promise is returned.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item loadScript(filename)
|
@item loadScript(filename)
|
||||||
|
@ -749,6 +761,9 @@ object containing optional parameters:
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@item getpid()
|
||||||
|
Return the current process ID.
|
||||||
|
|
||||||
@item waitpid(pid, options)
|
@item waitpid(pid, options)
|
||||||
@code{waitpid} Unix system call. Return the array @code{[ret,
|
@code{waitpid} Unix system call. Return the array @code{[ret,
|
||||||
status]}. @code{ret} contains @code{-errno} in case of error.
|
status]}. @code{ret} contains @code{-errno} in case of error.
|
||||||
|
@ -769,6 +784,17 @@ write_fd]} or null in case of error.
|
||||||
@item sleep(delay_ms)
|
@item sleep(delay_ms)
|
||||||
Sleep during @code{delay_ms} milliseconds.
|
Sleep during @code{delay_ms} milliseconds.
|
||||||
|
|
||||||
|
@item sleepAsync(delay_ms)
|
||||||
|
Asynchronouse sleep during @code{delay_ms} milliseconds. Returns a promise. Example:
|
||||||
|
@example
|
||||||
|
await os.sleepAsync(500);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@item now()
|
||||||
|
Return a timestamp in milliseconds with more precision than
|
||||||
|
@code{Date.now()}. The time origin is unspecified and is normally not
|
||||||
|
impacted by system clock adjustments.
|
||||||
|
|
||||||
@item setTimeout(func, delay)
|
@item setTimeout(func, delay)
|
||||||
Call the function @code{func} after @code{delay} ms. Return a handle
|
Call the function @code{func} after @code{delay} ms. Return a handle
|
||||||
to the timer.
|
to the timer.
|
||||||
|
@ -1053,7 +1079,7 @@ stack holds the Javascript parameters and local variables.
|
||||||
@section RegExp
|
@section RegExp
|
||||||
|
|
||||||
A specific regular expression engine was developed. It is both small
|
A specific regular expression engine was developed. It is both small
|
||||||
and efficient and supports all the ES2020 features including the
|
and efficient and supports all the ES2023 features including the
|
||||||
Unicode properties. As the Javascript compiler, it directly generates
|
Unicode properties. As the Javascript compiler, it directly generates
|
||||||
bytecode without a parse tree.
|
bytecode without a parse tree.
|
||||||
|
|
||||||
|
@ -1061,9 +1087,6 @@ Backtracking with an explicit stack is used so that there is no
|
||||||
recursion on the system stack. Simple quantifiers are specifically
|
recursion on the system stack. Simple quantifiers are specifically
|
||||||
optimized to avoid recursions.
|
optimized to avoid recursions.
|
||||||
|
|
||||||
Infinite recursions coming from quantifiers with empty terms are
|
|
||||||
avoided.
|
|
||||||
|
|
||||||
The full regexp library weights about 15 KiB (x86 code), excluding the
|
The full regexp library weights about 15 KiB (x86 code), excluding the
|
||||||
Unicode library.
|
Unicode library.
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,12 @@
|
||||||
|
|
||||||
/* enable it to check the multiplication result */
|
/* enable it to check the multiplication result */
|
||||||
//#define USE_MUL_CHECK
|
//#define USE_MUL_CHECK
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
/* enable it to use FFT/NTT multiplication */
|
/* enable it to use FFT/NTT multiplication */
|
||||||
#define USE_FFT_MUL
|
#define USE_FFT_MUL
|
||||||
/* enable decimal floating point support */
|
/* enable decimal floating point support */
|
||||||
#define USE_BF_DEC
|
#define USE_BF_DEC
|
||||||
|
#endif
|
||||||
|
|
||||||
//#define inline __attribute__((always_inline))
|
//#define inline __attribute__((always_inline))
|
||||||
|
|
||||||
|
@ -164,6 +166,21 @@ static inline slimb_t sat_add(slimb_t a, slimb_t b)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline __maybe_unused limb_t shrd(limb_t low, limb_t high, long shift)
|
||||||
|
{
|
||||||
|
if (shift != 0)
|
||||||
|
low = (low >> shift) | (high << (LIMB_BITS - shift));
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __maybe_unused limb_t shld(limb_t a1, limb_t a0, long shift)
|
||||||
|
{
|
||||||
|
if (shift != 0)
|
||||||
|
return (a1 << shift) | (a0 >> (LIMB_BITS - shift));
|
||||||
|
else
|
||||||
|
return a1;
|
||||||
|
}
|
||||||
|
|
||||||
#define malloc(s) malloc_is_forbidden(s)
|
#define malloc(s) malloc_is_forbidden(s)
|
||||||
#define free(p) free_is_forbidden(p)
|
#define free(p) free_is_forbidden(p)
|
||||||
#define realloc(p, s) realloc_is_forbidden(p, s)
|
#define realloc(p, s) realloc_is_forbidden(p, s)
|
||||||
|
@ -236,7 +253,7 @@ int bf_set_ui(bf_t *r, uint64_t a)
|
||||||
a1 = a >> 32;
|
a1 = a >> 32;
|
||||||
shift = clz(a1);
|
shift = clz(a1);
|
||||||
r->tab[0] = a0 << shift;
|
r->tab[0] = a0 << shift;
|
||||||
r->tab[1] = (a1 << shift) | (a0 >> (LIMB_BITS - shift));
|
r->tab[1] = shld(a1, a0, shift);
|
||||||
r->expn = 2 * LIMB_BITS - shift;
|
r->expn = 2 * LIMB_BITS - shift;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1585,7 +1602,9 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||||
r = &tmp;
|
r = &tmp;
|
||||||
}
|
}
|
||||||
if (bf_resize(r, a_len + b_len)) {
|
if (bf_resize(r, a_len + b_len)) {
|
||||||
|
#ifdef USE_FFT_MUL
|
||||||
fail:
|
fail:
|
||||||
|
#endif
|
||||||
bf_set_nan(r);
|
bf_set_nan(r);
|
||||||
ret = BF_ST_MEM_ERROR;
|
ret = BF_ST_MEM_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -2282,11 +2301,14 @@ static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b,
|
||||||
bf_t a;
|
bf_t a;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef USE_BF_DEC
|
||||||
if (a1 == 10 && b <= LIMB_DIGITS) {
|
if (a1 == 10 && b <= LIMB_DIGITS) {
|
||||||
/* use precomputed powers. We do not round at this point
|
/* use precomputed powers. We do not round at this point
|
||||||
because we expect the caller to do it */
|
because we expect the caller to do it */
|
||||||
ret = bf_set_ui(r, mp_pow_dec[b]);
|
ret = bf_set_ui(r, mp_pow_dec[b]);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
bf_init(r->ctx, &a);
|
bf_init(r->ctx, &a);
|
||||||
ret = bf_set_ui(&a, a1);
|
ret = bf_set_ui(&a, a1);
|
||||||
ret |= bf_pow_ui(r, &a, b, prec, flags);
|
ret |= bf_pow_ui(r, &a, b, prec, flags);
|
||||||
|
@ -5392,21 +5414,6 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
|
||||||
|
|
||||||
#endif /* LIMB_BITS != 64 */
|
#endif /* LIMB_BITS != 64 */
|
||||||
|
|
||||||
static inline __maybe_unused limb_t shrd(limb_t low, limb_t high, long shift)
|
|
||||||
{
|
|
||||||
if (shift != 0)
|
|
||||||
low = (low >> shift) | (high << (LIMB_BITS - shift));
|
|
||||||
return low;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __maybe_unused limb_t shld(limb_t a1, limb_t a0, long shift)
|
|
||||||
{
|
|
||||||
if (shift != 0)
|
|
||||||
return (a1 << shift) | (a0 >> (LIMB_BITS - shift));
|
|
||||||
else
|
|
||||||
return a1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LIMB_DIGITS == 19
|
#if LIMB_DIGITS == 19
|
||||||
|
|
||||||
/* WARNING: hardcoded for b = 1e19. It is assumed that:
|
/* WARNING: hardcoded for b = 1e19. It is assumed that:
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if INTPTR_MAX >= INT64_MAX
|
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
|
||||||
#define LIMB_LOG2_BITS 6
|
#define LIMB_LOG2_BITS 6
|
||||||
#else
|
#else
|
||||||
#define LIMB_LOG2_BITS 5
|
#define LIMB_LOG2_BITS 5
|
||||||
|
|
|
@ -50,8 +50,7 @@ DEF(range32, 3) /* variable length */
|
||||||
DEF(lookahead, 5)
|
DEF(lookahead, 5)
|
||||||
DEF(negative_lookahead, 5)
|
DEF(negative_lookahead, 5)
|
||||||
DEF(push_char_pos, 1) /* push the character position on the stack */
|
DEF(push_char_pos, 1) /* push the character position on the stack */
|
||||||
DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character
|
DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
|
||||||
position */
|
|
||||||
DEF(prev, 1) /* go to the previous char */
|
DEF(prev, 1) /* go to the previous char */
|
||||||
DEF(simple_greedy_quant, 17)
|
DEF(simple_greedy_quant, 17)
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- Add full unicode canonicalize rules for character ranges (not
|
|
||||||
really useful but needed for exact "ignorecase" compatibility).
|
|
||||||
|
|
||||||
- Add a lock step execution mode (=linear time execution guaranteed)
|
- Add a lock step execution mode (=linear time execution guaranteed)
|
||||||
when the regular expression is "simple" i.e. no backreference nor
|
when the regular expression is "simple" i.e. no backreference nor
|
||||||
complicated lookahead. The opcodes are designed for this execution
|
complicated lookahead. The opcodes are designed for this execution
|
||||||
|
@ -120,33 +117,6 @@ static int dbuf_insert(DynBuf *s, int pos, int len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* canonicalize with the specific JS regexp rules */
|
|
||||||
static uint32_t lre_canonicalize(uint32_t c, BOOL is_utf16)
|
|
||||||
{
|
|
||||||
uint32_t res[LRE_CC_RES_LEN_MAX];
|
|
||||||
int len;
|
|
||||||
if (is_utf16) {
|
|
||||||
if (likely(c < 128)) {
|
|
||||||
if (c >= 'A' && c <= 'Z')
|
|
||||||
c = c - 'A' + 'a';
|
|
||||||
} else {
|
|
||||||
lre_case_conv(res, c, 2);
|
|
||||||
c = res[0];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (likely(c < 128)) {
|
|
||||||
if (c >= 'a' && c <= 'z')
|
|
||||||
c = c - 'a' + 'A';
|
|
||||||
} else {
|
|
||||||
/* legacy regexp: to upper case if single char >= 128 */
|
|
||||||
len = lre_case_conv(res, c, FALSE);
|
|
||||||
if (len == 1 && res[0] >= 128)
|
|
||||||
c = res[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint16_t char_range_d[] = {
|
static const uint16_t char_range_d[] = {
|
||||||
1,
|
1,
|
||||||
0x0030, 0x0039 + 1,
|
0x0030, 0x0039 + 1,
|
||||||
|
@ -245,31 +215,6 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cr_canonicalize(CharRange *cr)
|
|
||||||
{
|
|
||||||
CharRange a;
|
|
||||||
uint32_t pt[2];
|
|
||||||
int i, ret;
|
|
||||||
|
|
||||||
cr_init(&a, cr->mem_opaque, lre_realloc);
|
|
||||||
pt[0] = 'a';
|
|
||||||
pt[1] = 'z' + 1;
|
|
||||||
ret = cr_op(&a, cr->points, cr->len, pt, 2, CR_OP_INTER);
|
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
/* convert to upper case */
|
|
||||||
/* XXX: the generic unicode case would be much more complicated
|
|
||||||
and not really useful */
|
|
||||||
for(i = 0; i < a.len; i++) {
|
|
||||||
a.points[i] += 'A' - 'a';
|
|
||||||
}
|
|
||||||
/* Note: for simplicity we keep the lower case ranges */
|
|
||||||
ret = cr_union1(cr, a.points, a.len);
|
|
||||||
fail:
|
|
||||||
cr_free(&a);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DUMP_REOP
|
#ifdef DUMP_REOP
|
||||||
static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
|
static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
|
||||||
int buf_len)
|
int buf_len)
|
||||||
|
@ -335,7 +280,6 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
|
||||||
case REOP_loop:
|
case REOP_loop:
|
||||||
case REOP_lookahead:
|
case REOP_lookahead:
|
||||||
case REOP_negative_lookahead:
|
case REOP_negative_lookahead:
|
||||||
case REOP_bne_char_pos:
|
|
||||||
val = get_u32(buf + pos + 1);
|
val = get_u32(buf + pos + 1);
|
||||||
val += (pos + 5);
|
val += (pos + 5);
|
||||||
printf(" %u", val);
|
printf(" %u", val);
|
||||||
|
@ -922,7 +866,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s->ignore_case) {
|
if (s->ignore_case) {
|
||||||
if (cr_canonicalize(cr))
|
if (cr_regexp_canonicalize(cr, s->is_utf16))
|
||||||
goto memory_error;
|
goto memory_error;
|
||||||
}
|
}
|
||||||
if (invert) {
|
if (invert) {
|
||||||
|
@ -943,22 +887,17 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return:
|
/* Return:
|
||||||
1 if the opcodes in bc_buf[] always advance the character pointer.
|
- true if the opcodes may not advance the char pointer
|
||||||
0 if the character pointer may not be advanced.
|
- false if the opcodes always advance the char pointer
|
||||||
-1 if the code may depend on side effects of its previous execution (backreference)
|
|
||||||
*/
|
*/
|
||||||
static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
|
static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
|
||||||
{
|
{
|
||||||
int pos, opcode, ret, len, i;
|
int pos, opcode, len;
|
||||||
uint32_t val, last;
|
uint32_t val;
|
||||||
BOOL has_back_reference;
|
BOOL ret;
|
||||||
uint8_t capture_bitmap[CAPTURE_COUNT_MAX];
|
|
||||||
|
|
||||||
ret = -2; /* not known yet */
|
ret = TRUE;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
has_back_reference = FALSE;
|
|
||||||
memset(capture_bitmap, 0, sizeof(capture_bitmap));
|
|
||||||
|
|
||||||
while (pos < bc_buf_len) {
|
while (pos < bc_buf_len) {
|
||||||
opcode = bc_buf[pos];
|
opcode = bc_buf[pos];
|
||||||
len = reopcode_info[opcode].size;
|
len = reopcode_info[opcode].size;
|
||||||
|
@ -976,8 +915,7 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
|
||||||
case REOP_dot:
|
case REOP_dot:
|
||||||
case REOP_any:
|
case REOP_any:
|
||||||
simple_char:
|
simple_char:
|
||||||
if (ret == -2)
|
ret = FALSE;
|
||||||
ret = 1;
|
|
||||||
break;
|
break;
|
||||||
case REOP_line_start:
|
case REOP_line_start:
|
||||||
case REOP_line_end:
|
case REOP_line_end:
|
||||||
|
@ -991,41 +929,16 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
|
||||||
break;
|
break;
|
||||||
case REOP_save_start:
|
case REOP_save_start:
|
||||||
case REOP_save_end:
|
case REOP_save_end:
|
||||||
val = bc_buf[pos + 1];
|
|
||||||
capture_bitmap[val] |= 1;
|
|
||||||
break;
|
|
||||||
case REOP_save_reset:
|
case REOP_save_reset:
|
||||||
{
|
|
||||||
val = bc_buf[pos + 1];
|
|
||||||
last = bc_buf[pos + 2];
|
|
||||||
while (val < last)
|
|
||||||
capture_bitmap[val++] |= 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case REOP_back_reference:
|
case REOP_back_reference:
|
||||||
case REOP_backward_back_reference:
|
case REOP_backward_back_reference:
|
||||||
val = bc_buf[pos + 1];
|
|
||||||
capture_bitmap[val] |= 2;
|
|
||||||
has_back_reference = TRUE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* safe behvior: we cannot predict the outcome */
|
/* safe behvior: we cannot predict the outcome */
|
||||||
if (ret == -2)
|
return TRUE;
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
if (has_back_reference) {
|
|
||||||
/* check if there is back reference which references a capture
|
|
||||||
made in the some code */
|
|
||||||
for(i = 0; i < CAPTURE_COUNT_MAX; i++) {
|
|
||||||
if (capture_bitmap[i] == 3)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ret == -2)
|
|
||||||
ret = 0;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,11 +984,10 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* '*pp' is the first char after '<' */
|
/* '*pp' is the first char after '<' */
|
||||||
static int re_parse_group_name(char *buf, int buf_size,
|
static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp)
|
||||||
const uint8_t **pp, BOOL is_utf16)
|
|
||||||
{
|
{
|
||||||
const uint8_t *p;
|
const uint8_t *p, *p1;
|
||||||
uint32_t c;
|
uint32_t c, d;
|
||||||
char *q;
|
char *q;
|
||||||
|
|
||||||
p = *pp;
|
p = *pp;
|
||||||
|
@ -1086,11 +998,18 @@ static int re_parse_group_name(char *buf, int buf_size,
|
||||||
p++;
|
p++;
|
||||||
if (*p != 'u')
|
if (*p != 'u')
|
||||||
return -1;
|
return -1;
|
||||||
c = lre_parse_escape(&p, is_utf16 * 2);
|
c = lre_parse_escape(&p, 2); // accept surrogate pairs
|
||||||
} else if (c == '>') {
|
} else if (c == '>') {
|
||||||
break;
|
break;
|
||||||
} else if (c >= 128) {
|
} else if (c >= 128) {
|
||||||
c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
|
c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
|
||||||
|
if (c >= 0xD800 && c <= 0xDBFF) {
|
||||||
|
d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
|
||||||
|
if (d >= 0xDC00 && d <= 0xDFFF) {
|
||||||
|
c = 0x10000 + 0x400 * (c - 0xD800) + (d - 0xDC00);
|
||||||
|
p = p1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
@ -1140,8 +1059,7 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures,
|
||||||
/* potential named capture */
|
/* potential named capture */
|
||||||
if (capture_name) {
|
if (capture_name) {
|
||||||
p += 3;
|
p += 3;
|
||||||
if (re_parse_group_name(name, sizeof(name), &p,
|
if (re_parse_group_name(name, sizeof(name), &p) == 0) {
|
||||||
s->is_utf16) == 0) {
|
|
||||||
if (!strcmp(name, capture_name))
|
if (!strcmp(name, capture_name))
|
||||||
return capture_index;
|
return capture_index;
|
||||||
}
|
}
|
||||||
|
@ -1314,7 +1232,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||||
} else if (p[2] == '<') {
|
} else if (p[2] == '<') {
|
||||||
p += 3;
|
p += 3;
|
||||||
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
|
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
|
||||||
&p, s->is_utf16)) {
|
&p)) {
|
||||||
return re_parse_error(s, "invalid group name");
|
return re_parse_error(s, "invalid group name");
|
||||||
}
|
}
|
||||||
if (find_group_name(s, s->u.tmp_buf) > 0) {
|
if (find_group_name(s, s->u.tmp_buf) > 0) {
|
||||||
|
@ -1378,7 +1296,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||||
}
|
}
|
||||||
p1 += 3;
|
p1 += 3;
|
||||||
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
|
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
|
||||||
&p1, s->is_utf16)) {
|
&p1)) {
|
||||||
if (s->is_utf16 || re_has_named_captures(s))
|
if (s->is_utf16 || re_has_named_captures(s))
|
||||||
return re_parse_error(s, "invalid group name");
|
return re_parse_error(s, "invalid group name");
|
||||||
else
|
else
|
||||||
|
@ -1591,8 +1509,12 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||||
|
|
||||||
if (dbuf_error(&s->byte_code))
|
if (dbuf_error(&s->byte_code))
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
add_zero_advance_check = (re_check_advance(s->byte_code.buf + last_atom_start,
|
/* the spec tells that if there is no advance when
|
||||||
s->byte_code.size - last_atom_start) == 0);
|
running the atom after the first quant_min times,
|
||||||
|
then there is no match. We remove this test when we
|
||||||
|
are sure the atom always advances the position. */
|
||||||
|
add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
|
||||||
|
s->byte_code.size - last_atom_start);
|
||||||
} else {
|
} else {
|
||||||
add_zero_advance_check = FALSE;
|
add_zero_advance_check = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1612,38 +1534,34 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||||
}
|
}
|
||||||
if (quant_max == 0) {
|
if (quant_max == 0) {
|
||||||
s->byte_code.size = last_atom_start;
|
s->byte_code.size = last_atom_start;
|
||||||
} else if (quant_max == 1) {
|
} else if (quant_max == 1 || quant_max == INT32_MAX) {
|
||||||
if (dbuf_insert(&s->byte_code, last_atom_start, 5))
|
BOOL has_goto = (quant_max == INT32_MAX);
|
||||||
goto out_of_memory;
|
|
||||||
s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
|
|
||||||
greedy;
|
|
||||||
put_u32(s->byte_code.buf + last_atom_start + 1, len);
|
|
||||||
} else if (quant_max == INT32_MAX) {
|
|
||||||
if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check))
|
if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check))
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
|
s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
|
||||||
greedy;
|
greedy;
|
||||||
put_u32(s->byte_code.buf + last_atom_start + 1,
|
put_u32(s->byte_code.buf + last_atom_start + 1,
|
||||||
len + 5 + add_zero_advance_check);
|
len + 5 * has_goto + add_zero_advance_check * 2);
|
||||||
if (add_zero_advance_check) {
|
if (add_zero_advance_check) {
|
||||||
/* avoid infinite loop by stoping the
|
|
||||||
recursion if no advance was made in the
|
|
||||||
atom (only works if the atom has no
|
|
||||||
side effect) */
|
|
||||||
s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos;
|
s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos;
|
||||||
re_emit_goto(s, REOP_bne_char_pos, last_atom_start);
|
re_emit_op(s, REOP_check_advance);
|
||||||
} else {
|
|
||||||
re_emit_goto(s, REOP_goto, last_atom_start);
|
|
||||||
}
|
}
|
||||||
|
if (has_goto)
|
||||||
|
re_emit_goto(s, REOP_goto, last_atom_start);
|
||||||
} else {
|
} else {
|
||||||
if (dbuf_insert(&s->byte_code, last_atom_start, 10))
|
if (dbuf_insert(&s->byte_code, last_atom_start, 10 + add_zero_advance_check))
|
||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
pos = last_atom_start;
|
pos = last_atom_start;
|
||||||
s->byte_code.buf[pos++] = REOP_push_i32;
|
s->byte_code.buf[pos++] = REOP_push_i32;
|
||||||
put_u32(s->byte_code.buf + pos, quant_max);
|
put_u32(s->byte_code.buf + pos, quant_max);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
s->byte_code.buf[pos++] = REOP_split_goto_first + greedy;
|
s->byte_code.buf[pos++] = REOP_split_goto_first + greedy;
|
||||||
put_u32(s->byte_code.buf + pos, len + 5);
|
put_u32(s->byte_code.buf + pos, len + 5 + add_zero_advance_check * 2);
|
||||||
|
pos += 4;
|
||||||
|
if (add_zero_advance_check) {
|
||||||
|
s->byte_code.buf[pos++] = REOP_push_char_pos;
|
||||||
|
re_emit_op(s, REOP_check_advance);
|
||||||
|
}
|
||||||
re_emit_goto(s, REOP_loop, last_atom_start + 5);
|
re_emit_goto(s, REOP_loop, last_atom_start + 5);
|
||||||
re_emit_op(s, REOP_drop);
|
re_emit_op(s, REOP_drop);
|
||||||
}
|
}
|
||||||
|
@ -1667,22 +1585,25 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
|
||||||
if (quant_max == INT32_MAX) {
|
if (quant_max == INT32_MAX) {
|
||||||
pos = s->byte_code.size;
|
pos = s->byte_code.size;
|
||||||
re_emit_op_u32(s, REOP_split_goto_first + greedy,
|
re_emit_op_u32(s, REOP_split_goto_first + greedy,
|
||||||
len + 5 + add_zero_advance_check);
|
len + 5 + add_zero_advance_check * 2);
|
||||||
if (add_zero_advance_check)
|
if (add_zero_advance_check)
|
||||||
re_emit_op(s, REOP_push_char_pos);
|
re_emit_op(s, REOP_push_char_pos);
|
||||||
/* copy the atom */
|
/* copy the atom */
|
||||||
dbuf_put_self(&s->byte_code, last_atom_start, len);
|
dbuf_put_self(&s->byte_code, last_atom_start, len);
|
||||||
if (add_zero_advance_check)
|
if (add_zero_advance_check)
|
||||||
re_emit_goto(s, REOP_bne_char_pos, pos);
|
re_emit_op(s, REOP_check_advance);
|
||||||
else
|
re_emit_goto(s, REOP_goto, pos);
|
||||||
re_emit_goto(s, REOP_goto, pos);
|
|
||||||
} else if (quant_max > quant_min) {
|
} else if (quant_max > quant_min) {
|
||||||
re_emit_op_u32(s, REOP_push_i32, quant_max - quant_min);
|
re_emit_op_u32(s, REOP_push_i32, quant_max - quant_min);
|
||||||
pos = s->byte_code.size;
|
pos = s->byte_code.size;
|
||||||
re_emit_op_u32(s, REOP_split_goto_first + greedy, len + 5);
|
re_emit_op_u32(s, REOP_split_goto_first + greedy,
|
||||||
|
len + 5 + add_zero_advance_check * 2);
|
||||||
|
if (add_zero_advance_check)
|
||||||
|
re_emit_op(s, REOP_push_char_pos);
|
||||||
/* copy the atom */
|
/* copy the atom */
|
||||||
dbuf_put_self(&s->byte_code, last_atom_start, len);
|
dbuf_put_self(&s->byte_code, last_atom_start, len);
|
||||||
|
if (add_zero_advance_check)
|
||||||
|
re_emit_op(s, REOP_check_advance);
|
||||||
re_emit_goto(s, REOP_loop, pos);
|
re_emit_goto(s, REOP_loop, pos);
|
||||||
re_emit_op(s, REOP_drop);
|
re_emit_op(s, REOP_drop);
|
||||||
}
|
}
|
||||||
|
@ -1796,7 +1717,7 @@ static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REOP_drop:
|
case REOP_drop:
|
||||||
case REOP_bne_char_pos:
|
case REOP_check_advance:
|
||||||
assert(stack_size > 0);
|
assert(stack_size > 0);
|
||||||
stack_size--;
|
stack_size--;
|
||||||
break;
|
break;
|
||||||
|
@ -2292,11 +2213,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
|
||||||
case REOP_push_char_pos:
|
case REOP_push_char_pos:
|
||||||
stack[stack_len++] = (uintptr_t)cptr;
|
stack[stack_len++] = (uintptr_t)cptr;
|
||||||
break;
|
break;
|
||||||
case REOP_bne_char_pos:
|
case REOP_check_advance:
|
||||||
val = get_u32(pc);
|
if (stack[--stack_len] == (uintptr_t)cptr)
|
||||||
pc += 4;
|
goto no_match;
|
||||||
if (stack[--stack_len] != (uintptr_t)cptr)
|
|
||||||
pc += (int)val;
|
|
||||||
break;
|
break;
|
||||||
case REOP_word_boundary:
|
case REOP_word_boundary:
|
||||||
case REOP_not_word_boundary:
|
case REOP_not_word_boundary:
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#define LRE_FLAG_DOTALL (1 << 3)
|
#define LRE_FLAG_DOTALL (1 << 3)
|
||||||
#define LRE_FLAG_UTF16 (1 << 4)
|
#define LRE_FLAG_UTF16 (1 << 4)
|
||||||
#define LRE_FLAG_STICKY (1 << 5)
|
#define LRE_FLAG_STICKY (1 << 5)
|
||||||
|
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
|
||||||
|
|
||||||
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
|
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
|
||||||
|
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -43,11 +43,111 @@ enum {
|
||||||
RUN_TYPE_UF_D1_EXT,
|
RUN_TYPE_UF_D1_EXT,
|
||||||
RUN_TYPE_U_EXT,
|
RUN_TYPE_U_EXT,
|
||||||
RUN_TYPE_LF_EXT,
|
RUN_TYPE_LF_EXT,
|
||||||
RUN_TYPE_U_EXT2,
|
RUN_TYPE_UF_EXT2,
|
||||||
RUN_TYPE_L_EXT2,
|
RUN_TYPE_LF_EXT2,
|
||||||
RUN_TYPE_U_EXT3,
|
RUN_TYPE_UF_EXT3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int lre_case_conv1(uint32_t c, int conv_type)
|
||||||
|
{
|
||||||
|
uint32_t res[LRE_CC_RES_LEN_MAX];
|
||||||
|
lre_case_conv(res, c, conv_type);
|
||||||
|
return res[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* case conversion using the table entry 'idx' with value 'v' */
|
||||||
|
static int lre_case_conv_entry(uint32_t *res, uint32_t c, int conv_type, uint32_t idx, uint32_t v)
|
||||||
|
{
|
||||||
|
uint32_t code, data, type, a, is_lower;
|
||||||
|
is_lower = (conv_type != 0);
|
||||||
|
type = (v >> (32 - 17 - 7 - 4)) & 0xf;
|
||||||
|
data = ((v & 0xf) << 8) | case_conv_table2[idx];
|
||||||
|
code = v >> (32 - 17);
|
||||||
|
switch(type) {
|
||||||
|
case RUN_TYPE_U:
|
||||||
|
case RUN_TYPE_L:
|
||||||
|
case RUN_TYPE_UF:
|
||||||
|
case RUN_TYPE_LF:
|
||||||
|
if (conv_type == (type & 1) ||
|
||||||
|
(type >= RUN_TYPE_UF && conv_type == 2)) {
|
||||||
|
c = c - code + (case_conv_table1[data] >> (32 - 17));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_UL:
|
||||||
|
a = c - code;
|
||||||
|
if ((a & 1) != (1 - is_lower))
|
||||||
|
break;
|
||||||
|
c = (a ^ 1) + code;
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_LSU:
|
||||||
|
a = c - code;
|
||||||
|
if (a == 1) {
|
||||||
|
c += 2 * is_lower - 1;
|
||||||
|
} else if (a == (1 - is_lower) * 2) {
|
||||||
|
c += (2 * is_lower - 1) * 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_U2L_399_EXT2:
|
||||||
|
if (!is_lower) {
|
||||||
|
res[0] = c - code + case_conv_ext[data >> 6];
|
||||||
|
res[1] = 0x399;
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
c = c - code + case_conv_ext[data & 0x3f];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_UF_D20:
|
||||||
|
if (conv_type == 1)
|
||||||
|
break;
|
||||||
|
c = data + (conv_type == 2) * 0x20;
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_UF_D1_EXT:
|
||||||
|
if (conv_type == 1)
|
||||||
|
break;
|
||||||
|
c = case_conv_ext[data] + (conv_type == 2);
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_U_EXT:
|
||||||
|
case RUN_TYPE_LF_EXT:
|
||||||
|
if (is_lower != (type - RUN_TYPE_U_EXT))
|
||||||
|
break;
|
||||||
|
c = case_conv_ext[data];
|
||||||
|
break;
|
||||||
|
case RUN_TYPE_LF_EXT2:
|
||||||
|
if (!is_lower)
|
||||||
|
break;
|
||||||
|
res[0] = c - code + case_conv_ext[data >> 6];
|
||||||
|
res[1] = case_conv_ext[data & 0x3f];
|
||||||
|
return 2;
|
||||||
|
case RUN_TYPE_UF_EXT2:
|
||||||
|
if (conv_type == 1)
|
||||||
|
break;
|
||||||
|
res[0] = c - code + case_conv_ext[data >> 6];
|
||||||
|
res[1] = case_conv_ext[data & 0x3f];
|
||||||
|
if (conv_type == 2) {
|
||||||
|
/* convert to lower */
|
||||||
|
res[0] = lre_case_conv1(res[0], 1);
|
||||||
|
res[1] = lre_case_conv1(res[1], 1);
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
case RUN_TYPE_UF_EXT3:
|
||||||
|
if (conv_type == 1)
|
||||||
|
break;
|
||||||
|
res[0] = case_conv_ext[data >> 8];
|
||||||
|
res[1] = case_conv_ext[(data >> 4) & 0xf];
|
||||||
|
res[2] = case_conv_ext[data & 0xf];
|
||||||
|
if (conv_type == 2) {
|
||||||
|
/* convert to lower */
|
||||||
|
res[0] = lre_case_conv1(res[0], 1);
|
||||||
|
res[1] = lre_case_conv1(res[1], 1);
|
||||||
|
res[2] = lre_case_conv1(res[2], 1);
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
res[0] = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* conv_type:
|
/* conv_type:
|
||||||
0 = to upper
|
0 = to upper
|
||||||
1 = to lower
|
1 = to lower
|
||||||
|
@ -66,10 +166,9 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint32_t v, code, data, type, len, a, is_lower;
|
uint32_t v, code, len;
|
||||||
int idx, idx_min, idx_max;
|
int idx, idx_min, idx_max;
|
||||||
|
|
||||||
is_lower = (conv_type != 0);
|
|
||||||
idx_min = 0;
|
idx_min = 0;
|
||||||
idx_max = countof(case_conv_table1) - 1;
|
idx_max = countof(case_conv_table1) - 1;
|
||||||
while (idx_min <= idx_max) {
|
while (idx_min <= idx_max) {
|
||||||
|
@ -82,74 +181,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
|
||||||
} else if (c >= code + len) {
|
} else if (c >= code + len) {
|
||||||
idx_min = idx + 1;
|
idx_min = idx + 1;
|
||||||
} else {
|
} else {
|
||||||
type = (v >> (32 - 17 - 7 - 4)) & 0xf;
|
return lre_case_conv_entry(res, c, conv_type, idx, v);
|
||||||
data = ((v & 0xf) << 8) | case_conv_table2[idx];
|
|
||||||
switch(type) {
|
|
||||||
case RUN_TYPE_U:
|
|
||||||
case RUN_TYPE_L:
|
|
||||||
case RUN_TYPE_UF:
|
|
||||||
case RUN_TYPE_LF:
|
|
||||||
if (conv_type == (type & 1) ||
|
|
||||||
(type >= RUN_TYPE_UF && conv_type == 2)) {
|
|
||||||
c = c - code + (case_conv_table1[data] >> (32 - 17));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_UL:
|
|
||||||
a = c - code;
|
|
||||||
if ((a & 1) != (1 - is_lower))
|
|
||||||
break;
|
|
||||||
c = (a ^ 1) + code;
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_LSU:
|
|
||||||
a = c - code;
|
|
||||||
if (a == 1) {
|
|
||||||
c += 2 * is_lower - 1;
|
|
||||||
} else if (a == (1 - is_lower) * 2) {
|
|
||||||
c += (2 * is_lower - 1) * 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_U2L_399_EXT2:
|
|
||||||
if (!is_lower) {
|
|
||||||
res[0] = c - code + case_conv_ext[data >> 6];
|
|
||||||
res[1] = 0x399;
|
|
||||||
return 2;
|
|
||||||
} else {
|
|
||||||
c = c - code + case_conv_ext[data & 0x3f];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_UF_D20:
|
|
||||||
if (conv_type == 1)
|
|
||||||
break;
|
|
||||||
c = data + (conv_type == 2) * 0x20;
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_UF_D1_EXT:
|
|
||||||
if (conv_type == 1)
|
|
||||||
break;
|
|
||||||
c = case_conv_ext[data] + (conv_type == 2);
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_U_EXT:
|
|
||||||
case RUN_TYPE_LF_EXT:
|
|
||||||
if (is_lower != (type - RUN_TYPE_U_EXT))
|
|
||||||
break;
|
|
||||||
c = case_conv_ext[data];
|
|
||||||
break;
|
|
||||||
case RUN_TYPE_U_EXT2:
|
|
||||||
case RUN_TYPE_L_EXT2:
|
|
||||||
if (conv_type != (type - RUN_TYPE_U_EXT2))
|
|
||||||
break;
|
|
||||||
res[0] = c - code + case_conv_ext[data >> 6];
|
|
||||||
res[1] = case_conv_ext[data & 0x3f];
|
|
||||||
return 2;
|
|
||||||
default:
|
|
||||||
case RUN_TYPE_U_EXT3:
|
|
||||||
if (conv_type != 0)
|
|
||||||
break;
|
|
||||||
res[0] = case_conv_ext[data >> 8];
|
|
||||||
res[1] = case_conv_ext[(data >> 4) & 0xf];
|
|
||||||
res[2] = case_conv_ext[data & 0xf];
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +189,77 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_unicode)
|
||||||
|
{
|
||||||
|
uint32_t res[LRE_CC_RES_LEN_MAX];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (is_unicode) {
|
||||||
|
len = lre_case_conv_entry(res, c, 2, idx, v);
|
||||||
|
if (len == 1) {
|
||||||
|
c = res[0];
|
||||||
|
} else {
|
||||||
|
/* handle the few specific multi-character cases (see
|
||||||
|
unicode_gen.c:dump_case_folding_special_cases()) */
|
||||||
|
if (c == 0xfb06) {
|
||||||
|
c = 0xfb05;
|
||||||
|
} else if (c == 0x01fd3) {
|
||||||
|
c = 0x390;
|
||||||
|
} else if (c == 0x01fe3) {
|
||||||
|
c = 0x3b0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (likely(c < 128)) {
|
||||||
|
if (c >= 'a' && c <= 'z')
|
||||||
|
c = c - 'a' + 'A';
|
||||||
|
} else {
|
||||||
|
/* legacy regexp: to upper case if single char >= 128 */
|
||||||
|
len = lre_case_conv_entry(res, c, FALSE, idx, v);
|
||||||
|
if (len == 1 && res[0] >= 128)
|
||||||
|
c = res[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JS regexp specific rules for case folding */
|
||||||
|
int lre_canonicalize(uint32_t c, BOOL is_unicode)
|
||||||
|
{
|
||||||
|
if (c < 128) {
|
||||||
|
/* fast case */
|
||||||
|
if (is_unicode) {
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
c = c - 'A' + 'a';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
c = c - 'a' + 'A';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint32_t v, code, len;
|
||||||
|
int idx, idx_min, idx_max;
|
||||||
|
|
||||||
|
idx_min = 0;
|
||||||
|
idx_max = countof(case_conv_table1) - 1;
|
||||||
|
while (idx_min <= idx_max) {
|
||||||
|
idx = (unsigned)(idx_max + idx_min) / 2;
|
||||||
|
v = case_conv_table1[idx];
|
||||||
|
code = v >> (32 - 17);
|
||||||
|
len = (v >> (32 - 17 - 7)) & 0x7f;
|
||||||
|
if (c < code) {
|
||||||
|
idx_max = idx - 1;
|
||||||
|
} else if (c >= code + len) {
|
||||||
|
idx_min = idx + 1;
|
||||||
|
} else {
|
||||||
|
return lre_case_folding_entry(c, idx, v, is_unicode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t get_le24(const uint8_t *ptr)
|
static uint32_t get_le24(const uint8_t *ptr)
|
||||||
{
|
{
|
||||||
#if defined(__x86__) || defined(__x86_64__)
|
#if defined(__x86__) || defined(__x86_64__)
|
||||||
|
@ -1179,11 +1282,11 @@ static int unicode_case1(CharRange *cr, int case_mask)
|
||||||
#define MR(x) (1 << RUN_TYPE_ ## x)
|
#define MR(x) (1 << RUN_TYPE_ ## x)
|
||||||
const uint32_t tab_run_mask[3] = {
|
const uint32_t tab_run_mask[3] = {
|
||||||
MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) |
|
MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) |
|
||||||
MR(UF_D1_EXT) | MR(U_EXT) | MR(U_EXT2) | MR(U_EXT3),
|
MR(UF_D1_EXT) | MR(U_EXT) | MR(UF_EXT2) | MR(UF_EXT3),
|
||||||
|
|
||||||
MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(L_EXT2),
|
MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2),
|
||||||
|
|
||||||
MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT),
|
MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT) | MR(UF_EXT2) | MR(UF_EXT3),
|
||||||
};
|
};
|
||||||
#undef MR
|
#undef MR
|
||||||
uint32_t mask, v, code, type, len, i, idx;
|
uint32_t mask, v, code, type, len, i, idx;
|
||||||
|
@ -1237,6 +1340,135 @@ static int unicode_case1(CharRange *cr, int case_mask)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int point_cmp(const void *p1, const void *p2, void *arg)
|
||||||
|
{
|
||||||
|
uint32_t v1 = *(uint32_t *)p1;
|
||||||
|
uint32_t v2 = *(uint32_t *)p2;
|
||||||
|
return (v1 > v2) - (v1 < v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cr_sort_and_remove_overlap(CharRange *cr)
|
||||||
|
{
|
||||||
|
uint32_t start, end, start1, end1, i, j;
|
||||||
|
|
||||||
|
/* the resulting ranges are not necessarily sorted and may overlap */
|
||||||
|
rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL);
|
||||||
|
j = 0;
|
||||||
|
for(i = 0; i < cr->len; ) {
|
||||||
|
start = cr->points[i];
|
||||||
|
end = cr->points[i + 1];
|
||||||
|
i += 2;
|
||||||
|
while (i < cr->len) {
|
||||||
|
start1 = cr->points[i];
|
||||||
|
end1 = cr->points[i + 1];
|
||||||
|
if (start1 > end) {
|
||||||
|
/* |------|
|
||||||
|
* |-------| */
|
||||||
|
break;
|
||||||
|
} else if (end1 <= end) {
|
||||||
|
/* |------|
|
||||||
|
* |--| */
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
|
/* |------|
|
||||||
|
* |-------| */
|
||||||
|
end = end1;
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cr->points[j] = start;
|
||||||
|
cr->points[j + 1] = end;
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
cr->len = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* canonicalize a character set using the JS regex case folding rules
|
||||||
|
(see lre_canonicalize()) */
|
||||||
|
int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode)
|
||||||
|
{
|
||||||
|
CharRange cr_inter, cr_mask, cr_result, cr_sub;
|
||||||
|
uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d;
|
||||||
|
|
||||||
|
cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func);
|
||||||
|
cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func);
|
||||||
|
cr_init(&cr_result, cr->mem_opaque, cr->realloc_func);
|
||||||
|
cr_init(&cr_sub, cr->mem_opaque, cr->realloc_func);
|
||||||
|
|
||||||
|
if (unicode_case1(&cr_mask, is_unicode ? CASE_F : CASE_U))
|
||||||
|
goto fail;
|
||||||
|
if (cr_op(&cr_inter, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (cr_invert(&cr_mask))
|
||||||
|
goto fail;
|
||||||
|
if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* cr_inter = cr & cr_mask */
|
||||||
|
/* cr_sub = cr & ~cr_mask */
|
||||||
|
|
||||||
|
/* use the case conversion table to compute the result */
|
||||||
|
d_start = -1;
|
||||||
|
d_end = -1;
|
||||||
|
idx = 0;
|
||||||
|
v = case_conv_table1[idx];
|
||||||
|
code = v >> (32 - 17);
|
||||||
|
len = (v >> (32 - 17 - 7)) & 0x7f;
|
||||||
|
for(i = 0; i < cr_inter.len; i += 2) {
|
||||||
|
start = cr_inter.points[i];
|
||||||
|
end = cr_inter.points[i + 1];
|
||||||
|
|
||||||
|
for(c = start; c < end; c++) {
|
||||||
|
for(;;) {
|
||||||
|
if (c >= code && c < code + len)
|
||||||
|
break;
|
||||||
|
idx++;
|
||||||
|
assert(idx < countof(case_conv_table1));
|
||||||
|
v = case_conv_table1[idx];
|
||||||
|
code = v >> (32 - 17);
|
||||||
|
len = (v >> (32 - 17 - 7)) & 0x7f;
|
||||||
|
}
|
||||||
|
d = lre_case_folding_entry(c, idx, v, is_unicode);
|
||||||
|
/* try to merge with the current interval */
|
||||||
|
if (d_start == -1) {
|
||||||
|
d_start = d;
|
||||||
|
d_end = d + 1;
|
||||||
|
} else if (d_end == d) {
|
||||||
|
d_end++;
|
||||||
|
} else {
|
||||||
|
cr_add_interval(&cr_result, d_start, d_end);
|
||||||
|
d_start = d;
|
||||||
|
d_end = d + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d_start != -1) {
|
||||||
|
if (cr_add_interval(&cr_result, d_start, d_end))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the resulting ranges are not necessarily sorted and may overlap */
|
||||||
|
cr_sort_and_remove_overlap(&cr_result);
|
||||||
|
|
||||||
|
/* or with the character not affected by the case folding */
|
||||||
|
cr->len = 0;
|
||||||
|
if (cr_op(cr, cr_result.points, cr_result.len, cr_sub.points, cr_sub.len, CR_OP_UNION))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
cr_free(&cr_inter);
|
||||||
|
cr_free(&cr_mask);
|
||||||
|
cr_free(&cr_result);
|
||||||
|
cr_free(&cr_sub);
|
||||||
|
return 0;
|
||||||
|
fail:
|
||||||
|
cr_free(&cr_inter);
|
||||||
|
cr_free(&cr_mask);
|
||||||
|
cr_free(&cr_result);
|
||||||
|
cr_free(&cr_sub);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
POP_GC,
|
POP_GC,
|
||||||
POP_PROP,
|
POP_PROP,
|
||||||
|
|
|
@ -41,6 +41,7 @@ typedef enum {
|
||||||
} UnicodeNormalizationEnum;
|
} UnicodeNormalizationEnum;
|
||||||
|
|
||||||
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
||||||
|
int lre_canonicalize(uint32_t c, BOOL is_unicode);
|
||||||
LRE_BOOL lre_is_cased(uint32_t c);
|
LRE_BOOL lre_is_cased(uint32_t c);
|
||||||
LRE_BOOL lre_is_case_ignorable(uint32_t c);
|
LRE_BOOL lre_is_case_ignorable(uint32_t c);
|
||||||
|
|
||||||
|
@ -101,6 +102,8 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
||||||
|
|
||||||
int cr_invert(CharRange *cr);
|
int cr_invert(CharRange *cr);
|
||||||
|
|
||||||
|
int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode);
|
||||||
|
|
||||||
#ifdef CONFIG_ALL_UNICODE
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
|
||||||
LRE_BOOL lre_is_id_start(uint32_t c);
|
LRE_BOOL lre_is_id_start(uint32_t c);
|
||||||
|
|
|
@ -36,8 +36,7 @@ struct list_head {
|
||||||
#define LIST_HEAD_INIT(el) { &(el), &(el) }
|
#define LIST_HEAD_INIT(el) { &(el), &(el) }
|
||||||
|
|
||||||
/* return the pointer of type 'type *' containing 'el' as field 'member' */
|
/* return the pointer of type 'type *' containing 'el' as field 'member' */
|
||||||
#define list_entry(el, type, member) \
|
#define list_entry(el, type, member) container_of(el, type, member)
|
||||||
((type *)((uint8_t *)(el) - offsetof(type, member)))
|
|
||||||
|
|
||||||
static inline void init_list_head(struct list_head *head)
|
static inline void init_list_head(struct list_head *head)
|
||||||
{
|
{
|
||||||
|
|
|
@ -140,19 +140,19 @@ static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default memory allocation functions with memory limitation */
|
/* default memory allocation functions with memory limitation */
|
||||||
static inline size_t js_trace_malloc_usable_size(void *ptr)
|
static size_t js_trace_malloc_usable_size(const void *ptr)
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
return malloc_size(ptr);
|
return malloc_size(ptr);
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
return _msize(ptr);
|
return _msize((void *)ptr);
|
||||||
#elif defined(EMSCRIPTEN)
|
#elif defined(EMSCRIPTEN)
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
return malloc_usable_size(ptr);
|
return malloc_usable_size((void *)ptr);
|
||||||
#else
|
#else
|
||||||
/* change this to `return 0;` if compilation fails */
|
/* change this to `return 0;` if compilation fails */
|
||||||
return malloc_usable_size(ptr);
|
return malloc_usable_size((void *)ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,18 +264,7 @@ static const JSMallocFunctions trace_mf = {
|
||||||
js_trace_malloc,
|
js_trace_malloc,
|
||||||
js_trace_free,
|
js_trace_free,
|
||||||
js_trace_realloc,
|
js_trace_realloc,
|
||||||
#if defined(__APPLE__)
|
js_trace_malloc_usable_size,
|
||||||
malloc_size,
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
(size_t (*)(const void *))_msize,
|
|
||||||
#elif defined(EMSCRIPTEN)
|
|
||||||
NULL,
|
|
||||||
#elif defined(__linux__)
|
|
||||||
(size_t (*)(const void *))malloc_usable_size,
|
|
||||||
#else
|
|
||||||
/* change this to `NULL,` if compilation fails */
|
|
||||||
malloc_usable_size,
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PROG_NAME "qjs"
|
#define PROG_NAME "qjs"
|
||||||
|
@ -454,8 +443,10 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
if (load_jscalc)
|
if (load_jscalc)
|
||||||
bignum_ext = 1;
|
bignum_ext = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (trace_memory) {
|
if (trace_memory) {
|
||||||
js_trace_malloc_init(&trace_data);
|
js_trace_malloc_init(&trace_data);
|
||||||
|
|
|
@ -76,9 +76,7 @@ static const FeatureEntry feature_list[] = {
|
||||||
{ "promise", "Promise" },
|
{ "promise", "Promise" },
|
||||||
#define FE_MODULE_LOADER 9
|
#define FE_MODULE_LOADER 9
|
||||||
{ "module-loader", NULL },
|
{ "module-loader", NULL },
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
{ "bigint", "BigInt" },
|
{ "bigint", "BigInt" },
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
||||||
|
@ -332,6 +330,7 @@ static const char main_c_template1[] =
|
||||||
|
|
||||||
static const char main_c_template2[] =
|
static const char main_c_template2[] =
|
||||||
" js_std_loop(ctx);\n"
|
" js_std_loop(ctx);\n"
|
||||||
|
" js_std_free_handlers(rt);\n"
|
||||||
" JS_FreeContext(ctx);\n"
|
" JS_FreeContext(ctx);\n"
|
||||||
" JS_FreeRuntime(rt);\n"
|
" JS_FreeRuntime(rt);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
|
@ -345,8 +344,8 @@ void help(void)
|
||||||
"usage: " PROG_NAME " [options] [files]\n"
|
"usage: " PROG_NAME " [options] [files]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"options are:\n"
|
"options are:\n"
|
||||||
"-c only output bytecode in a C file\n"
|
"-c only output bytecode to a C file\n"
|
||||||
"-e output main() and bytecode in a C file (default = executable output)\n"
|
"-e output main() and bytecode to a C file (default = executable output)\n"
|
||||||
"-o output set the output filename\n"
|
"-o output set the output filename\n"
|
||||||
"-N cname set the C name of the generated data\n"
|
"-N cname set the C name of the generated data\n"
|
||||||
"-m compile as Javascript module (default=autodetect)\n"
|
"-m compile as Javascript module (default=autodetect)\n"
|
||||||
|
|
|
@ -82,6 +82,7 @@ DEF(length, "length")
|
||||||
DEF(fileName, "fileName")
|
DEF(fileName, "fileName")
|
||||||
DEF(lineNumber, "lineNumber")
|
DEF(lineNumber, "lineNumber")
|
||||||
DEF(message, "message")
|
DEF(message, "message")
|
||||||
|
DEF(cause, "cause")
|
||||||
DEF(errors, "errors")
|
DEF(errors, "errors")
|
||||||
DEF(stack, "stack")
|
DEF(stack, "stack")
|
||||||
DEF(name, "name")
|
DEF(name, "name")
|
||||||
|
@ -166,22 +167,23 @@ DEF(revoke, "revoke")
|
||||||
DEF(async, "async")
|
DEF(async, "async")
|
||||||
DEF(exec, "exec")
|
DEF(exec, "exec")
|
||||||
DEF(groups, "groups")
|
DEF(groups, "groups")
|
||||||
|
DEF(indices, "indices")
|
||||||
DEF(status, "status")
|
DEF(status, "status")
|
||||||
DEF(reason, "reason")
|
DEF(reason, "reason")
|
||||||
DEF(globalThis, "globalThis")
|
DEF(globalThis, "globalThis")
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
DEF(bigint, "bigint")
|
DEF(bigint, "bigint")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
DEF(bigfloat, "bigfloat")
|
DEF(bigfloat, "bigfloat")
|
||||||
DEF(bigdecimal, "bigdecimal")
|
DEF(bigdecimal, "bigdecimal")
|
||||||
DEF(roundingMode, "roundingMode")
|
DEF(roundingMode, "roundingMode")
|
||||||
DEF(maximumSignificantDigits, "maximumSignificantDigits")
|
DEF(maximumSignificantDigits, "maximumSignificantDigits")
|
||||||
DEF(maximumFractionDigits, "maximumFractionDigits")
|
DEF(maximumFractionDigits, "maximumFractionDigits")
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ATOMICS
|
/* the following 3 atoms are only used with CONFIG_ATOMICS */
|
||||||
DEF(not_equal, "not-equal")
|
DEF(not_equal, "not-equal")
|
||||||
DEF(timed_out, "timed-out")
|
DEF(timed_out, "timed-out")
|
||||||
DEF(ok, "ok")
|
DEF(ok, "ok")
|
||||||
#endif
|
/* */
|
||||||
DEF(toJSON, "toJSON")
|
DEF(toJSON, "toJSON")
|
||||||
/* class names */
|
/* class names */
|
||||||
DEF(Object, "Object")
|
DEF(Object, "Object")
|
||||||
|
@ -209,15 +211,13 @@ DEF(Int16Array, "Int16Array")
|
||||||
DEF(Uint16Array, "Uint16Array")
|
DEF(Uint16Array, "Uint16Array")
|
||||||
DEF(Int32Array, "Int32Array")
|
DEF(Int32Array, "Int32Array")
|
||||||
DEF(Uint32Array, "Uint32Array")
|
DEF(Uint32Array, "Uint32Array")
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
DEF(BigInt64Array, "BigInt64Array")
|
DEF(BigInt64Array, "BigInt64Array")
|
||||||
DEF(BigUint64Array, "BigUint64Array")
|
DEF(BigUint64Array, "BigUint64Array")
|
||||||
#endif
|
|
||||||
DEF(Float32Array, "Float32Array")
|
DEF(Float32Array, "Float32Array")
|
||||||
DEF(Float64Array, "Float64Array")
|
DEF(Float64Array, "Float64Array")
|
||||||
DEF(DataView, "DataView")
|
DEF(DataView, "DataView")
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
DEF(BigInt, "BigInt")
|
DEF(BigInt, "BigInt")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
DEF(BigFloat, "BigFloat")
|
DEF(BigFloat, "BigFloat")
|
||||||
DEF(BigFloatEnv, "BigFloatEnv")
|
DEF(BigFloatEnv, "BigFloatEnv")
|
||||||
DEF(BigDecimal, "BigDecimal")
|
DEF(BigDecimal, "BigDecimal")
|
||||||
|
|
|
@ -751,6 +751,7 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val,
|
||||||
JSValue ret;
|
JSValue ret;
|
||||||
JSValueConst options_obj;
|
JSValueConst options_obj;
|
||||||
BOOL backtrace_barrier = FALSE;
|
BOOL backtrace_barrier = FALSE;
|
||||||
|
BOOL is_async = FALSE;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
|
@ -758,6 +759,9 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val,
|
||||||
if (get_bool_option(ctx, &backtrace_barrier, options_obj,
|
if (get_bool_option(ctx, &backtrace_barrier, options_obj,
|
||||||
"backtrace_barrier"))
|
"backtrace_barrier"))
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
|
if (get_bool_option(ctx, &is_async, options_obj,
|
||||||
|
"async"))
|
||||||
|
return JS_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
@ -770,6 +774,8 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val,
|
||||||
flags = JS_EVAL_TYPE_GLOBAL;
|
flags = JS_EVAL_TYPE_GLOBAL;
|
||||||
if (backtrace_barrier)
|
if (backtrace_barrier)
|
||||||
flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER;
|
flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER;
|
||||||
|
if (is_async)
|
||||||
|
flags |= JS_EVAL_FLAG_ASYNC;
|
||||||
ret = JS_Eval(ctx, str, len, "<evalScript>", flags);
|
ret = JS_Eval(ctx, str, len, "<evalScript>", flags);
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
if (!ts->recv_pipe && --ts->eval_script_recurse == 0) {
|
if (!ts->recv_pipe && --ts->eval_script_recurse == 0) {
|
||||||
|
@ -1970,6 +1976,13 @@ static int64_t get_time_ms(void)
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000);
|
return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t get_time_ns(void)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* more portable, but does not work if the date is updated */
|
/* more portable, but does not work if the date is updated */
|
||||||
static int64_t get_time_ms(void)
|
static int64_t get_time_ms(void)
|
||||||
|
@ -1978,8 +1991,21 @@ static int64_t get_time_ms(void)
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
|
return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t get_time_ns(void)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return (int64_t)tv.tv_sec * 1000000000 + (tv.tv_usec * 1000);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static JSValue js_os_now(JSContext *ctx, JSValue this_val,
|
||||||
|
int argc, JSValue *argv)
|
||||||
|
{
|
||||||
|
return JS_NewFloat64(ctx, (double)get_time_ns() / 1e6);
|
||||||
|
}
|
||||||
|
|
||||||
static void unlink_timer(JSRuntime *rt, JSOSTimer *th)
|
static void unlink_timer(JSRuntime *rt, JSOSTimer *th)
|
||||||
{
|
{
|
||||||
if (th->link.prev) {
|
if (th->link.prev) {
|
||||||
|
@ -2062,6 +2088,38 @@ static JSClassDef js_os_timer_class = {
|
||||||
.gc_mark = js_os_timer_mark,
|
.gc_mark = js_os_timer_mark,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* return a promise */
|
||||||
|
static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
JSRuntime *rt = JS_GetRuntime(ctx);
|
||||||
|
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
|
||||||
|
int64_t delay;
|
||||||
|
JSOSTimer *th;
|
||||||
|
JSValue promise, resolving_funcs[2];
|
||||||
|
|
||||||
|
if (JS_ToInt64(ctx, &delay, argv[0]))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
promise = JS_NewPromiseCapability(ctx, resolving_funcs);
|
||||||
|
if (JS_IsException(promise))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
|
||||||
|
th = js_mallocz(ctx, sizeof(*th));
|
||||||
|
if (!th) {
|
||||||
|
JS_FreeValue(ctx, promise);
|
||||||
|
JS_FreeValue(ctx, resolving_funcs[0]);
|
||||||
|
JS_FreeValue(ctx, resolving_funcs[1]);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
th->has_object = FALSE;
|
||||||
|
th->timeout = get_time_ms() + delay;
|
||||||
|
th->func = JS_DupValue(ctx, resolving_funcs[0]);
|
||||||
|
list_add_tail(&th->link, &ts->os_timers);
|
||||||
|
JS_FreeValue(ctx, resolving_funcs[0]);
|
||||||
|
JS_FreeValue(ctx, resolving_funcs[1]);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
static void call_handler(JSContext *ctx, JSValueConst func)
|
static void call_handler(JSContext *ctx, JSValueConst func)
|
||||||
{
|
{
|
||||||
JSValue ret, func1;
|
JSValue ret, func1;
|
||||||
|
@ -3030,6 +3088,13 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* getpid() -> pid */
|
||||||
|
static JSValue js_os_getpid(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
return JS_NewInt32(ctx, getpid());
|
||||||
|
}
|
||||||
|
|
||||||
/* waitpid(pid, block) -> [pid, status] */
|
/* waitpid(pid, block) -> [pid, status] */
|
||||||
static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val,
|
static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
|
@ -3274,6 +3339,7 @@ static void *worker_func(void *opaque)
|
||||||
JSRuntime *rt;
|
JSRuntime *rt;
|
||||||
JSThreadState *ts;
|
JSThreadState *ts;
|
||||||
JSContext *ctx;
|
JSContext *ctx;
|
||||||
|
JSValue promise;
|
||||||
|
|
||||||
rt = JS_NewRuntime();
|
rt = JS_NewRuntime();
|
||||||
if (rt == NULL) {
|
if (rt == NULL) {
|
||||||
|
@ -3300,8 +3366,11 @@ static void *worker_func(void *opaque)
|
||||||
|
|
||||||
js_std_add_helpers(ctx, -1, NULL);
|
js_std_add_helpers(ctx, -1, NULL);
|
||||||
|
|
||||||
if (!JS_RunModule(ctx, args->basename, args->filename))
|
promise = JS_LoadModule(ctx, args->basename, args->filename);
|
||||||
|
if (JS_IsException(promise))
|
||||||
js_std_dump_error(ctx);
|
js_std_dump_error(ctx);
|
||||||
|
/* XXX: check */
|
||||||
|
JS_FreeValue(ctx, promise);
|
||||||
free(args->filename);
|
free(args->filename);
|
||||||
free(args->basename);
|
free(args->basename);
|
||||||
free(args);
|
free(args);
|
||||||
|
@ -3621,8 +3690,10 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
OS_FLAG(SIGTTIN),
|
OS_FLAG(SIGTTIN),
|
||||||
OS_FLAG(SIGTTOU),
|
OS_FLAG(SIGTTOU),
|
||||||
#endif
|
#endif
|
||||||
|
JS_CFUNC_DEF("now", 0, js_os_now ),
|
||||||
JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ),
|
JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ),
|
||||||
JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ),
|
JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ),
|
||||||
|
JS_CFUNC_DEF("sleepAsync", 1, js_os_sleepAsync ),
|
||||||
JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ),
|
JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ),
|
||||||
JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ),
|
JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ),
|
||||||
JS_CFUNC_DEF("chdir", 0, js_os_chdir ),
|
JS_CFUNC_DEF("chdir", 0, js_os_chdir ),
|
||||||
|
@ -3650,6 +3721,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
|
JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
|
||||||
JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
|
JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
|
||||||
JS_CFUNC_DEF("exec", 1, js_os_exec ),
|
JS_CFUNC_DEF("exec", 1, js_os_exec ),
|
||||||
|
JS_CFUNC_DEF("getpid", 0, js_os_getpid ),
|
||||||
JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),
|
JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),
|
||||||
OS_FLAG(WNOHANG),
|
OS_FLAG(WNOHANG),
|
||||||
JS_CFUNC_DEF("pipe", 0, js_os_pipe ),
|
JS_CFUNC_DEF("pipe", 0, js_os_pipe ),
|
||||||
|
|
|
@ -172,6 +172,7 @@ DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||||
DEF( get_loc_check, 3, 0, 1, loc)
|
DEF( get_loc_check, 3, 0, 1, loc)
|
||||||
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||||
DEF( put_loc_check_init, 3, 1, 0, loc)
|
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||||
|
DEF(get_loc_checkthis, 3, 0, 1, loc)
|
||||||
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||||
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||||
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||||
|
@ -182,6 +183,7 @@ DEF( goto, 5, 0, 0, label) /* must come after if_true */
|
||||||
DEF( catch, 5, 0, 1, label)
|
DEF( catch, 5, 0, 1, label)
|
||||||
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
|
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
|
||||||
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
|
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
|
||||||
|
DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
|
||||||
|
|
||||||
DEF( to_object, 1, 1, 1, none)
|
DEF( to_object, 1, 1, 1, none)
|
||||||
//DEF( to_string, 1, 1, 1, none)
|
//DEF( to_string, 1, 1, 1, none)
|
||||||
|
@ -208,7 +210,6 @@ DEF( for_of_next, 2, 3, 5, u8)
|
||||||
DEF(iterator_check_object, 1, 1, 1, none)
|
DEF(iterator_check_object, 1, 1, 1, none)
|
||||||
DEF(iterator_get_value_done, 1, 1, 2, none)
|
DEF(iterator_get_value_done, 1, 1, 2, none)
|
||||||
DEF( iterator_close, 1, 3, 0, none)
|
DEF( iterator_close, 1, 3, 0, none)
|
||||||
DEF(iterator_close_return, 1, 4, 4, none)
|
|
||||||
DEF( iterator_next, 1, 4, 4, none)
|
DEF( iterator_next, 1, 4, 4, none)
|
||||||
DEF( iterator_call, 2, 4, 5, u8)
|
DEF( iterator_call, 2, 4, 5, u8)
|
||||||
DEF( initial_yield, 1, 0, 0, none)
|
DEF( initial_yield, 1, 0, 0, none)
|
||||||
|
@ -256,6 +257,7 @@ DEF( and, 1, 2, 1, none)
|
||||||
DEF( xor, 1, 2, 1, none)
|
DEF( xor, 1, 2, 1, none)
|
||||||
DEF( or, 1, 2, 1, none)
|
DEF( or, 1, 2, 1, none)
|
||||||
DEF(is_undefined_or_null, 1, 1, 1, none)
|
DEF(is_undefined_or_null, 1, 1, 1, none)
|
||||||
|
DEF( private_in, 1, 2, 1, none)
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
DEF( mul_pow10, 1, 2, 1, none)
|
DEF( mul_pow10, 1, 2, 1, none)
|
||||||
DEF( math_mod, 1, 2, 1, none)
|
DEF( math_mod, 1, 2, 1, none)
|
||||||
|
@ -270,6 +272,8 @@ def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
|
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
|
||||||
|
/* the following opcodes must be in the same order as the 'with_x' and
|
||||||
|
get_var_undef, get_var and put_var opcodes */
|
||||||
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
@ -277,10 +281,13 @@ def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase
|
||||||
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
|
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
|
||||||
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
||||||
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
||||||
def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
|
||||||
|
def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
|
||||||
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -307,6 +307,9 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
|
||||||
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
|
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
|
||||||
/* don't include the stack frames before this eval in the Error() backtraces */
|
/* don't include the stack frames before this eval in the Error() backtraces */
|
||||||
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
|
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
|
||||||
|
/* allow top-level await in normal script. JS_Eval() returns a
|
||||||
|
promise. Only allowed with JS_EVAL_TYPE_GLOBAL */
|
||||||
|
#define JS_EVAL_FLAG_ASYNC (1 << 7)
|
||||||
|
|
||||||
typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
|
typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
|
||||||
typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
|
typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
|
||||||
|
@ -733,13 +736,13 @@ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
|
||||||
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
||||||
uint32_t idx);
|
uint32_t idx);
|
||||||
|
|
||||||
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
|
int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
||||||
JSAtom prop, JSValue val,
|
JSAtom prop, JSValue val, JSValueConst this_obj,
|
||||||
int flags);
|
int flags);
|
||||||
static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
|
static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
|
||||||
JSAtom prop, JSValue val)
|
JSAtom prop, JSValue val)
|
||||||
{
|
{
|
||||||
return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
|
return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW);
|
||||||
}
|
}
|
||||||
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
|
||||||
uint32_t idx, JSValue val);
|
uint32_t idx, JSValue val);
|
||||||
|
@ -831,7 +834,15 @@ typedef struct {
|
||||||
void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
|
void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
|
||||||
const JSSharedArrayBufferFunctions *sf);
|
const JSSharedArrayBufferFunctions *sf);
|
||||||
|
|
||||||
|
typedef enum JSPromiseStateEnum {
|
||||||
|
JS_PROMISE_PENDING,
|
||||||
|
JS_PROMISE_FULFILLED,
|
||||||
|
JS_PROMISE_REJECTED,
|
||||||
|
} JSPromiseStateEnum;
|
||||||
|
|
||||||
JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
|
JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
|
||||||
|
JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise);
|
||||||
|
JSValue JS_PromiseResult(JSContext *ctx, JSValue promise);
|
||||||
|
|
||||||
/* is_handled = TRUE means that the rejection is handled */
|
/* is_handled = TRUE means that the rejection is handled */
|
||||||
typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise,
|
typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise,
|
||||||
|
@ -902,8 +913,8 @@ int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
|
||||||
/* only exported for os.Worker() */
|
/* only exported for os.Worker() */
|
||||||
JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
|
JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
|
||||||
/* only exported for os.Worker() */
|
/* only exported for os.Worker() */
|
||||||
JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
|
JSValue JS_LoadModule(JSContext *ctx, const char *basename,
|
||||||
const char *filename);
|
const char *filename);
|
||||||
|
|
||||||
/* C function definition */
|
/* C function definition */
|
||||||
typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
|
typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
|
||||||
|
|
|
@ -8,12 +8,12 @@ version=`cat VERSION`
|
||||||
if [ "$1" = "-h" ] ; then
|
if [ "$1" = "-h" ] ; then
|
||||||
echo "release.sh [release_list]"
|
echo "release.sh [release_list]"
|
||||||
echo ""
|
echo ""
|
||||||
echo "release_list: extras binary win_binary quickjs"
|
echo "release_list: extras binary win_binary cosmo_binary quickjs"
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
release_list="extras binary win_binary quickjs"
|
release_list="extras binary win_binary cosmo_binary quickjs"
|
||||||
|
|
||||||
if [ "$1" != "" ] ; then
|
if [ "$1" != "" ] ; then
|
||||||
release_list="$1"
|
release_list="$1"
|
||||||
|
@ -84,6 +84,28 @@ cp $dlldir/libwinpthread-1.dll $outdir
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#################################################"
|
||||||
|
# Cosmopolitan binary release
|
||||||
|
|
||||||
|
if echo $release_list | grep -w -q cosmo_binary ; then
|
||||||
|
|
||||||
|
export PATH=$PATH:$HOME/cosmocc/bin
|
||||||
|
|
||||||
|
d="quickjs-cosmo-${version}"
|
||||||
|
outdir="/tmp/${d}"
|
||||||
|
|
||||||
|
rm -rf $outdir
|
||||||
|
mkdir -p $outdir
|
||||||
|
|
||||||
|
make clean
|
||||||
|
make CONFIG_COSMO=y -j4 qjs run-test262
|
||||||
|
cp qjs run-test262 $outdir
|
||||||
|
cp readme-cosmo.txt $outdir/readme.txt
|
||||||
|
|
||||||
|
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
#################################################"
|
#################################################"
|
||||||
# Linux binary release
|
# Linux binary release
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ import * as os from "os";
|
||||||
var utf8 = true;
|
var utf8 = true;
|
||||||
var show_time = false;
|
var show_time = false;
|
||||||
var show_colors = true;
|
var show_colors = true;
|
||||||
|
var eval_start_time;
|
||||||
var eval_time = 0;
|
var eval_time = 0;
|
||||||
|
|
||||||
var mexpr = "";
|
var mexpr = "";
|
||||||
|
@ -814,10 +815,8 @@ import * as os from "os";
|
||||||
prompt += ps2;
|
prompt += ps2;
|
||||||
} else {
|
} else {
|
||||||
if (show_time) {
|
if (show_time) {
|
||||||
var t = Math.round(eval_time) + " ";
|
var t = eval_time / 1000;
|
||||||
eval_time = 0;
|
prompt += t.toFixed(6) + " ";
|
||||||
t = dupstr("0", 5 - t.length) + t;
|
|
||||||
prompt += t.substring(0, t.length - 4) + "." + t.substring(t.length - 4);
|
|
||||||
}
|
}
|
||||||
plen = prompt.length;
|
plen = prompt.length;
|
||||||
prompt += ps1;
|
prompt += ps1;
|
||||||
|
@ -1224,37 +1223,6 @@ import * as os from "os";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function eval_and_print(expr) {
|
|
||||||
var result;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (eval_mode === "math")
|
|
||||||
expr = '"use math"; void 0;' + expr;
|
|
||||||
var now = (new Date).getTime();
|
|
||||||
/* eval as a script */
|
|
||||||
result = std.evalScript(expr, { backtrace_barrier: true });
|
|
||||||
eval_time = (new Date).getTime() - now;
|
|
||||||
std.puts(colors[styles.result]);
|
|
||||||
print(result);
|
|
||||||
std.puts("\n");
|
|
||||||
std.puts(colors.none);
|
|
||||||
/* set the last result */
|
|
||||||
g._ = result;
|
|
||||||
} catch (error) {
|
|
||||||
std.puts(colors[styles.error_msg]);
|
|
||||||
if (error instanceof Error) {
|
|
||||||
console.log(error);
|
|
||||||
if (error.stack) {
|
|
||||||
std.puts(error.stack);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std.puts("Throw: ");
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
std.puts(colors.none);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function cmd_start() {
|
function cmd_start() {
|
||||||
if (!config_numcalc) {
|
if (!config_numcalc) {
|
||||||
if (has_jscalc)
|
if (has_jscalc)
|
||||||
|
@ -1281,29 +1249,32 @@ import * as os from "os";
|
||||||
}
|
}
|
||||||
|
|
||||||
function readline_handle_cmd(expr) {
|
function readline_handle_cmd(expr) {
|
||||||
handle_cmd(expr);
|
if (!handle_cmd(expr)) {
|
||||||
cmd_readline_start();
|
cmd_readline_start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return true if async termination */
|
||||||
function handle_cmd(expr) {
|
function handle_cmd(expr) {
|
||||||
var colorstate, cmd;
|
var colorstate, cmd;
|
||||||
|
|
||||||
if (expr === null) {
|
if (expr === null) {
|
||||||
expr = "";
|
expr = "";
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (expr === "?") {
|
if (expr === "?") {
|
||||||
help();
|
help();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
cmd = extract_directive(expr);
|
cmd = extract_directive(expr);
|
||||||
if (cmd.length > 0) {
|
if (cmd.length > 0) {
|
||||||
if (!handle_directive(cmd, expr))
|
if (!handle_directive(cmd, expr)) {
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
expr = expr.substring(cmd.length + 1);
|
expr = expr.substring(cmd.length + 1);
|
||||||
}
|
}
|
||||||
if (expr === "")
|
if (expr === "")
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (mexpr)
|
if (mexpr)
|
||||||
expr = mexpr + '\n' + expr;
|
expr = mexpr + '\n' + expr;
|
||||||
|
@ -1312,20 +1283,73 @@ import * as os from "os";
|
||||||
level = colorstate[1];
|
level = colorstate[1];
|
||||||
if (pstate) {
|
if (pstate) {
|
||||||
mexpr = expr;
|
mexpr = expr;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
mexpr = "";
|
mexpr = "";
|
||||||
|
|
||||||
if (has_bignum) {
|
if (has_bignum) {
|
||||||
BigFloatEnv.setPrec(eval_and_print.bind(null, expr),
|
/* XXX: async is not supported in this case */
|
||||||
|
BigFloatEnv.setPrec(eval_and_print_start.bind(null, expr, false),
|
||||||
prec, expBits);
|
prec, expBits);
|
||||||
} else {
|
} else {
|
||||||
eval_and_print(expr);
|
eval_and_print_start(expr, true);
|
||||||
}
|
}
|
||||||
level = 0;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function eval_and_print_start(expr, is_async) {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (eval_mode === "math")
|
||||||
|
expr = '"use math"; void 0;' + expr;
|
||||||
|
eval_start_time = os.now();
|
||||||
|
/* eval as a script */
|
||||||
|
result = std.evalScript(expr, { backtrace_barrier: true, async: is_async });
|
||||||
|
if (is_async) {
|
||||||
|
/* result is a promise */
|
||||||
|
result.then(print_eval_result, print_eval_error);
|
||||||
|
} else {
|
||||||
|
print_eval_result(result);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
print_eval_error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_eval_result(result) {
|
||||||
|
eval_time = os.now() - eval_start_time;
|
||||||
|
std.puts(colors[styles.result]);
|
||||||
|
print(result);
|
||||||
|
std.puts("\n");
|
||||||
|
std.puts(colors.none);
|
||||||
|
/* set the last result */
|
||||||
|
g._ = result;
|
||||||
|
|
||||||
|
handle_cmd_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_eval_error(error) {
|
||||||
|
std.puts(colors[styles.error_msg]);
|
||||||
|
if (error instanceof Error) {
|
||||||
|
console.log(error);
|
||||||
|
if (error.stack) {
|
||||||
|
std.puts(error.stack);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std.puts("Throw: ");
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
std.puts(colors.none);
|
||||||
|
|
||||||
|
handle_cmd_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_cmd_end() {
|
||||||
|
level = 0;
|
||||||
/* run the garbage collector after each command */
|
/* run the garbage collector after each command */
|
||||||
std.gc();
|
std.gc();
|
||||||
|
cmd_readline_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
function colorize_js(str) {
|
function colorize_js(str) {
|
||||||
|
|
|
@ -1174,7 +1174,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
|
||||||
{
|
{
|
||||||
JSValue res_val, exception_val;
|
JSValue res_val, exception_val;
|
||||||
int ret, error_line, pos, pos_line;
|
int ret, error_line, pos, pos_line;
|
||||||
BOOL is_error, has_error_line;
|
BOOL is_error, has_error_line, ret_promise;
|
||||||
const char *error_name;
|
const char *error_name;
|
||||||
|
|
||||||
pos = skip_comments(buf, 1, &pos_line);
|
pos = skip_comments(buf, 1, &pos_line);
|
||||||
|
@ -1183,12 +1183,19 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
|
||||||
exception_val = JS_UNDEFINED;
|
exception_val = JS_UNDEFINED;
|
||||||
error_name = NULL;
|
error_name = NULL;
|
||||||
|
|
||||||
|
/* a module evaluation returns a promise */
|
||||||
|
ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0);
|
||||||
async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
|
async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
|
||||||
|
|
||||||
res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
||||||
|
|
||||||
if (is_async && !JS_IsException(res_val)) {
|
if ((is_async || ret_promise) && !JS_IsException(res_val)) {
|
||||||
JS_FreeValue(ctx, res_val);
|
JSValue promise = JS_UNDEFINED;
|
||||||
|
if (ret_promise) {
|
||||||
|
promise = res_val;
|
||||||
|
} else {
|
||||||
|
JS_FreeValue(ctx, res_val);
|
||||||
|
}
|
||||||
for(;;) {
|
for(;;) {
|
||||||
JSContext *ctx1;
|
JSContext *ctx1;
|
||||||
ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
|
ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
|
||||||
|
@ -1196,15 +1203,27 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
|
||||||
res_val = JS_EXCEPTION;
|
res_val = JS_EXCEPTION;
|
||||||
break;
|
break;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
/* test if the test called $DONE() once */
|
if (is_async) {
|
||||||
if (async_done != 1) {
|
/* test if the test called $DONE() once */
|
||||||
res_val = JS_ThrowTypeError(ctx, "$DONE() not called");
|
if (async_done != 1) {
|
||||||
|
res_val = JS_ThrowTypeError(ctx, "$DONE() not called");
|
||||||
|
} else {
|
||||||
|
res_val = JS_UNDEFINED;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
res_val = JS_UNDEFINED;
|
/* check that the returned promise is fulfilled */
|
||||||
|
JSPromiseStateEnum state = JS_PromiseState(ctx, promise);
|
||||||
|
if (state == JS_PROMISE_FULFILLED)
|
||||||
|
res_val = JS_UNDEFINED;
|
||||||
|
else if (state == JS_PROMISE_REJECTED)
|
||||||
|
res_val = JS_Throw(ctx, JS_PromiseResult(ctx, promise));
|
||||||
|
else
|
||||||
|
res_val = JS_ThrowTypeError(ctx, "promise is pending");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JS_FreeValue(ctx, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JS_IsException(res_val)) {
|
if (JS_IsException(res_val)) {
|
||||||
|
@ -1498,7 +1517,7 @@ void update_stats(JSRuntime *rt, const char *filename) {
|
||||||
#undef update
|
#undef update
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_test_buf(const char *filename, char *harness, namelist_t *ip,
|
int run_test_buf(const char *filename, const char *harness, namelist_t *ip,
|
||||||
char *buf, size_t buf_len, const char* error_type,
|
char *buf, size_t buf_len, const char* error_type,
|
||||||
int eval_flags, BOOL is_negative, BOOL is_async,
|
int eval_flags, BOOL is_negative, BOOL is_async,
|
||||||
BOOL can_block)
|
BOOL can_block)
|
||||||
|
@ -1582,6 +1601,8 @@ int run_test(const char *filename, int index)
|
||||||
if (p) {
|
if (p) {
|
||||||
snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s",
|
snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s",
|
||||||
(int)(p - filename), filename, "harness");
|
(int)(p - filename), filename, "harness");
|
||||||
|
} else {
|
||||||
|
pstrcpy(harnessbuf, sizeof(harnessbuf), "");
|
||||||
}
|
}
|
||||||
harness = harnessbuf;
|
harness = harnessbuf;
|
||||||
}
|
}
|
||||||
|
@ -1669,6 +1690,8 @@ int run_test(const char *filename, int index)
|
||||||
if (p) {
|
if (p) {
|
||||||
snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s",
|
snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s",
|
||||||
(int)(p - filename), filename, "test/harness");
|
(int)(p - filename), filename, "test/harness");
|
||||||
|
} else {
|
||||||
|
pstrcpy(harnessbuf, sizeof(harnessbuf), "");
|
||||||
}
|
}
|
||||||
harness = harnessbuf;
|
harness = harnessbuf;
|
||||||
}
|
}
|
||||||
|
@ -1835,17 +1858,32 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
|
||||||
js_std_dump_error(ctx);
|
js_std_dump_error(ctx);
|
||||||
ret_code = 1;
|
ret_code = 1;
|
||||||
} else {
|
} else {
|
||||||
JS_FreeValue(ctx, res_val);
|
JSValue promise = JS_UNDEFINED;
|
||||||
|
if (is_module) {
|
||||||
|
promise = res_val;
|
||||||
|
} else {
|
||||||
|
JS_FreeValue(ctx, res_val);
|
||||||
|
}
|
||||||
for(;;) {
|
for(;;) {
|
||||||
JSContext *ctx1;
|
JSContext *ctx1;
|
||||||
ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
|
ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
js_std_dump_error(ctx1);
|
js_std_dump_error(ctx1);
|
||||||
ret_code = 1;
|
ret_code = 1;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* dump the error if the module returned an error. */
|
||||||
|
if (is_module) {
|
||||||
|
JSPromiseStateEnum state = JS_PromiseState(ctx, promise);
|
||||||
|
if (state == JS_PROMISE_REJECTED) {
|
||||||
|
JS_Throw(ctx, JS_PromiseResult(ctx, promise));
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
ret_code = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JS_FreeValue(ctx, promise);
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
#ifdef CONFIG_AGENT
|
#ifdef CONFIG_AGENT
|
||||||
|
|
|
@ -47,16 +47,25 @@ testdir=test262/test
|
||||||
# Standard language features and proposed extensions
|
# Standard language features and proposed extensions
|
||||||
# list the features that are included
|
# list the features that are included
|
||||||
# skipped features are tagged as such to avoid warnings
|
# skipped features are tagged as such to avoid warnings
|
||||||
|
# Keep this list alpha-sorted (:sort i in vim)
|
||||||
|
|
||||||
|
__getter__
|
||||||
|
__proto__
|
||||||
|
__setter__
|
||||||
AggregateError
|
AggregateError
|
||||||
align-detached-buffer-semantics-with-web-reality
|
align-detached-buffer-semantics-with-web-reality
|
||||||
arbitrary-module-namespace-names=skip
|
arbitrary-module-namespace-names=skip
|
||||||
Array.prototype.at=skip
|
array-find-from-last
|
||||||
|
array-grouping
|
||||||
|
Array.fromAsync=skip
|
||||||
|
Array.prototype.at
|
||||||
Array.prototype.flat
|
Array.prototype.flat
|
||||||
Array.prototype.flatMap
|
Array.prototype.flatMap
|
||||||
Array.prototype.flatten
|
Array.prototype.flatten
|
||||||
|
Array.prototype.includes
|
||||||
Array.prototype.values
|
Array.prototype.values
|
||||||
ArrayBuffer
|
ArrayBuffer
|
||||||
|
arraybuffer-transfer=skip
|
||||||
arrow-function
|
arrow-function
|
||||||
async-functions
|
async-functions
|
||||||
async-iteration
|
async-iteration
|
||||||
|
@ -64,12 +73,15 @@ Atomics
|
||||||
Atomics.waitAsync=skip
|
Atomics.waitAsync=skip
|
||||||
BigInt
|
BigInt
|
||||||
caller
|
caller
|
||||||
|
change-array-by-copy
|
||||||
class
|
class
|
||||||
class-fields-private
|
class-fields-private
|
||||||
|
class-fields-private-in
|
||||||
class-fields-public
|
class-fields-public
|
||||||
class-methods-private
|
class-methods-private
|
||||||
class-static-fields-public
|
class-static-block
|
||||||
class-static-fields-private
|
class-static-fields-private
|
||||||
|
class-static-fields-public
|
||||||
class-static-methods-private
|
class-static-methods-private
|
||||||
cleanupSome=skip
|
cleanupSome=skip
|
||||||
coalesce-expression
|
coalesce-expression
|
||||||
|
@ -85,14 +97,17 @@ DataView.prototype.getInt8
|
||||||
DataView.prototype.getUint16
|
DataView.prototype.getUint16
|
||||||
DataView.prototype.getUint32
|
DataView.prototype.getUint32
|
||||||
DataView.prototype.setUint8
|
DataView.prototype.setUint8
|
||||||
|
decorators=skip
|
||||||
default-parameters
|
default-parameters
|
||||||
destructuring-assignment
|
destructuring-assignment
|
||||||
destructuring-binding
|
destructuring-binding
|
||||||
dynamic-import
|
dynamic-import
|
||||||
|
error-cause
|
||||||
|
exponentiation
|
||||||
export-star-as-namespace-from-module
|
export-star-as-namespace-from-module
|
||||||
FinalizationGroup=skip
|
FinalizationGroup=skip
|
||||||
FinalizationRegistry=skip
|
|
||||||
FinalizationRegistry.prototype.cleanupSome=skip
|
FinalizationRegistry.prototype.cleanupSome=skip
|
||||||
|
FinalizationRegistry=skip
|
||||||
Float32Array
|
Float32Array
|
||||||
Float64Array
|
Float64Array
|
||||||
for-in-order
|
for-in-order
|
||||||
|
@ -101,11 +116,16 @@ generators
|
||||||
globalThis
|
globalThis
|
||||||
hashbang
|
hashbang
|
||||||
host-gc-required=skip
|
host-gc-required=skip
|
||||||
|
import-assertions=skip
|
||||||
|
import-attributes=skip
|
||||||
import.meta
|
import.meta
|
||||||
Int16Array
|
Int16Array
|
||||||
Int32Array
|
Int32Array
|
||||||
Int8Array
|
Int8Array
|
||||||
IsHTMLDDA
|
IsHTMLDDA
|
||||||
|
iterator-helpers=skip
|
||||||
|
json-modules=skip
|
||||||
|
json-parse-with-source=skip
|
||||||
json-superset
|
json-superset
|
||||||
legacy-regexp=skip
|
legacy-regexp=skip
|
||||||
let
|
let
|
||||||
|
@ -116,10 +136,12 @@ numeric-separator-literal
|
||||||
object-rest
|
object-rest
|
||||||
object-spread
|
object-spread
|
||||||
Object.fromEntries
|
Object.fromEntries
|
||||||
|
Object.hasOwn
|
||||||
Object.is
|
Object.is
|
||||||
optional-catch-binding
|
optional-catch-binding
|
||||||
optional-chaining
|
optional-chaining
|
||||||
Promise
|
Promise
|
||||||
|
promise-with-resolvers
|
||||||
Promise.allSettled
|
Promise.allSettled
|
||||||
Promise.any
|
Promise.any
|
||||||
Promise.prototype.finally
|
Promise.prototype.finally
|
||||||
|
@ -130,20 +152,27 @@ Reflect.construct
|
||||||
Reflect.set
|
Reflect.set
|
||||||
Reflect.setPrototypeOf
|
Reflect.setPrototypeOf
|
||||||
regexp-dotall
|
regexp-dotall
|
||||||
|
regexp-duplicate-named-groups=skip
|
||||||
regexp-lookbehind
|
regexp-lookbehind
|
||||||
regexp-match-indices=skip
|
regexp-match-indices
|
||||||
regexp-named-groups
|
regexp-named-groups
|
||||||
regexp-unicode-property-escapes
|
regexp-unicode-property-escapes
|
||||||
|
regexp-v-flag=skip
|
||||||
|
resizable-arraybuffer=skip
|
||||||
rest-parameters
|
rest-parameters
|
||||||
Set
|
Set
|
||||||
|
set-methods=skip
|
||||||
|
ShadowRealm=skip
|
||||||
SharedArrayBuffer
|
SharedArrayBuffer
|
||||||
string-trimming
|
string-trimming
|
||||||
String.fromCodePoint
|
String.fromCodePoint
|
||||||
|
String.prototype.at
|
||||||
String.prototype.endsWith
|
String.prototype.endsWith
|
||||||
String.prototype.includes
|
String.prototype.includes
|
||||||
String.prototype.at=skip
|
String.prototype.isWellFormed
|
||||||
String.prototype.matchAll
|
String.prototype.matchAll
|
||||||
String.prototype.replaceAll
|
String.prototype.replaceAll
|
||||||
|
String.prototype.toWellFormed
|
||||||
String.prototype.trimEnd
|
String.prototype.trimEnd
|
||||||
String.prototype.trimStart
|
String.prototype.trimStart
|
||||||
super
|
super
|
||||||
|
@ -162,11 +191,13 @@ Symbol.split
|
||||||
Symbol.toPrimitive
|
Symbol.toPrimitive
|
||||||
Symbol.toStringTag
|
Symbol.toStringTag
|
||||||
Symbol.unscopables
|
Symbol.unscopables
|
||||||
|
symbols-as-weakmap-keys=skip
|
||||||
tail-call-optimization=skip
|
tail-call-optimization=skip
|
||||||
template
|
template
|
||||||
top-level-await=skip
|
Temporal=skip
|
||||||
|
top-level-await
|
||||||
TypedArray
|
TypedArray
|
||||||
TypedArray.prototype.at=skip
|
TypedArray.prototype.at
|
||||||
u180e
|
u180e
|
||||||
Uint16Array
|
Uint16Array
|
||||||
Uint32Array
|
Uint32Array
|
||||||
|
@ -176,9 +207,6 @@ WeakMap
|
||||||
WeakRef=skip
|
WeakRef=skip
|
||||||
WeakSet
|
WeakSet
|
||||||
well-formed-json-stringify
|
well-formed-json-stringify
|
||||||
__getter__
|
|
||||||
__proto__
|
|
||||||
__setter__
|
|
||||||
|
|
||||||
[exclude]
|
[exclude]
|
||||||
# list excluded tests and directories here
|
# list excluded tests and directories here
|
||||||
|
|
|
@ -1,35 +1,8 @@
|
||||||
test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: Test262Error: Expected a ReferenceError but got a ReferenceError
|
test262/test/annexB/language/eval-code/direct/script-decl-lex-collision-in-sloppy-mode.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||||
test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError
|
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: Test262Error: Expected a DummyError but got a TypeError
|
||||||
test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: SyntaxError: invalid group name
|
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
|
||||||
test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: strict mode: SyntaxError: invalid group name
|
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: Test262Error: Expected a DummyError but got a TypeError
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: Test262Error: (Testing with BigInt64Array.)
|
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: strict mode: Test262Error: (Testing with BigInt64Array.)
|
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated.
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:47: Test262Error: (Testing with Float64Array.)
|
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated.
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:47: strict mode: Test262Error: (Testing with Float64Array.)
|
test262/test/language/global-code/script-decl-lex-var-declared-via-eval-sloppy.js:13: Test262Error: variable Expected a SyntaxError to be thrown but no exception was thrown at all
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer-realm.js:37: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:34: TypeError: cannot convert bigint to number (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-minus-zero.js:20: Test262Error: Reflect.set("new TA([42n])", "-0", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-minus-zero.js:20: strict mode: Test262Error: Reflect.set("new TA([42n])", "-0", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-not-integer.js:21: Test262Error: Reflect.set("new TA([42n])", "1.1", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-not-integer.js:21: strict mode: Test262Error: Reflect.set("new TA([42n])", "1.1", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds.js:27: Test262Error: Reflect.set("new TA([42n])", "-1", 1n) must return false Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds.js:27: strict mode: Test262Error: Reflect.set("new TA([42n])", "-1", 1n) must return false Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/tonumber-value-detached-buffer.js:24: Test262Error: Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/tonumber-value-detached-buffer.js:24: strict mode: Test262Error: Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer-realm.js:37: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:22: Test262Error: Reflect.set(sample, "-0", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:22: strict mode: Test262Error: Reflect.set(sample, "-0", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js:22: Test262Error: Reflect.set(sample, "1.1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js:22: strict mode: Test262Error: Reflect.set(sample, "1.1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js:22: Test262Error: Reflect.set(sample, "-1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js:22: strict mode: Test262Error: Reflect.set(sample, "-1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js:39: Test262Error: Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js:39: strict mode: Test262Error: Expected SameValue(«false», «true») to be true (Testing with Float64Array.)
|
|
||||||
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called
|
|
||||||
test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called
|
|
||||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined
|
|
||||||
test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined
|
|
||||||
test262/test/language/statements/for-of/head-lhs-async-invalid.js:14: unexpected error type: Test262: This statement should not be evaluated.
|
|
||||||
test262/test/language/statements/for-of/head-lhs-async-invalid.js:14: strict mode: unexpected error type: Test262: This statement should not be evaluated.
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
import * as std from "std";
|
import * as std from "std";
|
||||||
|
import * as os from "os";
|
||||||
|
|
||||||
function pad(str, n) {
|
function pad(str, n) {
|
||||||
str += "";
|
str += "";
|
||||||
|
@ -93,21 +94,12 @@ function log_line() {
|
||||||
console.log(s);
|
console.log(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
var clocks_per_sec = 1000000;
|
var clocks_per_sec = 1000;
|
||||||
var max_iterations = 100;
|
var max_iterations = 10;
|
||||||
var clock_threshold = 2000; /* favoring short measuring spans */
|
var clock_threshold = 100; /* favoring short measuring spans */
|
||||||
var min_n_argument = 1;
|
var min_n_argument = 1;
|
||||||
var get_clock;
|
//var get_clock = Date.now;
|
||||||
|
var get_clock = os.now;
|
||||||
if (typeof globalThis.__date_clock != "function") {
|
|
||||||
console.log("using fallback millisecond clock");
|
|
||||||
clocks_per_sec = 1000;
|
|
||||||
max_iterations = 10;
|
|
||||||
clock_threshold = 100;
|
|
||||||
get_clock = Date.now;
|
|
||||||
} else {
|
|
||||||
get_clock = globalThis.__date_clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_one(text, n, ti) {
|
function log_one(text, n, ti) {
|
||||||
var ref;
|
var ref;
|
||||||
|
|
|
@ -538,7 +538,17 @@ function test_regexp()
|
||||||
|
|
||||||
assert(/{1a}/.toString(), "/{1a}/");
|
assert(/{1a}/.toString(), "/{1a}/");
|
||||||
a = /a{1+/.exec("a{11");
|
a = /a{1+/.exec("a{11");
|
||||||
assert(a, ["a{11"] );
|
assert(a, ["a{11"]);
|
||||||
|
|
||||||
|
/* test zero length matches */
|
||||||
|
a = /(?:(?=(abc)))a/.exec("abc");
|
||||||
|
assert(a, ["a", "abc"]);
|
||||||
|
a = /(?:(?=(abc)))?a/.exec("abc");
|
||||||
|
assert(a, ["a", undefined]);
|
||||||
|
a = /(?:(?=(abc))){0,2}a/.exec("abc");
|
||||||
|
assert(a, ["a", undefined]);
|
||||||
|
a = /(?:|[\w])+([0-9])/.exec("123a23");
|
||||||
|
assert(a, ["123a23", "3"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_symbol()
|
function test_symbol()
|
||||||
|
@ -645,6 +655,18 @@ function test_generator()
|
||||||
assert(ret, "ret_val");
|
assert(ret, "ret_val");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
function *f3() {
|
||||||
|
var ret;
|
||||||
|
/* test stack consistency with nip_n to handle yield return +
|
||||||
|
* finally clause */
|
||||||
|
try {
|
||||||
|
ret = 2 + (yield 1);
|
||||||
|
} catch(e) {
|
||||||
|
} finally {
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
var g, v;
|
var g, v;
|
||||||
g = f();
|
g = f();
|
||||||
v = g.next();
|
v = g.next();
|
||||||
|
@ -665,6 +687,12 @@ function test_generator()
|
||||||
assert(v.value === 3 && v.done === true);
|
assert(v.value === 3 && v.done === true);
|
||||||
v = g.next();
|
v = g.next();
|
||||||
assert(v.value === undefined && v.done === true);
|
assert(v.value === undefined && v.done === true);
|
||||||
|
|
||||||
|
g = f3();
|
||||||
|
v = g.next();
|
||||||
|
assert(v.value === 1 && v.done === false);
|
||||||
|
v = g.next(3);
|
||||||
|
assert(v.value === 6 && v.done === true);
|
||||||
}
|
}
|
||||||
|
|
||||||
test();
|
test();
|
||||||
|
|
|
@ -120,6 +120,7 @@ function test_cvt()
|
||||||
assert((Infinity >>> 0) === 0);
|
assert((Infinity >>> 0) === 0);
|
||||||
assert(((-Infinity) >>> 0) === 0);
|
assert(((-Infinity) >>> 0) === 0);
|
||||||
assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4));
|
assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4));
|
||||||
|
assert((19686109595169230000).toString() === "19686109595169230000");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_eq()
|
function test_eq()
|
||||||
|
@ -325,6 +326,15 @@ function test_class()
|
||||||
/* test class name scope */
|
/* test class name scope */
|
||||||
var E1 = class E { static F() { return E; } };
|
var E1 = class E { static F() { return E; } };
|
||||||
assert(E1 === E1.F());
|
assert(E1 === E1.F());
|
||||||
|
|
||||||
|
class S {
|
||||||
|
static x = 42;
|
||||||
|
static y = S.x;
|
||||||
|
static z = this.x;
|
||||||
|
}
|
||||||
|
assert(S.x === 42);
|
||||||
|
assert(S.y === 42);
|
||||||
|
assert(S.z === 42);
|
||||||
};
|
};
|
||||||
|
|
||||||
function test_template()
|
function test_template()
|
||||||
|
@ -526,6 +536,53 @@ function test_function_expr_name()
|
||||||
assert_throws(TypeError, f);
|
assert_throws(TypeError, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_parse_semicolon()
|
||||||
|
{
|
||||||
|
/* 'yield' or 'await' may not be considered as a token if the
|
||||||
|
previous ';' is missing */
|
||||||
|
function *f()
|
||||||
|
{
|
||||||
|
function func() {
|
||||||
|
}
|
||||||
|
yield 1;
|
||||||
|
var h = x => x + 1
|
||||||
|
yield 2;
|
||||||
|
}
|
||||||
|
async function g()
|
||||||
|
{
|
||||||
|
function func() {
|
||||||
|
}
|
||||||
|
await 1;
|
||||||
|
var h = x => x + 1
|
||||||
|
await 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* optional chaining tests not present in test262 */
|
||||||
|
function test_optional_chaining()
|
||||||
|
{
|
||||||
|
var a, z;
|
||||||
|
z = null;
|
||||||
|
a = { b: { c: 2 } };
|
||||||
|
assert(delete z?.b.c, true);
|
||||||
|
assert(delete a?.b.c, true);
|
||||||
|
assert(JSON.stringify(a), '{"b":{}}', "optional chaining delete");
|
||||||
|
|
||||||
|
a = { b: { c: 2 } };
|
||||||
|
assert(delete z?.b["c"], true);
|
||||||
|
assert(delete a?.b["c"], true);
|
||||||
|
assert(JSON.stringify(a), '{"b":{}}');
|
||||||
|
|
||||||
|
a = {
|
||||||
|
b() { return this._b; },
|
||||||
|
_b: { c: 42 }
|
||||||
|
};
|
||||||
|
|
||||||
|
assert((a?.b)().c, 42);
|
||||||
|
|
||||||
|
assert((a?.["b"])().c, 42);
|
||||||
|
}
|
||||||
|
|
||||||
test_op1();
|
test_op1();
|
||||||
test_cvt();
|
test_cvt();
|
||||||
test_eq();
|
test_eq();
|
||||||
|
@ -545,3 +602,5 @@ test_spread();
|
||||||
test_function_length();
|
test_function_length();
|
||||||
test_argument_scope();
|
test_argument_scope();
|
||||||
test_function_expr_name();
|
test_function_expr_name();
|
||||||
|
test_parse_semicolon();
|
||||||
|
test_optional_chaining();
|
||||||
|
|
|
@ -167,6 +167,29 @@ function test_for_in2()
|
||||||
assert(tab.toString() == "x,y");
|
assert(tab.toString() == "x,y");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_for_in_proxy() {
|
||||||
|
let removed_key = "";
|
||||||
|
let target = {}
|
||||||
|
let proxy = new Proxy(target, {
|
||||||
|
ownKeys: function() {
|
||||||
|
return ["a", "b", "c"];
|
||||||
|
},
|
||||||
|
getOwnPropertyDescriptor: function(target, key) {
|
||||||
|
if (removed_key != "" && key == removed_key)
|
||||||
|
return undefined;
|
||||||
|
else
|
||||||
|
return { enumerable: true, configurable: true, value: this[key] };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let str = "";
|
||||||
|
for(let o in proxy) {
|
||||||
|
str += " " + o;
|
||||||
|
if (o == "a")
|
||||||
|
removed_key = "b";
|
||||||
|
}
|
||||||
|
assert(str == " a c");
|
||||||
|
}
|
||||||
|
|
||||||
function test_for_break()
|
function test_for_break()
|
||||||
{
|
{
|
||||||
var i, c;
|
var i, c;
|
||||||
|
@ -357,6 +380,7 @@ test_switch1();
|
||||||
test_switch2();
|
test_switch2();
|
||||||
test_for_in();
|
test_for_in();
|
||||||
test_for_in2();
|
test_for_in2();
|
||||||
|
test_for_in_proxy();
|
||||||
|
|
||||||
test_try_catch1();
|
test_try_catch1();
|
||||||
test_try_catch2();
|
test_try_catch2();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#! (shebang test)
|
||||||
import * as std from "std";
|
import * as std from "std";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
|
|
||||||
|
@ -270,6 +271,26 @@ function test_timer()
|
||||||
os.clearTimeout(th[i]);
|
os.clearTimeout(th[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* test closure variable handling when freeing asynchronous
|
||||||
|
function */
|
||||||
|
function test_async_gc()
|
||||||
|
{
|
||||||
|
(async function run () {
|
||||||
|
let obj = {}
|
||||||
|
|
||||||
|
let done = () => {
|
||||||
|
obj
|
||||||
|
std.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.resolve().then(done)
|
||||||
|
|
||||||
|
const p = new Promise(() => {})
|
||||||
|
|
||||||
|
await p
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
test_printf();
|
test_printf();
|
||||||
test_file1();
|
test_file1();
|
||||||
test_file2();
|
test_file2();
|
||||||
|
@ -279,3 +300,5 @@ test_os();
|
||||||
test_os_exec();
|
test_os_exec();
|
||||||
test_timer();
|
test_timer();
|
||||||
test_ext_json();
|
test_ext_json();
|
||||||
|
test_async_gc();
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ function handle_msg(e) {
|
||||||
switch(ev.type) {
|
switch(ev.type) {
|
||||||
case "abort":
|
case "abort":
|
||||||
parent.postMessage({ type: "done" });
|
parent.postMessage({ type: "done" });
|
||||||
|
parent.onMessage = null; /* terminate the worker */
|
||||||
break;
|
break;
|
||||||
case "sab":
|
case "sab":
|
||||||
/* modify the SharedArrayBuffer */
|
/* modify the SharedArrayBuffer */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
url="ftp://ftp.unicode.org/Public/13.0.0/ucd"
|
url="ftp://ftp.unicode.org/Public/15.0.0/ucd"
|
||||||
emoji_url="${url}/emoji/emoji-data.txt"
|
emoji_url="${url}/emoji/emoji-data.txt"
|
||||||
|
|
||||||
files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \
|
files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \
|
||||||
|
@ -11,9 +11,9 @@ PropertyValueAliases.txt"
|
||||||
|
|
||||||
mkdir -p unicode
|
mkdir -p unicode
|
||||||
|
|
||||||
#for f in $files; do
|
for f in $files; do
|
||||||
# g="${url}/${f}"
|
g="${url}/${f}"
|
||||||
# wget $g -O unicode/$f
|
wget $g -O unicode/$f
|
||||||
#done
|
done
|
||||||
|
|
||||||
wget $emoji_url -O unicode/emoji-data.txt
|
wget $emoji_url -O unicode/emoji-data.txt
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
//#define DUMP_TABLE_SIZE
|
//#define DUMP_TABLE_SIZE
|
||||||
//#define DUMP_CC_TABLE
|
//#define DUMP_CC_TABLE
|
||||||
//#define DUMP_DECOMP_TABLE
|
//#define DUMP_DECOMP_TABLE
|
||||||
|
//#define DUMP_CASE_FOLDING_SPECIAL_CASES
|
||||||
|
|
||||||
/* Ideas:
|
/* Ideas:
|
||||||
- Generalize run length encoding + index for all tables
|
- Generalize run length encoding + index for all tables
|
||||||
|
@ -217,15 +218,16 @@ static const char *unicode_prop_short_name[] = {
|
||||||
#undef DEF
|
#undef DEF
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef UNICODE_SPROP_LIST
|
#undef UNICODE_PROP_LIST
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* case conv */
|
/* case conv */
|
||||||
uint8_t u_len;
|
uint8_t u_len;
|
||||||
uint8_t l_len;
|
uint8_t l_len;
|
||||||
int u_data[CC_LEN_MAX];
|
uint8_t f_len;
|
||||||
int l_data[CC_LEN_MAX];
|
int u_data[CC_LEN_MAX]; /* to upper case */
|
||||||
int f_code;
|
int l_data[CC_LEN_MAX]; /* to lower case */
|
||||||
|
int f_data[CC_LEN_MAX]; /* to case folding */
|
||||||
|
|
||||||
uint8_t combining_class;
|
uint8_t combining_class;
|
||||||
uint8_t is_compat:1;
|
uint8_t is_compat:1;
|
||||||
|
@ -499,7 +501,7 @@ void parse_case_folding(CCInfo *tab, const char *filename)
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
const char *p;
|
const char *p;
|
||||||
int code;
|
int code, status;
|
||||||
CCInfo *ci;
|
CCInfo *ci;
|
||||||
|
|
||||||
f = fopen(filename, "rb");
|
f = fopen(filename, "rb");
|
||||||
|
@ -530,14 +532,28 @@ void parse_case_folding(CCInfo *tab, const char *filename)
|
||||||
/* locale dependent casing */
|
/* locale dependent casing */
|
||||||
while (isspace(*p))
|
while (isspace(*p))
|
||||||
p++;
|
p++;
|
||||||
if (*p != 'C' && *p != 'S')
|
status = *p;
|
||||||
|
if (status != 'C' && status != 'S' && status != 'F')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
p = get_field(line, 2);
|
p = get_field(line, 2);
|
||||||
assert(p != 0);
|
assert(p != NULL);
|
||||||
assert(ci->f_code == 0);
|
if (status == 'S') {
|
||||||
ci->f_code = strtoul(p, NULL, 16);
|
/* we always select the simple case folding and assume it
|
||||||
assert(ci->f_code != 0 && ci->f_code != code);
|
* comes after the full case folding case */
|
||||||
|
assert(ci->f_len >= 2);
|
||||||
|
ci->f_len = 0;
|
||||||
|
} else {
|
||||||
|
assert(ci->f_len == 0);
|
||||||
|
}
|
||||||
|
for(;;) {
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
if (*p == ';')
|
||||||
|
break;
|
||||||
|
assert(ci->l_len < CC_LEN_MAX);
|
||||||
|
ci->f_data[ci->f_len++] = strtoul(p, (char **)&p, 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -864,19 +880,21 @@ void dump_cc_info(CCInfo *ci, int i)
|
||||||
for(j = 0; j < ci->l_len; j++)
|
for(j = 0; j < ci->l_len; j++)
|
||||||
printf(" %05x", ci->l_data[j]);
|
printf(" %05x", ci->l_data[j]);
|
||||||
}
|
}
|
||||||
if (ci->f_code != 0) {
|
if (ci->f_len != 0) {
|
||||||
printf(" F: %05x", ci->f_code);
|
printf(" F:");
|
||||||
|
for(j = 0; j < ci->f_len; j++)
|
||||||
|
printf(" %05x", ci->f_data[j]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_data(CCInfo *tab)
|
void dump_unicode_data(CCInfo *tab)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
CCInfo *ci;
|
CCInfo *ci;
|
||||||
for(i = 0; i <= CHARCODE_MAX; i++) {
|
for(i = 0; i <= CHARCODE_MAX; i++) {
|
||||||
ci = &tab[i];
|
ci = &tab[i];
|
||||||
if (ci->u_len != 0 || ci->l_len != 0 || ci->f_code != 0) {
|
if (ci->u_len != 0 || ci->l_len != 0 || ci->f_len != 0) {
|
||||||
dump_cc_info(ci, i);
|
dump_cc_info(ci, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,8 +904,8 @@ BOOL is_complicated_case(const CCInfo *ci)
|
||||||
{
|
{
|
||||||
return (ci->u_len > 1 || ci->l_len > 1 ||
|
return (ci->u_len > 1 || ci->l_len > 1 ||
|
||||||
(ci->u_len > 0 && ci->l_len > 0) ||
|
(ci->u_len > 0 && ci->l_len > 0) ||
|
||||||
(ci->f_code != 0) != ci->l_len ||
|
(ci->f_len != ci->l_len) ||
|
||||||
(ci->f_code != 0 && ci->l_data[0] != ci->f_code));
|
(memcmp(ci->f_data, ci->l_data, ci->f_len * sizeof(ci->f_data[0])) != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_TEST
|
#ifndef USE_TEST
|
||||||
|
@ -903,9 +921,9 @@ enum {
|
||||||
RUN_TYPE_UF_D1_EXT,
|
RUN_TYPE_UF_D1_EXT,
|
||||||
RUN_TYPE_U_EXT,
|
RUN_TYPE_U_EXT,
|
||||||
RUN_TYPE_LF_EXT,
|
RUN_TYPE_LF_EXT,
|
||||||
RUN_TYPE_U_EXT2,
|
RUN_TYPE_UF_EXT2,
|
||||||
RUN_TYPE_L_EXT2,
|
RUN_TYPE_LF_EXT2,
|
||||||
RUN_TYPE_U_EXT3,
|
RUN_TYPE_UF_EXT3,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -921,9 +939,9 @@ const char *run_type_str[] = {
|
||||||
"UF_D1_EXT",
|
"UF_D1_EXT",
|
||||||
"U_EXT",
|
"U_EXT",
|
||||||
"LF_EXT",
|
"LF_EXT",
|
||||||
"U_EXT2",
|
"UF_EXT2",
|
||||||
"L_EXT2",
|
"LF_EXT2",
|
||||||
"U_EXT3",
|
"UF_EXT3",
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -936,6 +954,13 @@ typedef struct {
|
||||||
int data_index; /* 'data' coming from the table */
|
int data_index; /* 'data' coming from the table */
|
||||||
} TableEntry;
|
} TableEntry;
|
||||||
|
|
||||||
|
static int simple_to_lower(CCInfo *tab, int c)
|
||||||
|
{
|
||||||
|
if (tab[c].l_len != 1)
|
||||||
|
return c;
|
||||||
|
return tab[c].l_data[0];
|
||||||
|
}
|
||||||
|
|
||||||
/* code (17), len (7), type (4) */
|
/* code (17), len (7), type (4) */
|
||||||
|
|
||||||
void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
|
@ -949,15 +974,15 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
te->code = code;
|
te->code = code;
|
||||||
|
|
||||||
if (ci->l_len == 1 && ci->l_data[0] == code + 2 &&
|
if (ci->l_len == 1 && ci->l_data[0] == code + 2 &&
|
||||||
ci->f_code == ci->l_data[0] &&
|
ci->f_len == 1 && ci->f_data[0] == ci->l_data[0] &&
|
||||||
ci->u_len == 0 &&
|
ci->u_len == 0 &&
|
||||||
|
|
||||||
ci1->l_len == 1 && ci1->l_data[0] == code + 2 &&
|
ci1->l_len == 1 && ci1->l_data[0] == code + 2 &&
|
||||||
ci1->f_code == ci1->l_data[0] &&
|
ci1->f_len == 1 && ci1->f_data[0] == ci1->l_data[0] &&
|
||||||
ci1->u_len == 1 && ci1->u_data[0] == code &&
|
ci1->u_len == 1 && ci1->u_data[0] == code &&
|
||||||
|
|
||||||
ci2->l_len == 0 &&
|
ci2->l_len == 0 &&
|
||||||
ci2->f_code == 0 &&
|
ci2->f_len == 0 &&
|
||||||
ci2->u_len == 1 && ci2->u_data[0] == code) {
|
ci2->u_len == 1 && ci2->u_data[0] == code) {
|
||||||
te->len = 3;
|
te->len = 3;
|
||||||
te->data = 0;
|
te->data = 0;
|
||||||
|
@ -972,7 +997,7 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
if (ci1->u_len != 1 ||
|
if (ci1->u_len != 1 ||
|
||||||
ci1->u_data[0] != ci->u_data[0] + len ||
|
ci1->u_data[0] != ci->u_data[0] + len ||
|
||||||
ci1->l_len != 0 ||
|
ci1->l_len != 0 ||
|
||||||
ci1->f_code != ci1->u_data[0])
|
ci1->f_len != 1 || ci1->f_data[0] != ci1->u_data[0])
|
||||||
break;
|
break;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
@ -983,21 +1008,25 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci->u_len == 2 && ci->u_data[1] == 0x399 &&
|
if (ci->l_len == 0 &&
|
||||||
ci->f_code == 0 && ci->l_len == 0) {
|
ci->u_len == 2 && ci->u_data[1] == 0x399 &&
|
||||||
|
ci->f_len == 2 && ci->f_data[1] == 0x3B9 &&
|
||||||
|
ci->f_data[0] == simple_to_lower(tab, ci->u_data[0])) {
|
||||||
len = 1;
|
len = 1;
|
||||||
while (code + len <= CHARCODE_MAX) {
|
while (code + len <= CHARCODE_MAX) {
|
||||||
ci1 = &tab[code + len];
|
ci1 = &tab[code + len];
|
||||||
if (!(ci1->u_len == 2 &&
|
if (!(ci1->u_len == 2 &&
|
||||||
ci1->u_data[1] == 0x399 &&
|
ci1->u_data[1] == ci->u_data[1] &&
|
||||||
ci1->u_data[0] == ci->u_data[0] + len &&
|
ci1->u_data[0] == ci->u_data[0] + len &&
|
||||||
ci1->f_code == 0 &&
|
ci1->f_len == 2 &&
|
||||||
|
ci1->f_data[1] == ci->f_data[1] &&
|
||||||
|
ci1->f_data[0] == ci->f_data[0] + len &&
|
||||||
ci1->l_len == 0))
|
ci1->l_len == 0))
|
||||||
break;
|
break;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
te->len = len;
|
te->len = len;
|
||||||
te->type = RUN_TYPE_U_EXT2;
|
te->type = RUN_TYPE_UF_EXT2;
|
||||||
te->ext_data[0] = ci->u_data[0];
|
te->ext_data[0] = ci->u_data[0];
|
||||||
te->ext_data[1] = ci->u_data[1];
|
te->ext_data[1] = ci->u_data[1];
|
||||||
te->ext_len = 2;
|
te->ext_len = 2;
|
||||||
|
@ -1005,7 +1034,8 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci->u_len == 2 && ci->u_data[1] == 0x399 &&
|
if (ci->u_len == 2 && ci->u_data[1] == 0x399 &&
|
||||||
ci->l_len == 1 && ci->f_code == ci->l_data[0]) {
|
ci->l_len == 1 &&
|
||||||
|
ci->f_len == 1 && ci->f_data[0] == ci->l_data[0]) {
|
||||||
len = 1;
|
len = 1;
|
||||||
while (code + len <= CHARCODE_MAX) {
|
while (code + len <= CHARCODE_MAX) {
|
||||||
ci1 = &tab[code + len];
|
ci1 = &tab[code + len];
|
||||||
|
@ -1014,7 +1044,7 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
ci1->u_data[0] == ci->u_data[0] + len &&
|
ci1->u_data[0] == ci->u_data[0] + len &&
|
||||||
ci1->l_len == 1 &&
|
ci1->l_len == 1 &&
|
||||||
ci1->l_data[0] == ci->l_data[0] + len &&
|
ci1->l_data[0] == ci->l_data[0] + len &&
|
||||||
ci1->f_code == ci1->l_data[0]))
|
ci1->f_len == 1 && ci1->f_data[0] == ci1->l_data[0]))
|
||||||
break;
|
break;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
@ -1026,13 +1056,13 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci->l_len == 1 && ci->u_len == 0 && ci->f_code == 0) {
|
if (ci->l_len == 1 && ci->u_len == 0 && ci->f_len == 0) {
|
||||||
len = 1;
|
len = 1;
|
||||||
while (code + len <= CHARCODE_MAX) {
|
while (code + len <= CHARCODE_MAX) {
|
||||||
ci1 = &tab[code + len];
|
ci1 = &tab[code + len];
|
||||||
if (!(ci1->l_len == 1 &&
|
if (!(ci1->l_len == 1 &&
|
||||||
ci1->l_data[0] == ci->l_data[0] + len &&
|
ci1->l_data[0] == ci->l_data[0] + len &&
|
||||||
ci1->u_len == 0 && ci1->f_code == 0))
|
ci1->u_len == 0 && ci1->f_len == 0))
|
||||||
break;
|
break;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
@ -1045,32 +1075,39 @@ void find_run_type(TableEntry *te, CCInfo *tab, int code)
|
||||||
if (ci->l_len == 0 &&
|
if (ci->l_len == 0 &&
|
||||||
ci->u_len == 1 &&
|
ci->u_len == 1 &&
|
||||||
ci->u_data[0] < 0x1000 &&
|
ci->u_data[0] < 0x1000 &&
|
||||||
ci->f_code == ci->u_data[0] + 0x20) {
|
ci->f_len == 1 && ci->f_data[0] == ci->u_data[0] + 0x20) {
|
||||||
te->len = 1;
|
te->len = 1;
|
||||||
te->type = RUN_TYPE_UF_D20;
|
te->type = RUN_TYPE_UF_D20;
|
||||||
te->data = ci->u_data[0];
|
te->data = ci->u_data[0];
|
||||||
} else if (ci->l_len == 0 &&
|
} else if (ci->l_len == 0 &&
|
||||||
ci->u_len == 1 &&
|
ci->u_len == 1 &&
|
||||||
ci->f_code == ci->u_data[0] + 1) {
|
ci->f_len == 1 && ci->f_data[0] == ci->u_data[0] + 1) {
|
||||||
te->len = 1;
|
te->len = 1;
|
||||||
te->type = RUN_TYPE_UF_D1_EXT;
|
te->type = RUN_TYPE_UF_D1_EXT;
|
||||||
te->ext_data[0] = ci->u_data[0];
|
te->ext_data[0] = ci->u_data[0];
|
||||||
te->ext_len = 1;
|
te->ext_len = 1;
|
||||||
} else if (ci->l_len == 2 && ci->u_len == 0 && ci->f_code == 0) {
|
} else if (ci->l_len == 2 && ci->u_len == 0 && ci->f_len == 2 &&
|
||||||
|
ci->l_data[0] == ci->f_data[0] &&
|
||||||
|
ci->l_data[1] == ci->f_data[1]) {
|
||||||
te->len = 1;
|
te->len = 1;
|
||||||
te->type = RUN_TYPE_L_EXT2;
|
te->type = RUN_TYPE_LF_EXT2;
|
||||||
te->ext_data[0] = ci->l_data[0];
|
te->ext_data[0] = ci->l_data[0];
|
||||||
te->ext_data[1] = ci->l_data[1];
|
te->ext_data[1] = ci->l_data[1];
|
||||||
te->ext_len = 2;
|
te->ext_len = 2;
|
||||||
} else if (ci->u_len == 2 && ci->l_len == 0 && ci->f_code == 0) {
|
} else if (ci->u_len == 2 && ci->l_len == 0 && ci->f_len == 2 &&
|
||||||
|
ci->f_data[0] == simple_to_lower(tab, ci->u_data[0]) &&
|
||||||
|
ci->f_data[1] == simple_to_lower(tab, ci->u_data[1])) {
|
||||||
te->len = 1;
|
te->len = 1;
|
||||||
te->type = RUN_TYPE_U_EXT2;
|
te->type = RUN_TYPE_UF_EXT2;
|
||||||
te->ext_data[0] = ci->u_data[0];
|
te->ext_data[0] = ci->u_data[0];
|
||||||
te->ext_data[1] = ci->u_data[1];
|
te->ext_data[1] = ci->u_data[1];
|
||||||
te->ext_len = 2;
|
te->ext_len = 2;
|
||||||
} else if (ci->u_len == 3 && ci->l_len == 0 && ci->f_code == 0) {
|
} else if (ci->u_len == 3 && ci->l_len == 0 && ci->f_len == 3 &&
|
||||||
|
ci->f_data[0] == simple_to_lower(tab, ci->u_data[0]) &&
|
||||||
|
ci->f_data[1] == simple_to_lower(tab, ci->u_data[1]) &&
|
||||||
|
ci->f_data[2] == simple_to_lower(tab, ci->u_data[2])) {
|
||||||
te->len = 1;
|
te->len = 1;
|
||||||
te->type = RUN_TYPE_U_EXT3;
|
te->type = RUN_TYPE_UF_EXT3;
|
||||||
te->ext_data[0] = ci->u_data[0];
|
te->ext_data[0] = ci->u_data[0];
|
||||||
te->ext_data[1] = ci->u_data[1];
|
te->ext_data[1] = ci->u_data[1];
|
||||||
te->ext_data[2] = ci->u_data[2];
|
te->ext_data[2] = ci->u_data[2];
|
||||||
|
@ -1188,7 +1225,7 @@ void build_conv_table(CCInfo *tab)
|
||||||
te = conv_table;
|
te = conv_table;
|
||||||
for(code = 0; code <= CHARCODE_MAX; code++) {
|
for(code = 0; code <= CHARCODE_MAX; code++) {
|
||||||
ci = &tab[code];
|
ci = &tab[code];
|
||||||
if (ci->u_len == 0 && ci->l_len == 0 && ci->f_code == 0)
|
if (ci->u_len == 0 && ci->l_len == 0 && ci->f_len == 0)
|
||||||
continue;
|
continue;
|
||||||
assert(te - conv_table < countof(conv_table));
|
assert(te - conv_table < countof(conv_table));
|
||||||
find_run_type(te, tab, code);
|
find_run_type(te, tab, code);
|
||||||
|
@ -1244,7 +1281,7 @@ void build_conv_table(CCInfo *tab)
|
||||||
/* find the data index for ext_data */
|
/* find the data index for ext_data */
|
||||||
for(i = 0; i < conv_table_len; i++) {
|
for(i = 0; i < conv_table_len; i++) {
|
||||||
te = &conv_table[i];
|
te = &conv_table[i];
|
||||||
if (te->type == RUN_TYPE_U_EXT3) {
|
if (te->type == RUN_TYPE_UF_EXT3) {
|
||||||
int p, v;
|
int p, v;
|
||||||
v = 0;
|
v = 0;
|
||||||
for(j = 0; j < 3; j++) {
|
for(j = 0; j < 3; j++) {
|
||||||
|
@ -1258,8 +1295,8 @@ void build_conv_table(CCInfo *tab)
|
||||||
|
|
||||||
for(i = 0; i < conv_table_len; i++) {
|
for(i = 0; i < conv_table_len; i++) {
|
||||||
te = &conv_table[i];
|
te = &conv_table[i];
|
||||||
if (te->type == RUN_TYPE_L_EXT2 ||
|
if (te->type == RUN_TYPE_LF_EXT2 ||
|
||||||
te->type == RUN_TYPE_U_EXT2 ||
|
te->type == RUN_TYPE_UF_EXT2 ||
|
||||||
te->type == RUN_TYPE_U2L_399_EXT2) {
|
te->type == RUN_TYPE_U2L_399_EXT2) {
|
||||||
int p, v;
|
int p, v;
|
||||||
v = 0;
|
v = 0;
|
||||||
|
@ -1322,6 +1359,54 @@ void dump_case_conv_table(FILE *f)
|
||||||
fprintf(f, "\n};\n\n");
|
fprintf(f, "\n};\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static CCInfo *global_tab;
|
||||||
|
|
||||||
|
static int sp_cc_cmp(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
CCInfo *c1 = &global_tab[*(const int *)p1];
|
||||||
|
CCInfo *c2 = &global_tab[*(const int *)p2];
|
||||||
|
if (c1->f_len < c2->f_len) {
|
||||||
|
return -1;
|
||||||
|
} else if (c2->f_len < c1->f_len) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return memcmp(c1->f_data, c2->f_data, sizeof(c1->f_data[0]) * c1->f_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dump the case special cases (multi character results which are
|
||||||
|
identical and need specific handling in lre_canonicalize() */
|
||||||
|
void dump_case_folding_special_cases(CCInfo *tab)
|
||||||
|
{
|
||||||
|
int i, len, j;
|
||||||
|
int *perm;
|
||||||
|
|
||||||
|
perm = malloc(sizeof(perm[0]) * (CHARCODE_MAX + 1));
|
||||||
|
for(i = 0; i <= CHARCODE_MAX; i++)
|
||||||
|
perm[i] = i;
|
||||||
|
global_tab = tab;
|
||||||
|
qsort(perm, CHARCODE_MAX + 1, sizeof(perm[0]), sp_cc_cmp);
|
||||||
|
for(i = 0; i <= CHARCODE_MAX;) {
|
||||||
|
if (tab[perm[i]].f_len <= 1) {
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
len = 1;
|
||||||
|
while ((i + len) <= CHARCODE_MAX && !sp_cc_cmp(&perm[i], &perm[i + len]))
|
||||||
|
len++;
|
||||||
|
|
||||||
|
if (len > 1) {
|
||||||
|
for(j = i; j < i + len; j++)
|
||||||
|
dump_cc_info(&tab[perm[j]], perm[j]);
|
||||||
|
}
|
||||||
|
i += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(perm);
|
||||||
|
global_tab = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int tabcmp(const int *tab1, const int *tab2, int n)
|
int tabcmp(const int *tab1, const int *tab2, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1348,7 +1433,7 @@ void compute_internal_props(void)
|
||||||
|
|
||||||
for(i = 0; i <= CHARCODE_MAX; i++) {
|
for(i = 0; i <= CHARCODE_MAX; i++) {
|
||||||
CCInfo *ci = &unicode_db[i];
|
CCInfo *ci = &unicode_db[i];
|
||||||
has_ul = (ci->u_len != 0 || ci->l_len != 0 || ci->f_code != 0);
|
has_ul = (ci->u_len != 0 || ci->l_len != 0 || ci->f_len != 0);
|
||||||
if (has_ul) {
|
if (has_ul) {
|
||||||
assert(get_prop(i, PROP_Cased));
|
assert(get_prop(i, PROP_Cased));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1363,10 +1448,10 @@ void compute_internal_props(void)
|
||||||
set_prop(i, PROP_Changes_When_Titlecased1,
|
set_prop(i, PROP_Changes_When_Titlecased1,
|
||||||
get_prop(i, PROP_Changes_When_Titlecased) ^ (ci->u_len != 0));
|
get_prop(i, PROP_Changes_When_Titlecased) ^ (ci->u_len != 0));
|
||||||
set_prop(i, PROP_Changes_When_Casefolded1,
|
set_prop(i, PROP_Changes_When_Casefolded1,
|
||||||
get_prop(i, PROP_Changes_When_Casefolded) ^ (ci->f_code != 0));
|
get_prop(i, PROP_Changes_When_Casefolded) ^ (ci->f_len != 0));
|
||||||
/* XXX: reduce table size (438 bytes) */
|
/* XXX: reduce table size (438 bytes) */
|
||||||
set_prop(i, PROP_Changes_When_NFKC_Casefolded1,
|
set_prop(i, PROP_Changes_When_NFKC_Casefolded1,
|
||||||
get_prop(i, PROP_Changes_When_NFKC_Casefolded) ^ (ci->f_code != 0));
|
get_prop(i, PROP_Changes_When_NFKC_Casefolded) ^ (ci->f_len != 0));
|
||||||
#if 0
|
#if 0
|
||||||
/* TEST */
|
/* TEST */
|
||||||
#define M(x) (1U << GCAT_ ## x)
|
#define M(x) (1U << GCAT_ ## x)
|
||||||
|
@ -1797,8 +1882,10 @@ void check_case_conv(void)
|
||||||
ci->u_len = 1;
|
ci->u_len = 1;
|
||||||
ci->u_data[0] = code;
|
ci->u_data[0] = code;
|
||||||
}
|
}
|
||||||
if (ci->f_code == 0)
|
if (ci->f_len == 0) {
|
||||||
ci->f_code = code;
|
ci->f_len = 1;
|
||||||
|
ci->f_data[0] = code;
|
||||||
|
}
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
l = check_conv(res, code, 0);
|
l = check_conv(res, code, 0);
|
||||||
|
@ -1812,7 +1899,7 @@ void check_case_conv(void)
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
l = check_conv(res, code, 2);
|
l = check_conv(res, code, 2);
|
||||||
if (l != 1 || res[0] != ci->f_code) {
|
if (l != ci->f_len || tabcmp((int *)res, ci->f_data, l)) {
|
||||||
printf("ERROR: F\n");
|
printf("ERROR: F\n");
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
|
@ -3007,11 +3094,12 @@ int main(int argc, char **argv)
|
||||||
unicode_db_path);
|
unicode_db_path);
|
||||||
parse_prop_list(filename);
|
parse_prop_list(filename);
|
||||||
|
|
||||||
// dump_data(unicode_db);
|
// dump_unicode_data(unicode_db);
|
||||||
|
|
||||||
build_conv_table(unicode_db);
|
build_conv_table(unicode_db);
|
||||||
|
|
||||||
// dump_table();
|
#ifdef DUMP_CASE_FOLDING_SPECIAL_CASES
|
||||||
|
dump_case_folding_special_cases(unicode_db);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!outfilename) {
|
if (!outfilename) {
|
||||||
#ifdef USE_TEST
|
#ifdef USE_TEST
|
||||||
|
|
|
@ -72,6 +72,7 @@ DEF(Coptic, "Copt,Qaac")
|
||||||
DEF(Cuneiform, "Xsux")
|
DEF(Cuneiform, "Xsux")
|
||||||
DEF(Cypriot, "Cprt")
|
DEF(Cypriot, "Cprt")
|
||||||
DEF(Cyrillic, "Cyrl")
|
DEF(Cyrillic, "Cyrl")
|
||||||
|
DEF(Cypro_Minoan, "Cpmn")
|
||||||
DEF(Deseret, "Dsrt")
|
DEF(Deseret, "Dsrt")
|
||||||
DEF(Devanagari, "Deva")
|
DEF(Devanagari, "Deva")
|
||||||
DEF(Dives_Akuru, "Diak")
|
DEF(Dives_Akuru, "Diak")
|
||||||
|
@ -104,6 +105,7 @@ DEF(Javanese, "Java")
|
||||||
DEF(Kaithi, "Kthi")
|
DEF(Kaithi, "Kthi")
|
||||||
DEF(Kannada, "Knda")
|
DEF(Kannada, "Knda")
|
||||||
DEF(Katakana, "Kana")
|
DEF(Katakana, "Kana")
|
||||||
|
DEF(Kawi, "Kawi")
|
||||||
DEF(Kayah_Li, "Kali")
|
DEF(Kayah_Li, "Kali")
|
||||||
DEF(Kharoshthi, "Khar")
|
DEF(Kharoshthi, "Khar")
|
||||||
DEF(Khmer, "Khmr")
|
DEF(Khmer, "Khmr")
|
||||||
|
@ -138,6 +140,7 @@ DEF(Mro, "Mroo")
|
||||||
DEF(Multani, "Mult")
|
DEF(Multani, "Mult")
|
||||||
DEF(Myanmar, "Mymr")
|
DEF(Myanmar, "Mymr")
|
||||||
DEF(Nabataean, "Nbat")
|
DEF(Nabataean, "Nbat")
|
||||||
|
DEF(Nag_Mundari, "Nagm")
|
||||||
DEF(Nandinagari, "Nand")
|
DEF(Nandinagari, "Nand")
|
||||||
DEF(New_Tai_Lue, "Talu")
|
DEF(New_Tai_Lue, "Talu")
|
||||||
DEF(Newa, "Newa")
|
DEF(Newa, "Newa")
|
||||||
|
@ -154,6 +157,7 @@ DEF(Old_Persian, "Xpeo")
|
||||||
DEF(Old_Sogdian, "Sogo")
|
DEF(Old_Sogdian, "Sogo")
|
||||||
DEF(Old_South_Arabian, "Sarb")
|
DEF(Old_South_Arabian, "Sarb")
|
||||||
DEF(Old_Turkic, "Orkh")
|
DEF(Old_Turkic, "Orkh")
|
||||||
|
DEF(Old_Uyghur, "Ougr")
|
||||||
DEF(Oriya, "Orya")
|
DEF(Oriya, "Orya")
|
||||||
DEF(Osage, "Osge")
|
DEF(Osage, "Osge")
|
||||||
DEF(Osmanya, "Osma")
|
DEF(Osmanya, "Osma")
|
||||||
|
@ -192,8 +196,11 @@ DEF(Thai, "Thai")
|
||||||
DEF(Tibetan, "Tibt")
|
DEF(Tibetan, "Tibt")
|
||||||
DEF(Tifinagh, "Tfng")
|
DEF(Tifinagh, "Tfng")
|
||||||
DEF(Tirhuta, "Tirh")
|
DEF(Tirhuta, "Tirh")
|
||||||
|
DEF(Tangsa, "Tnsa")
|
||||||
|
DEF(Toto, "Toto")
|
||||||
DEF(Ugaritic, "Ugar")
|
DEF(Ugaritic, "Ugar")
|
||||||
DEF(Vai, "Vaii")
|
DEF(Vai, "Vaii")
|
||||||
|
DEF(Vithkuqi, "Vith")
|
||||||
DEF(Wancho, "Wcho")
|
DEF(Wancho, "Wcho")
|
||||||
DEF(Warang_Citi, "Wara")
|
DEF(Warang_Citi, "Wara")
|
||||||
DEF(Yezidi, "Yezi")
|
DEF(Yezidi, "Yezi")
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"git": {
|
"git": {
|
||||||
"repositoryUrl": "https://github.com/bellard/quickjs",
|
"repositoryUrl": "https://github.com/bellard/quickjs",
|
||||||
"commitHash": "b5e62895c619d4ffc75c9d822c8d85f1ece77e5b"
|
"commitHash": "3f81070e573e3592728dbbbd04c84c498b20d6dc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Загрузка…
Ссылка в новой задаче