forked from cory/tildefriends
		
	Quick experiment with quickjs.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3423 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										22
									
								
								SConstruct
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								SConstruct
									
									
									
									
									
								
							| @@ -105,7 +105,29 @@ if sys.platform == 'linux2': | ||||
| 	env.Append(LIBS=['crypto', 'ssl']) | ||||
| 	env.Append(LINKFLAGS=['-std=c++0x']) | ||||
|  | ||||
| quickjsEnv = env.Clone() | ||||
| quickjsEnv.Append(CPPDEFINES=[ | ||||
| 	'CONFIG_VERSION=\\"' + open('deps/quickjs/VERSION').read().strip() + '\\"', | ||||
| 	'_GNU_SOURCE', | ||||
| ]) | ||||
| quickjs = quickjsEnv.Library('build/quickjs', [ | ||||
| 	'build/deps/quickjs/bjson.c', | ||||
| 	'build/deps/quickjs/cutils.c', | ||||
| 	'build/deps/quickjs/jscompress.c', | ||||
| 	'build/deps/quickjs/libbf.c', | ||||
| 	'build/deps/quickjs/libregexp.c', | ||||
| 	'build/deps/quickjs/libunicode.c', | ||||
| 	'build/deps/quickjs/quickjs-libc.c', | ||||
| 	'build/deps/quickjs/quickjs.c', | ||||
| 	'build/deps/quickjs/unicode_gen.c', | ||||
| ]) | ||||
| env.Append(LIBS=[quickjs]) | ||||
| env.Append(CPPPATH=['deps/quickjs']) | ||||
|  | ||||
| env.Program('qjst', ['build/src/quickjstest.c'], LIBS=['m', 'dl', quickjs]) | ||||
|  | ||||
| source = [s for s in Glob('build/src/*.cpp') if not os.path.basename(str(s)).startswith("SecureSocket_")] | ||||
|  | ||||
| if sys.platform == 'darwin': | ||||
| 	env.Append(FRAMEWORKS=['CoreFoundation', 'Security']) | ||||
| elif sys.platform == 'win32': | ||||
|   | ||||
							
								
								
									
										61
									
								
								deps/quickjs/Changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								deps/quickjs/Changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| 2019-09-18: | ||||
|  | ||||
| - added os.exec and other system calls | ||||
| - exported JS_ValueToAtom() | ||||
| - qjsc: added 'qjsc_' prefix to the generated C identifiers | ||||
| - added cross-compilation support | ||||
| - misc bug fixes | ||||
|  | ||||
| 2019-09-01: | ||||
|  | ||||
| - added globalThis | ||||
| - documented JS_EVAL_FLAG_COMPILE_ONLY | ||||
| - added import.meta.url and import.meta.main | ||||
| - added 'debugger' statement | ||||
| - misc bug fixes | ||||
|  | ||||
| 2019-08-18: | ||||
|  | ||||
| - added os.realpath, os.getcwd, os.mkdir, os.stat, os.lstat, | ||||
|   os.readlink, os.readdir, os.utimes, std.popen | ||||
| - module autodetection | ||||
| - added import.meta | ||||
| - misc bug fixes | ||||
|  | ||||
| 2019-08-10: | ||||
|  | ||||
| - added public class fields and private class fields, methods and | ||||
|   accessors (TC39 proposal) | ||||
| - changed JS_ToCStringLen() prototype | ||||
| - qjsc: handle '-' in module names and modules with the same filename | ||||
| - added std.urlGet | ||||
| - exported JS_GetOwnPropertyNames() and JS_GetOwnProperty() | ||||
| - exported some bigint C functions | ||||
| - added support for eshost in run-test262 | ||||
| - misc bug fixes | ||||
|  | ||||
| 2019-07-28: | ||||
|  | ||||
| - added dynamic import | ||||
| - added Promise.allSettled | ||||
| - added String.prototype.matchAll | ||||
| - added Object.fromEntries | ||||
| - reduced number of ticks in await | ||||
| - added BigInt support in Atomics | ||||
| - exported JS_NewPromiseCapability() | ||||
| - misc async function and async generator fixes | ||||
| - enabled hashbang support by default | ||||
|  | ||||
| 2019-07-21: | ||||
|  | ||||
| - updated test262 tests | ||||
| - updated to Unicode version 12.1.0 | ||||
| - fixed missing Date object in qjsc | ||||
| - fixed multi-context creation | ||||
| - misc ES2020 related fixes | ||||
| - simplified power and division operators in bignum extension | ||||
| - fixed several crash conditions | ||||
|  | ||||
| 2019-07-09: | ||||
|  | ||||
| - first public release | ||||
							
								
								
									
										498
									
								
								deps/quickjs/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										498
									
								
								deps/quickjs/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,498 @@ | ||||
| # | ||||
| # QuickJS Javascript Engine | ||||
| #  | ||||
| # Copyright (c) 2017-2019 Fabrice Bellard | ||||
| # Copyright (c) 2017-2019 Charlie Gordon | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in | ||||
| # all copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
| # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| # THE SOFTWARE. | ||||
|  | ||||
| ifeq ($(shell uname -s),Darwin) | ||||
| CONFIG_DARWIN=y | ||||
| endif | ||||
| # Windows cross compilation from Linux | ||||
| #CONFIG_WIN32=y | ||||
| # use link time optimization (smaller and faster executables but slower build) | ||||
| CONFIG_LTO=y | ||||
| # consider warnings as errors (for development) | ||||
| #CONFIG_WERROR=y | ||||
| # force 32 bit build for some utilities | ||||
| #CONFIG_M32=y | ||||
|  | ||||
| ifdef CONFIG_DARWIN | ||||
| # use clang instead of gcc | ||||
| CONFIG_CLANG=y | ||||
| CONFIG_DEFAULT_AR=y | ||||
| endif | ||||
|  | ||||
| # installation directory | ||||
| prefix=/usr/local | ||||
|  | ||||
| # use the gprof profiler | ||||
| #CONFIG_PROFILE=y | ||||
| # use address sanitizer | ||||
| #CONFIG_ASAN=y | ||||
|  | ||||
| OBJDIR=.obj | ||||
|  | ||||
| ifdef CONFIG_WIN32 | ||||
|   CROSS_PREFIX=i686-w64-mingw32- | ||||
|   EXE=.exe | ||||
| else | ||||
|   CROSS_PREFIX= | ||||
|   EXE= | ||||
| endif | ||||
| ifdef CONFIG_CLANG | ||||
|   HOST_CC=clang | ||||
|   CC=$(CROSS_PREFIX)clang | ||||
|   CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d | ||||
|   CFLAGS += -Wextra | ||||
|   CFLAGS += -Wno-sign-compare | ||||
|   CFLAGS += -Wno-missing-field-initializers | ||||
|   CFLAGS += -Wundef -Wuninitialized | ||||
|   CFLAGS += -Wunused -Wno-unused-parameter | ||||
|   CFLAGS += -Wwrite-strings | ||||
|   CFLAGS += -Wchar-subscripts -funsigned-char | ||||
|   CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d | ||||
|   ifdef CONFIG_DEFAULT_AR | ||||
|     AR=$(CROSS_PREFIX)ar | ||||
|   else | ||||
|     ifdef CONFIG_LTO | ||||
|       AR=$(CROSS_PREFIX)llvm-ar | ||||
|     else | ||||
|       AR=$(CROSS_PREFIX)ar | ||||
|     endif | ||||
|   endif | ||||
| else | ||||
|   HOST_CC=gcc | ||||
|   CC=$(CROSS_PREFIX)gcc | ||||
|   CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d | ||||
|   CFLAGS += -Wno-array-bounds -Wno-format-truncation | ||||
|   ifdef CONFIG_LTO | ||||
|     AR=$(CROSS_PREFIX)gcc-ar | ||||
|   else | ||||
|     AR=$(CROSS_PREFIX)ar | ||||
|   endif | ||||
| endif | ||||
| STRIP=$(CROSS_PREFIX)strip | ||||
| ifdef CONFIG_WERROR | ||||
| CFLAGS+=-Werror | ||||
| endif | ||||
| DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\" | ||||
| CFLAGS+=$(DEFINES) | ||||
| CFLAGS_DEBUG=$(CFLAGS) -O0 | ||||
| CFLAGS_SMALL=$(CFLAGS) -Os | ||||
| CFLAGS_OPT=$(CFLAGS) -O2 | ||||
| CFLAGS_NOLTO:=$(CFLAGS_OPT) | ||||
| LDFLAGS=-g | ||||
| ifdef CONFIG_LTO | ||||
| CFLAGS_SMALL+=-flto | ||||
| CFLAGS_OPT+=-flto | ||||
| LDFLAGS+=-flto | ||||
| endif | ||||
| ifdef CONFIG_PROFILE | ||||
| CFLAGS+=-p | ||||
| LDFLAGS+=-p | ||||
| endif | ||||
| ifdef CONFIG_ASAN | ||||
| CFLAGS+=-fsanitize=address | ||||
| LDFLAGS+=-fsanitize=address | ||||
| endif | ||||
| ifdef CONFIG_WIN32 | ||||
| LDEXPORT= | ||||
| else | ||||
| LDEXPORT=-rdynamic | ||||
| endif | ||||
|  | ||||
| PROGS=qjs$(EXE) qjsbn$(EXE) qjsc$(EXE) qjsbnc$(EXE) run-test262 run-test262-bn | ||||
| ifneq ($(CROSS_PREFIX),) | ||||
| QJSC_CC=gcc | ||||
| QJSC=./host-qjsc | ||||
| QJSBNC=./host-qjsbnc | ||||
| PROGS+=$(QJSC) $(QJSBNC) | ||||
| else | ||||
| QJSC_CC=$(CC) | ||||
| QJSC=./qjsc$(EXE) | ||||
| QJSBNC=./qjsbnc$(EXE) | ||||
| endif | ||||
| ifndef CONFIG_WIN32 | ||||
| PROGS+=qjscalc | ||||
| endif | ||||
| ifdef CONFIG_M32 | ||||
| PROGS+=qjs32 qjs32_s qjsbn32 | ||||
| endif | ||||
| PROGS+=libquickjs.a libquickjs.bn.a | ||||
| ifdef CONFIG_LTO | ||||
| PROGS+=libquickjs.lto.a libquickjs.bn.lto.a | ||||
| endif | ||||
|  | ||||
| # examples | ||||
| ifeq ($(CROSS_PREFIX),) | ||||
| ifdef CONFIG_ASAN | ||||
| PROGS+= | ||||
| else | ||||
| PROGS+=examples/hello examples/hello_module examples/c_module | ||||
| endif | ||||
| endif | ||||
|  | ||||
| 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 | ||||
|  | ||||
| QJSBN_LIB_OBJS=$(patsubst %.o, %.bn.o, $(QJS_LIB_OBJS)) $(OBJDIR)/libbf.bn.o | ||||
|  | ||||
| QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS) | ||||
|  | ||||
| QJSBN_OBJS=$(OBJDIR)/qjs.bn.o $(OBJDIR)/repl-bn.bn.o $(OBJDIR)/qjscalc.bn.o $(QJSBN_LIB_OBJS) | ||||
|  | ||||
| LIBS=-lm | ||||
| ifndef CONFIG_WIN32 | ||||
| LIBS+=-ldl | ||||
| endif | ||||
|  | ||||
| $(OBJDIR): | ||||
| 	mkdir -p $(OBJDIR) | ||||
|  | ||||
| qjs$(EXE): $(QJS_OBJS) | ||||
| 	$(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) | ||||
|  | ||||
| qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS)) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| qjsbnc$(EXE): $(OBJDIR)/qjsc.bn.o $(QJSBN_LIB_OBJS) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| ifneq ($(CROSS_PREFIX),) | ||||
|  | ||||
| $(QJSC): $(OBJDIR)/qjsc.host.o \ | ||||
|     $(patsubst %.o, %.host.o, $(QJS_LIB_OBJS)) | ||||
| 	$(HOST_CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| $(QJSBNC): $(OBJDIR)/qjsc.bn.host.o \ | ||||
|     $(patsubst %.o, %.host.o, $(QJSBN_LIB_OBJS)) | ||||
| 	$(HOST_CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| endif #CROSS_PREFIX | ||||
|  | ||||
| QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(prefix)\" | ||||
| ifdef CONFIG_LTO | ||||
| QJSC_DEFINES+=-DCONFIG_LTO | ||||
| endif | ||||
| QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(prefix)\" | ||||
|  | ||||
| $(OBJDIR)/qjsc.o $(OBJDIR)/qjsc.bn.o: CFLAGS+=$(QJSC_DEFINES) | ||||
| $(OBJDIR)/qjsc.host.o $(OBJDIR)/qjsc.bn.host.o: CFLAGS+=$(QJSC_HOST_DEFINES) | ||||
|  | ||||
| qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS)) | ||||
| 	$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) | ||||
|  | ||||
| qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS)) | ||||
| 	$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
| 	@size $@ | ||||
|  | ||||
| qjsbn$(EXE): $(QJSBN_OBJS) | ||||
| 	$(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) | ||||
|  | ||||
| qjsbn32: $(patsubst %.o, %.m32.o, $(QJSBN_OBJS)) | ||||
| 	$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) | ||||
|  | ||||
| qjscalc: qjsbn | ||||
| 	ln -sf $< $@ | ||||
|  | ||||
| qjsbn-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJSBN_OBJS)) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| ifdef CONFIG_LTO | ||||
| LTOEXT=.lto | ||||
| else | ||||
| LTOEXT= | ||||
| endif | ||||
|  | ||||
| libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS) | ||||
| 	$(AR) rcs $@ $^ | ||||
|  | ||||
| libquickjs.bn$(LTOEXT).a: $(QJSBN_LIB_OBJS) | ||||
| 	$(AR) rcs $@ $^ | ||||
|  | ||||
| ifdef CONFIG_LTO | ||||
| libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS)) | ||||
| 	$(AR) rcs $@ $^ | ||||
|  | ||||
| libquickjs.bn.a: $(patsubst %.o, %.nolto.o, $(QJSBN_LIB_OBJS)) | ||||
| 	$(AR) rcs $@ $^ | ||||
| endif # CONFIG_LTO | ||||
|  | ||||
| repl.c: $(QJSC) repl.js  | ||||
| 	$(QJSC) -c -o $@ -m repl.js | ||||
|  | ||||
| repl-bn.c: $(QJSBNC) repl.js  | ||||
| 	$(QJSBNC) -c -o $@ -m repl.js | ||||
|  | ||||
| qjscalc.c: $(QJSBNC) qjscalc.js | ||||
| 	$(QJSBNC) -c -o $@ qjscalc.js | ||||
|  | ||||
| ifneq ($(wildcard unicode/UnicodeData.txt),) | ||||
| $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o $(OBJDIR)/libunicode.bn.o $(OBJDIR)/libunicode.bn.m32.o \ | ||||
|     $(OBJDIR)/libunicode.nolto.o $(OBJDIR)/libunicode.bn.nolto.o: libunicode-table.h | ||||
|  | ||||
| libunicode-table.h: unicode_gen | ||||
| 	./unicode_gen unicode $@ | ||||
| endif | ||||
|  | ||||
| run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread | ||||
|  | ||||
| run-test262-bn: $(OBJDIR)/run-test262.bn.o $(QJSBN_LIB_OBJS) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread | ||||
|  | ||||
| run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread | ||||
|  | ||||
| run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) | ||||
| 	$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread | ||||
|  | ||||
| run-test262-bn32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.bn.o $(QJSBN_LIB_OBJS)) | ||||
| 	$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread | ||||
|  | ||||
| # object suffix order: bn, nolto, [m32|m32s] | ||||
|  | ||||
| $(OBJDIR)/%.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_OPT) -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.host.o: %.c | $(OBJDIR) | ||||
| 	$(HOST_CC) $(CFLAGS_OPT) -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.pic.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.bn.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.bn.host.o: %.c | $(OBJDIR) | ||||
| 	$(HOST_CC) $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.nolto.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_NOLTO) -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.bn.nolto.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_NOLTO) -DCONFIG_BIGNUM -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.m32.o: %.c | $(OBJDIR) | ||||
| 	$(CC) -m32 $(CFLAGS_OPT) -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.m32s.o: %.c | $(OBJDIR) | ||||
| 	$(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.bn.m32.o: %.c | $(OBJDIR) | ||||
| 	$(CC) -m32 $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.debug.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_DEBUG) -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.bn.debug.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS_DEBUG) -DCONFIG_BIGNUM -c -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.check.o: %.c | $(OBJDIR) | ||||
| 	$(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $< | ||||
|  | ||||
| regexp_test: libregexp.c libunicode.c cutils.c | ||||
| 	$(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS) | ||||
|  | ||||
| jscompress: jscompress.c | ||||
| 	$(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c | ||||
|  | ||||
| unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h | ||||
| 	$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o | ||||
|  | ||||
| clean: | ||||
| 	rm -f repl.c repl-bn.c qjscalc.c out.c | ||||
| 	rm -f *.a *.so *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS) | ||||
| 	rm -f hello.c hello_module.c c_module.c  | ||||
| 	rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug qjsbn-debug | ||||
| 	rm -rf run-test262-debug run-test262-32 run-test262-bn32 | ||||
|  | ||||
| install: all | ||||
| 	mkdir -p "$(DESTDIR)$(prefix)/bin" | ||||
| 	$(STRIP) qjs qjsbn qjsc qjsbnc | ||||
| 	install -m755 qjs qjsbn qjsc qjsbnc "$(DESTDIR)$(prefix)/bin" | ||||
| 	ln -sf qjsbn "$(DESTDIR)$(prefix)/bin/qjscalc" | ||||
| 	mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs" | ||||
| 	install -m644 libquickjs.a libquickjs.bn.a "$(DESTDIR)$(prefix)/lib/quickjs" | ||||
| ifdef CONFIG_LTO | ||||
| 	install -m644 libquickjs.lto.a libquickjs.bn.lto.a "$(DESTDIR)$(prefix)/lib/quickjs" | ||||
| endif | ||||
| 	mkdir -p "$(DESTDIR)$(prefix)/include/quickjs" | ||||
| 	install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(prefix)/include/quickjs" | ||||
|  | ||||
| ############################################################################### | ||||
| # examples | ||||
|  | ||||
| # example of static JS compilation | ||||
| HELLO_SRCS=examples/hello.js | ||||
| HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ | ||||
|            -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ | ||||
|            -fno-date -fno-module-loader | ||||
|  | ||||
| hello.c: $(QJSC) $(HELLO_SRCS) | ||||
| 	$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS) | ||||
|  | ||||
| ifdef CONFIG_M32 | ||||
| examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS)) | ||||
| 	$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
| else | ||||
| examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS) | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
| endif | ||||
|  | ||||
| # example of static JS compilation with modules | ||||
| HELLO_MODULE_SRCS=examples/hello_module.js | ||||
| HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ | ||||
|            -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ | ||||
|            -fno-date -m | ||||
| examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS) | ||||
| 	$(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS) | ||||
|  | ||||
| # use of an external C module (static compilation) | ||||
|  | ||||
| c_module.c: $(QJSC) examples/c_module.js | ||||
| 	$(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/c_module.js | ||||
|  | ||||
| examples/c_module: $(OBJDIR)/c_module.o $(OBJDIR)/fib.o libquickjs$(LTOEXT).a | ||||
| 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) | ||||
|  | ||||
| $(OBJDIR)/fib.o: examples/fib.c | ||||
| 	$(CC) $(CFLAGS_OPT) -c -o $@ $< | ||||
|  | ||||
| ############################################################################### | ||||
| # documentation | ||||
|  | ||||
| DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html  | ||||
|  | ||||
| build_doc: $(DOCS) | ||||
|  | ||||
| clean_doc:  | ||||
| 	rm -f $(DOCS) | ||||
|  | ||||
| doc/%.pdf: doc/%.texi | ||||
| 	texi2pdf --clean -o $@ -q $< | ||||
|  | ||||
| doc/%.html.pre: doc/%.texi | ||||
| 	makeinfo --html --no-headers --no-split --number-sections -o $@ $< | ||||
|  | ||||
| doc/%.html: doc/%.html.pre | ||||
| 	sed -e 's|</style>|</style>\n<meta name="viewport" content="width=device-width, initial-scale=1.0">|' < $< > $@ | ||||
|  | ||||
| ############################################################################### | ||||
| # tests | ||||
|  | ||||
| ifndef CONFIG_DARWIN | ||||
| test: bjson.so | ||||
| endif | ||||
|  | ||||
| test: qjs qjsbn | ||||
| 	./qjs tests/test_closure.js | ||||
| 	./qjs tests/test_op.js | ||||
| 	./qjs tests/test_builtin.js | ||||
| 	./qjs tests/test_loop.js | ||||
| 	./qjs tests/test_std.js | ||||
| ifndef CONFIG_DARWIN | ||||
| 	./qjs tests/test_bjson.js | ||||
| endif | ||||
| 	./qjsbn tests/test_closure.js | ||||
| 	./qjsbn tests/test_op.js | ||||
| 	./qjsbn tests/test_builtin.js | ||||
| 	./qjsbn tests/test_loop.js | ||||
| 	./qjsbn tests/test_std.js | ||||
| 	./qjsbn --qjscalc tests/test_bignum.js | ||||
|  | ||||
| test-32: qjs32 qjsbn32 | ||||
| 	./qjs32 tests/test_closure.js | ||||
| 	./qjs32 tests/test_op.js | ||||
| 	./qjs32 tests/test_builtin.js | ||||
| 	./qjs32 tests/test_loop.js | ||||
| 	./qjs32 tests/test_std.js | ||||
| 	./qjsbn32 tests/test_closure.js | ||||
| 	./qjsbn32 tests/test_op.js | ||||
| 	./qjsbn32 tests/test_builtin.js | ||||
| 	./qjsbn32 tests/test_loop.js | ||||
| 	./qjsbn32 tests/test_std.js | ||||
| 	./qjsbn32 --qjscalc tests/test_bignum.js | ||||
|  | ||||
| stats: qjs qjs32 | ||||
| 	./qjs -qd | ||||
| 	./qjs32 -qd | ||||
|  | ||||
| microbench: qjs | ||||
| 	./qjs --std tests/microbench.js | ||||
|  | ||||
| microbench-32: qjs32 | ||||
| 	./qjs32 --std tests/microbench.js | ||||
|  | ||||
| # ES5 tests (obsolete) | ||||
| test2o: run-test262 | ||||
| 	time ./run-test262 -m -c test262o.conf | ||||
|  | ||||
| test2o-32: run-test262-32 | ||||
| 	time ./run-test262-32 -m -c test262o.conf | ||||
|  | ||||
| test2o-update: run-test262 | ||||
| 	./run-test262 -u -c test262o.conf | ||||
|  | ||||
| # Test262 tests | ||||
| test2-default: run-test262 | ||||
| 	time ./run-test262 -m -c test262.conf | ||||
|  | ||||
| test2: run-test262 | ||||
| 	time ./run-test262 -m -c test262.conf -a | ||||
|  | ||||
| test2-32: run-test262-32 | ||||
| 	time ./run-test262-32 -m -c test262.conf -a | ||||
|  | ||||
| test2-update: run-test262 | ||||
| 	./run-test262 -u -c test262.conf -a | ||||
|  | ||||
| test2-check: run-test262 | ||||
| 	time ./run-test262 -m -c test262.conf -E -a | ||||
|  | ||||
| # Test262 + BigInt tests | ||||
| test2bn-default: run-test262-bn | ||||
| 	time ./run-test262-bn -m -c test262bn.conf | ||||
|  | ||||
| test2bn: run-test262-bn | ||||
| 	time ./run-test262-bn -m -c test262bn.conf -a | ||||
|  | ||||
| test2bn-32: run-test262-bn32 | ||||
| 	time ./run-test262-bn32 -m -c test262bn.conf -a | ||||
|  | ||||
| testall: all test microbench test2o test2 test2bn | ||||
|  | ||||
| testall-32: all test-32 microbench-32 test2o-32 test2-32 test2bn-32 | ||||
|  | ||||
| testall-complete: testall testall-32 | ||||
|  | ||||
| bench-v8: qjs qjs32 | ||||
| 	make -C tests/bench-v8 | ||||
| 	./qjs -d tests/bench-v8/combined.js | ||||
|  | ||||
| bjson.so: $(OBJDIR)/bjson.pic.o | ||||
| 	$(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS) | ||||
|  | ||||
| -include $(wildcard $(OBJDIR)/*.d) | ||||
							
								
								
									
										80
									
								
								deps/quickjs/TODO
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								deps/quickjs/TODO
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| - 64-bit atoms in 64-bit mode? | ||||
| - rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ? | ||||
| - unify coding style and naming conventions | ||||
| - use names from the ECMA spec in library implementation | ||||
| - modules: if no ".", use a well known module loading path ? | ||||
| - use JSHoistedDef only for global variables (JSHoistedDef.var_name != JS_ATOM_NULL) | ||||
| - add index in JSVarDef and is_arg flag to merge args and vars in JSFunctionDef | ||||
| - replace most JSVarDef flags with var_type enumeration | ||||
| - use byte code emitters with typed arguments (for clarity) | ||||
| - use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing | ||||
|   and use the same wrappers in all phases | ||||
| - use more generic method for line numbers in resolve_variables and resolve_labels | ||||
|  | ||||
| Memory: | ||||
| - test border cases for max number of atoms, object properties, string length | ||||
| - add emergency malloc mode for out of memory exceptions. | ||||
| - test all DynBuf memory errors | ||||
| - test all js_realloc memory errors | ||||
| - bignum: handle memory errors | ||||
| - use memory pools for objects, etc? | ||||
| - improve JS_ComputeMemoryUsage() with more info | ||||
|  | ||||
| Optimizations: | ||||
| - use auto-init properties for more global objects | ||||
| - reuse stack slots for disjoint scopes, if strip | ||||
| - optimize `for of` iterator for built-in array objects | ||||
| - add heuristic to avoid some cycles in closures | ||||
| - small String (0-2 charcodes) with immediate storage | ||||
| - perform static string concatenation at compile time | ||||
| - optimize string concatenation with ropes or miniropes? | ||||
| - add implicit numeric strings for Uint32 numbers? | ||||
| - optimize `s += a + b`, `s += a.b` and similar simple expressions | ||||
| - ensure string canonical representation and optimise comparisons and hashes? | ||||
| - remove JSObject.first_weak_ref, use bit+context based hashed array for weak references | ||||
| - optimize function storage with length and name accessors? | ||||
| - property access optimization on the global object, functions, | ||||
|   prototypes and special non extensible objects. | ||||
| - create object literals with the correct length by backpatching length argument | ||||
| - remove redundant set_loc_uninitialized/check_uninitialized opcodes | ||||
| - peephole optim: push_atom_value, to_propkey -> push_atom_value | ||||
| - peephole optim: put_loc x, get_loc_check x -> set_loc x | ||||
| - comparative performance benchmark | ||||
| - use variable name when throwing uninitialized exception if available | ||||
| - convert slow array to fast array when all properties != length are numeric | ||||
| - optimize destructuring assignments for global and local variables | ||||
| - implement some form of tail-call-optimization | ||||
| - debugger keyword support | ||||
| - optimize OP_apply | ||||
| - optimize f(...b) | ||||
|  | ||||
| Extensions: | ||||
| - support more features in [features] section | ||||
| - add built-in preprocessor in compiler, get rid of jscompress | ||||
|   handle #if, #ifdef, #line, limited support for #define | ||||
| - limited support for web assembly  | ||||
| - get rid of __loadScript, use more common name | ||||
| - BSD sockets | ||||
| - Process or thread control | ||||
| - use custom printf to avoid C library compatibility issues | ||||
| - use custom timezone support to avoid C library compatibility issues | ||||
|  | ||||
| REPL: | ||||
| - strip internal functions from stack trace | ||||
| - readline: support MS Windows terminal | ||||
| - readline: handle dynamic terminal resizing | ||||
| - multiline editing | ||||
| - debugger | ||||
| - runtime object and function inspectors | ||||
| - interactive object browser | ||||
| - use more generic approach to display evaluation results | ||||
| - improve directive handling: dispatch, colorize, completion... | ||||
| - save history | ||||
| - close all predefined methods in repl.js and jscalc.js | ||||
|  | ||||
| Test262o:   0/11262 errors, 463 excluded | ||||
| Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch) | ||||
|  | ||||
| Test262:   2/67351 errors, 839 excluded, 1370 skipped | ||||
| Test262bn: 2/69452 errors, 772 excluded, 383 skipped | ||||
| test262 commit: d65b9b35be091147edf31ec527a47cb95a327217 | ||||
							
								
								
									
										1
									
								
								deps/quickjs/VERSION
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								deps/quickjs/VERSION
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 2019-09-18 | ||||
							
								
								
									
										88
									
								
								deps/quickjs/bjson.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								deps/quickjs/bjson.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| /* | ||||
|  * QuickJS: binary JSON module (test only) | ||||
|  *  | ||||
|  * Copyright (c) 2017-2019 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #include "quickjs-libc.h" | ||||
| #include "cutils.h" | ||||
|  | ||||
| static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, | ||||
|                              int argc, JSValueConst *argv) | ||||
| { | ||||
|     uint8_t *buf; | ||||
|     uint64_t pos, len; | ||||
|     JSValue obj; | ||||
|     size_t size; | ||||
|      | ||||
|     if (JS_ToIndex(ctx, &pos, argv[1])) | ||||
|         return JS_EXCEPTION; | ||||
|     if (JS_ToIndex(ctx, &len, argv[2])) | ||||
|         return JS_EXCEPTION; | ||||
|     buf = JS_GetArrayBuffer(ctx, &size, argv[0]); | ||||
|     if (!buf) | ||||
|         return JS_EXCEPTION; | ||||
|     if (pos + len > size) | ||||
|         return JS_ThrowRangeError(ctx, "array buffer overflow"); | ||||
|     obj = JS_ReadObject(ctx, buf + pos, len, 0); | ||||
|     return obj; | ||||
| } | ||||
|  | ||||
| static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, | ||||
|                               int argc, JSValueConst *argv) | ||||
| { | ||||
|     size_t len; | ||||
|     uint8_t *buf; | ||||
|     JSValue array; | ||||
|      | ||||
|     buf = JS_WriteObject(ctx, &len, argv[0], 0); | ||||
|     if (!buf) | ||||
|         return JS_EXCEPTION; | ||||
|     array = JS_NewArrayBufferCopy(ctx, buf, len); | ||||
|     js_free(ctx, buf); | ||||
|     return array; | ||||
| } | ||||
|  | ||||
| static const JSCFunctionListEntry js_bjson_funcs[] = { | ||||
|     JS_CFUNC_DEF("read", 3, js_bjson_read ), | ||||
|     JS_CFUNC_DEF("write", 1, js_bjson_write ), | ||||
| }; | ||||
|  | ||||
| static int js_bjson_init(JSContext *ctx, JSModuleDef *m) | ||||
| { | ||||
|     return JS_SetModuleExportList(ctx, m, js_bjson_funcs, | ||||
|                                   countof(js_bjson_funcs)); | ||||
| } | ||||
|  | ||||
| #ifdef JS_SHARED_LIBRARY | ||||
| #define JS_INIT_MODULE js_init_module | ||||
| #else | ||||
| #define JS_INIT_MODULE js_init_module_bjson | ||||
| #endif | ||||
|  | ||||
| JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) | ||||
| { | ||||
|     JSModuleDef *m; | ||||
|     m = JS_NewCModule(ctx, module_name, js_bjson_init); | ||||
|     if (!m) | ||||
|         return NULL; | ||||
|     JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs)); | ||||
|     return m; | ||||
| } | ||||
							
								
								
									
										620
									
								
								deps/quickjs/cutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										620
									
								
								deps/quickjs/cutils.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,620 @@ | ||||
| /* | ||||
|  * C utilities | ||||
|  *  | ||||
|  * Copyright (c) 2017 Fabrice Bellard | ||||
|  * Copyright (c) 2018 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "cutils.h" | ||||
|  | ||||
| void pstrcpy(char *buf, int buf_size, const char *str) | ||||
| { | ||||
|     int c; | ||||
|     char *q = buf; | ||||
|  | ||||
|     if (buf_size <= 0) | ||||
|         return; | ||||
|  | ||||
|     for(;;) { | ||||
|         c = *str++; | ||||
|         if (c == 0 || q >= buf + buf_size - 1) | ||||
|             break; | ||||
|         *q++ = c; | ||||
|     } | ||||
|     *q = '\0'; | ||||
| } | ||||
|  | ||||
| /* strcat and truncate. */ | ||||
| char *pstrcat(char *buf, int buf_size, const char *s) | ||||
| { | ||||
|     int len; | ||||
|     len = strlen(buf); | ||||
|     if (len < buf_size) | ||||
|         pstrcpy(buf + len, buf_size - len, s); | ||||
|     return buf; | ||||
| } | ||||
|  | ||||
| int strstart(const char *str, const char *val, const char **ptr) | ||||
| { | ||||
|     const char *p, *q; | ||||
|     p = str; | ||||
|     q = val; | ||||
|     while (*q != '\0') { | ||||
|         if (*p != *q) | ||||
|             return 0; | ||||
|         p++; | ||||
|         q++; | ||||
|     } | ||||
|     if (ptr) | ||||
|         *ptr = p; | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| int has_suffix(const char *str, const char *suffix) | ||||
| { | ||||
|     size_t len = strlen(str); | ||||
|     size_t slen = strlen(suffix); | ||||
|     return (len >= slen && !memcmp(str + len - slen, suffix, slen)); | ||||
| } | ||||
|  | ||||
| /* Dynamic buffer package */ | ||||
|  | ||||
| static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) | ||||
| { | ||||
|     return realloc(ptr, size); | ||||
| } | ||||
|  | ||||
| void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) | ||||
| { | ||||
|     memset(s, 0, sizeof(*s)); | ||||
|     if (!realloc_func) | ||||
|         realloc_func = dbuf_default_realloc; | ||||
|     s->opaque = opaque; | ||||
|     s->realloc_func = realloc_func; | ||||
| } | ||||
|  | ||||
| void dbuf_init(DynBuf *s) | ||||
| { | ||||
|     dbuf_init2(s, NULL, NULL); | ||||
| } | ||||
|  | ||||
| /* return < 0 if error */ | ||||
| int dbuf_realloc(DynBuf *s, size_t new_size) | ||||
| { | ||||
|     size_t size; | ||||
|     uint8_t *new_buf; | ||||
|     if (new_size > s->allocated_size) { | ||||
|         if (s->error) | ||||
|             return -1; | ||||
|         size = s->allocated_size * 3 / 2; | ||||
|         if (size > new_size) | ||||
|             new_size = size; | ||||
|         new_buf = s->realloc_func(s->opaque, s->buf, new_size); | ||||
|         if (!new_buf) { | ||||
|             s->error = TRUE; | ||||
|             return -1; | ||||
|         } | ||||
|         s->buf = new_buf; | ||||
|         s->allocated_size = new_size; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) | ||||
| { | ||||
|     size_t end; | ||||
|     end = offset + len; | ||||
|     if (dbuf_realloc(s, end)) | ||||
|         return -1; | ||||
|     memcpy(s->buf + offset, data, len); | ||||
|     if (end > s->size) | ||||
|         s->size = end; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) | ||||
| { | ||||
|     if (unlikely((s->size + len) > s->allocated_size)) { | ||||
|         if (dbuf_realloc(s, s->size + len)) | ||||
|             return -1; | ||||
|     } | ||||
|     memcpy(s->buf + s->size, data, len); | ||||
|     s->size += len; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int dbuf_put_self(DynBuf *s, size_t offset, size_t len) | ||||
| { | ||||
|     if (unlikely((s->size + len) > s->allocated_size)) { | ||||
|         if (dbuf_realloc(s, s->size + len)) | ||||
|             return -1; | ||||
|     } | ||||
|     memcpy(s->buf + s->size, s->buf + offset, len); | ||||
|     s->size += len; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int dbuf_putc(DynBuf *s, uint8_t c) | ||||
| { | ||||
|     return dbuf_put(s, &c, 1); | ||||
| } | ||||
|  | ||||
| int dbuf_putstr(DynBuf *s, const char *str) | ||||
| { | ||||
|     return dbuf_put(s, (const uint8_t *)str, strlen(str)); | ||||
| } | ||||
|  | ||||
| int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, | ||||
|                                                       const char *fmt, ...) | ||||
| { | ||||
|     va_list ap; | ||||
|     char buf[128]; | ||||
|     int len; | ||||
|      | ||||
|     va_start(ap, fmt); | ||||
|     len = vsnprintf(buf, sizeof(buf), fmt, ap); | ||||
|     va_end(ap); | ||||
|     if (len < sizeof(buf)) { | ||||
|         /* fast case */ | ||||
|         return dbuf_put(s, (uint8_t *)buf, len); | ||||
|     } else { | ||||
|         if (dbuf_realloc(s, s->size + len + 1)) | ||||
|             return -1; | ||||
|         va_start(ap, fmt); | ||||
|         vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, | ||||
|                   fmt, ap); | ||||
|         va_end(ap); | ||||
|         s->size += len; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void dbuf_free(DynBuf *s) | ||||
| { | ||||
|     /* we test s->buf as a fail safe to avoid crashing if dbuf_free() | ||||
|        is called twice */ | ||||
|     if (s->buf) { | ||||
|         s->realloc_func(s->opaque, s->buf, 0); | ||||
|     } | ||||
|     memset(s, 0, sizeof(*s)); | ||||
| } | ||||
|  | ||||
| /* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes | ||||
|    are output. */ | ||||
| int unicode_to_utf8(uint8_t *buf, unsigned int c) | ||||
| { | ||||
|     uint8_t *q = buf; | ||||
|  | ||||
|     if (c < 0x80) { | ||||
|         *q++ = c; | ||||
|     } else { | ||||
|         if (c < 0x800) { | ||||
|             *q++ = (c >> 6) | 0xc0; | ||||
|         } else { | ||||
|             if (c < 0x10000) { | ||||
|                 *q++ = (c >> 12) | 0xe0; | ||||
|             } else { | ||||
|                 if (c < 0x00200000) { | ||||
|                     *q++ = (c >> 18) | 0xf0; | ||||
|                 } else { | ||||
|                     if (c < 0x04000000) { | ||||
|                         *q++ = (c >> 24) | 0xf8; | ||||
|                     } else if (c < 0x80000000) { | ||||
|                         *q++ = (c >> 30) | 0xfc; | ||||
|                         *q++ = ((c >> 24) & 0x3f) | 0x80; | ||||
|                     } else { | ||||
|                         return 0; | ||||
|                     } | ||||
|                     *q++ = ((c >> 18) & 0x3f) | 0x80; | ||||
|                 } | ||||
|                 *q++ = ((c >> 12) & 0x3f) | 0x80; | ||||
|             } | ||||
|             *q++ = ((c >> 6) & 0x3f) | 0x80; | ||||
|         } | ||||
|         *q++ = (c & 0x3f) | 0x80; | ||||
|     } | ||||
|     return q - buf; | ||||
| } | ||||
|  | ||||
| static const unsigned int utf8_min_code[5] = { | ||||
|     0x80, 0x800, 0x10000, 0x00200000, 0x04000000, | ||||
| }; | ||||
|  | ||||
| static const unsigned char utf8_first_code_mask[5] = { | ||||
|     0x1f, 0xf, 0x7, 0x3, 0x1, | ||||
| }; | ||||
|  | ||||
| /* return -1 if error. *pp is not updated in this case. max_len must | ||||
|    be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */ | ||||
| int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp) | ||||
| { | ||||
|     int l, c, b, i; | ||||
|  | ||||
|     c = *p++; | ||||
|     if (c < 0x80) { | ||||
|         *pp = p; | ||||
|         return c; | ||||
|     } | ||||
|     switch(c) { | ||||
|     case 0xc0 ... 0xdf: | ||||
|         l = 1; | ||||
|         break; | ||||
|     case 0xe0 ... 0xef: | ||||
|         l = 2; | ||||
|         break; | ||||
|     case 0xf0 ... 0xf7: | ||||
|         l = 3; | ||||
|         break; | ||||
|     case 0xf8 ... 0xfb: | ||||
|         l = 4; | ||||
|         break; | ||||
|     case 0xfc ... 0xfd: | ||||
|         l = 5; | ||||
|         break; | ||||
|     default: | ||||
|         return -1; | ||||
|     } | ||||
|     /* check that we have enough characters */ | ||||
|     if (l > (max_len - 1)) | ||||
|         return -1; | ||||
|     c &= utf8_first_code_mask[l - 1]; | ||||
|     for(i = 0; i < l; i++) { | ||||
|         b = *p++; | ||||
|         if (b < 0x80 || b >= 0xc0) | ||||
|             return -1; | ||||
|         c = (c << 6) | (b & 0x3f); | ||||
|     } | ||||
|     if (c < utf8_min_code[l - 1]) | ||||
|         return -1; | ||||
|     *pp = p; | ||||
|     return c; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
|  | ||||
| #if defined(EMSCRIPTEN) || defined(__ANDROID__) | ||||
|  | ||||
| static void *rqsort_arg; | ||||
| static int (*rqsort_cmp)(const void *, const void *, void *); | ||||
|  | ||||
| static int rqsort_cmp2(const void *p1, const void *p2) | ||||
| { | ||||
|     return rqsort_cmp(p1, p2, rqsort_arg); | ||||
| } | ||||
|  | ||||
| /* not reentrant, but not needed with emscripten */ | ||||
| void rqsort(void *base, size_t nmemb, size_t size, | ||||
|             int (*cmp)(const void *, const void *, void *), | ||||
|             void *arg) | ||||
| { | ||||
|     rqsort_arg = arg; | ||||
|     rqsort_cmp = cmp; | ||||
|     qsort(base, nmemb, size, rqsort_cmp2); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #else | ||||
|  | ||||
| typedef void (*exchange_f)(void *a, void *b, size_t size); | ||||
| typedef int (*cmp_f)(const void *, const void *, void *opaque); | ||||
|  | ||||
| static void exchange_bytes(void *a, void *b, size_t size) { | ||||
|     uint8_t *ap = (uint8_t *)a; | ||||
|     uint8_t *bp = (uint8_t *)b; | ||||
|  | ||||
|     while (size-- != 0) { | ||||
|         uint8_t t = *ap; | ||||
|         *ap++ = *bp; | ||||
|         *bp++ = t; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void exchange_one_byte(void *a, void *b, size_t size) { | ||||
|     uint8_t *ap = (uint8_t *)a; | ||||
|     uint8_t *bp = (uint8_t *)b; | ||||
|     uint8_t t = *ap; | ||||
|     *ap = *bp; | ||||
|     *bp = t; | ||||
| } | ||||
|  | ||||
| static void exchange_int16s(void *a, void *b, size_t size) { | ||||
|     uint16_t *ap = (uint16_t *)a; | ||||
|     uint16_t *bp = (uint16_t *)b; | ||||
|  | ||||
|     for (size /= sizeof(uint16_t); size-- != 0;) { | ||||
|         uint16_t t = *ap; | ||||
|         *ap++ = *bp; | ||||
|         *bp++ = t; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void exchange_one_int16(void *a, void *b, size_t size) { | ||||
|     uint16_t *ap = (uint16_t *)a; | ||||
|     uint16_t *bp = (uint16_t *)b; | ||||
|     uint16_t t = *ap; | ||||
|     *ap = *bp; | ||||
|     *bp = t; | ||||
| } | ||||
|  | ||||
| static void exchange_int32s(void *a, void *b, size_t size) { | ||||
|     uint32_t *ap = (uint32_t *)a; | ||||
|     uint32_t *bp = (uint32_t *)b; | ||||
|  | ||||
|     for (size /= sizeof(uint32_t); size-- != 0;) { | ||||
|         uint32_t t = *ap; | ||||
|         *ap++ = *bp; | ||||
|         *bp++ = t; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void exchange_one_int32(void *a, void *b, size_t size) { | ||||
|     uint32_t *ap = (uint32_t *)a; | ||||
|     uint32_t *bp = (uint32_t *)b; | ||||
|     uint32_t t = *ap; | ||||
|     *ap = *bp; | ||||
|     *bp = t; | ||||
| } | ||||
|  | ||||
| static void exchange_int64s(void *a, void *b, size_t size) { | ||||
|     uint64_t *ap = (uint64_t *)a; | ||||
|     uint64_t *bp = (uint64_t *)b; | ||||
|  | ||||
|     for (size /= sizeof(uint64_t); size-- != 0;) { | ||||
|         uint64_t t = *ap; | ||||
|         *ap++ = *bp; | ||||
|         *bp++ = t; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void exchange_one_int64(void *a, void *b, size_t size) { | ||||
|     uint64_t *ap = (uint64_t *)a; | ||||
|     uint64_t *bp = (uint64_t *)b; | ||||
|     uint64_t t = *ap; | ||||
|     *ap = *bp; | ||||
|     *bp = t; | ||||
| } | ||||
|  | ||||
| static void exchange_int128s(void *a, void *b, size_t size) { | ||||
|     uint64_t *ap = (uint64_t *)a; | ||||
|     uint64_t *bp = (uint64_t *)b; | ||||
|  | ||||
|     for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { | ||||
|         uint64_t t = ap[0]; | ||||
|         uint64_t u = ap[1]; | ||||
|         ap[0] = bp[0]; | ||||
|         ap[1] = bp[1]; | ||||
|         bp[0] = t; | ||||
|         bp[1] = u; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void exchange_one_int128(void *a, void *b, size_t size) { | ||||
|     uint64_t *ap = (uint64_t *)a; | ||||
|     uint64_t *bp = (uint64_t *)b; | ||||
|     uint64_t t = ap[0]; | ||||
|     uint64_t u = ap[1]; | ||||
|     ap[0] = bp[0]; | ||||
|     ap[1] = bp[1]; | ||||
|     bp[0] = t; | ||||
|     bp[1] = u; | ||||
| } | ||||
|  | ||||
| static inline exchange_f exchange_func(const void *base, size_t size) { | ||||
|     switch (((uintptr_t)base | (uintptr_t)size) & 15) { | ||||
|     case 0: | ||||
|         if (size == sizeof(uint64_t) * 2) | ||||
|             return exchange_one_int128; | ||||
|         else | ||||
|             return exchange_int128s; | ||||
|     case 8: | ||||
|         if (size == sizeof(uint64_t)) | ||||
|             return exchange_one_int64; | ||||
|         else | ||||
|             return exchange_int64s; | ||||
|     case 4: | ||||
|     case 12: | ||||
|         if (size == sizeof(uint32_t)) | ||||
|             return exchange_one_int32; | ||||
|         else | ||||
|             return exchange_int32s; | ||||
|     case 2: | ||||
|     case 6: | ||||
|     case 10: | ||||
|     case 14: | ||||
|         if (size == sizeof(uint16_t)) | ||||
|             return exchange_one_int16; | ||||
|         else | ||||
|             return exchange_int16s; | ||||
|     default: | ||||
|         if (size == 1) | ||||
|             return exchange_one_byte; | ||||
|         else | ||||
|             return exchange_bytes; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) | ||||
| { | ||||
|     uint8_t *basep = (uint8_t *)base; | ||||
|     size_t i, n, c, r; | ||||
|     exchange_f swap = exchange_func(base, size); | ||||
|  | ||||
|     if (nmemb > 1) { | ||||
|         i = (nmemb / 2) * size; | ||||
|         n = nmemb * size; | ||||
|  | ||||
|         while (i > 0) { | ||||
|             i -= size; | ||||
|             for (r = i; (c = r * 2 + size) < n; r = c) { | ||||
|                 if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) | ||||
|                     c += size; | ||||
|                 if (cmp(basep + r, basep + c, opaque) > 0) | ||||
|                     break; | ||||
|                 swap(basep + r, basep + c, size); | ||||
|             } | ||||
|         } | ||||
|         for (i = n - size; i > 0; i -= size) { | ||||
|             swap(basep, basep + i, size); | ||||
|  | ||||
|             for (r = 0; (c = r * 2 + size) < i; r = c) { | ||||
|                 if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) | ||||
|                     c += size; | ||||
|                 if (cmp(basep + r, basep + c, opaque) > 0) | ||||
|                     break; | ||||
|                 swap(basep + r, basep + c, size); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) | ||||
| { | ||||
|     return cmp(a, b, opaque) < 0 ? | ||||
|         (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : | ||||
|         (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); | ||||
| } | ||||
|  | ||||
| /* pointer based version with local stack and insertion sort threshhold */ | ||||
| void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) | ||||
| { | ||||
|     struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; | ||||
|     uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; | ||||
|     size_t m4, i, lt, gt, span, span2; | ||||
|     int c, depth; | ||||
|     exchange_f swap = exchange_func(base, size); | ||||
|     exchange_f swap_block = exchange_func(base, size | 128); | ||||
|  | ||||
|     if (nmemb < 2 || size <= 0) | ||||
|         return; | ||||
|  | ||||
|     sp->base = (uint8_t *)base; | ||||
|     sp->count = nmemb; | ||||
|     sp->depth = 0; | ||||
|     sp++; | ||||
|  | ||||
|     while (sp > stack) { | ||||
|         sp--; | ||||
|         ptr = sp->base; | ||||
|         nmemb = sp->count; | ||||
|         depth = sp->depth; | ||||
|  | ||||
|         while (nmemb > 6) { | ||||
|             if (++depth > 50) { | ||||
|                 /* depth check to ensure worst case logarithmic time */ | ||||
|                 heapsortx(ptr, nmemb, size, cmp, opaque); | ||||
|                 nmemb = 0; | ||||
|                 break; | ||||
|             } | ||||
|             /* select median of 3 from 1/4, 1/2, 3/4 positions */ | ||||
|             /* should use median of 5 or 9? */ | ||||
|             m4 = (nmemb >> 2) * size; | ||||
|             m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); | ||||
|             swap(ptr, m, size);  /* move the pivot to the start or the array */ | ||||
|             i = lt = 1; | ||||
|             pi = plt = ptr + size; | ||||
|             gt = nmemb; | ||||
|             pj = pgt = top = ptr + nmemb * size; | ||||
|             for (;;) { | ||||
|                 while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { | ||||
|                     if (c == 0) { | ||||
|                         swap(plt, pi, size); | ||||
|                         lt++; | ||||
|                         plt += size; | ||||
|                     } | ||||
|                     i++; | ||||
|                     pi += size; | ||||
|                 } | ||||
|                 while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { | ||||
|                     if (c == 0) { | ||||
|                         gt--; | ||||
|                         pgt -= size; | ||||
|                         swap(pgt, pj, size); | ||||
|                     } | ||||
|                 } | ||||
|                 if (pi >= pj) | ||||
|                     break; | ||||
|                 swap(pi, pj, size); | ||||
|                 i++; | ||||
|                 pi += size; | ||||
|             } | ||||
|             /* array has 4 parts: | ||||
|              * from 0 to lt excluded: elements identical to pivot | ||||
|              * from lt to pi excluded: elements smaller than pivot | ||||
|              * from pi to gt excluded: elements greater than pivot | ||||
|              * from gt to n excluded: elements identical to pivot | ||||
|              */ | ||||
|             /* move elements identical to pivot in the middle of the array: */ | ||||
|             /* swap values in ranges [0..lt[ and [i-lt..i[ | ||||
|                swapping the smallest span between lt and i-lt is sufficient | ||||
|              */ | ||||
|             span = plt - ptr; | ||||
|             span2 = pi - plt; | ||||
|             lt = i - lt; | ||||
|             if (span > span2) | ||||
|                 span = span2; | ||||
|             swap_block(ptr, pi - span, span); | ||||
|             /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ | ||||
|                swapping the smallest span between top-gt and gt-i is sufficient | ||||
|              */ | ||||
|             span = top - pgt; | ||||
|             span2 = pgt - pi; | ||||
|             pgt = top - span2; | ||||
|             gt = nmemb - (gt - i); | ||||
|             if (span > span2) | ||||
|                 span = span2; | ||||
|             swap_block(pi, top - span, span); | ||||
|  | ||||
|             /* now array has 3 parts: | ||||
|              * from 0 to lt excluded: elements smaller than pivot | ||||
|              * from lt to gt excluded: elements identical to pivot | ||||
|              * from gt to n excluded: elements greater than pivot | ||||
|              */ | ||||
|             /* stack the larger segment and keep processing the smaller one | ||||
|                to minimize stack use for pathological distributions */ | ||||
|             if (lt > nmemb - gt) { | ||||
|                 sp->base = ptr; | ||||
|                 sp->count = lt; | ||||
|                 sp->depth = depth; | ||||
|                 sp++; | ||||
|                 ptr = pgt; | ||||
|                 nmemb -= gt; | ||||
|             } else { | ||||
|                 sp->base = pgt; | ||||
|                 sp->count = nmemb - gt; | ||||
|                 sp->depth = depth; | ||||
|                 sp++; | ||||
|                 nmemb = lt; | ||||
|             } | ||||
|         } | ||||
|         /* Use insertion sort for small fragments */ | ||||
|         for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { | ||||
|             for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) | ||||
|                 swap(pj, pj - size, size); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										293
									
								
								deps/quickjs/cutils.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								deps/quickjs/cutils.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | ||||
| /* | ||||
|  * C utilities | ||||
|  *  | ||||
|  * Copyright (c) 2017 Fabrice Bellard | ||||
|  * Copyright (c) 2018 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef CUTILS_H | ||||
| #define CUTILS_H | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <inttypes.h> | ||||
|  | ||||
| /* set if CPU is big endian */ | ||||
| #undef WORDS_BIGENDIAN | ||||
|  | ||||
| #define likely(x)       __builtin_expect(!!(x), 1) | ||||
| #define unlikely(x)     __builtin_expect(!!(x), 0) | ||||
| #define force_inline inline __attribute__((always_inline)) | ||||
| #define no_inline __attribute__((noinline)) | ||||
| #define __maybe_unused __attribute__((unused)) | ||||
|  | ||||
| #define xglue(x, y) x ## y | ||||
| #define glue(x, y) xglue(x, y) | ||||
| #define stringify(s)    tostring(s) | ||||
| #define tostring(s)     #s | ||||
|  | ||||
| #ifndef offsetof | ||||
| #define offsetof(type, field) ((size_t) &((type *)0)->field) | ||||
| #endif | ||||
| #ifndef countof | ||||
| #define countof(x) (sizeof(x) / sizeof((x)[0])) | ||||
| #endif | ||||
|  | ||||
| typedef int BOOL; | ||||
|  | ||||
| #ifndef FALSE | ||||
| enum { | ||||
|     FALSE = 0, | ||||
|     TRUE = 1, | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| void pstrcpy(char *buf, int buf_size, const char *str); | ||||
| char *pstrcat(char *buf, int buf_size, const char *s); | ||||
| int strstart(const char *str, const char *val, const char **ptr); | ||||
| int has_suffix(const char *str, const char *suffix); | ||||
|  | ||||
| static inline int max_int(int a, int b) | ||||
| { | ||||
|     if (a > b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| static inline int min_int(int a, int b) | ||||
| { | ||||
|     if (a < b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| static inline uint32_t max_uint32(uint32_t a, uint32_t b) | ||||
| { | ||||
|     if (a > b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| static inline uint32_t min_uint32(uint32_t a, uint32_t b) | ||||
| { | ||||
|     if (a < b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| static inline int64_t max_int64(int64_t a, int64_t b) | ||||
| { | ||||
|     if (a > b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| static inline int64_t min_int64(int64_t a, int64_t b) | ||||
| { | ||||
|     if (a < b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| /* WARNING: undefined if a = 0 */ | ||||
| static inline int clz32(unsigned int a) | ||||
| { | ||||
|     return __builtin_clz(a); | ||||
| } | ||||
|  | ||||
| /* WARNING: undefined if a = 0 */ | ||||
| static inline int clz64(uint64_t a) | ||||
| { | ||||
|     return __builtin_clzll(a); | ||||
| } | ||||
|  | ||||
| /* WARNING: undefined if a = 0 */ | ||||
| static inline int ctz32(unsigned int a) | ||||
| { | ||||
|     return __builtin_ctz(a); | ||||
| } | ||||
|  | ||||
| /* WARNING: undefined if a = 0 */ | ||||
| static inline int ctz64(uint64_t a) | ||||
| { | ||||
|     return __builtin_ctzll(a); | ||||
| } | ||||
|  | ||||
| struct __attribute__((packed)) packed_u64 { | ||||
|     uint64_t v; | ||||
| }; | ||||
|  | ||||
| struct __attribute__((packed)) packed_u32 { | ||||
|     uint32_t v; | ||||
| }; | ||||
|  | ||||
| struct __attribute__((packed)) packed_u16 { | ||||
|     uint16_t v; | ||||
| }; | ||||
|  | ||||
| static inline uint64_t get_u64(const uint8_t *tab) | ||||
| { | ||||
|     return ((const struct packed_u64 *)tab)->v; | ||||
| } | ||||
|  | ||||
| static inline int64_t get_i64(const uint8_t *tab) | ||||
| { | ||||
|     return (int64_t)((const struct packed_u64 *)tab)->v; | ||||
| } | ||||
|  | ||||
| static inline void put_u64(uint8_t *tab, uint64_t val) | ||||
| { | ||||
|     ((struct packed_u64 *)tab)->v = val; | ||||
| } | ||||
|  | ||||
| static inline uint32_t get_u32(const uint8_t *tab) | ||||
| { | ||||
|     return ((const struct packed_u32 *)tab)->v; | ||||
| } | ||||
|  | ||||
| static inline int32_t get_i32(const uint8_t *tab) | ||||
| { | ||||
|     return (int32_t)((const struct packed_u32 *)tab)->v; | ||||
| } | ||||
|  | ||||
| static inline void put_u32(uint8_t *tab, uint32_t val) | ||||
| { | ||||
|     ((struct packed_u32 *)tab)->v = val; | ||||
| } | ||||
|  | ||||
| static inline uint32_t get_u16(const uint8_t *tab) | ||||
| { | ||||
|     return ((const struct packed_u16 *)tab)->v; | ||||
| } | ||||
|  | ||||
| static inline int32_t get_i16(const uint8_t *tab) | ||||
| { | ||||
|     return (int16_t)((const struct packed_u16 *)tab)->v; | ||||
| } | ||||
|  | ||||
| static inline void put_u16(uint8_t *tab, uint16_t val) | ||||
| { | ||||
|     ((struct packed_u16 *)tab)->v = val; | ||||
| } | ||||
|  | ||||
| static inline uint32_t get_u8(const uint8_t *tab) | ||||
| { | ||||
|     return *tab; | ||||
| } | ||||
|  | ||||
| static inline int32_t get_i8(const uint8_t *tab) | ||||
| { | ||||
|     return (int8_t)*tab; | ||||
| } | ||||
|  | ||||
| static inline void put_u8(uint8_t *tab, uint8_t val) | ||||
| { | ||||
|     *tab = val; | ||||
| } | ||||
|  | ||||
| static inline uint16_t bswap16(uint16_t x) | ||||
| { | ||||
|     return (x >> 8) | (x << 8); | ||||
| } | ||||
|  | ||||
| static inline uint32_t bswap32(uint32_t v) | ||||
| { | ||||
|     return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >>  8) | | ||||
|         ((v & 0x0000ff00) <<  8) | ((v & 0x000000ff) << 24); | ||||
| } | ||||
|  | ||||
| static inline uint64_t bswap64(uint64_t v) | ||||
| { | ||||
|     return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |  | ||||
|         ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8)); | ||||
| } | ||||
|  | ||||
| /* XXX: should take an extra argument to pass slack information to the caller */ | ||||
| typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size); | ||||
|  | ||||
| typedef struct DynBuf { | ||||
|     uint8_t *buf; | ||||
|     size_t size; | ||||
|     size_t allocated_size; | ||||
|     BOOL error; /* true if a memory allocation error occurred */ | ||||
|     DynBufReallocFunc *realloc_func; | ||||
|     void *opaque; /* for realloc_func */ | ||||
| } DynBuf; | ||||
|  | ||||
| void dbuf_init(DynBuf *s); | ||||
| void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); | ||||
| int dbuf_realloc(DynBuf *s, size_t new_size); | ||||
| int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); | ||||
| int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); | ||||
| int dbuf_put_self(DynBuf *s, size_t offset, size_t len); | ||||
| int dbuf_putc(DynBuf *s, uint8_t c); | ||||
| int dbuf_putstr(DynBuf *s, const char *str); | ||||
| static inline int dbuf_put_u16(DynBuf *s, uint16_t val) | ||||
| { | ||||
|     return dbuf_put(s, (uint8_t *)&val, 2); | ||||
| } | ||||
| static inline int dbuf_put_u32(DynBuf *s, uint32_t val) | ||||
| { | ||||
|     return dbuf_put(s, (uint8_t *)&val, 4); | ||||
| } | ||||
| static inline int dbuf_put_u64(DynBuf *s, uint64_t val) | ||||
| { | ||||
|     return dbuf_put(s, (uint8_t *)&val, 8); | ||||
| } | ||||
| int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, | ||||
|                                                       const char *fmt, ...); | ||||
| void dbuf_free(DynBuf *s); | ||||
| static inline BOOL dbuf_error(DynBuf *s) { | ||||
|     return s->error; | ||||
| } | ||||
|  | ||||
| #define UTF8_CHAR_LEN_MAX 6 | ||||
|  | ||||
| int unicode_to_utf8(uint8_t *buf, unsigned int c); | ||||
| int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp); | ||||
|  | ||||
| static inline int from_hex(int c) | ||||
| { | ||||
|     if (c >= '0' && c <= '9') | ||||
|         return c - '0'; | ||||
|     else if (c >= 'A' && c <= 'F') | ||||
|         return c - 'A' + 10; | ||||
|     else if (c >= 'a' && c <= 'f') | ||||
|         return c - 'a' + 10; | ||||
|     else | ||||
|         return -1; | ||||
| } | ||||
|  | ||||
| void rqsort(void *base, size_t nmemb, size_t size, | ||||
|             int (*cmp)(const void *, const void *, void *), | ||||
|             void *arg); | ||||
|  | ||||
| #endif  /* CUTILS_H */ | ||||
							
								
								
									
										1037
									
								
								deps/quickjs/doc/jsbignum.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1037
									
								
								deps/quickjs/doc/jsbignum.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								deps/quickjs/doc/jsbignum.pdf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								deps/quickjs/doc/jsbignum.pdf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										829
									
								
								deps/quickjs/doc/jsbignum.texi
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										829
									
								
								deps/quickjs/doc/jsbignum.texi
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,829 @@ | ||||
| \input texinfo | ||||
|  | ||||
| @iftex | ||||
| @afourpaper | ||||
| @headings double | ||||
| @end iftex | ||||
|  | ||||
| @titlepage | ||||
| @afourpaper | ||||
| @sp 7 | ||||
| @center @titlefont{Javascript Bignum Extensions} | ||||
| @sp 3 | ||||
| @center Version 2018-06-16 | ||||
| @sp 3 | ||||
| @center Author: Fabrice Bellard | ||||
| @end titlepage | ||||
|  | ||||
| @setfilename spec.info | ||||
| @settitle Javascript Bignum Extensions | ||||
|  | ||||
| @contents | ||||
|  | ||||
| @chapter Introduction | ||||
|  | ||||
| The Bignum extensions add the following features to the Javascript | ||||
| language while being 100% backward compatible: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item Overloading of the standard operators | ||||
| to support new types such as complex numbers, fractions or matrixes. | ||||
|  | ||||
| @item Bigint mode where arbitrarily large integers are available by default (no @code{n} suffix is necessary as in the TC39 BigInt proposal@footnote{@url{https://tc39.github.io/proposal-bigint/}}). | ||||
|  | ||||
| @item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics. | ||||
|  | ||||
| @item Optional @code{math} mode which modifies the semantics of the division, modulo and power operator. The division and power operator return a fraction with integer operands and the modulo operator is defined as the Euclidian remainder. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| The extensions are independent from each other except the @code{math} | ||||
| mode which relies on the bigint mode and the operator overloading. | ||||
|  | ||||
| @chapter Operator overloading | ||||
|  | ||||
| @section Introduction | ||||
|  | ||||
| If the operands of an operator have at least one object type, a custom | ||||
| operator method is searched before doing the legacy Javascript | ||||
| @code{ToNumber} conversion. | ||||
|  | ||||
| For unary operators, the custom function is looked up in the object | ||||
| and has the following name: | ||||
|  | ||||
| @table @code | ||||
| @item unary +  | ||||
| @code{Symbol.operatorPlus} | ||||
|  | ||||
| @item unary - | ||||
| @code{Symbol.operatorNeg} | ||||
|  | ||||
| @item ++ | ||||
| @code{Symbol.operatorInc} | ||||
|  | ||||
| @item -- | ||||
| @code{Symbol.operatorDec} | ||||
|  | ||||
| @item ~ | ||||
| @code{Symbol.operatorNot} | ||||
|  | ||||
| @end table | ||||
|  | ||||
| For binary operators: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item | ||||
| If both operands have the same constructor function, then the operator | ||||
| is looked up in the constructor. | ||||
|  | ||||
| @item | ||||
| Otherwise, the property @code{Symbol.operatorOrder} is looked up in both | ||||
| constructors and converted to @code{Int32}. The operator is then | ||||
| looked in the constructor with the larger @code{Symbol.operatorOrder} | ||||
| value. A @code{TypeError} is raised if both constructors have the same | ||||
| @code{Symbol.operatorOrder} value. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| The operator is looked up with the following name: | ||||
|  | ||||
| @table @code | ||||
| @item +  | ||||
| @code{Symbol.operatorAdd} | ||||
|  | ||||
| @item - | ||||
| @code{Symbol.operatorSub} | ||||
|  | ||||
| @item * | ||||
| @code{Symbol.operatorMul} | ||||
|  | ||||
| @item / | ||||
| @code{Symbol.operatorDiv} | ||||
|  | ||||
| @item % | ||||
| @code{Symbol.operatorMod} | ||||
|  | ||||
| @item % (math mode) | ||||
| @code{Symbol.operatorMathMod} | ||||
|  | ||||
| @item ** | ||||
| @code{Symbol.operatorPow} | ||||
|  | ||||
| @item | | ||||
| @code{Symbol.operatorOr} | ||||
|  | ||||
| @item ^ | ||||
| @code{Symbol.operatorXor} | ||||
|  | ||||
| @item & | ||||
| @code{Symbol.operatorAnd} | ||||
|  | ||||
| @item << | ||||
| @code{Symbol.operatorShl} | ||||
|  | ||||
| @item >> | ||||
| @code{Symbol.operatorShr} | ||||
|  | ||||
| @item < | ||||
| @code{Symbol.operatorCmpLT} | ||||
|  | ||||
| @item > | ||||
| @code{Symbol.operatorCmpLT}, operands swapped | ||||
|  | ||||
| @item <= | ||||
| @code{Symbol.operatorCmpLE} | ||||
|  | ||||
| @item >= | ||||
| @code{Symbol.operatorCmpLE}, operands swapped | ||||
|  | ||||
| @item ==, != | ||||
| @code{Symbol.operatorCmpEQ} | ||||
|  | ||||
| @end table | ||||
|  | ||||
| The return value of @code{Symbol.operatorCmpLT}, @code{Symbol.operatorCmpLE} and | ||||
| @code{Symbol.operatorCmpEQ} is converted to @code{Boolean}. | ||||
|  | ||||
| @section Builtin Object changes | ||||
|  | ||||
| @subsection @code{Symbol} constructor | ||||
|  | ||||
| The following global symbols are added for the operator overloading: | ||||
| @table @code | ||||
| @item operatorOrder | ||||
| @item operatorAdd | ||||
| @item operatorSub | ||||
| @item operatorMul | ||||
| @item operatorDiv | ||||
| @item operatorMod | ||||
| @item operatorPow | ||||
| @item operatorShl | ||||
| @item operatorShr | ||||
| @item operatorAnd | ||||
| @item operatorOr | ||||
| @item operatorXor | ||||
| @item operatorCmpLT | ||||
| @item operatorCmpLE | ||||
| @item operatorCmpEQ | ||||
| @item operatorPlus | ||||
| @item operatorNeg | ||||
| @item operatorNot | ||||
| @item operatorInc | ||||
| @item operatorDec | ||||
| @end table | ||||
|  | ||||
|  | ||||
| @chapter The BigInt Mode | ||||
|  | ||||
| @section Introduction | ||||
|  | ||||
| The bigint mode is enabled with the @code{"use bigint"} directive. It | ||||
| propagates the same way as the strict mode. In bigint mode, all | ||||
| integers are considered as @code{bigint} (arbitrarily large integer, | ||||
| similar to the TC39 BigInt | ||||
| proposal@footnote{@url{https://tc39.github.io/proposal-bigint/}}) | ||||
| instead of @code{number} (floating point number). In order to be able | ||||
| to exchange data between standard and bigint modes, numbers are | ||||
| internally represented as 3 different types: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item Small integer (SmallInt): 32 bit integer@footnote{Could be extended to 53 bits without changing the principle.}. | ||||
|  | ||||
| @item Big integer (BigInt): arbitrarily large integer. | ||||
|  | ||||
| @item Floating point number (Float). | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| In standard mode, the semantics of each operation is modified so that | ||||
| when it returns a @code{number}, it is either of SmallInt or | ||||
| Float. But the difference between SmallInt and Float is not observable | ||||
| in standard mode. | ||||
|  | ||||
| In bigint mode, each operation behaves differently whether its | ||||
| operands are integer or float. The difference between SmallInt and | ||||
| BigInt is not observable (i.e. they are both integers). | ||||
|  | ||||
| The following table summarizes the observable types: | ||||
|  | ||||
| @multitable @columnfractions .3 .3 .3 | ||||
| @headitem Internal type @tab Observable type@* (standard mode) @tab Observable type@* (bigint mode) | ||||
| @item SmallInt @tab number @tab bigint | ||||
| @item BigInt @tab bigint @tab bigint | ||||
| @item Float @tab number @tab number | ||||
| @end multitable | ||||
|  | ||||
| @section Changes that introduce incompatibilities with Javascript | ||||
|  | ||||
| @subsection Standard mode | ||||
|  | ||||
| There is no incompatibility with Javascript. | ||||
|  | ||||
| @subsection Bigint mode | ||||
|  | ||||
| The following changes are visible: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item Integer and Float are different types. Constants are typed. For example: @code{typeof 1.0 === "number"} and @code{typeof 1 === "bigint"}. Another consequence is that @code{1.0 === 1} is false. | ||||
|  | ||||
| @item The range of integers is unlimited. In standard mode: @code{2**53 + 1 === 2**53}. This is no longer true with the bignum extensions. | ||||
|  | ||||
| @item Binary bitwise operators do not truncate to 32 bits i.e. @code{0x800000000 | 1 === 0x800000001} while it gives @code{1} in standard mode. | ||||
|  | ||||
| @item Bitwise shift operators do not truncate to 32 bits and do not mask the shift count with @code{0x1f} i.e. @code{1 << 32 === 4294967296} while it gives @code{1} in standard mode. However, the @code{>>>} operator (unsigned right shift) which is useless with bignums keeps its standard mode behavior@footnote{The unsigned right right operator could be removed in bigint mode.}. | ||||
|  | ||||
| @item Operators with integer operands never return the minus zero floating point value as result. Hence @code{Object.is(0, -0) === true}. Use @code{-0.0} to create a minus zero floating point value. | ||||
|  | ||||
| @item The @code{ToPrimitive} abstract operation is called with the @code{"integer"} preferred type when an integer is required (e.g. for bitwise binary or shift operations). | ||||
|  | ||||
| @item The prototype of integers is no longer @code{Number.prototype}. Instead@* @code{Object.getPrototypeOf(1) === BigInt.prototype}. The prototype of floats remains Number.prototype. | ||||
|  | ||||
| @item If the TC39 BigInt proposal is supported, there is no observable difference between integers and @code{bigint}s. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @section Operators | ||||
|  | ||||
| @subsection Arithmetic operators | ||||
|  | ||||
| The operands are converted to number values as in normal | ||||
| Javascript. Then the general case is that an Integer is returned if | ||||
| both operands are Integer. Otherwise, a float is returned. | ||||
|  | ||||
| The @code{+} operator also accepts strings as input and behaves like | ||||
| standard Javascript in this case. | ||||
|  | ||||
| The binary operator @code{%} returns the truncated remainder of the | ||||
| division. When the result is an Integer type, a dividend of zero yields a | ||||
| RangeError exception. | ||||
|  | ||||
| The binary operator @code{%} in math mode returns the Euclidian | ||||
| remainder of the division i.e. it is always positive.  | ||||
|  | ||||
| The binary operator @code{/} returns a float. | ||||
|  | ||||
| The binary operator @code{/} in math mode returns a float if one of | ||||
| the operands is float. Otherwise, @code{BigInt[Symbol.operatorDiv]} is | ||||
| invoked. | ||||
|  | ||||
| The returned type of @code{a ** b} is Float if @math{a} or @math{b} | ||||
| are Float. If @math{a} and @math{b} are integers: | ||||
| @itemize | ||||
| @item @math{b < 0} returns a Float in bigint mode. In math mode, @code{BigInt[Symbol.operatorPow]} is invoked. | ||||
|  | ||||
| @item @math{b >= 0} returns an integer. | ||||
| @end itemize | ||||
|  | ||||
| The unary @code{-} and unary @code{+} return the same type as their | ||||
| operand. They performs no floating point rounding when the result is a | ||||
| float. | ||||
|  | ||||
| The unary operators @code{++} and @code{--} return the same type as | ||||
| their operand. | ||||
|  | ||||
| In standard mode: | ||||
|  | ||||
| If the operator returns an Integer and that the result fits a | ||||
| SmallInt, it is converted to SmallInt. Otherwise, the Integer is | ||||
| converted to a Float. | ||||
|  | ||||
| In bigint mode: | ||||
|  | ||||
| If the operator returns an Integer and that the result fits a | ||||
| SmallInt, it is converted to SmallInt. Otherwise it is a BigInt. | ||||
|  | ||||
| @subsection Logical operators | ||||
|  | ||||
| In standard mode: | ||||
|  | ||||
| The operands have their standard behavior. If the result fits a | ||||
| SmallInt it is converted to a SmallInt. Otherwise it is a Float. | ||||
|  | ||||
| In bigint mode: | ||||
|  | ||||
| The operands are converted to integer values. The floating point | ||||
| values are converted to integer by rounding them to zero. | ||||
|  | ||||
| The logical operators are defined assuming the integers are | ||||
| represented in two complement notation. | ||||
|  | ||||
| For @code{<<} and @code{<<}, the shift can be positive or negative. So | ||||
| @code{a << b} is defined as @math{\lfloor a/2^{-b} \rfloor} and | ||||
| @code{a >> b} is defined as @math{\lfloor a/2^{b} \rfloor}. | ||||
|  | ||||
| The operator @code{>>>} is supported for backward compatibility and | ||||
| behaves the same way as Javascript i.e. implicit conversion to @code{Uint32}. | ||||
|  | ||||
| If the result fits a SmallInt it is converted to a SmallInt. Otherwise | ||||
| it is a BigInt. | ||||
|  | ||||
| @subsection Relational operators | ||||
|  | ||||
| The relational operators <, <=, >, >=, ==, != work as expected with | ||||
| integers and floating point numbers (e.g. @code{1.0 == 1} is true). | ||||
|  | ||||
| The strict equality operators === and !== have the usual Javascript | ||||
| semantics. In particular, different types never equal, so @code{1.0 | ||||
| === 1} is false. | ||||
|  | ||||
| @section Number literals | ||||
|  | ||||
| Number literals in bigint mode have a slightly different behavior than | ||||
| in standard Javascript: | ||||
|  | ||||
| @enumerate | ||||
|  | ||||
| @item | ||||
| A number literal without a decimal point or an exponent is considered | ||||
| as an Integer. Otherwise it is a Float. | ||||
|  | ||||
| @item | ||||
| Hexadecimal, octal or binary floating point literals are accepted with | ||||
| a decimal point or an exponent. The exponent is specified with the | ||||
| @code{p} letter assuming a base 2. The same convention is used by | ||||
| C99. Example: @code{0x1p3} is the same as @code{8.0}. | ||||
|  | ||||
| @end enumerate | ||||
|  | ||||
| @section Builtin Object changes | ||||
|  | ||||
| @subsection @code{BigInt} function | ||||
|  | ||||
| The @code{BigInt} function cannot be invoked as a constructor. When | ||||
| invoked as a function, it converts its first parameter to an | ||||
| integer. When a floating point number is given as parameter, it is | ||||
| truncated to an integer with infinite precision. | ||||
|  | ||||
| @code{BigInt} properties: | ||||
|  | ||||
| @table @code | ||||
|  | ||||
| @item asIntN(bits, a) | ||||
| Set @math{b=a \pmod{2^{bits}}}. Return @math{b} if @math{b < 2^{bits-1}} | ||||
| otherwise @math{b-2^{bits}}. | ||||
|  | ||||
| @item asUintN(bits, a) | ||||
| Return @math{a \pmod{2^{bits}}}. | ||||
|  | ||||
| @item tdiv(a, b) | ||||
| Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError | ||||
| exception. | ||||
|  | ||||
| @item fdiv(a, b) | ||||
| Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError | ||||
| exception. | ||||
|  | ||||
| @item cdiv(a, b) | ||||
| Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError | ||||
| exception. | ||||
|  | ||||
| @item ediv(a, b) | ||||
| Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian | ||||
| division). @code{b = 0} raises a RangeError exception. | ||||
|  | ||||
| @item tdivrem(a, b) | ||||
| @item fdivrem(a, b) | ||||
| @item cdivrem(a, b) | ||||
| @item edivrem(a, b) | ||||
| Return an array of two elements. The first element is the quotient, | ||||
| the second is the remainder. The same rounding is done as the | ||||
| corresponding division operation. | ||||
|  | ||||
| @item sqrt(a) | ||||
| Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is | ||||
| raised if @math{a < 0}. | ||||
|  | ||||
| @item sqrtrem(a) | ||||
| Return an array of two elements. The first element is @math{\lfloor | ||||
| \sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a} | ||||
| \rfloor^2}. A RangeError exception is raised if @math{a < 0}. | ||||
|  | ||||
| @item floorLog2(a) | ||||
| Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}. | ||||
|  | ||||
| @item ctz(a) | ||||
| Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{BigInt.prototype} | ||||
|  | ||||
| It is a normal object. | ||||
|  | ||||
| @subsection @code{Number} constructor | ||||
|  | ||||
| The number constructor returns its argument rounded to a Float using | ||||
| the global floating point environement. In bigint mode, the Number | ||||
| constructor returns a Float. In standard mode, it returns a SmallInt | ||||
| if the value fits it, otherwise a Float. | ||||
|  | ||||
| @subsection @code{Number.prototype} | ||||
|  | ||||
| The following properties are modified: | ||||
|  | ||||
| @table @code | ||||
| @item toString(radix) | ||||
|  | ||||
| In bigint mode, integers are converted to the specified radix with | ||||
| infinite precision. | ||||
|  | ||||
| @item toPrecision(p) | ||||
| @item toFixed(p) | ||||
| @item toExponential(p) | ||||
|  | ||||
| In bigint mode, integers are accepted and converted to string with | ||||
| infinite precision. | ||||
|  | ||||
| @item parseInt(string, radix) | ||||
|  | ||||
| In bigint mode, an integer is returned and the conversion is done with | ||||
| infinite precision. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{Math} object | ||||
|  | ||||
| The following properties are modified: | ||||
|  | ||||
| @table @code | ||||
| @item abs(x) | ||||
| Absolute value. Return an integer if @code{x} is an Integer. Otherwise | ||||
| return a Float. No rounding is performed. | ||||
|  | ||||
| @item min(a, b) | ||||
| @item max(a, b) | ||||
| No rounding is performed. The returned type is the same one as the | ||||
| minimum (resp. maximum) value. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @chapter Arbitrarily large floating point numbers | ||||
|  | ||||
| @section Introduction | ||||
|  | ||||
| This extension adds the @code{BigFloat} primitive type. The | ||||
| @code{BigFloat} type represents floating point numbers are in base 2 | ||||
| with the IEEE 754 semantics. A floating | ||||
| point number is represented as a sign, mantissa and exponent. The | ||||
| special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0} | ||||
| are supported. The mantissa and exponent can have any bit length with | ||||
| an implementation specific minimum and maximum. | ||||
|  | ||||
| @section Floating point rounding | ||||
|  | ||||
| Each floating point operation operates with infinite precision and | ||||
| then rounds the result according to the specified floating point | ||||
| environment (@code{BigFloatEnv} object). The status flags of the | ||||
| environment are also set according to the result of the operation. | ||||
|  | ||||
| If no floating point environment is provided, the global floating | ||||
| point environment is used. | ||||
|  | ||||
| The rounding mode of the global floating point environment is always | ||||
| @code{RNDN} (``round to nearest with ties to even'')@footnote{The | ||||
| rationale is that the rounding mode changes must always be | ||||
| explicit.}. The status flags of the global environment cannot be | ||||
| read@footnote{The rationale is to avoid side effects for the built-in | ||||
| operators.}. The precision of the global environment is | ||||
| @code{BigFloatEnv.prec}. The number of exponent bits of the global | ||||
| environment is @code{BigFloatEnv.expBits}.  If @code{BigFloatEnv.expBits} is | ||||
| strictly smaller than the maximum allowed number of exponent bits | ||||
| (@code{BigFloatEnv.expBitsMax}), then the global environment subnormal | ||||
| flag is set to @code{true}. Otherwise it is set to @code{false}; | ||||
|  | ||||
| For example, @code{prec = 53} and @code{ expBits = 11} give exactly | ||||
| the same precision as the IEEE 754 64 bit floating point type. It is | ||||
| the default floating point precision. | ||||
|  | ||||
| The global floating point environment can only be modified temporarily | ||||
| when calling a function (see @code{BigFloatEnv.setPrec}). Hence a | ||||
| function can change the global floating point environment for its | ||||
| callees but not for its caller. | ||||
|  | ||||
| @section Operators | ||||
|  | ||||
| The builtin operators are extended so that a BigFloat is returned if | ||||
| at least one operand is a BigFloat. The computations are always done | ||||
| with infinite precision and rounded according to the global floating | ||||
| point environment. | ||||
|  | ||||
| @code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}. | ||||
|  | ||||
| BigFloat can be compared with all the other numeric types and the | ||||
| result follows the expected mathematical relations. | ||||
|  | ||||
| However, since BigFloat and Number are different types they are never | ||||
| equal when using the strict comparison operators (e.g. @code{0.0 === | ||||
| 0.0l} is false). | ||||
|  | ||||
| @section BigFloat literals | ||||
|  | ||||
| BigFloat literals are floating point numbers with a trailing @code{l} | ||||
| suffix. BigFloat literals have an infinite precision. They are rounded | ||||
| according to the global floating point environment when they are | ||||
| evaluated.@footnote{Base 10 floating point literals cannot usually be | ||||
| exactly represented as base 2 floating point number. In order to | ||||
| ensure that the literal is represented accurately with the current | ||||
| precision, it must be evaluated at runtime.} | ||||
|  | ||||
| @section Builtin Object changes | ||||
|  | ||||
| @subsection @code{BigFloat} function | ||||
|  | ||||
| The @code{BigFloat} function cannot be invoked as a constructor. When | ||||
| invoked as a function: the parameter is converted to a primitive | ||||
| type. If the result is a numeric type, it is converted to BigFloat | ||||
| without rounding. If the result is a string, it is converted to | ||||
| BigFloat using the precision of the global floating point environment. | ||||
|  | ||||
| @code{BigFloat} properties: | ||||
|  | ||||
| @table @code | ||||
|  | ||||
| @item LN2 | ||||
| @item PI | ||||
| Getter. Return the value of the corresponding mathematical constant | ||||
| rounded to nearest, ties to even with the current global | ||||
| precision. The constant values are cached for small precisions. | ||||
|  | ||||
| @item MIN_VALUE | ||||
| @item MAX_VALUE | ||||
| @item EPSILON | ||||
| Getter. Return the minimum, maximum and epsilon @code{BigFloat} values | ||||
| (same definition as the corresponding @code{Number} constants). | ||||
|  | ||||
| @item fpRound(a[, e]) | ||||
| Round the floating point number @code{a} according to the floating | ||||
| point environment @code{e} or the global environment if @code{e} is | ||||
| undefined. | ||||
|  | ||||
| @item parseFloat(a[, radix[, e]]) | ||||
| Parse the string @code{a} as a floating point number in radix | ||||
| @code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0 | ||||
| means radix 10 unless there is a hexadecimal or binary prefix. The | ||||
| result is rounded according to the floating point environment @code{e} | ||||
| or the global environment if @code{e} is undefined. | ||||
|  | ||||
| @item add(a, b[, e]) | ||||
| @item sub(a, b[, e]) | ||||
| @item mul(a, b[, e]) | ||||
| @item div(a, b[, e]) | ||||
| Perform the specified floating point operation and round the floating | ||||
| point number @code{a} according to the floating point environment | ||||
| @code{e} or the global environment if @code{e} is undefined. If | ||||
| @code{e} is specified, the floating point status flags are updated. | ||||
|  | ||||
| @item floor(x[, e]) | ||||
| @item ceil(x[, e]) | ||||
| @item round(x[, e]) | ||||
| @item trunc(x[, e]) | ||||
| Round to integer. A rounded @code{BigFloat} is returned. @code{e} is an | ||||
| optional floating point environment. | ||||
|  | ||||
| @item fmod(x, y[, e]) | ||||
| @item remainder(x, y[, e]) | ||||
| Floating point remainder. The quotient is truncated to zero (fmod) or | ||||
| to the nearest integer with ties to even (remainder). @code{e} is an | ||||
| optional floating point environment. | ||||
|  | ||||
| @item sqrt(x[, e]) | ||||
| Square root. Return a rounded floating point number. @code{e} is an | ||||
| optional floating point environment. | ||||
|  | ||||
| @item sin(x[, e]) | ||||
| @item cos(x[, e]) | ||||
| @item tan(x[, e]) | ||||
| @item asin(x[, e]) | ||||
| @item acos(x[, e]) | ||||
| @item atan(x[, e]) | ||||
| @item atan2(x, y[, e]) | ||||
| @item exp(x[, e]) | ||||
| @item log(x[, e]) | ||||
| @item pow(x, y[, e]) | ||||
| Transcendental operations. Return a rounded floating point | ||||
| number. @code{e} is an optional floating point environment. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{BigFloat.prototype} | ||||
|  | ||||
| The following properties are modified: | ||||
|  | ||||
| @table @code | ||||
| @item toString(radix) | ||||
|  | ||||
| For floating point numbers: | ||||
|  | ||||
| @itemize | ||||
| @item | ||||
| If the radix is a power of two, the conversion is done with infinite | ||||
| precision. | ||||
| @item | ||||
| Otherwise, the number is rounded to nearest with ties to even using | ||||
| the global precision. It is then converted to string using the minimum | ||||
| number of digits so that its conversion back to a floating point using | ||||
| the global precision and round to nearest gives the same number.  | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @item toPrecision(p[, rnd_mode]) | ||||
| @item toFixed(p[, rnd_mode]) | ||||
| @item toExponential(p[, rnd_mode]) | ||||
| Same semantics as the corresponding @code{Number} functions with | ||||
| BigFloats. There is no limit on the accepted precision @code{p}. The | ||||
| rounding mode can be optionally specified. It is set by default to | ||||
| @code{BigFloatEnv.RNDNA}. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{BigFloatEnv} constructor | ||||
|  | ||||
| The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a | ||||
| function. The floating point environment contains: | ||||
|  | ||||
| @itemize | ||||
| @item the mantissa precision in bits | ||||
|  | ||||
| @item the exponent size in bits assuming an IEEE 754 representation; | ||||
|  | ||||
| @item the subnormal flag (if true, subnormal floating point numbers can | ||||
| be generated by the floating point operations). | ||||
|  | ||||
| @item the rounding mode | ||||
|  | ||||
| @item the floating point status. The status flags can only be set by the floating point operations. They can be reset with @code{BigFloatEnv.prototype.clearStatus()} or with the various status flag setters. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point | ||||
| environment. The status flags are reset. If no parameter is given the | ||||
| precision, exponent bits and subnormal flags are copied from the | ||||
| global floating point environment. Otherwise, the precision is set to | ||||
| @code{p}, the number of exponent bits is set to @code{expBitsMax} and the | ||||
| subnormal flags is set to @code{false}. If @code{rndMode} is | ||||
| @code{undefined}, the rounding mode is set to @code{RNDN}. | ||||
|  | ||||
| @code{BigFloatEnv} properties: | ||||
|  | ||||
| @table @code | ||||
|  | ||||
| @item prec | ||||
| Getter. Return the precision in bits of the global floating point | ||||
| environment. The initial value is @code{53}. | ||||
|  | ||||
| @item expBits | ||||
| Getter. Return the exponent size in bits of the global floating point | ||||
| environment assuming an IEEE 754 representation. If @code{expBits < | ||||
| expBitsMax}, then subnormal numbers are supported. The initial value | ||||
| is @code{11}. | ||||
|  | ||||
| @item setPrec(f, p[, e]) | ||||
| Set the precision of the global floating point environment to @code{p} | ||||
| and the exponent size to @code{e} then call the function | ||||
| @code{f}. Then the Float precision and exponent size are reset to | ||||
| their precious value and the return value of @code{f} is returned (or | ||||
| an exception is raised if @code{f} raised an exception). If @code{e} | ||||
| is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}. @code{p} | ||||
| must be >= 53 and @code{e} must be >= 11 so that the global precision | ||||
| is at least equivalent to the IEEE 754 64 bit doubles. | ||||
|  | ||||
| @item precMin | ||||
| Read-only integer. Return the minimum allowed precision. Must be at least 2. | ||||
|  | ||||
| @item precMax | ||||
| Read-only integer. Return the maximum allowed precision. Must be at least 53. | ||||
|  | ||||
| @item expBitsMin | ||||
| Read-only integer. Return the minimum allowed exponent size in | ||||
| bits. Must be at least 3. | ||||
|  | ||||
| @item expBitsMax | ||||
| Read-only integer. Return the maximum allowed exponent size in | ||||
| bits. Must be at least 11. | ||||
|  | ||||
| @item RNDN | ||||
| Read-only integer. Round to nearest, with ties to even rounding mode. | ||||
|  | ||||
| @item RNDZ | ||||
| Read-only integer. Round to zero rounding mode. | ||||
|  | ||||
| @item RNDD | ||||
| Read-only integer. Round to -Infinity rounding mode. | ||||
|  | ||||
| @item RNDU | ||||
| Read-only integer. Round to +Infinity rounding mode. | ||||
|  | ||||
| @item RNDNA | ||||
| Read-only integer. Round to nearest, with ties away from zero rounding mode. | ||||
|  | ||||
| @item RNDNU | ||||
| Read-only integer. Round to nearest, with ties to +Infinity rounding mode. | ||||
|  | ||||
| @item RNDF@footnote{Could be removed in case a deterministic behvior for floating point operations is required.} | ||||
| Read-only integer. Faithful rounding mode. The result is | ||||
| non-deterministicly rounded to -Infinity or +Infinity. This rounding | ||||
| mode usually gives a faster and deterministic running time for the | ||||
| floating point operations. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @code{BigFloatEnv.prototype} properties: | ||||
|  | ||||
| @table @code | ||||
|  | ||||
| @item prec | ||||
| Getter and setter (Integer). Return or set the precision in bits. | ||||
|  | ||||
| @item expBits | ||||
| Getter and setter (Integer). Return or set the exponent size in bits | ||||
| assuming an IEEE 754 representation. | ||||
|  | ||||
| @item rndMode | ||||
| Getter and setter (Integer). Return or set the rounding mode. | ||||
|  | ||||
| @item subnormal | ||||
| Getter and setter (Boolean). subnormal flag. It is false when | ||||
| @code{expBits = expBitsMax}. | ||||
|  | ||||
| @item clearStatus() | ||||
| Clear the status flags. | ||||
|  | ||||
| @item invalidOperation | ||||
| @item divideByZero | ||||
| @item overflow | ||||
| @item underflow | ||||
| @item inexact | ||||
| Getter and setter (Boolean). Status flags. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{Math} object | ||||
|  | ||||
| The following properties are modified: | ||||
|  | ||||
| @table @code | ||||
| @item abs(x) | ||||
| Absolute value. If @code{x} is a BigFloat, its absolute value is | ||||
| returned as a BigFloat. No rounding is performed. | ||||
|  | ||||
| @item min(a, b) | ||||
| @item max(a, b) | ||||
| The returned type is the same one as the minimum (resp. maximum) | ||||
| value, so @code{BigFloat} values are accepted. When a @code{BigFloat} | ||||
| is returned, no rounding is performed. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @chapter Math mode | ||||
|  | ||||
| @section Introduction | ||||
|  | ||||
| A new @emph{math mode} is enabled with the @code{"use math"} | ||||
| directive. @code{"use bigint"} is implied in math mode. With this | ||||
| mode, writing mathematical expressions is more intuitive, exact | ||||
| results (e.g. fractions) can be computed for all operators and floating | ||||
| point literals have the @code{BigFloat} type by default. | ||||
|  | ||||
| It propagates the same way as the @emph{strict mode}. In | ||||
| this mode: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item The @code{^} operator is a similar to the power operator (@code{**}). | ||||
|  | ||||
| @item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}. | ||||
|  | ||||
| @item The logical xor operator is still available with the @code{^^} operator. | ||||
|  | ||||
| @item The division operator invokes @code{BigInt[Symbol.operatorDiv]} in case both operands are integers. | ||||
|  | ||||
| @item The power operator invokes @code{BigInt[Symbol.operatorPow]} in case both operands are integers and the exponent is strictly negative. | ||||
|  | ||||
| @item The modulo operator returns the Euclidian remainder (always positive) instead of the truncated remainder. | ||||
|  | ||||
| @item Floating point literals are @code{BigFloat} by default (i.e. a @code{l} suffix is implied). | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @section Builtin Object changes | ||||
|  | ||||
| @subsection @code{Symbol} constructor | ||||
|  | ||||
| The following global symbol is added for the operator overloading: | ||||
| @table @code | ||||
| @item operatorMathMod | ||||
| @end table | ||||
|  | ||||
| @section Remaining issues | ||||
|  | ||||
| @enumerate | ||||
|  | ||||
| @item A new floating point literal suffix could be added for @code{Number} literals. | ||||
|  | ||||
| @end enumerate | ||||
|  | ||||
| @bye | ||||
							
								
								
									
										1245
									
								
								deps/quickjs/doc/quickjs.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1245
									
								
								deps/quickjs/doc/quickjs.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								deps/quickjs/doc/quickjs.pdf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								deps/quickjs/doc/quickjs.pdf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										979
									
								
								deps/quickjs/doc/quickjs.texi
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										979
									
								
								deps/quickjs/doc/quickjs.texi
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,979 @@ | ||||
| \input texinfo | ||||
|  | ||||
| @iftex | ||||
| @afourpaper | ||||
| @headings double | ||||
| @end iftex | ||||
|  | ||||
| @titlepage | ||||
| @afourpaper | ||||
| @sp 7 | ||||
| @center @titlefont{QuickJS Javascript Engine} | ||||
| @sp 3 | ||||
| @end titlepage | ||||
|  | ||||
| @setfilename spec.info | ||||
| @settitle QuickJS Javascript Engine | ||||
|  | ||||
| @contents | ||||
|  | ||||
| @chapter Introduction | ||||
|  | ||||
| QuickJS is a small and embeddable Javascript engine. It supports the | ||||
| ES2019 specification | ||||
| @footnote{@url{https://www.ecma-international.org/ecma-262/10.0}} | ||||
| including modules, asynchronous generators and proxies. | ||||
|  | ||||
| It optionally supports mathematical extensions such as big integers | ||||
| (BigInt), big floating point numbers (BigFloat) and operator | ||||
| overloading. | ||||
|  | ||||
| @section Main Features | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item Small and easily embeddable: just a few C files, no external dependency, 180 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 Almost complete ES2019 support including modules, asynchronous | ||||
| generators and full Annex B support (legacy web compatibility). Many | ||||
| features from the upcoming ES2020 specification | ||||
| @footnote{@url{https://tc39.github.io/ecma262/}} are also supported. | ||||
|  | ||||
| @item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features. | ||||
|  | ||||
| @item Can compile Javascript sources to executables with no external dependency. | ||||
|  | ||||
| @item Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal. | ||||
|  | ||||
| @item Mathematical extensions: BigInt, BigFloat, operator overloading, bigint mode, math mode. | ||||
|  | ||||
| @item Command line interpreter with contextual colorization and completion implemented in Javascript. | ||||
|  | ||||
| @item Small built-in standard library with C library wrappers. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @chapter Usage | ||||
|  | ||||
| @section Installation | ||||
|  | ||||
| A Makefile is provided to compile the engine on Linux or MacOS/X.  A | ||||
| preliminary Windows support is available thru cross compilation on a | ||||
| Linux host with the MingGW tools. | ||||
|  | ||||
| Edit the top of the @code{Makefile} if you wish to select specific | ||||
| options then run @code{make}. | ||||
|  | ||||
| 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). | ||||
|  | ||||
| @section Quick start | ||||
|  | ||||
| @code{qjs} is the command line interpreter (Read-Eval-Print Loop). You can pass | ||||
| Javascript files and/or expressions as arguments to execute them: | ||||
|  | ||||
| @example | ||||
| ./qjs examples/hello.js | ||||
| @end example | ||||
|  | ||||
| @code{qjsc} is the command line compiler: | ||||
|  | ||||
| @example | ||||
| ./qjsc -o hello examples/hello.js | ||||
| ./hello | ||||
| @end example | ||||
|  | ||||
| generates a @code{hello} executable with no external dependency. | ||||
|  | ||||
| @code{qjsbn} and @code{qjscbn} are the corresponding interpreter and | ||||
| compiler with the mathematical extensions: | ||||
|  | ||||
| @example | ||||
| ./qjsbn examples/pi.js 1000 | ||||
| @end example | ||||
|  | ||||
| displays 1000 digits of PI. | ||||
|  | ||||
| @example | ||||
| ./qjsbnc -o pi examples/pi.js | ||||
| ./pi 1000 | ||||
| @end example | ||||
|  | ||||
| compiles and executes the PI program. | ||||
|  | ||||
| @section Command line options | ||||
|  | ||||
| @subsection @code{qjs} interpreter | ||||
|  | ||||
| @verbatim | ||||
| usage: qjs [options] [files] | ||||
| @end verbatim | ||||
|  | ||||
| Options are: | ||||
| @table @code | ||||
| @item -h | ||||
| @item --help | ||||
| List options. | ||||
|  | ||||
| @item -e @code{EXPR} | ||||
| @item --eval @code{EXPR} | ||||
| Evaluate EXPR. | ||||
|  | ||||
| @item -i | ||||
| @item --interactive | ||||
| Go to interactive mode (it is not the default when files are provided on the command line). | ||||
|  | ||||
| @item -m | ||||
| @item --module | ||||
| Load as ES6 module (default=autodetect). | ||||
|  | ||||
| @item --script | ||||
| Load as ES6 script (default=autodetect). | ||||
|  | ||||
| @end table | ||||
|  | ||||
| Advanced options are: | ||||
|  | ||||
| @table @code | ||||
| @item -d | ||||
| @item --dump | ||||
| Dump the memory usage stats. | ||||
|  | ||||
| @item -q | ||||
| @item --quit | ||||
| just instantiate the interpreter and quit. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{qjsc} compiler | ||||
|  | ||||
| @verbatim | ||||
| usage: qjsc [options] [files] | ||||
| @end verbatim | ||||
|  | ||||
| Options are: | ||||
| @table @code | ||||
| @item -c | ||||
| Only output bytecode in a C file. The default is to output an executable file. | ||||
| @item -e  | ||||
| Output @code{main()} and bytecode in a C file. The default is to output an | ||||
| executable file. | ||||
| @item -o output | ||||
| Set the output filename (default = @file{out.c} or @file{a.out}). | ||||
|  | ||||
| @item -N cname | ||||
| Set the C name of the generated data. | ||||
|  | ||||
| @item -m | ||||
| Compile as Javascript module (default=autodetect). | ||||
|  | ||||
| @item -M module_name[,cname] | ||||
| Add initialization code for an external C module. See the | ||||
| @code{c_module} example. | ||||
|  | ||||
| @item -x | ||||
| Byte swapped output (only used for cross compilation). | ||||
|  | ||||
| @item -flto | ||||
| Use link time optimization. The compilation is slower but the | ||||
| executable is smaller and faster. This option is automatically set | ||||
| when the @code{-fno-x} options are used. | ||||
|  | ||||
| @item -fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise] | ||||
| Disable selected language features to produce a smaller executable file. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @section @code{qjscalc} application | ||||
|  | ||||
| The @code{qjscalc} application is a superset of the @code{qjsbn} | ||||
| command line interpreter implementing a Javascript calculator with | ||||
| arbitrarily large integer and floating point numbers, fractions, | ||||
| complex numbers, polynomials and matrices. The source code is in | ||||
| @file{qjscalc.js}. More documentation and a web version are available at | ||||
| @url{http://numcalc.com}. | ||||
|  | ||||
| @section Built-in tests | ||||
|  | ||||
| Run @code{make test} to run the few built-in tests included in the | ||||
| QuickJS archive. | ||||
|  | ||||
| @section Test262 (ECMAScript Test Suite) | ||||
|  | ||||
| A test262 runner is included in the QuickJS archive. | ||||
|  | ||||
| For reference, the full test262 tests are provided in the archive | ||||
| @file{qjs-tests-yyyy-mm-dd.tar.xz}. You just need to untar it into the | ||||
| QuickJS source code directory. | ||||
|  | ||||
| Alternatively, the test262 tests can be installed with: | ||||
|  | ||||
| @example | ||||
| git clone https://github.com/tc39/test262.git test262 | ||||
| cd test262 | ||||
| patch -p1 < ../tests/test262.patch | ||||
| cd .. | ||||
| @end example | ||||
|  | ||||
| The patch adds the implementation specific @code{harness} functions | ||||
| and optimizes the inefficient RegExp character classes and Unicode | ||||
| property escapes tests (the tests themselves are not modified, only a | ||||
| slow string initialization function is optimized). | ||||
|  | ||||
| The tests can be run with | ||||
| @example | ||||
| make test2 | ||||
| @end example | ||||
|  | ||||
| The configuration files @code{test262.conf} (resp | ||||
| @code{test262bn.conf} for the bignum version, @code{test262o.conf} for | ||||
| the old ES5.1 tests@footnote{The old ES5.1 tests can be extracted with | ||||
| @code{git clone --single-branch --branch es5-tests | ||||
| https://github.com/tc39/test262.git test262o}})) contain the options | ||||
| to run the various tests. Tests can be excluded based on features or | ||||
| filename. | ||||
|  | ||||
| The file @code{test262_errors.txt} contains the current list of | ||||
| errors. The runner displays a message when a new error appears or when | ||||
| an existing error is corrected or modified. Use the @code{-u} option | ||||
| to update the current list of errors (or @code{make test2-update}). | ||||
|  | ||||
| The file @code{test262_report.txt} contains the logs of all the | ||||
| tests. It is useful to have a clearer analysis of a particular | ||||
| error. In case of crash, the last line corresponds to the failing | ||||
| test. | ||||
|  | ||||
| Use the syntax @code{./run-test262 -c test262.conf -f filename.js} to | ||||
| run a single test. Use the syntax @code{./run-test262 -c test262.conf | ||||
| N} to start testing at test number @code{N}. | ||||
|  | ||||
| For more information, run @code{./run-test262} to see the command line | ||||
| options of the test262 runner. | ||||
|  | ||||
| @code{run-test262} accepts the @code{-N} option to be invoked from | ||||
| @code{test262-harness}@footnote{@url{https://github.com/bterlson/test262-harness}} | ||||
| thru @code{eshost}. Unless you want to compare QuickJS with other | ||||
| engines under the same conditions, we do not recommend to run the | ||||
| tests this way as it is much slower (typically half an hour instead of | ||||
| about 100 seconds). | ||||
|  | ||||
| @chapter Specifications | ||||
|  | ||||
| @section Language support | ||||
|  | ||||
| @subsection ES2019 support | ||||
|  | ||||
| The ES2019 specification is almost fully supported including the Annex | ||||
| B (legacy web compatibility) and the Unicode related features. | ||||
|  | ||||
| The following features are not supported yet: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item Realms (althougth the C API supports different runtimes and contexts) | ||||
|  | ||||
| @item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.} | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @subsection JSON | ||||
|  | ||||
| The JSON parser is currently more tolerant than the specification. | ||||
|  | ||||
| @subsection ECMA402 | ||||
|  | ||||
| ECMA402 (Internationalization API) is not supported. | ||||
|  | ||||
| @subsection Extensions | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item The directive @code{"use strip"} indicates that the debug information (including the source code of the functions) should not be retained to save memory. As @code{"use strict"}, the directive can be global to a script or local to a function. | ||||
|  | ||||
| @item The first line of a script beginning with @code{#!} is ignored. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @subsection Mathematical extensions | ||||
|  | ||||
| The mathematical extensions are available in the @code{qjsbn} version and are fully | ||||
| backward compatible with standard Javascript. See @code{jsbignum.pdf} | ||||
| for more information. | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item The @code{BigInt} (big integers) TC39 proposal is supported. | ||||
|  | ||||
| @item @code{BigFloat} support: arbitrary large floating point numbers in base 2. | ||||
|  | ||||
| @item Operator overloading. | ||||
|  | ||||
| @item The directive @code{"use bigint"} enables the bigint mode where integers are @code{BigInt} by default. | ||||
|  | ||||
| @item The directive @code{"use math"} enables the math mode where the division and power operators on integers produce fractions. Floating point literals are @code{BigFloat} by default and integers are @code{BigInt} by default. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @section Modules | ||||
|  | ||||
| ES6 modules are fully supported. The default name resolution is the | ||||
| following: | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item Module names with a leading @code{.} or @code{..} are relative | ||||
| to the current module path. | ||||
|  | ||||
| @item Module names without a leading @code{.} or @code{..} are system | ||||
| modules, such as @code{std} or @code{os}. | ||||
|  | ||||
| @item Module names ending with @code{.so} are native modules using the | ||||
| QuickJS C API. | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @section Standard library | ||||
|  | ||||
| The standard library is included by default in the command line | ||||
| interpreter. It contains the two modules @code{std} and @code{os} and | ||||
| a few global objects. | ||||
|  | ||||
| @subsection Global objects | ||||
|  | ||||
| @table @code | ||||
| @item scriptArgs | ||||
| Provides the command line arguments. The first argument is the script name. | ||||
| @item print(...args) | ||||
| Print the arguments separated by spaces and a trailing newline. | ||||
| @item console.log(...args) | ||||
| Same as print(). | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection @code{std} module | ||||
|  | ||||
| The @code{std} module provides wrappers to the libc @file{stdlib.h} | ||||
| and @file{stdio.h} and a few other utilities. | ||||
|  | ||||
| Available exports: | ||||
|  | ||||
| @table @code | ||||
|  | ||||
| @item exit(n) | ||||
| Exit the process. | ||||
|  | ||||
| @item evalScript(str) | ||||
| Evaluate the string @code{str} as a script (global eval). | ||||
|  | ||||
| @item loadScript(filename) | ||||
| Evaluate the file @code{filename} as a script (global eval). | ||||
|  | ||||
| @item Error(errno) | ||||
|  | ||||
| @code{std.Error} constructor. Error instances contain the field | ||||
| @code{errno} (error code) and @code{message} (result of | ||||
| @code{std.Error.strerror(errno)}). | ||||
|  | ||||
| The constructor contains the following fields: | ||||
|  | ||||
|   @table @code | ||||
|   @item EINVAL | ||||
|   @item EIO | ||||
|   @item EACCES | ||||
|   @item EEXIST | ||||
|   @item ENOSPC | ||||
|   @item ENOSYS | ||||
|   @item EBUSY | ||||
|   @item ENOENT | ||||
|   @item EPERM | ||||
|   @item EPIPE | ||||
|     Integer value of common errors (additional error codes may be defined). | ||||
|   @item strerror(errno) | ||||
|     Return a string that describes the error @code{errno}. | ||||
|   @end table | ||||
|  | ||||
| @item open(filename, flags) | ||||
| Open a file (wrapper to the libc @code{fopen()}). Throws  | ||||
| @code{std.Error} in case of I/O error. | ||||
|  | ||||
| @item popen(command, flags) | ||||
| Open a process by creating a pipe (wrapper to the libc @code{popen()}). Throws  | ||||
| @code{std.Error} in case of I/O error. | ||||
|  | ||||
| @item fdopen(fd, flags) | ||||
| Open a file from a file handle (wrapper to the libc | ||||
| @code{fdopen()}). Throws @code{std.Error} in case of I/O error. | ||||
|  | ||||
| @item tmpfile() | ||||
| Open a temporary file. Throws @code{std.Error} in case of I/O error. | ||||
|  | ||||
| @item puts(str) | ||||
| Equivalent to @code{std.out.puts(str)}. | ||||
|  | ||||
| @item printf(fmt, ...args) | ||||
| Equivalent to @code{std.out.printf(fmt, ...args)} | ||||
|  | ||||
| @item sprintf(fmt, ...args) | ||||
| Equivalent to the libc sprintf(). | ||||
|  | ||||
| @item in | ||||
| @item out | ||||
| @item err | ||||
| Wrappers to the libc file @code{stdin}, @code{stdout}, @code{stderr}. | ||||
|  | ||||
| @item SEEK_SET | ||||
| @item SEEK_CUR | ||||
| @item SEEK_END | ||||
| Constants for seek(). | ||||
|  | ||||
| @item gc() | ||||
| Manually invoke the cycle removal algorithm. The cycle removal | ||||
| algorithm is automatically started when needed, so this function is | ||||
| useful in case of specific memory constraints or for testing. | ||||
|  | ||||
| @item getenv(name) | ||||
| Return the value of the environment variable @code{name} or | ||||
| @code{undefined} if it is not defined. | ||||
|  | ||||
| @item urlGet(url, options = undefined) | ||||
|  | ||||
| Download @code{url} using the @file{curl} command line | ||||
| utility. @code{options} is an optional object containing the following | ||||
| optional properties: | ||||
|  | ||||
|   @table @code | ||||
|   @item binary | ||||
|   Boolean (default = false). If true, the response is an ArrayBuffer | ||||
|   instead of a string. When a string is returned, the data is assumed | ||||
|   to be UTF-8 encoded. | ||||
|  | ||||
|   @item full | ||||
|   Boolean (default = false). If true, return the an object contains | ||||
|   the properties @code{response} (response content), | ||||
|   @code{responseHeaders} (headers separated by CRLF), @code{status} | ||||
|   (status code). If @code{full} is false, only the response is | ||||
|   returned if the status is between 200 and 299. Otherwise an | ||||
|   @code{std.Error} exception is raised. | ||||
|  | ||||
|   @end table | ||||
|  | ||||
| @end table | ||||
|  | ||||
| FILE prototype: | ||||
|  | ||||
| @table @code | ||||
| @item close() | ||||
| Close the file. | ||||
| @item puts(str) | ||||
| Outputs the string with the UTF-8 encoding. | ||||
| @item printf(fmt, ...args) | ||||
| Formatted printf, same formats as the libc printf. | ||||
| @item flush() | ||||
| Flush the buffered file. | ||||
| @item seek(offset, whence) | ||||
| Seek to a give file position (whence is @code{std.SEEK_*}). Throws a | ||||
| @code{std.Error} in case of I/O error. | ||||
| @item tell() | ||||
| Return the current file position. | ||||
| @item eof() | ||||
| Return true if end of file. | ||||
| @item fileno() | ||||
| Return the associated OS handle. | ||||
|  | ||||
| @item read(buffer, position, length) | ||||
| Read @code{length} bytes from the file to the ArrayBuffer @code{buffer} at byte | ||||
| position @code{position} (wrapper to the libc @code{fread}). | ||||
|  | ||||
| @item write(buffer, position, length) | ||||
| Write @code{length} bytes to the file from the ArrayBuffer @code{buffer} at byte | ||||
| position @code{position} (wrapper to the libc @code{fread}). | ||||
|  | ||||
| @item getline() | ||||
| Return the next line from the file, assuming UTF-8 encoding, excluding | ||||
| the trailing line feed. | ||||
|  | ||||
| @item getByte() | ||||
| Return the next byte from the file. | ||||
|  | ||||
| @item putByte(c) | ||||
| Write one byte to the file. | ||||
| @end table | ||||
|  | ||||
| @subsection @code{os} module | ||||
|  | ||||
| The @code{os} module provides Operating System specific functions: | ||||
|  | ||||
| @itemize | ||||
| @item low level file access | ||||
| @item signals | ||||
| @item timers | ||||
| @item asynchronous I/O | ||||
| @end itemize | ||||
|  | ||||
| The OS functions usually return 0 if OK or an OS specific negative | ||||
| error code. | ||||
|  | ||||
| Available exports: | ||||
|  | ||||
| @table @code | ||||
| @item open(filename, flags, mode = 0o666) | ||||
| Open a file. Return a handle or < 0 if error. | ||||
|  | ||||
| @item O_RDONLY | ||||
| @item O_WRONLY         | ||||
| @item O_RDWR | ||||
| @item O_APPEND | ||||
| @item O_CREAT | ||||
| @item O_EXCL | ||||
| @item O_TRUNC | ||||
| POSIX open flags. | ||||
|  | ||||
| @item O_TEXT | ||||
| (Windows specific). Open the file in text mode. The default is binary mode. | ||||
|  | ||||
| @item close(fd) | ||||
| Close the file handle @code{fd}. | ||||
|  | ||||
| @item seek(fd, offset, whence) | ||||
| Seek in the file. Use @code{std.SEEK_*} for @code{whence}. | ||||
|  | ||||
| @item read(fd, buffer, offset, length) | ||||
| Read @code{length} bytes from the file handle @code{fd} to the | ||||
| ArrayBuffer @code{buffer} at byte position @code{offset}. | ||||
| Return the number of read bytes or < 0 if error. | ||||
|  | ||||
| @item write(fd, buffer, offset, length) | ||||
| Write @code{length} bytes to the file handle @code{fd} from the | ||||
| ArrayBuffer @code{buffer} at byte position @code{offset}. | ||||
| Return the number of written bytes or < 0 if error. | ||||
|  | ||||
| @item isatty(fd) | ||||
| Return @code{true} is @code{fd} is a TTY (terminal) handle. | ||||
|  | ||||
| @item ttyGetWinSize(fd) | ||||
| Return the TTY size as @code{[width, height]} or @code{null} if not available. | ||||
|  | ||||
| @item ttySetRaw(fd) | ||||
| Set the TTY in raw mode. | ||||
|  | ||||
| @item remove(filename) | ||||
| Remove a file. Return 0 if OK or < 0 if error. | ||||
|  | ||||
| @item rename(oldname, newname) | ||||
| Rename a file. Return 0 if OK or < 0 if error. | ||||
|  | ||||
| @item realpath(path) | ||||
| Return @code{[str, err]} where @code{str} is the canonicalized absolute | ||||
| pathname of @code{path} and @code{err} the error code. | ||||
|  | ||||
| @item getcwd() | ||||
| Return @code{[str, err]} where @code{str} is the current working directory | ||||
| and @code{err} the error code. | ||||
|  | ||||
| @item mkdir(path, mode = 0o777) | ||||
| Create a directory at @code{path}. Return the error code. | ||||
|  | ||||
| @item stat(path) | ||||
| @item lstat(path) | ||||
|  | ||||
| Return @code{[obj, err]} where @code{obj} is an object containing the | ||||
| file status of @code{path}. @code{err} is the error code. The | ||||
| following fields are defined in @code{obj}: dev, ino, mode, nlink, | ||||
| uid, gid, rdev, size, blocks, atime, mtime, ctime. The times are | ||||
| specified in milliseconds since 1970. @code{lstat()} is the same as | ||||
| @code{stat()} excepts that it returns information about the link | ||||
| itself. | ||||
|  | ||||
| @item S_IFMT | ||||
| @item S_IFIFO | ||||
| @item S_IFCHR | ||||
| @item S_IFDIR | ||||
| @item S_IFBLK | ||||
| @item S_IFREG | ||||
| @item S_IFSOCK | ||||
| @item S_IFLNK | ||||
| @item S_ISGID | ||||
| @item S_ISUID | ||||
| Constants to interpret the @code{mode} property returned by | ||||
| @code{stat()}. They have the same value as in the C system header | ||||
| @file{sys/stat.h}. | ||||
|  | ||||
| @item utimes(path, atime, mtime) | ||||
| Change the access and modification times of the file @code{path}. The | ||||
| times are specified in milliseconds since 1970. | ||||
|  | ||||
| @item symlink(target, linkpath) | ||||
| Create a link at @code{linkpath} containing the string @code{target}. | ||||
|  | ||||
| @item readlink(path) | ||||
| Return @code{[str, err]} where @code{str} is the link target and @code{err} | ||||
| the error code. | ||||
|  | ||||
| @item readdir(path) | ||||
| Return @code{[array, err]} where @code{array} is an array of strings | ||||
| containing the filenames of the directory @code{path}. @code{err} is | ||||
| the error code. | ||||
|  | ||||
| @item setReadHandler(fd, func) | ||||
| Add a read handler to the file handle @code{fd}. @code{func} is called | ||||
| each time there is data pending for @code{fd}. A single read handler | ||||
| per file handle is supported. Use @code{func = null} to remove the | ||||
| hander. | ||||
|  | ||||
| @item setWriteHandler(fd, func) | ||||
| Add a write handler to the file handle @code{fd}. @code{func} is | ||||
| called each time data can be written to @code{fd}. A single write | ||||
| handler per file handle is supported. Use @code{func = null} to remove | ||||
| the hander. | ||||
|  | ||||
| @item signal(signal, func) | ||||
| Call the function @code{func} when the signal @code{signal} | ||||
| happens. Only a single handler per signal number is supported. Use | ||||
| @code{null} to set the default handler or @code{undefined} to ignore | ||||
| the signal. | ||||
|  | ||||
| @item SIGINT | ||||
| @item SIGABRT | ||||
| @item SIGFPE | ||||
| @item SIGILL | ||||
| @item SIGSEGV | ||||
| @item SIGTERM | ||||
| POSIX signal numbers. | ||||
|  | ||||
| @item kill(pid, sig) | ||||
| Send the signal @code{sig} to the process @code{pid}. | ||||
|  | ||||
| @item exec(args[, options]) | ||||
| Execute a process with the arguments @code{args}. @code{options} is an | ||||
| object containing optional parameters: | ||||
|  | ||||
|   @table @code | ||||
|   @item block | ||||
|   Boolean (default = true). If true, wait until the process is | ||||
|   termined. In this case, @code{exec} return the exit code if positive | ||||
|   or the negated signal number if the process was interrupted by a | ||||
|   signal. If false, do not block and return the process id of the child. | ||||
|    | ||||
|   @item usePath | ||||
|   Boolean (default = true). If true, the file is searched in the | ||||
|   @code{PATH} environment variable. | ||||
|  | ||||
|   @item file | ||||
|   String (default = @code{args[0]}). Set the file to be executed. | ||||
|  | ||||
|   @item cwd | ||||
|   String. If present, set the working directory of the new process. | ||||
|  | ||||
|   @item stdin | ||||
|   @item stdout | ||||
|   @item stderr | ||||
|   If present, set the handle in the child for stdin, stdout or stderr. | ||||
|   | ||||
|   @end table | ||||
|  | ||||
| @item waitpid(pid, options) | ||||
| @code{waitpid} Unix system call. Return the array @code{[ret, status]}. | ||||
|  | ||||
| @item WNOHANG | ||||
| Constant for the @code{options} argument of @code{waitpid}. | ||||
|  | ||||
| @item dup(fd) | ||||
| @code{dup} Unix system call. | ||||
|  | ||||
| @item dup2(oldfd, newfd) | ||||
| @code{dup2} Unix system call. | ||||
|  | ||||
| @item pipe() | ||||
| @code{pipe} Unix system call. Return two handles as @code{[read_fd, | ||||
| write_fd]} or null in case of error. | ||||
|  | ||||
| @item sleep(delay_ms) | ||||
| Sleep during @code{delay_ms} milliseconds. | ||||
|  | ||||
| @item setTimeout(func, delay) | ||||
| Call the function @code{func} after @code{delay} ms. Return a handle | ||||
| to the timer. | ||||
|  | ||||
| @item clearTimeout(handle) | ||||
| Cancel a timer. | ||||
|  | ||||
| @item platform | ||||
| Return a string representing the platform: @code{"linux"}, @code{"darwin"}, | ||||
| @code{"win32"} or @code{"js"}. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @section QuickJS C API | ||||
|  | ||||
| The C API was designed to be simple and efficient. The C API is | ||||
| defined in the header @code{quickjs.h}. | ||||
|  | ||||
| @subsection Runtime and contexts | ||||
|  | ||||
| @code{JSRuntime} represents a Javascript runtime corresponding to an | ||||
| object heap. Several runtimes can exist at the same time but they | ||||
| cannot exchange objects. Inside a given runtime, no multi-threading is | ||||
| supported. | ||||
|  | ||||
| @code{JSContext} represents a Javascript context (or Realm). Each | ||||
| JSContext has its own global objects and system objects. There can be | ||||
| several JSContexts per JSRuntime and they can share objects, similary | ||||
| to frames of the same origin sharing Javascript objects in a | ||||
| web browser. | ||||
|  | ||||
| @subsection JSValue | ||||
|  | ||||
| @code{JSValue} represents a Javascript value which can be a primitive | ||||
| type or an object. Reference counting is used, so it is important to | ||||
| explicitely duplicate (@code{JS_DupValue()}, increment the reference | ||||
| count) or free (@code{JS_FreeValue()}, decrement the reference count) | ||||
| JSValues. | ||||
|  | ||||
| @subsection C functions | ||||
|  | ||||
| C functions can be created with | ||||
| @code{JS_NewCFunction()}. @code{JS_SetPropertyFunctionList()} is a | ||||
| shortcut to easily add functions, setters and getters properties to a | ||||
| given object. | ||||
|  | ||||
| Unlike other embedded Javascript engines, there is no implicit stack, | ||||
| so C functions get their parameters as normal C parameters. As a | ||||
| general rule, C functions take constant @code{JSValue}s as parameters | ||||
| (so they don't need to free them) and return a newly allocated (=live) | ||||
| @code{JSValue}. | ||||
|  | ||||
| @subsection Exceptions | ||||
|  | ||||
| Exceptions: most C functions can return a Javascript exception. It | ||||
| must be explicitely tested and handled by the C code. The specific | ||||
| @code{JSValue} @code{JS_EXCEPTION} indicates that an exception | ||||
| occured. The actual exception object is stored in the | ||||
| @code{JSContext} and can be retrieved with @code{JS_GetException()}. | ||||
|  | ||||
| @subsection Script evaluation | ||||
|  | ||||
| Use @code{JS_Eval()} to evaluate a script or module source. | ||||
|  | ||||
| If the script or module was compiled to bytecode with @code{qjsc}, it | ||||
| can be evaluated by calling @code{js_std_eval_binary()}. The advantage | ||||
| is that no compilation is needed so it is faster and smaller because | ||||
| the compiler can be removed from the executable if no @code{eval} is | ||||
| required. | ||||
|  | ||||
| Note: the bytecode format is linked to a given QuickJS | ||||
| version. Moreover, no security check is done before its | ||||
| execution. Hence the bytecode should not be loaded from untrusted | ||||
| sources. That's why there is no option to output the bytecode to a | ||||
| binary file in @code{qjsc}. | ||||
|  | ||||
| @subsection JS Classes | ||||
|  | ||||
| C opaque data can be attached to a Javascript object. The type of the | ||||
| C opaque data is determined with the class ID (@code{JSClassID}) of | ||||
| the object. Hence the first step is to register a new class ID and JS | ||||
| class (@code{JS_NewClassID()}, @code{JS_NewClass()}). Then you can | ||||
| create objects of this class with @code{JS_NewObjectClass()} and get or | ||||
| set the C opaque point with | ||||
| @code{JS_GetOpaque()}/@code{JS_SetOpaque()}. | ||||
|  | ||||
| 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} method | ||||
| can be provided so that the cycle removal algorithm can find the other | ||||
| objects referenced by this object. Other methods are available to | ||||
| define exotic object behaviors. | ||||
|  | ||||
| The Class ID are globally allocated (i.e. for all runtimes). The | ||||
| JSClass are allocated per @code{JSRuntime}. @code{JS_SetClassProto()} | ||||
| is used to define a prototype for a given class in a given | ||||
| JSContext. @code{JS_NewObjectClass()} sets this prototype in the | ||||
| created object. | ||||
|  | ||||
| Examples are available in @file{quickjs-libc.c}. | ||||
|  | ||||
| @subsection C Modules | ||||
|  | ||||
| Native ES6 modules are supported and can be dynamically or statically | ||||
| linked. Look at the @file{test_bjson} and @file{bjson.so} | ||||
| examples. The standard library @file{quickjs-libc.c} is also a good example | ||||
| of a native module. | ||||
|  | ||||
| @subsection Memory handling | ||||
|  | ||||
| Use @code{JS_SetMemoryLimit()} to set a global memory allocation limit | ||||
| to a given JSRuntime. | ||||
|  | ||||
| Custom memory allocation functions can be provided with | ||||
| @code{JS_NewRuntime2()}. | ||||
|  | ||||
| The maximum system stack size can be set with @code{JS_SetMaxStackSize()}. | ||||
|  | ||||
| @subsection Execution timeout and interrupts | ||||
|  | ||||
| Use @code{JS_SetInterruptHandler()} to set a callback which is | ||||
| regularly called by the engine when it is executing code. This | ||||
| callback can be used to implement an execution timeout. | ||||
|  | ||||
| It is used by the command line interpreter to implement a | ||||
| @code{Ctrl-C} handler. | ||||
|  | ||||
| @chapter Internals | ||||
|  | ||||
| @section Bytecode | ||||
|  | ||||
| The compiler generates bytecode directly with no intermediate | ||||
| representation such as a parse tree, hence it is very fast. Several | ||||
| optimizations passes are done over the generated bytecode. | ||||
|  | ||||
| A stack-based bytecode was chosen because it is simple and generates  | ||||
| compact code. | ||||
|  | ||||
| For each function, the maximum stack size is computed at compile time so that | ||||
| no runtime stack overflow tests are needed. | ||||
|  | ||||
| A separate compressed line number table is maintained for the debug | ||||
| information. | ||||
|  | ||||
| Access to closure variables is optimized and is almost as fast as local | ||||
| variables. | ||||
|  | ||||
| Direct @code{eval} in strict mode is optimized. | ||||
|  | ||||
| @section Executable generation | ||||
|  | ||||
| @subsection @code{qjsc} compiler | ||||
|  | ||||
| The @code{qjsc} compiler generates C sources from Javascript files. By | ||||
| default the C sources are compiled with the system compiler | ||||
| (@code{gcc} or @code{clang}). | ||||
|  | ||||
| The generated C source contains the bytecode of the compiled functions | ||||
| or modules. If a full complete executable is needed, it also | ||||
| contains a @code{main()} function with the necessary C code to initialize the | ||||
| Javascript engine and to load and execute the compiled functions and | ||||
| modules. | ||||
|  | ||||
| Javascript code can be mixed with C modules. | ||||
|  | ||||
| In order to have smaller executables, specific Javascript features can | ||||
| be disabled, in particular @code{eval} or the regular expressions. The | ||||
| code removal relies on the Link Time Optimization of the system | ||||
| compiler. | ||||
|  | ||||
| @subsection Binary JSON | ||||
|  | ||||
| @code{qjsc} works by compiling scripts or modules and then serializing | ||||
| them to a binary format. A subset of this format (without functions or | ||||
| modules) can be used as binary JSON. The example @file{test_bjson.js} | ||||
| shows how to use it. | ||||
|  | ||||
| Warning: the binary JSON format may change without notice, so it | ||||
| should not be used to store persistent data. The @file{test_bjson.js} | ||||
| example is only used to test the binary object format functions. | ||||
|  | ||||
| @section Runtime | ||||
|  | ||||
| @subsection Strings | ||||
|  | ||||
| Strings are stored either as an 8 bit or a 16 bit array of | ||||
| characters. Hence random access to characters is always fast. | ||||
|  | ||||
| The C API provides functions to convert Javascript Strings to C UTF-8 encoded | ||||
| strings. The most common case where the Javascript string contains | ||||
| only ASCII characters involves no copying. | ||||
|  | ||||
| @subsection Objects | ||||
|  | ||||
| The object shapes (object prototype, property names and flags) are shared | ||||
| between objects to save memory. | ||||
|  | ||||
| Arrays with no holes (except at the end of the array) are optimized. | ||||
|  | ||||
| TypedArray accesses are optimized. | ||||
|  | ||||
| @subsection Atoms | ||||
|  | ||||
| Object property names and some strings are stored as Atoms (unique | ||||
| strings) to save memory and allow fast comparison. Atoms are | ||||
| represented as a 32 bit integer. Half of the atom range is reserved for | ||||
| immediate integer literals from @math{0} to @math{2^{31}-1}. | ||||
|  | ||||
| @subsection Numbers | ||||
|  | ||||
| Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754 | ||||
| floating point values. Most operations have fast paths for the 32-bit | ||||
| integer case. | ||||
|  | ||||
| @subsection Garbage collection | ||||
|  | ||||
| Reference counting is used to free objects automatically and | ||||
| deterministically. A separate cycle removal pass is done when the allocated | ||||
| memory becomes too large. The cycle removal algorithm only uses the | ||||
| reference counts and the object content, so no explicit garbage | ||||
| collection roots need to be manipulated in the C code. | ||||
|  | ||||
| @subsection JSValue | ||||
|  | ||||
| It is a Javascript value which can be a primitive type (such as | ||||
| Number, String, ...) or an Object. NaN boxing is used in the 32-bit version | ||||
| to store 64-bit floating point numbers. The representation is | ||||
| optimized so that 32-bit integers and reference counted values can be | ||||
| efficiently tested. | ||||
|  | ||||
| In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The | ||||
| rationale is that in 64-bit code memory usage is less critical. | ||||
|  | ||||
| In both cases (32 or 64 bits), JSValue exactly fits two CPU registers, | ||||
| so it can be efficiently returned by C functions. | ||||
|  | ||||
| @subsection Function call | ||||
|  | ||||
| The engine is optimized so that function calls are fast. The system | ||||
| stack holds the Javascript parameters and local variables. | ||||
|  | ||||
| @section RegExp | ||||
|  | ||||
| A specific regular expression engine was developped. It is both small | ||||
| and efficient and supports all the ES2020 features including the | ||||
| Unicode properties. As the Javascript compiler, it directly generates | ||||
| bytecode without a parse tree. | ||||
|  | ||||
| Backtracking with an explicit stack is used so that there is no | ||||
| recursion on the system stack. Simple quantizers are specifically | ||||
| optimized to avoid recursions. | ||||
|  | ||||
| Infinite recursions coming from quantizers with empty terms are | ||||
| avoided. | ||||
|  | ||||
| The full regexp library weights about 15 KiB (x86 code), excluding the | ||||
| Unicode library. | ||||
|  | ||||
| @section Unicode | ||||
|  | ||||
| A specific Unicode library was developped so that there is no | ||||
| dependency on an external large Unicode library such as ICU. All the | ||||
| Unicode tables are compressed while keeping a reasonnable access | ||||
| speed. | ||||
|  | ||||
| The library supports case conversion, Unicode normalization, Unicode | ||||
| script queries, Unicode general category queries and all Unicode | ||||
| binary properties. | ||||
|  | ||||
| The full Unicode library weights about 45 KiB (x86 code). | ||||
|  | ||||
| @section BigInt and BigFloat | ||||
|  | ||||
| BigInt and BigFloat are implemented with the @code{libbf} | ||||
| library@footnote{@url{https://bellard.org/libbf}}. It weights about 60 | ||||
| KiB (x86 code) and provides arbitrary precision IEEE 754 floating | ||||
| point operations and transcendental functions with exact rounding. | ||||
|  | ||||
| @chapter License | ||||
|  | ||||
| QuickJS is released under the MIT license. | ||||
|  | ||||
| Unless otherwise specified, the QuickJS sources are copyright Fabrice | ||||
| Bellard and Charlie Gordon. | ||||
|  | ||||
| @bye | ||||
							
								
								
									
										6
									
								
								deps/quickjs/examples/c_module.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								deps/quickjs/examples/c_module.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| /* example of JS module importing a C module */ | ||||
|  | ||||
| import { fib } from "./fib.so"; | ||||
|  | ||||
| console.log("Hello World"); | ||||
| console.log("fib(10)=", fib(10)); | ||||
							
								
								
									
										72
									
								
								deps/quickjs/examples/fib.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								deps/quickjs/examples/fib.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| /* | ||||
|  * QuickJS: Example of C module | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #include "../quickjs.h" | ||||
|  | ||||
| #define countof(x) (sizeof(x) / sizeof((x)[0])) | ||||
|  | ||||
| static int fib(int n) | ||||
| { | ||||
|     if (n <= 0) | ||||
|         return 0; | ||||
|     else if (n == 1) | ||||
|         return 1; | ||||
|     else | ||||
|         return fib(n - 1) + fib(n - 2); | ||||
| } | ||||
|  | ||||
| static JSValue js_fib(JSContext *ctx, JSValueConst this_val, | ||||
|                       int argc, JSValueConst *argv) | ||||
| { | ||||
|     int n, res; | ||||
|     if (JS_ToInt32(ctx, &n, argv[0])) | ||||
|         return JS_EXCEPTION; | ||||
|     res = fib(n); | ||||
|     return JS_NewInt32(ctx, res); | ||||
| } | ||||
|  | ||||
| static const JSCFunctionListEntry js_fib_funcs[] = { | ||||
|     JS_CFUNC_DEF("fib", 1, js_fib ), | ||||
| }; | ||||
|  | ||||
| static int js_fib_init(JSContext *ctx, JSModuleDef *m) | ||||
| { | ||||
|     return JS_SetModuleExportList(ctx, m, js_fib_funcs, | ||||
|                                   countof(js_fib_funcs)); | ||||
| } | ||||
|  | ||||
| #ifdef JS_SHARED_LIBRARY | ||||
| #define JS_INIT_MODULE js_init_module | ||||
| #else | ||||
| #define JS_INIT_MODULE js_init_module_fib | ||||
| #endif | ||||
|  | ||||
| JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) | ||||
| { | ||||
|     JSModuleDef *m; | ||||
|     m = JS_NewCModule(ctx, module_name, js_fib_init); | ||||
|     if (!m) | ||||
|         return NULL; | ||||
|     JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs)); | ||||
|     return m; | ||||
| } | ||||
							
								
								
									
										10
									
								
								deps/quickjs/examples/fib_module.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								deps/quickjs/examples/fib_module.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| /* fib module */ | ||||
| export function fib(n) | ||||
| { | ||||
|     if (n <= 0) | ||||
|         return 0; | ||||
|     else if (n == 1) | ||||
|         return 1; | ||||
|     else | ||||
|         return fib(n - 1) + fib(n - 2); | ||||
| } | ||||
							
								
								
									
										1
									
								
								deps/quickjs/examples/hello.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								deps/quickjs/examples/hello.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| console.log("Hello World"); | ||||
							
								
								
									
										6
									
								
								deps/quickjs/examples/hello_module.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								deps/quickjs/examples/hello_module.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| /* example of JS module */ | ||||
|  | ||||
| import { fib } from "./fib_module.js"; | ||||
|  | ||||
| console.log("Hello World"); | ||||
| console.log("fib(10)=", fib(10)); | ||||
							
								
								
									
										66
									
								
								deps/quickjs/examples/pi.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								deps/quickjs/examples/pi.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  * PI computation in Javascript using the QuickJS bignum extensions | ||||
|  */ | ||||
| "use strict"; | ||||
| "use bigint"; | ||||
|  | ||||
| /* compute PI with a precision of 'prec' bits */ | ||||
| function calc_pi(prec) { | ||||
|     const CHUD_A = 13591409; | ||||
|     const CHUD_B = 545140134; | ||||
|     const CHUD_C = 640320; | ||||
|     const CHUD_C3 = 10939058860032000; /* C^3/24 */ | ||||
|     const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ | ||||
|      | ||||
|     /* return [P, Q, G] */ | ||||
|     function chud_bs(a, b, need_G) { | ||||
|         var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; | ||||
|         if (a == (b - 1)) { | ||||
|             G = (2 * b - 1) * (6 * b - 1) * (6 * b - 5); | ||||
|             P = BigFloat(G * (CHUD_B * b + CHUD_A)); | ||||
|             if (b & 1) | ||||
|                 P = -P; | ||||
|             G = BigFloat(G); | ||||
|             Q = BigFloat(b * b * b * CHUD_C3); | ||||
|         } else { | ||||
|             c = (a + b) >> 1; | ||||
|             [P1, Q1, G1] = chud_bs(a, c, true); | ||||
|             [P2, Q2, G2] = chud_bs(c, b, need_G); | ||||
|             P = P1 * Q2 + P2 * G1; | ||||
|             Q = Q1 * Q2; | ||||
|             if (need_G) | ||||
|                 G = G1 * G2; | ||||
|             else | ||||
|                 G = 0; | ||||
|         } | ||||
|         return [P, Q, G]; | ||||
|     } | ||||
|  | ||||
|     var n, P, Q, G; | ||||
|     /* number of serie terms */ | ||||
|     n = Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM) + 10; | ||||
|     [P, Q, G] = chud_bs(0, n, false); | ||||
|     Q = Q / (P + Q * CHUD_A); | ||||
|     G = (CHUD_C / 12) * BigFloat.sqrt(CHUD_C); | ||||
|     return Q * G; | ||||
| } | ||||
|  | ||||
| (function() { | ||||
|     var r, n_digits, n_bits; | ||||
|     if (typeof scriptArgs != "undefined") { | ||||
|         if (scriptArgs.length < 2) { | ||||
|             print("usage: pi n_digits"); | ||||
|             return; | ||||
|         } | ||||
|         n_digits = scriptArgs[1]; | ||||
|     } else { | ||||
|         n_digits = 1000; | ||||
|     } | ||||
|     n_bits = Math.ceil(n_digits * Math.log2(10)); | ||||
|     /* we add more bits to reduce the probability of bad rounding for | ||||
|        the last digits */ | ||||
|     BigFloatEnv.setPrec( () => { | ||||
|         r = calc_pi(); | ||||
|         print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); | ||||
|     }, n_bits + 32); | ||||
| })(); | ||||
							
								
								
									
										918
									
								
								deps/quickjs/jscompress.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										918
									
								
								deps/quickjs/jscompress.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,918 @@ | ||||
| /* | ||||
|  * Javascript Compressor | ||||
|  *  | ||||
|  * Copyright (c) 2008-2018 Fabrice Bellard | ||||
|  * Copyright (c) 2017-2018 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <getopt.h> | ||||
| #include <stdarg.h> | ||||
| #include <string.h> | ||||
| #include <inttypes.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "cutils.h" | ||||
|  | ||||
| typedef struct JSToken { | ||||
|     int tok; | ||||
|     char buf[20]; | ||||
|     char *str; | ||||
|     int len; | ||||
|     int size; | ||||
|     int line_num;  /* line number for start of token */ | ||||
|     int lines;     /* number of embedded linefeeds in token */ | ||||
| } JSToken; | ||||
|  | ||||
| enum { | ||||
|     TOK_EOF = 256, | ||||
|     TOK_IDENT, | ||||
|     TOK_STR1, | ||||
|     TOK_STR2, | ||||
|     TOK_STR3, | ||||
|     TOK_NUM, | ||||
|     TOK_COM, | ||||
|     TOK_LCOM, | ||||
| }; | ||||
|  | ||||
| void tok_reset(JSToken *tt) | ||||
| { | ||||
|     if (tt->str != tt->buf) { | ||||
|         free(tt->str); | ||||
|         tt->str = tt->buf; | ||||
|         tt->size = sizeof(tt->buf); | ||||
|     } | ||||
|     tt->len = 0; | ||||
| } | ||||
|  | ||||
| void tok_add_ch(JSToken *tt, int c) | ||||
| { | ||||
|     if (tt->len + 1 > tt->size) { | ||||
|         tt->size *= 2; | ||||
|         if (tt->str == tt->buf) { | ||||
|             tt->str = malloc(tt->size); | ||||
|             memcpy(tt->str, tt->buf, tt->len); | ||||
|         } else { | ||||
|             tt->str = realloc(tt->str, tt->size); | ||||
|         } | ||||
|     } | ||||
|     tt->str[tt->len++] = c; | ||||
| } | ||||
|  | ||||
| FILE *infile; | ||||
| const char *filename; | ||||
| int output_line_num; | ||||
| int line_num; | ||||
| int ch; | ||||
| JSToken tokc; | ||||
|  | ||||
| int skip_mask; | ||||
| #define DEFINE_MAX 20 | ||||
| char *define_tab[DEFINE_MAX]; | ||||
| int define_len; | ||||
|  | ||||
| void error(const char *fmt, ...) | ||||
| { | ||||
|     va_list ap; | ||||
|     va_start(ap, fmt); | ||||
|     if (filename) { | ||||
|         fprintf(stderr, "%s:%d: ", filename, line_num); | ||||
|     } else { | ||||
|         fprintf(stderr, "jscompress: "); | ||||
|     } | ||||
|     vfprintf(stderr, fmt, ap); | ||||
|     fprintf(stderr, "\n"); | ||||
|     va_end(ap); | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
| void define_symbol(const char *def) | ||||
| { | ||||
|     int i; | ||||
|     for (i = 0; i < define_len; i++) { | ||||
|         if (!strcmp(tokc.str, define_tab[i])) | ||||
|             return; | ||||
|     } | ||||
|     if (define_len >= DEFINE_MAX) | ||||
|         error("too many defines"); | ||||
|     define_tab[define_len++] = strdup(def); | ||||
| } | ||||
|  | ||||
| void undefine_symbol(const char *def) | ||||
| { | ||||
|     int i, j; | ||||
|     for (i = j = 0; i < define_len; i++) { | ||||
|         if (!strcmp(tokc.str, define_tab[i])) { | ||||
|             free(define_tab[i]); | ||||
|         } else { | ||||
|             define_tab[j++] = define_tab[i]; | ||||
|         } | ||||
|     } | ||||
|     define_len = j; | ||||
| } | ||||
|  | ||||
| const char *find_symbol(const char *def) | ||||
| { | ||||
|     int i; | ||||
|     for (i = 0; i < define_len; i++) { | ||||
|         if (!strcmp(tokc.str, define_tab[i])) | ||||
|             return "1"; | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| void next(void); | ||||
|  | ||||
| void nextch(void) | ||||
| { | ||||
|     ch = fgetc(infile); | ||||
|     if (ch == '\n') | ||||
|         line_num++; | ||||
| } | ||||
|  | ||||
| int skip_blanks(void) | ||||
| { | ||||
|     for (;;) { | ||||
|         next(); | ||||
|         if (tokc.tok != ' ' && tokc.tok != '\t' && | ||||
|             tokc.tok != TOK_COM && tokc.tok != TOK_LCOM) | ||||
|             return tokc.tok; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void parse_directive(void) | ||||
| { | ||||
|     int ifdef, mask = skip_mask; | ||||
|     /* simplistic preprocessor: | ||||
|        #define / #undef / #ifdef / #ifndef / #else / #endif | ||||
|        no symbol substitution. | ||||
|      */ | ||||
|     skip_mask = 0;  /* disable skipping to parse preprocessor line */ | ||||
|     nextch(); | ||||
|     if (skip_blanks() != TOK_IDENT) | ||||
|         error("expected preprocessing directive after #"); | ||||
|  | ||||
|     if (!strcmp(tokc.str, "define")) { | ||||
|         if (skip_blanks() != TOK_IDENT) | ||||
|             error("expected identifier after #define"); | ||||
|         define_symbol(tokc.str); | ||||
|     } else if (!strcmp(tokc.str, "undef")) { | ||||
|         if (skip_blanks() != TOK_IDENT) | ||||
|             error("expected identifier after #undef"); | ||||
|         undefine_symbol(tokc.str); | ||||
|     } else if ((ifdef = 1, !strcmp(tokc.str, "ifdef")) || | ||||
|                (ifdef = 0, !strcmp(tokc.str, "ifndef"))) { | ||||
|         if (skip_blanks() != TOK_IDENT) | ||||
|             error("expected identifier after #ifdef/#ifndef"); | ||||
|         mask = (mask << 2) | 2 | ifdef; | ||||
|         if (find_symbol(tokc.str)) | ||||
|             mask ^= 1; | ||||
|     } else if (!strcmp(tokc.str, "else")) { | ||||
|         if (!(mask & 2)) | ||||
|             error("#else without a #if"); | ||||
|         mask ^= 1; | ||||
|     } else if (!strcmp(tokc.str, "endif")) { | ||||
|         if (!(mask & 2)) | ||||
|             error("#endif without a #if"); | ||||
|         mask >>= 2; | ||||
|     } else { | ||||
|         error("unsupported preprocessing directive"); | ||||
|     } | ||||
|     if (skip_blanks() != '\n') | ||||
|         error("extra characters on preprocessing line"); | ||||
|     skip_mask = mask; | ||||
| } | ||||
|  | ||||
| /* return -1 if invalid char */ | ||||
| static int hex_to_num(int ch) | ||||
| { | ||||
|     if (ch >= 'a' && ch <= 'f') | ||||
|         return ch - 'a' + 10; | ||||
|     else if (ch >= 'A' && ch <= 'F') | ||||
|         return ch - 'A' + 10; | ||||
|     else if (ch >= '0' && ch <= '9') | ||||
|         return ch - '0'; | ||||
|     else | ||||
|         return -1; | ||||
| } | ||||
|  | ||||
| void next(void) | ||||
| { | ||||
| again:     | ||||
|     tok_reset(&tokc); | ||||
|     tokc.line_num = line_num; | ||||
|     tokc.lines = 0; | ||||
|     switch(ch) { | ||||
|     case EOF: | ||||
|         tokc.tok = TOK_EOF; | ||||
|         if (skip_mask) | ||||
|             error("missing #endif"); | ||||
|         break; | ||||
|     case 'a' ... 'z': | ||||
|     case 'A' ... 'Z': | ||||
|     case '_': | ||||
|     case '$': | ||||
|         tok_add_ch(&tokc, ch); | ||||
|         nextch(); | ||||
|         while ((ch >= 'a' && ch <= 'z') || | ||||
|                (ch >= 'A' && ch <= 'Z') || | ||||
|                (ch >= '0' && ch <= '9') || | ||||
|                (ch == '_' || ch == '$')) { | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             nextch(); | ||||
|         } | ||||
|         tok_add_ch(&tokc, '\0'); | ||||
|         tokc.tok = TOK_IDENT; | ||||
|         break; | ||||
|     case '.': | ||||
|         nextch(); | ||||
|         if (ch >= '0' && ch <= '9') { | ||||
|             tok_add_ch(&tokc, '.'); | ||||
|             goto has_dot; | ||||
|         } | ||||
|         tokc.tok = '.'; | ||||
|         break; | ||||
|     case '0': | ||||
|         tok_add_ch(&tokc, ch); | ||||
|         nextch(); | ||||
|         if (ch == 'x' || ch == 'X') { | ||||
|             /* hexa */ | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             nextch(); | ||||
|             while ((ch >= 'a' && ch <= 'f') || | ||||
|                    (ch >= 'A' && ch <= 'F') || | ||||
|                    (ch >= '0' && ch <= '9')) { | ||||
|                 tok_add_ch(&tokc, ch); | ||||
|                 nextch(); | ||||
|             } | ||||
|             tok_add_ch(&tokc, '\0'); | ||||
|             tokc.tok = TOK_NUM; | ||||
|             break; | ||||
|         } | ||||
|         goto has_digit; | ||||
|  | ||||
|     case '1' ... '9': | ||||
|         tok_add_ch(&tokc, ch); | ||||
|         nextch(); | ||||
|     has_digit: | ||||
|         /* decimal */ | ||||
|         while (ch >= '0' && ch <= '9') { | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             nextch(); | ||||
|         } | ||||
|         if (ch == '.') { | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             nextch(); | ||||
|         has_dot: | ||||
|             while (ch >= '0' && ch <= '9') { | ||||
|                 tok_add_ch(&tokc, ch); | ||||
|                 nextch(); | ||||
|             } | ||||
|         } | ||||
|         if (ch == 'e' || ch == 'E') { | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             nextch(); | ||||
|             if (ch == '+' || ch == '-') { | ||||
|                 tok_add_ch(&tokc, ch); | ||||
|                 nextch(); | ||||
|             } | ||||
|             while (ch >= '0' && ch <= '9') { | ||||
|                 tok_add_ch(&tokc, ch); | ||||
|                 nextch(); | ||||
|             } | ||||
|         } | ||||
|         tok_add_ch(&tokc, '\0'); | ||||
|         tokc.tok = TOK_NUM; | ||||
|         break; | ||||
|     case '`': | ||||
|         { | ||||
|             nextch(); | ||||
|             while (ch != '`' && ch != EOF) { | ||||
|                 if (ch == '\\') { | ||||
|                     tok_add_ch(&tokc, ch); | ||||
|                     nextch(); | ||||
|                     if (ch == EOF) { | ||||
|                         error("unexpected char after '\\'"); | ||||
|                     } | ||||
|                     tok_add_ch(&tokc, ch); | ||||
|                 } else { | ||||
|                     tok_add_ch(&tokc, ch); | ||||
|                     nextch(); | ||||
|                 } | ||||
|             } | ||||
|             nextch(); | ||||
|             tok_add_ch(&tokc, 0); | ||||
|             tokc.tok = TOK_STR3; | ||||
|         } | ||||
|         break; | ||||
|     case '\"': | ||||
|     case '\'': | ||||
|         { | ||||
|             int n, i, c, hex_digit_count; | ||||
|             int quote_ch; | ||||
|             quote_ch = ch; | ||||
|             nextch(); | ||||
|             while (ch != quote_ch && ch != EOF) { | ||||
|                 if (ch == '\\') { | ||||
|                     nextch(); | ||||
|                     switch(ch) { | ||||
|                     case 'n': | ||||
|                         tok_add_ch(&tokc, '\n'); | ||||
|                         nextch(); | ||||
|                         break; | ||||
|                     case 'r': | ||||
|                         tok_add_ch(&tokc, '\r'); | ||||
|                         nextch(); | ||||
|                         break; | ||||
|                     case 't': | ||||
|                         tok_add_ch(&tokc, '\t'); | ||||
|                         nextch(); | ||||
|                         break; | ||||
|                     case 'v': | ||||
|                         tok_add_ch(&tokc, '\v'); | ||||
|                         nextch(); | ||||
|                         break; | ||||
|                     case '\"': | ||||
|                     case '\'': | ||||
|                     case '\\': | ||||
|                         tok_add_ch(&tokc, ch); | ||||
|                         nextch(); | ||||
|                         break; | ||||
|                     case '0' ... '7': | ||||
|                         n = 0; | ||||
|                         while (ch >= '0' && ch <= '7') { | ||||
|                             n = n * 8 + (ch - '0'); | ||||
|                             nextch(); | ||||
|                         } | ||||
|                         tok_add_ch(&tokc, n); | ||||
|                         break; | ||||
|                     case 'x': | ||||
|                     case 'u': | ||||
|                         if (ch == 'x') | ||||
|                             hex_digit_count = 2; | ||||
|                         else | ||||
|                             hex_digit_count = 4; | ||||
|                         nextch(); | ||||
|                         n = 0; | ||||
|                         for(i = 0; i < hex_digit_count; i++) { | ||||
|                             c = hex_to_num(ch); | ||||
|                             if (c < 0)  | ||||
|                                 error("unexpected char after '\\x'"); | ||||
|                             n = n * 16 + c; | ||||
|                             nextch(); | ||||
|                         } | ||||
|                         if (n >= 256) | ||||
|                             error("unicode is currently unsupported"); | ||||
|                         tok_add_ch(&tokc, n); | ||||
|                         break; | ||||
|  | ||||
|                     default: | ||||
|                         error("unexpected char after '\\'"); | ||||
|                     } | ||||
|                 } else { | ||||
|                     /* XXX: should refuse embedded newlines */ | ||||
|                     tok_add_ch(&tokc, ch); | ||||
|                     nextch(); | ||||
|                 } | ||||
|             } | ||||
|             nextch(); | ||||
|             tok_add_ch(&tokc, 0); | ||||
|             if (quote_ch == '\'') | ||||
|                 tokc.tok = TOK_STR1; | ||||
|             else | ||||
|                 tokc.tok = TOK_STR2; | ||||
|         } | ||||
|         break; | ||||
|     case '/': | ||||
|         nextch(); | ||||
|         if (ch == '/') { | ||||
|             tok_add_ch(&tokc, '/'); | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             nextch(); | ||||
|             while (ch != '\n' && ch != EOF) { | ||||
|                 tok_add_ch(&tokc, ch); | ||||
|                 nextch(); | ||||
|             } | ||||
|             tok_add_ch(&tokc, '\0'); | ||||
|             tokc.tok = TOK_LCOM; | ||||
|         } else if (ch == '*') { | ||||
|             int last; | ||||
|             tok_add_ch(&tokc, '/'); | ||||
|             tok_add_ch(&tokc, ch); | ||||
|             last = 0; | ||||
|             for(;;) { | ||||
|                 nextch(); | ||||
|                 if (ch == EOF) | ||||
|                     error("unterminated comment"); | ||||
|                 if (ch == '\n') | ||||
|                     tokc.lines++; | ||||
|                 tok_add_ch(&tokc, ch); | ||||
|                 if (last == '*' && ch == '/') | ||||
|                     break; | ||||
|                 last = ch; | ||||
|             } | ||||
|             nextch(); | ||||
|             tok_add_ch(&tokc, '\0'); | ||||
|             tokc.tok = TOK_COM; | ||||
|         } else { | ||||
|             tokc.tok = '/'; | ||||
|         } | ||||
|         break; | ||||
|     case '#': | ||||
|         parse_directive(); | ||||
|         goto again; | ||||
|     case '\n': | ||||
|         /* adjust line number */ | ||||
|         tokc.line_num--; | ||||
|         tokc.lines++; | ||||
|         /* fall thru */ | ||||
|     default: | ||||
|         tokc.tok = ch; | ||||
|         nextch(); | ||||
|         break; | ||||
|     } | ||||
|     if (skip_mask & 1) | ||||
|         goto again; | ||||
| } | ||||
|  | ||||
| void print_tok(FILE *f, JSToken *tt) | ||||
| { | ||||
|     /* keep output lines in sync with input lines */ | ||||
|     while (output_line_num < tt->line_num) { | ||||
|         putc('\n', f); | ||||
|         output_line_num++; | ||||
|     } | ||||
|  | ||||
|     switch(tt->tok) { | ||||
|     case TOK_IDENT: | ||||
|     case TOK_COM: | ||||
|     case TOK_LCOM: | ||||
|         fprintf(f, "%s", tt->str); | ||||
|         break; | ||||
|     case TOK_NUM: | ||||
|         { | ||||
|             unsigned long a; | ||||
|             char *p; | ||||
|             a = strtoul(tt->str, &p, 0); | ||||
|             if (*p == '\0' && a <= 0x7fffffff) { | ||||
|                 /* must be an integer */ | ||||
|                 fprintf(f, "%d", (int)a); | ||||
|             } else { | ||||
|                 fprintf(f, "%s", tt->str); | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     case TOK_STR3: | ||||
|         fprintf(f, "`%s`", tt->str); | ||||
|         break; | ||||
|     case TOK_STR1: | ||||
|     case TOK_STR2: | ||||
|         { | ||||
|             int i, c, quote_ch; | ||||
|             if (tt->tok == TOK_STR1) | ||||
|                 quote_ch = '\''; | ||||
|             else | ||||
|                 quote_ch = '\"'; | ||||
|             fprintf(f, "%c", quote_ch); | ||||
|             for(i = 0; i < tt->len - 1; i++) { | ||||
|                 c = (uint8_t)tt->str[i]; | ||||
|                 switch(c) { | ||||
|                 case '\r': | ||||
|                     fprintf(f, "\\r"); | ||||
|                     break; | ||||
|                 case '\n': | ||||
|                     fprintf(f, "\\n"); | ||||
|                     break; | ||||
|                 case '\t': | ||||
|                     fprintf(f, "\\t"); | ||||
|                     break; | ||||
|                 case '\v': | ||||
|                     fprintf(f, "\\v"); | ||||
|                     break; | ||||
|                 case '\"': | ||||
|                 case '\'': | ||||
|                     if (c == quote_ch) | ||||
|                         fprintf(f, "\\%c", c); | ||||
|                     else | ||||
|                         fprintf(f, "%c", c); | ||||
|                     break; | ||||
|                 case '\\': | ||||
|                     fprintf(f, "\\\\"); | ||||
|                     break; | ||||
|                 default: | ||||
|                     /* XXX: no utf-8 support! */ | ||||
|                     if (c >= 32 && c <= 255) { | ||||
|                         fprintf(f, "%c", c); | ||||
|                     } else if (c <= 255)  | ||||
|                         fprintf(f, "\\x%02x", c); | ||||
|                     else | ||||
|                         fprintf(f, "\\u%04x", c); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             fprintf(f, "%c", quote_ch); | ||||
|         } | ||||
|         break; | ||||
|     default: | ||||
|         if (tokc.tok >= 256) | ||||
|             error("unsupported token in print_tok: %d", tt->tok); | ||||
|         fprintf(f, "%c", tt->tok); | ||||
|         break; | ||||
|     } | ||||
|     output_line_num += tt->lines; | ||||
| } | ||||
|  | ||||
| /* check if token pasting could occur */                     | ||||
| static BOOL compat_token(int c1, int c2) | ||||
| { | ||||
|     if ((c1 == TOK_IDENT || c1 == TOK_NUM) && | ||||
|         (c2 == TOK_IDENT || c2 == TOK_NUM)) | ||||
|         return FALSE; | ||||
|  | ||||
|     if ((c1 == c2 && strchr("+-<>&|=*/.", c1)) | ||||
|     ||  (c2 == '=' && strchr("+-<>&|!*/^%", c1)) | ||||
|     ||  (c1 == '=' && c2 == '>') | ||||
|     ||  (c1 == '/' && c2 == '*') | ||||
|     ||  (c1 == '.' && c2 == TOK_NUM) | ||||
|     ||  (c1 == TOK_NUM && c2 == '.')) | ||||
|         return FALSE; | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
|  | ||||
| void js_compress(const char *filename, const char *outfilename, | ||||
|                  BOOL do_strip, BOOL keep_header) | ||||
| { | ||||
|     FILE *outfile; | ||||
|     int ltok, seen_space; | ||||
|      | ||||
|     line_num = 1; | ||||
|     infile = fopen(filename, "rb"); | ||||
|     if (!infile) { | ||||
|         perror(filename); | ||||
|         exit(1); | ||||
|     } | ||||
|      | ||||
|     output_line_num = 1; | ||||
|     outfile = fopen(outfilename, "wb"); | ||||
|     if (!outfile) { | ||||
|         perror(outfilename); | ||||
|         exit(1); | ||||
|     } | ||||
|          | ||||
|     nextch(); | ||||
|     next(); | ||||
|     ltok = 0; | ||||
|     seen_space = 0; | ||||
|     if (do_strip) { | ||||
|         if (keep_header) { | ||||
|             while (tokc.tok == ' ' || | ||||
|                    tokc.tok == '\n' || | ||||
|                    tokc.tok == '\t' || | ||||
|                    tokc.tok == '\v' || | ||||
|                    tokc.tok == '\b' || | ||||
|                    tokc.tok == '\f') { | ||||
|                 seen_space = 1; | ||||
|                 next(); | ||||
|             } | ||||
|             if (tokc.tok == TOK_COM) { | ||||
|                 print_tok(outfile, &tokc); | ||||
|                 //fprintf(outfile, "\n"); | ||||
|                 ltok = tokc.tok; | ||||
|                 seen_space = 0; | ||||
|                 next(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for(;;) { | ||||
|             if (tokc.tok == TOK_EOF) | ||||
|                 break; | ||||
|             if (tokc.tok == ' ' || | ||||
|                 tokc.tok == '\r' || | ||||
|                 tokc.tok == '\t' || | ||||
|                 tokc.tok == '\v' || | ||||
|                 tokc.tok == '\b' || | ||||
|                 tokc.tok == '\f' || | ||||
|                 tokc.tok == TOK_LCOM || | ||||
|                 tokc.tok == TOK_COM) { | ||||
|                 /* don't print spaces or comments */ | ||||
|                 seen_space = 1; | ||||
|             } else if (tokc.tok == TOK_STR3) { | ||||
|                 print_tok(outfile, &tokc); | ||||
|                 ltok = tokc.tok; | ||||
|                 seen_space = 0; | ||||
|             } else if (tokc.tok == TOK_STR1 || tokc.tok == TOK_STR2) { | ||||
|                 int count, i; | ||||
|                 /* find the optimal quote char */ | ||||
|                 count = 0; | ||||
|                 for(i = 0; i < tokc.len; i++) { | ||||
|                     if (tokc.str[i] == '\'') | ||||
|                         count++; | ||||
|                     else if (tokc.str[i] == '\"') | ||||
|                         count--; | ||||
|                 } | ||||
|                 if (count > 0) | ||||
|                     tokc.tok = TOK_STR2; | ||||
|                 else if (count < 0) | ||||
|                     tokc.tok = TOK_STR1; | ||||
|                 print_tok(outfile, &tokc); | ||||
|                 ltok = tokc.tok; | ||||
|                 seen_space = 0; | ||||
|             } else { | ||||
|                 if (seen_space && !compat_token(ltok, tokc.tok)) { | ||||
|                     fprintf(outfile, " "); | ||||
|                 } | ||||
|                 print_tok(outfile, &tokc); | ||||
|                 ltok = tokc.tok; | ||||
|                 seen_space = 0; | ||||
|             } | ||||
|             next(); | ||||
|         } | ||||
|     } else { | ||||
|         /* just handle preprocessing */ | ||||
|         while (tokc.tok != TOK_EOF) { | ||||
|             print_tok(outfile, &tokc); | ||||
|             next(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fclose(outfile); | ||||
|     fclose(infile); | ||||
| } | ||||
|  | ||||
| #define HASH_SIZE 30011 | ||||
| #define MATCH_LEN_MIN 3 | ||||
| #define MATCH_LEN_MAX (4 + 63) | ||||
| #define DIST_MAX 65535 | ||||
|  | ||||
| static int find_longest_match(int *pdist, const uint8_t *src, int src_len, | ||||
|                               const int *hash_next, int cur_pos) | ||||
| { | ||||
|     int pos, i, match_len, match_pos, pos_min, len_max; | ||||
|  | ||||
|     len_max = min_int(src_len - cur_pos, MATCH_LEN_MAX); | ||||
|     match_len = 0; | ||||
|     match_pos = 0; | ||||
|     pos_min = max_int(cur_pos - DIST_MAX - 1, 0); | ||||
|     pos = hash_next[cur_pos]; | ||||
|     while (pos >= pos_min) { | ||||
|         for(i = 0; i < len_max; i++) { | ||||
|             if (src[cur_pos + i] != src[pos + i]) | ||||
|                 break; | ||||
|         } | ||||
|         if (i > match_len) { | ||||
|             match_len = i; | ||||
|             match_pos = pos; | ||||
|         } | ||||
|         pos = hash_next[pos]; | ||||
|     } | ||||
|     *pdist = cur_pos - match_pos - 1; | ||||
|     return match_len; | ||||
| } | ||||
|  | ||||
| int lz_compress(uint8_t **pdst, const uint8_t *src, int src_len) | ||||
| { | ||||
|     int *hash_table, *hash_next; | ||||
|     uint32_t h, v; | ||||
|     int i, dist, len, len1, dist1; | ||||
|     uint8_t *dst, *q; | ||||
|      | ||||
|     /* build the hash table */ | ||||
|      | ||||
|     hash_table = malloc(sizeof(hash_table[0]) * HASH_SIZE); | ||||
|     for(i = 0; i < HASH_SIZE; i++) | ||||
|         hash_table[i] = -1; | ||||
|     hash_next = malloc(sizeof(hash_next[0]) * src_len); | ||||
|     for(i = 0; i < src_len; i++) | ||||
|         hash_next[i] = -1; | ||||
|  | ||||
|     for(i = 0; i < src_len - MATCH_LEN_MIN + 1; i++) { | ||||
|         h = ((src[i] << 16) | (src[i + 1] << 8) | src[i + 2]) % HASH_SIZE; | ||||
|         hash_next[i] = hash_table[h]; | ||||
|         hash_table[h] = i; | ||||
|     } | ||||
|     for(;i < src_len; i++) { | ||||
|         hash_next[i] = -1; | ||||
|     } | ||||
|     free(hash_table); | ||||
|  | ||||
|     dst = malloc(src_len + 4); /* never larger than the source */ | ||||
|     q = dst; | ||||
|     *q++ = src_len >> 24; | ||||
|     *q++ = src_len >> 16; | ||||
|     *q++ = src_len >> 8; | ||||
|     *q++ = src_len >> 0; | ||||
|     /* compress */ | ||||
|     i = 0; | ||||
|     while (i < src_len) { | ||||
|         if (src[i] >= 128) | ||||
|             return -1; | ||||
|         len = find_longest_match(&dist, src, src_len, hash_next, i); | ||||
|         if (len >= MATCH_LEN_MIN) { | ||||
|             /* heuristic: see if better length just after */ | ||||
|             len1 = find_longest_match(&dist1, src, src_len, hash_next, i + 1); | ||||
|             if (len1 > len) | ||||
|                 goto no_match; | ||||
|         } | ||||
|         if (len < MATCH_LEN_MIN) { | ||||
|         no_match: | ||||
|             *q++ = src[i]; | ||||
|             i++; | ||||
|         } else if (len <= (3 + 15) && dist < (1 << 10)) { | ||||
|             v = 0x8000 | ((len - 3) << 10) | dist; | ||||
|             *q++ = v >> 8; | ||||
|             *q++ = v; | ||||
|             i += len; | ||||
|         } else if (len >= 4 && len <= (4 + 63) && dist < (1 << 16)) { | ||||
|             v = 0xc00000 | ((len - 4) << 16) | dist; | ||||
|             *q++ = v >> 16; | ||||
|             *q++ = v >> 8; | ||||
|             *q++ = v; | ||||
|             i += len; | ||||
|         } else { | ||||
|             goto no_match; | ||||
|         } | ||||
|     } | ||||
|     free(hash_next); | ||||
|     *pdst = dst; | ||||
|     return q - dst; | ||||
| } | ||||
|  | ||||
| static int load_file(uint8_t **pbuf, const char *filename) | ||||
| { | ||||
|     FILE *f; | ||||
|     uint8_t *buf; | ||||
|     int buf_len; | ||||
|  | ||||
|     f = fopen(filename, "rb"); | ||||
|     if (!f) { | ||||
|         perror(filename); | ||||
|         exit(1); | ||||
|     } | ||||
|     fseek(f, 0, SEEK_END); | ||||
|     buf_len = ftell(f); | ||||
|     fseek(f, 0, SEEK_SET); | ||||
|     buf = malloc(buf_len + 1); | ||||
|     fread(buf, 1, buf_len, f); | ||||
|     buf[buf_len] = '\0'; | ||||
|     fclose(f); | ||||
|     *pbuf = buf; | ||||
|     return buf_len; | ||||
| } | ||||
|  | ||||
| static void save_file(const char *filename, const uint8_t *buf, int buf_len) | ||||
| { | ||||
|     FILE *f; | ||||
|      | ||||
|     f = fopen(filename, "wb"); | ||||
|     if (!f) { | ||||
|         perror(filename); | ||||
|         exit(1); | ||||
|     } | ||||
|     fwrite(buf, 1, buf_len, f); | ||||
|     fclose(f); | ||||
| } | ||||
|  | ||||
| static void save_c_source(const char *filename, const uint8_t *buf, int buf_len, | ||||
|                           const char *var_name) | ||||
| { | ||||
|     FILE *f; | ||||
|     int i; | ||||
|      | ||||
|     f = fopen(filename, "wb"); | ||||
|     if (!f) { | ||||
|         perror(filename); | ||||
|         exit(1); | ||||
|     } | ||||
|     fprintf(f, "/* This file is automatically generated - do not edit */\n\n"); | ||||
|     fprintf(f, "const uint8_t %s[] = {\n", var_name); | ||||
|     for(i = 0; i < buf_len; i++) { | ||||
|         fprintf(f, " 0x%02x,", buf[i]); | ||||
|         if ((i % 8) == 7 || (i == buf_len - 1)) | ||||
|             fprintf(f, "\n"); | ||||
|     } | ||||
|     fprintf(f, "};\n"); | ||||
|     fclose(f); | ||||
| } | ||||
|  | ||||
| #define DEFAULT_OUTPUT_FILENAME "out.js" | ||||
|  | ||||
| void help(void) | ||||
| { | ||||
|     printf("jscompress version 1.0 Copyright (c) 2008-2018 Fabrice Bellard\n" | ||||
|            "usage: jscompress [options] filename\n" | ||||
|            "Javascript compressor\n" | ||||
|            "\n" | ||||
|            "-h          print this help\n" | ||||
|            "-n          do not compress spaces\n" | ||||
|            "-H          keep the first comment\n" | ||||
|            "-c          compress to file\n" | ||||
|            "-C name     compress to C source ('name' is the variable name)\n" | ||||
|            "-D symbol   define preprocessor symbol\n" | ||||
|            "-U symbol   undefine preprocessor symbol\n" | ||||
|            "-o outfile  set the output filename (default=%s)\n", | ||||
|            DEFAULT_OUTPUT_FILENAME); | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     int c, do_strip, keep_header, compress; | ||||
|     const char *out_filename, *c_var, *fname; | ||||
|     char tmpfilename[1024]; | ||||
|  | ||||
|     do_strip = 1; | ||||
|     keep_header = 0; | ||||
|     out_filename = DEFAULT_OUTPUT_FILENAME; | ||||
|     compress = 0; | ||||
|     c_var = NULL; | ||||
|     for(;;) { | ||||
|         c = getopt(argc, argv, "hno:HcC:D:U:"); | ||||
|         if (c == -1) | ||||
|             break; | ||||
|         switch(c) { | ||||
|         case 'h': | ||||
|             help(); | ||||
|             break; | ||||
|         case 'n': | ||||
|             do_strip = 0; | ||||
|             break; | ||||
|         case 'o': | ||||
|             out_filename = optarg; | ||||
|             break; | ||||
|         case 'H': | ||||
|             keep_header = 1; | ||||
|             break; | ||||
|         case 'c': | ||||
|             compress = 1; | ||||
|             break; | ||||
|         case 'C': | ||||
|             c_var = optarg; | ||||
|             compress = 1; | ||||
|             break; | ||||
|         case 'D': | ||||
|             define_symbol(optarg); | ||||
|             break; | ||||
|         case 'U': | ||||
|             undefine_symbol(optarg); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     if (optind >= argc) | ||||
|         help(); | ||||
|  | ||||
|     filename = argv[optind++]; | ||||
|  | ||||
|     if (compress) { | ||||
| #if defined(__ANDROID__) | ||||
|         /* XXX: use another directory ? */ | ||||
|         snprintf(tmpfilename, sizeof(tmpfilename), "out.%d", getpid()); | ||||
| #else | ||||
|         snprintf(tmpfilename, sizeof(tmpfilename), "/tmp/out.%d", getpid()); | ||||
| #endif | ||||
|         fname = tmpfilename; | ||||
|     } else { | ||||
|         fname = out_filename; | ||||
|     } | ||||
|     js_compress(filename, fname, do_strip, keep_header); | ||||
|      | ||||
|     if (compress) { | ||||
|         uint8_t *buf1, *buf2;  | ||||
|         int buf1_len, buf2_len; | ||||
|          | ||||
|         buf1_len = load_file(&buf1, fname); | ||||
|         unlink(fname); | ||||
|         buf2_len = lz_compress(&buf2, buf1, buf1_len); | ||||
|         if (buf2_len < 0) { | ||||
|             fprintf(stderr, "Could not compress file (UTF8 chars are forbidden)\n"); | ||||
|             exit(1); | ||||
|         } | ||||
|          | ||||
|         if (c_var) { | ||||
|             save_c_source(out_filename, buf2, buf2_len, c_var); | ||||
|         } else { | ||||
|             save_file(out_filename, buf2, buf2_len); | ||||
|         } | ||||
|         free(buf1); | ||||
|         free(buf2); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										5807
									
								
								deps/quickjs/libbf.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5807
									
								
								deps/quickjs/libbf.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										352
									
								
								deps/quickjs/libbf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								deps/quickjs/libbf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,352 @@ | ||||
| /* | ||||
|  * Tiny arbitrary precision floating point library | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef LIBBF_H | ||||
| #define LIBBF_H | ||||
|  | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #if defined(__x86_64__) | ||||
| #define LIMB_LOG2_BITS 6 | ||||
| #else | ||||
| #define LIMB_LOG2_BITS 5 | ||||
| #endif | ||||
|  | ||||
| #define LIMB_BITS (1 << LIMB_LOG2_BITS) | ||||
|  | ||||
| #if LIMB_BITS == 64 | ||||
| typedef __int128 int128_t; | ||||
| typedef unsigned __int128 uint128_t; | ||||
| typedef int64_t slimb_t; | ||||
| typedef uint64_t limb_t; | ||||
| typedef uint128_t dlimb_t; | ||||
| #define EXP_MIN INT64_MIN | ||||
| #define EXP_MAX INT64_MAX | ||||
|  | ||||
| #else | ||||
|  | ||||
| typedef int32_t slimb_t; | ||||
| typedef uint32_t limb_t; | ||||
| typedef uint64_t dlimb_t; | ||||
| #define EXP_MIN INT32_MIN | ||||
| #define EXP_MAX INT32_MAX | ||||
|  | ||||
| #endif | ||||
|  | ||||
| /* in bits */ | ||||
| #define BF_EXP_BITS_MIN 3 | ||||
| #define BF_EXP_BITS_MAX (LIMB_BITS - 2) | ||||
| #define BF_PREC_MIN 2 | ||||
| #define BF_PREC_MAX (((limb_t)1 << BF_EXP_BITS_MAX) - 2) | ||||
| #define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */ | ||||
|  | ||||
| #if LIMB_BITS == 64 | ||||
| #define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197)) | ||||
| #else | ||||
| #define BF_CHKSUM_MOD 975620677U | ||||
| #endif | ||||
|  | ||||
| #define BF_EXP_ZERO EXP_MIN | ||||
| #define BF_EXP_INF (EXP_MAX - 1) | ||||
| #define BF_EXP_NAN EXP_MAX | ||||
|  | ||||
| /* +/-zero is represented with expn = BF_EXP_ZERO and len = 0, | ||||
|    +/-infinity is represented with expn = BF_EXP_INF and len = 0, | ||||
|    NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored) | ||||
|  */ | ||||
| typedef struct { | ||||
|     struct bf_context_t *ctx; | ||||
|     int sign; | ||||
|     slimb_t expn; | ||||
|     limb_t len; | ||||
|     limb_t *tab; | ||||
| } bf_t; | ||||
|  | ||||
| typedef enum { | ||||
|     BF_RNDN, /* round to nearest, ties to even */ | ||||
|     BF_RNDZ, /* round to zero */ | ||||
|     BF_RNDD, /* round to -inf */ | ||||
|     BF_RNDU, /* round to +inf */ | ||||
|     BF_RNDNA, /* round to nearest, ties away from zero */ | ||||
|     BF_RNDNU, /* round to nearest, ties to +inf */ | ||||
|     BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU, | ||||
|                 inexact flag is always set)  */ | ||||
| } bf_rnd_t; | ||||
|  | ||||
| /* allow subnormal numbers (only available if the number of exponent | ||||
|    bits is < BF_EXP_BITS_MAX and prec != BF_PREC_INF) */ | ||||
| #define BF_FLAG_SUBNORMAL (1 << 3) | ||||
|  | ||||
| #define BF_RND_MASK 0x7 | ||||
| #define BF_EXP_BITS_SHIFT 4 | ||||
| #define BF_EXP_BITS_MASK 0x3f | ||||
|  | ||||
| /* contains the rounding mode and number of exponents bits */ | ||||
| typedef uint32_t bf_flags_t; | ||||
|  | ||||
| typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size); | ||||
|  | ||||
| typedef struct { | ||||
|     bf_t val; | ||||
|     limb_t prec; | ||||
| } BFConstCache; | ||||
|  | ||||
| typedef struct bf_context_t { | ||||
|     void *realloc_opaque; | ||||
|     bf_realloc_func_t *realloc_func; | ||||
|     BFConstCache log2_cache; | ||||
|     BFConstCache pi_cache; | ||||
|     struct BFNTTState *ntt_state; | ||||
| } bf_context_t; | ||||
|  | ||||
| static inline int bf_get_exp_bits(bf_flags_t flags) | ||||
| { | ||||
|     return BF_EXP_BITS_MAX - ((flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK); | ||||
| } | ||||
|  | ||||
| static inline bf_flags_t bf_set_exp_bits(int n) | ||||
| { | ||||
|     return (BF_EXP_BITS_MAX - n) << BF_EXP_BITS_SHIFT; | ||||
| } | ||||
|  | ||||
| /* returned status */ | ||||
| #define BF_ST_INVALID_OP  (1 << 0) | ||||
| #define BF_ST_DIVIDE_ZERO (1 << 1) | ||||
| #define BF_ST_OVERFLOW    (1 << 2) | ||||
| #define BF_ST_UNDERFLOW   (1 << 3) | ||||
| #define BF_ST_INEXACT     (1 << 4) | ||||
| /* not used yet, indicate that a memory allocation error occured. NaN | ||||
|    is returned */ | ||||
| #define BF_ST_MEM_ERROR   (1 << 5)  | ||||
|  | ||||
| #define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */ | ||||
|  | ||||
| static inline slimb_t bf_max(slimb_t a, slimb_t b) | ||||
| { | ||||
|     if (a > b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| static inline slimb_t bf_min(slimb_t a, slimb_t b) | ||||
| { | ||||
|     if (a < b) | ||||
|         return a; | ||||
|     else | ||||
|         return b; | ||||
| } | ||||
|  | ||||
| void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func, | ||||
|                      void *realloc_opaque); | ||||
| void bf_context_end(bf_context_t *s); | ||||
| /* free memory allocated for the bf cache data */ | ||||
| void bf_clear_cache(bf_context_t *s); | ||||
|  | ||||
| static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size) | ||||
| { | ||||
|     return s->realloc_func(s->realloc_opaque, ptr, size); | ||||
| } | ||||
|  | ||||
| void bf_init(bf_context_t *s, bf_t *r); | ||||
|  | ||||
| static inline void bf_delete(bf_t *r) | ||||
| { | ||||
|     bf_context_t *s = r->ctx; | ||||
|     /* we accept to delete a zeroed bf_t structure */ | ||||
|     if (s) { | ||||
|         bf_realloc(s, r->tab, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static inline void bf_neg(bf_t *r) | ||||
| { | ||||
|     r->sign ^= 1; | ||||
| } | ||||
|  | ||||
| static inline int bf_is_finite(const bf_t *a) | ||||
| { | ||||
|     return (a->expn < BF_EXP_INF); | ||||
| } | ||||
|  | ||||
| static inline int bf_is_nan(const bf_t *a) | ||||
| { | ||||
|     return (a->expn == BF_EXP_NAN); | ||||
| } | ||||
|  | ||||
| static inline int bf_is_zero(const bf_t *a) | ||||
| { | ||||
|     return (a->expn == BF_EXP_ZERO); | ||||
| } | ||||
|  | ||||
| void bf_set_ui(bf_t *r, uint64_t a); | ||||
| void bf_set_si(bf_t *r, int64_t a); | ||||
| void bf_set_nan(bf_t *r); | ||||
| void bf_set_zero(bf_t *r, int is_neg); | ||||
| void bf_set_inf(bf_t *r, int is_neg); | ||||
| void bf_set(bf_t *r, const bf_t *a); | ||||
| void bf_move(bf_t *r, bf_t *a); | ||||
| int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode); | ||||
| void bf_set_float64(bf_t *a, double d); | ||||
|  | ||||
| int bf_cmpu(const bf_t *a, const bf_t *b); | ||||
| int bf_cmp_full(const bf_t *a, const bf_t *b); | ||||
| int bf_cmp_eq(const bf_t *a, const bf_t *b); | ||||
| int bf_cmp_le(const bf_t *a, const bf_t *b); | ||||
| int bf_cmp_lt(const bf_t *a, const bf_t *b); | ||||
| int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); | ||||
| int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); | ||||
| int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags); | ||||
| int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); | ||||
| int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags); | ||||
| int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,  | ||||
|               bf_flags_t flags); | ||||
| int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags); | ||||
| int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); | ||||
| #define BF_DIVREM_EUCLIDIAN BF_RNDF | ||||
| int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, | ||||
|               limb_t prec, bf_flags_t flags, int rnd_mode); | ||||
| int bf_fmod(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, | ||||
|             bf_flags_t flags); | ||||
| int bf_remainder(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, | ||||
|                  bf_flags_t flags); | ||||
| int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, | ||||
|               bf_flags_t flags); | ||||
| int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec, | ||||
|               bf_flags_t flags); | ||||
| int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b, limb_t prec, bf_flags_t flags); | ||||
| int bf_rint(bf_t *r, limb_t prec, bf_flags_t flags); | ||||
| int bf_round(bf_t *r, limb_t prec, bf_flags_t flags); | ||||
| int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a); | ||||
| int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| slimb_t bf_get_exp_min(const bf_t *a); | ||||
| void bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b); | ||||
| void bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b); | ||||
| void bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b); | ||||
|  | ||||
| /* additional flags for bf_atof */ | ||||
| /* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */ | ||||
| #define BF_ATOF_NO_HEX       (1 << 16) | ||||
| /* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */ | ||||
| #define BF_ATOF_BIN_OCT      (1 << 17) | ||||
| /* Only accept integers (no decimal point, no exponent, no infinity nor NaN */ | ||||
| #define BF_ATOF_INT_ONLY     (1 << 18) | ||||
| /* Do not accept radix prefix after sign  */ | ||||
| #define BF_ATOF_NO_PREFIX_AFTER_SIGN (1 << 19) | ||||
| /* Do not parse NaN and parse case sensitive 'Infinity' */ | ||||
| #define BF_ATOF_JS_QUIRKS    (1 << 20) | ||||
| /* Do not round integers to the indicated precision */ | ||||
| #define BF_ATOF_INT_PREC_INF (1 << 21) | ||||
| /* Support legacy octal syntax for well formed numbers */ | ||||
| #define BF_ATOF_LEGACY_OCTAL (1 << 22) | ||||
| /* accept _ between digits as a digit separator */ | ||||
| #define BF_ATOF_UNDERSCORE_SEP (1 << 23) | ||||
| /* if a 'n' suffix is present, force integer parsing (XXX: remove) */ | ||||
| #define BF_ATOF_INT_N_SUFFIX   (1 << 24) | ||||
| /* if set return NaN if empty number string (instead of 0) */ | ||||
| #define BF_ATOF_NAN_IF_EMPTY   (1 << 25) | ||||
| /* only accept decimal floating point if radix = 0 */ | ||||
| #define BF_ATOF_ONLY_DEC_FLOAT (1 << 26) | ||||
|  | ||||
| /* additional return flags */ | ||||
| /* indicate that the parsed number is an integer (only set when the | ||||
|    flags BF_ATOF_INT_PREC_INF or BF_ATOF_INT_N_SUFFIX are used) */ | ||||
| #define BF_ATOF_ST_INTEGER   (1 << 5) | ||||
| /* integer parsed as legacy octal */ | ||||
| #define BF_ATOF_ST_LEGACY_OCTAL (1 << 6) | ||||
|  | ||||
| int bf_atof(bf_t *a, const char *str, const char **pnext, int radix, | ||||
|             limb_t prec, bf_flags_t flags); | ||||
| /* this version accepts prec = BF_PREC_INF and returns the radix | ||||
|    exponent */ | ||||
| int bf_atof2(bf_t *r, slimb_t *pexponent, | ||||
|              const char *str, const char **pnext, int radix, | ||||
|              limb_t prec, bf_flags_t flags); | ||||
| int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix, | ||||
|                      slimb_t expn, limb_t prec, bf_flags_t flags); | ||||
|  | ||||
| #define BF_FTOA_FORMAT_MASK (3 << 16) | ||||
| /* fixed format: prec significant digits rounded with (flags & | ||||
|    BF_RND_MASK). Exponential notation is used if too many zeros are | ||||
|    needed. */ | ||||
| #define BF_FTOA_FORMAT_FIXED (0 << 16) | ||||
| /* fractional format: prec digits after the decimal point rounded with | ||||
|    (flags & BF_RND_MASK) */ | ||||
| #define BF_FTOA_FORMAT_FRAC  (1 << 16) | ||||
| /* free format: use as many digits as necessary so that bf_atof() | ||||
|    return the same number when using precision 'prec', rounding to | ||||
|    nearest and the subnormal+exponent configuration of 'flags'. The | ||||
|    result is meaningful only if 'a' is already rounded to the wanted | ||||
|    precision. | ||||
|     | ||||
|    Infinite precision (BF_PREC_INF) is supported when the radix is a | ||||
|    power of two. */ | ||||
| #define BF_FTOA_FORMAT_FREE  (2 << 16) | ||||
| /* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits | ||||
|    (takes more computation time). */ | ||||
| #define BF_FTOA_FORMAT_FREE_MIN (3 << 16) | ||||
|  | ||||
| /* force exponential notation for fixed or free format */ | ||||
| #define BF_FTOA_FORCE_EXP    (1 << 20) | ||||
| /* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for | ||||
|    base 2 if non zero value */ | ||||
| #define BF_FTOA_ADD_PREFIX   (1 << 21) | ||||
| #define BF_FTOA_JS_QUIRKS    (1 << 22) | ||||
|  | ||||
| size_t bf_ftoa(char **pbuf, const bf_t *a, int radix, limb_t prec, | ||||
|                bf_flags_t flags); | ||||
|  | ||||
| /* modulo 2^n instead of saturation. NaN and infinity return 0 */ | ||||
| #define BF_GET_INT_MOD (1 << 0)  | ||||
| int bf_get_int32(int *pres, const bf_t *a, int flags); | ||||
| int bf_get_int64(int64_t *pres, const bf_t *a, int flags); | ||||
|  | ||||
| /* the following functions are exported for testing only. */ | ||||
| void bf_print_str(const char *str, const bf_t *a); | ||||
| void bf_resize(bf_t *r, limb_t len); | ||||
| int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len); | ||||
| void bf_recip(bf_t *r, const bf_t *a, limb_t prec); | ||||
| void bf_rsqrt(bf_t *a, const bf_t *x, limb_t prec); | ||||
| int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags); | ||||
| int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k); | ||||
| slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, | ||||
|                           int is_ceil1); | ||||
|  | ||||
| /* transcendental functions */ | ||||
| int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags); | ||||
| int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags); | ||||
| int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| #define BF_POW_JS_QUICKS (1 << 16) | ||||
| int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags); | ||||
| int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x, | ||||
|              limb_t prec, bf_flags_t flags); | ||||
| int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
| int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); | ||||
|  | ||||
| #endif /* LIBBF_H */ | ||||
							
								
								
									
										58
									
								
								deps/quickjs/libregexp-opcode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								deps/quickjs/libregexp-opcode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* | ||||
|  * Regular Expression Engine | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #ifdef DEF | ||||
|  | ||||
| DEF(invalid, 1) /* never used */ | ||||
| DEF(char, 3) | ||||
| DEF(char32, 5) | ||||
| DEF(dot, 1) | ||||
| DEF(any, 1) /* same as dot but match any character including line terminator */ | ||||
| DEF(line_start, 1) | ||||
| DEF(line_end, 1) | ||||
| DEF(goto, 5) | ||||
| DEF(split_goto_first, 5) | ||||
| DEF(split_next_first, 5) | ||||
| DEF(match, 1) | ||||
| DEF(save_start, 2) /* save start position */ | ||||
| DEF(save_end, 2) /* save end position, must come after saved_start */ | ||||
| DEF(save_reset, 3) /* reset save positions */ | ||||
| DEF(loop, 5) /* decrement the top the stack and goto if != 0 */ | ||||
| DEF(push_i32, 5) /* push integer on the stack */ | ||||
| DEF(drop, 1) | ||||
| DEF(word_boundary, 1) | ||||
| DEF(not_word_boundary, 1) | ||||
| DEF(back_reference, 2) | ||||
| DEF(backward_back_reference, 2) /* must come after back_reference */ | ||||
| DEF(range, 3) /* variable length */ | ||||
| DEF(range32, 3) /* variable length */ | ||||
| DEF(lookahead, 5) | ||||
| DEF(negative_lookahead, 5) | ||||
| 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 | ||||
|  position */ | ||||
| DEF(prev, 1) /* go to the previous char */ | ||||
| DEF(simple_greedy_quant, 17) | ||||
|  | ||||
| #endif /* DEF */ | ||||
							
								
								
									
										2541
									
								
								deps/quickjs/libregexp.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2541
									
								
								deps/quickjs/libregexp.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										91
									
								
								deps/quickjs/libregexp.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								deps/quickjs/libregexp.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| /* | ||||
|  * Regular Expression Engine | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef LIBREGEXP_H | ||||
| #define LIBREGEXP_H | ||||
|  | ||||
| #include <stddef.h> | ||||
|  | ||||
| #include "libunicode.h" | ||||
|  | ||||
| #define LRE_BOOL  int       /* for documentation purposes */ | ||||
|  | ||||
| #define LRE_FLAG_GLOBAL     (1 << 0) | ||||
| #define LRE_FLAG_IGNORECASE (1 << 1) | ||||
| #define LRE_FLAG_MULTILINE  (1 << 2) | ||||
| #define LRE_FLAG_DOTALL     (1 << 3) | ||||
| #define LRE_FLAG_UTF16      (1 << 4) | ||||
| #define LRE_FLAG_STICKY     (1 << 5) | ||||
|  | ||||
| #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */ | ||||
|  | ||||
| uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, | ||||
|                      const char *buf, size_t buf_len, int re_flags, | ||||
|                      void *opaque); | ||||
| int lre_get_capture_count(const uint8_t *bc_buf); | ||||
| int lre_get_flags(const uint8_t *bc_buf); | ||||
| int lre_exec(uint8_t **capture, | ||||
|              const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen, | ||||
|              int cbuf_type, void *opaque); | ||||
|  | ||||
| int lre_parse_escape(const uint8_t **pp, int allow_utf16); | ||||
| LRE_BOOL lre_is_space(int c); | ||||
|  | ||||
| /* must be provided by the user */ | ||||
| LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);  | ||||
| void *lre_realloc(void *opaque, void *ptr, size_t size); | ||||
|  | ||||
| /* JS identifier test */ | ||||
| extern uint32_t const lre_id_start_table_ascii[4]; | ||||
| extern uint32_t const lre_id_continue_table_ascii[4]; | ||||
|  | ||||
| static inline int lre_js_is_ident_first(int c) | ||||
| { | ||||
|     if ((uint32_t)c < 128) { | ||||
|         return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1; | ||||
|     } else { | ||||
| #ifdef CONFIG_ALL_UNICODE | ||||
|         return lre_is_id_start(c); | ||||
| #else | ||||
|         return !lre_is_space(c); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| static inline int lre_js_is_ident_next(int c) | ||||
| { | ||||
|     if ((uint32_t)c < 128) { | ||||
|         return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; | ||||
|     } else { | ||||
|         /* ZWNJ and ZWJ are accepted in identifiers */ | ||||
| #ifdef CONFIG_ALL_UNICODE | ||||
|         return lre_is_id_continue(c) || c == 0x200C || c == 0x200D; | ||||
| #else | ||||
|         return !lre_is_space(c) || c == 0x200C || c == 0x200D; | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| #undef LRE_BOOL | ||||
|  | ||||
| #endif /* LIBREGEXP_H */ | ||||
							
								
								
									
										4313
									
								
								deps/quickjs/libunicode-table.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4313
									
								
								deps/quickjs/libunicode-table.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1538
									
								
								deps/quickjs/libunicode.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1538
									
								
								deps/quickjs/libunicode.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										124
									
								
								deps/quickjs/libunicode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								deps/quickjs/libunicode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| /* | ||||
|  * Unicode utilities | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef LIBUNICODE_H | ||||
| #define LIBUNICODE_H | ||||
|  | ||||
| #include <inttypes.h> | ||||
|  | ||||
| #define LRE_BOOL  int       /* for documentation purposes */ | ||||
|  | ||||
| /* define it to include all the unicode tables (40KB larger) */ | ||||
| #define CONFIG_ALL_UNICODE | ||||
|  | ||||
| #define LRE_CC_RES_LEN_MAX 3 | ||||
|  | ||||
| typedef enum { | ||||
|     UNICODE_NFC, | ||||
|     UNICODE_NFD, | ||||
|     UNICODE_NFKC, | ||||
|     UNICODE_NFKD, | ||||
| } UnicodeNormalizationEnum; | ||||
|  | ||||
| int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); | ||||
| LRE_BOOL lre_is_cased(uint32_t c); | ||||
| LRE_BOOL lre_is_case_ignorable(uint32_t c); | ||||
|  | ||||
| /* char ranges */ | ||||
|  | ||||
| typedef struct { | ||||
|     int len; /* in points, always even */ | ||||
|     int size; | ||||
|     uint32_t *points; /* points sorted by increasing value */ | ||||
|     void *mem_opaque; | ||||
|     void *(*realloc_func)(void *opaque, void *ptr, size_t size); | ||||
| } CharRange; | ||||
|  | ||||
| typedef enum { | ||||
|     CR_OP_UNION, | ||||
|     CR_OP_INTER, | ||||
|     CR_OP_XOR, | ||||
| } CharRangeOpEnum; | ||||
|  | ||||
| void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); | ||||
| void cr_free(CharRange *cr); | ||||
| int cr_realloc(CharRange *cr, int size); | ||||
| int cr_copy(CharRange *cr, const CharRange *cr1); | ||||
|  | ||||
| static inline int cr_add_point(CharRange *cr, uint32_t v) | ||||
| { | ||||
|     if (cr->len >= cr->size) { | ||||
|         if (cr_realloc(cr, cr->len + 1)) | ||||
|             return -1; | ||||
|     } | ||||
|     cr->points[cr->len++] = v; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2) | ||||
| { | ||||
|     if ((cr->len + 2) > cr->size) { | ||||
|         if (cr_realloc(cr, cr->len + 2)) | ||||
|             return -1; | ||||
|     } | ||||
|     cr->points[cr->len++] = c1; | ||||
|     cr->points[cr->len++] = c2; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len); | ||||
|  | ||||
| static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2) | ||||
| { | ||||
|     uint32_t b_pt[2]; | ||||
|     b_pt[0] = c1; | ||||
|     b_pt[1] = c2 + 1; | ||||
|     return cr_union1(cr, b_pt, 2); | ||||
| } | ||||
|  | ||||
| int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, | ||||
|           const uint32_t *b_pt, int b_len, int op); | ||||
|  | ||||
| int cr_invert(CharRange *cr); | ||||
|  | ||||
| #ifdef CONFIG_ALL_UNICODE | ||||
|  | ||||
| LRE_BOOL lre_is_id_start(uint32_t c); | ||||
| LRE_BOOL lre_is_id_continue(uint32_t c); | ||||
|  | ||||
| int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, | ||||
|                       UnicodeNormalizationEnum n_type, | ||||
|                       void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); | ||||
|  | ||||
| /* Unicode character range functions */ | ||||
|  | ||||
| int unicode_script(CharRange *cr, | ||||
|                    const char *script_name, LRE_BOOL is_ext); | ||||
| int unicode_general_category(CharRange *cr, const char *gc_name); | ||||
| int unicode_prop(CharRange *cr, const char *prop_name); | ||||
|  | ||||
| #endif /* CONFIG_ALL_UNICODE */ | ||||
|  | ||||
| #undef LRE_BOOL | ||||
|  | ||||
| #endif /* LIBUNICODE_H */ | ||||
							
								
								
									
										100
									
								
								deps/quickjs/list.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								deps/quickjs/list.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| /* | ||||
|  * Linux klist like system | ||||
|  *  | ||||
|  * Copyright (c) 2016-2017 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef LIST_H | ||||
| #define LIST_H | ||||
|  | ||||
| #ifndef NULL | ||||
| #include <stddef.h> | ||||
| #endif | ||||
|  | ||||
| struct list_head { | ||||
|     struct list_head *prev; | ||||
|     struct list_head *next; | ||||
| }; | ||||
|  | ||||
| #define LIST_HEAD_INIT(el) { &(el), &(el) } | ||||
|  | ||||
| /* return the pointer of type 'type *' containing 'el' as field 'member' */ | ||||
| #define list_entry(el, type, member) \ | ||||
|     ((type *)((uint8_t *)(el) - offsetof(type, member))) | ||||
|  | ||||
| static inline void init_list_head(struct list_head *head) | ||||
| { | ||||
|     head->prev = head; | ||||
|     head->next = head; | ||||
| } | ||||
|  | ||||
| /* insert 'el' between 'prev' and 'next' */ | ||||
| static inline void __list_add(struct list_head *el,  | ||||
|                               struct list_head *prev, struct list_head *next) | ||||
| { | ||||
|     prev->next = el; | ||||
|     el->prev = prev; | ||||
|     el->next = next; | ||||
|     next->prev = el; | ||||
| } | ||||
|  | ||||
| /* add 'el' at the head of the list 'head' (= after element head) */ | ||||
| static inline void list_add(struct list_head *el, struct list_head *head) | ||||
| { | ||||
|     __list_add(el, head, head->next); | ||||
| } | ||||
|  | ||||
| /* add 'el' at the end of the list 'head' (= before element head) */ | ||||
| static inline void list_add_tail(struct list_head *el, struct list_head *head) | ||||
| { | ||||
|     __list_add(el, head->prev, head); | ||||
| } | ||||
|  | ||||
| static inline void list_del(struct list_head *el) | ||||
| { | ||||
|     struct list_head *prev, *next; | ||||
|     prev = el->prev; | ||||
|     next = el->next; | ||||
|     prev->next = next; | ||||
|     next->prev = prev; | ||||
|     el->prev = NULL; /* fail safe */ | ||||
|     el->next = NULL; /* fail safe */ | ||||
| } | ||||
|  | ||||
| static inline int list_empty(struct list_head *el) | ||||
| { | ||||
|     return el->next == el; | ||||
| } | ||||
|  | ||||
| #define list_for_each(el, head) \ | ||||
|   for(el = (head)->next; el != (head); el = el->next) | ||||
|  | ||||
| #define list_for_each_safe(el, el1, head)                \ | ||||
|     for(el = (head)->next, el1 = el->next; el != (head); \ | ||||
|         el = el1, el1 = el->next) | ||||
|  | ||||
| #define list_for_each_prev(el, head) \ | ||||
|   for(el = (head)->prev; el != (head); el = el->prev) | ||||
|  | ||||
| #define list_for_each_prev_safe(el, el1, head)           \ | ||||
|     for(el = (head)->prev, el1 = el->prev; el != (head); \ | ||||
|         el = el1, el1 = el->prev) | ||||
|  | ||||
| #endif /* LIST_H */ | ||||
							
								
								
									
										485
									
								
								deps/quickjs/qjs.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										485
									
								
								deps/quickjs/qjs.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,485 @@ | ||||
| /* | ||||
|  * QuickJS stand alone interpreter | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * Copyright (c) 2017-2018 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <inttypes.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <time.h> | ||||
| #if defined(__APPLE__) | ||||
| #include <malloc/malloc.h> | ||||
| #elif defined(__linux__) | ||||
| #include <malloc.h> | ||||
| #endif | ||||
|  | ||||
| #include "cutils.h" | ||||
| #include "quickjs-libc.h" | ||||
|  | ||||
| extern const uint8_t qjsc_repl[]; | ||||
| extern const uint32_t qjsc_repl_size; | ||||
| #ifdef CONFIG_BIGNUM | ||||
| extern const uint8_t qjsc_qjscalc[]; | ||||
| extern const uint32_t qjsc_qjscalc_size; | ||||
| #endif | ||||
|  | ||||
| static int eval_buf(JSContext *ctx, const void *buf, int buf_len, | ||||
|                     const char *filename, int eval_flags) | ||||
| { | ||||
|     JSValue val; | ||||
|     int ret; | ||||
|  | ||||
|     if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) { | ||||
|         /* for the modules, we compile then run to be able to set | ||||
|            import.meta */ | ||||
|         val = JS_Eval(ctx, buf, buf_len, filename, | ||||
|                       eval_flags | JS_EVAL_FLAG_COMPILE_ONLY); | ||||
|         if (!JS_IsException(val)) { | ||||
|             js_module_set_import_meta(ctx, val, TRUE, TRUE); | ||||
|             val = JS_EvalFunction(ctx, val); | ||||
|         } | ||||
|     } else { | ||||
|         val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); | ||||
|     } | ||||
|     if (JS_IsException(val)) { | ||||
|         js_std_dump_error(ctx); | ||||
|         ret = -1; | ||||
|     } else { | ||||
|         ret = 0; | ||||
|     } | ||||
|     JS_FreeValue(ctx, val); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int eval_file(JSContext *ctx, const char *filename, int module) | ||||
| { | ||||
|     uint8_t *buf; | ||||
|     int ret, eval_flags; | ||||
|     size_t buf_len; | ||||
|      | ||||
|     buf = js_load_file(ctx, &buf_len, filename); | ||||
|     if (!buf) { | ||||
|         perror(filename); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     if (module < 0) { | ||||
|         module = (has_suffix(filename, ".mjs") || | ||||
|                   JS_DetectModule((const char *)buf, buf_len)); | ||||
|     } | ||||
|     if (module) | ||||
|         eval_flags = JS_EVAL_TYPE_MODULE; | ||||
|     else | ||||
|         eval_flags = JS_EVAL_TYPE_GLOBAL; | ||||
|     ret = eval_buf(ctx, buf, buf_len, filename, eval_flags); | ||||
|     js_free(ctx, buf); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| #if defined(__APPLE__) | ||||
| #define MALLOC_OVERHEAD  0 | ||||
| #else | ||||
| #define MALLOC_OVERHEAD  8 | ||||
| #endif | ||||
|  | ||||
| struct trace_malloc_data { | ||||
|     uint8_t *base; | ||||
| }; | ||||
|  | ||||
| static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr, | ||||
|                                                 struct trace_malloc_data *dp) | ||||
| { | ||||
|     return ptr - dp->base; | ||||
| } | ||||
|  | ||||
| /* default memory allocation functions with memory limitation */ | ||||
| static inline size_t js_trace_malloc_usable_size(void *ptr) | ||||
| { | ||||
| #if defined(__APPLE__) | ||||
|     return malloc_size(ptr); | ||||
| #elif defined(_WIN32) | ||||
|     return _msize(ptr); | ||||
| #elif defined(EMSCRIPTEN) | ||||
|     return 0; | ||||
| #elif defined(__linux__) | ||||
|     return malloc_usable_size(ptr); | ||||
| #else | ||||
|     /* change this to `return 0;` if compilation fails */ | ||||
|     return malloc_usable_size(ptr); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void __attribute__((format(printf, 2, 3))) | ||||
|     js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...) | ||||
| { | ||||
|     va_list ap; | ||||
|     int c; | ||||
|  | ||||
|     va_start(ap, fmt); | ||||
|     while ((c = *fmt++) != '\0') { | ||||
|         if (c == '%') { | ||||
|             /* only handle %p and %zd */ | ||||
|             if (*fmt == 'p') { | ||||
|                 uint8_t *ptr = va_arg(ap, void *); | ||||
|                 if (ptr == NULL) { | ||||
|                     printf("NULL"); | ||||
|                 } else { | ||||
|                     printf("H%+06lld.%zd", | ||||
|                            js_trace_malloc_ptr_offset(ptr, s->opaque), | ||||
|                            js_trace_malloc_usable_size(ptr)); | ||||
|                 } | ||||
|                 fmt++; | ||||
|                 continue; | ||||
|             } | ||||
|             if (fmt[0] == 'z' && fmt[1] == 'd') { | ||||
|                 size_t sz = va_arg(ap, size_t); | ||||
|                 printf("%zd", sz); | ||||
|                 fmt += 2; | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|         putc(c, stdout); | ||||
|     } | ||||
|     va_end(ap); | ||||
| } | ||||
|  | ||||
| static void js_trace_malloc_init(struct trace_malloc_data *s) | ||||
| { | ||||
|     free(s->base = malloc(8)); | ||||
| } | ||||
|  | ||||
| static void *js_trace_malloc(JSMallocState *s, size_t size) | ||||
| { | ||||
|     void *ptr; | ||||
|  | ||||
|     /* Do not allocate zero bytes: behavior is platform dependent */ | ||||
|     assert(size != 0); | ||||
|  | ||||
|     if (unlikely(s->malloc_size + size > s->malloc_limit)) | ||||
|         return NULL; | ||||
|     ptr = malloc(size); | ||||
|     js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr); | ||||
|     if (ptr) { | ||||
|         s->malloc_count++; | ||||
|         s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; | ||||
|     } | ||||
|     return ptr; | ||||
| } | ||||
|  | ||||
| static void js_trace_free(JSMallocState *s, void *ptr) | ||||
| { | ||||
|     if (!ptr) | ||||
|         return; | ||||
|  | ||||
|     js_trace_malloc_printf(s, "F %p\n", ptr); | ||||
|     s->malloc_count--; | ||||
|     s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; | ||||
|     free(ptr); | ||||
| } | ||||
|  | ||||
| static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size) | ||||
| { | ||||
|     size_t old_size; | ||||
|  | ||||
|     if (!ptr) { | ||||
|         if (size == 0) | ||||
|             return NULL; | ||||
|         return js_trace_malloc(s, size); | ||||
|     } | ||||
|     old_size = js_trace_malloc_usable_size(ptr); | ||||
|     if (size == 0) { | ||||
|         js_trace_malloc_printf(s, "R %zd %p\n", size, ptr); | ||||
|         s->malloc_count--; | ||||
|         s->malloc_size -= old_size + MALLOC_OVERHEAD; | ||||
|         free(ptr); | ||||
|         return NULL; | ||||
|     } | ||||
|     if (s->malloc_size + size - old_size > s->malloc_limit) | ||||
|         return NULL; | ||||
|  | ||||
|     js_trace_malloc_printf(s, "R %zd %p", size, ptr); | ||||
|  | ||||
|     ptr = realloc(ptr, size); | ||||
|     js_trace_malloc_printf(s, " -> %p\n", ptr); | ||||
|     if (ptr) { | ||||
|         s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size; | ||||
|     } | ||||
|     return ptr; | ||||
| } | ||||
|  | ||||
| static const JSMallocFunctions trace_mf = { | ||||
|     js_trace_malloc, | ||||
|     js_trace_free, | ||||
|     js_trace_realloc, | ||||
| #if defined(__APPLE__) | ||||
|     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 | ||||
| }; | ||||
|  | ||||
| #ifdef CONFIG_BIGNUM | ||||
| #define PROG_NAME "qjsbn" | ||||
| #else | ||||
| #define PROG_NAME "qjs" | ||||
| #endif | ||||
|  | ||||
| void help(void) | ||||
| { | ||||
|     printf("QuickJS version " CONFIG_VERSION "\n" | ||||
|            "usage: " PROG_NAME " [options] [file]\n" | ||||
|            "-h  --help         list options\n" | ||||
|            "-e  --eval EXPR    evaluate EXPR\n" | ||||
|            "-i  --interactive  go to interactive mode\n" | ||||
|            "-m  --module       load as ES6 module (default=autodetect)\n" | ||||
|            "    --script       load as ES6 script (default=autodetect)\n" | ||||
|            "    --std          make 'std' and 'os' available to the loaded script\n" | ||||
| #ifdef CONFIG_BIGNUM | ||||
|            "    --qjscalc      load the QJSCalc runtime (default if invoked as qjscalc)\n" | ||||
| #endif | ||||
|            "-T  --trace        trace memory allocation\n" | ||||
|            "-d  --dump         dump the memory usage stats\n" | ||||
|            "-q  --quit         just instantiate the interpreter and quit\n"); | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     JSRuntime *rt; | ||||
|     JSContext *ctx; | ||||
|     struct trace_malloc_data trace_data = { NULL }; | ||||
|     int optind; | ||||
|     char *expr = NULL; | ||||
|     int interactive = 0; | ||||
|     int dump_memory = 0; | ||||
|     int trace_memory = 0; | ||||
|     int empty_run = 0; | ||||
|     int module = -1; | ||||
|     int load_std = 0; | ||||
| #ifdef CONFIG_BIGNUM | ||||
|     int load_jscalc; | ||||
| #endif | ||||
|  | ||||
| #ifdef CONFIG_BIGNUM | ||||
|     /* load jscalc runtime if invoked as 'qjscalc' */ | ||||
|     { | ||||
|         const char *p, *exename; | ||||
|         exename = argv[0]; | ||||
|         p = strrchr(exename, '/'); | ||||
|         if (p) | ||||
|             exename = p + 1; | ||||
|         load_jscalc = !strcmp(exename, "qjscalc"); | ||||
|     } | ||||
| #endif | ||||
|      | ||||
|     /* cannot use getopt because we want to pass the command line to | ||||
|        the script */ | ||||
|     optind = 1; | ||||
|     while (optind < argc && *argv[optind] == '-') { | ||||
|         char *arg = argv[optind] + 1; | ||||
|         const char *longopt = ""; | ||||
|         /* a single - is not an option, it also stops argument scanning */ | ||||
|         if (!*arg) | ||||
|             break; | ||||
|         optind++; | ||||
|         if (*arg == '-') { | ||||
|             longopt = arg + 1; | ||||
|             arg += strlen(arg); | ||||
|             /* -- stops argument scanning */ | ||||
|             if (!*longopt) | ||||
|                 break; | ||||
|         } | ||||
|         for (; *arg || *longopt; longopt = "") { | ||||
|             char opt = *arg; | ||||
|             if (opt) | ||||
|                 arg++; | ||||
|             if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { | ||||
|                 help(); | ||||
|                 continue; | ||||
|             } | ||||
|             if (opt == 'e' || !strcmp(longopt, "eval")) { | ||||
|                 if (*arg) { | ||||
|                     expr = arg; | ||||
|                     break; | ||||
|                 } | ||||
|                 if (optind < argc) { | ||||
|                     expr = argv[optind++]; | ||||
|                     break; | ||||
|                 } | ||||
|                 fprintf(stderr, "qjs: missing expression for -e\n"); | ||||
|                 exit(2); | ||||
|             } | ||||
|             if (opt == 'i' || !strcmp(longopt, "interactive")) { | ||||
|                 interactive++; | ||||
|                 continue; | ||||
|             } | ||||
|             if (opt == 'm' || !strcmp(longopt, "module")) { | ||||
|                 module = 1; | ||||
|                 continue; | ||||
|             } | ||||
|             if (!strcmp(longopt, "script")) { | ||||
|                 module = 0; | ||||
|                 continue; | ||||
|             } | ||||
|             if (opt == 'd' || !strcmp(longopt, "dump")) { | ||||
|                 dump_memory++; | ||||
|                 continue; | ||||
|             } | ||||
|             if (opt == 'T' || !strcmp(longopt, "trace")) { | ||||
|                 trace_memory++; | ||||
|                 continue; | ||||
|             } | ||||
|             if (!strcmp(longopt, "std")) { | ||||
|                 load_std = 1; | ||||
|                 continue; | ||||
|             } | ||||
| #ifdef CONFIG_BIGNUM | ||||
|             if (!strcmp(longopt, "qjscalc")) { | ||||
|                 load_jscalc = 1; | ||||
|                 continue; | ||||
|             } | ||||
| #endif | ||||
|             if (opt == 'q' || !strcmp(longopt, "quit")) { | ||||
|                 empty_run++; | ||||
|                 continue; | ||||
|             } | ||||
|             if (opt) { | ||||
|                 fprintf(stderr, "qjs: unknown option '-%c'\n", opt); | ||||
|             } else { | ||||
|                 fprintf(stderr, "qjs: unknown option '--%s'\n", longopt); | ||||
|             } | ||||
|             help(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (trace_memory) { | ||||
|         js_trace_malloc_init(&trace_data); | ||||
|         rt = JS_NewRuntime2(&trace_mf, &trace_data); | ||||
|     } else { | ||||
|         rt = JS_NewRuntime(); | ||||
|     } | ||||
|     if (!rt) { | ||||
|         fprintf(stderr, "qjs: cannot allocate JS runtime\n"); | ||||
|         exit(2); | ||||
|     } | ||||
|     ctx = JS_NewContext(rt); | ||||
|     if (!ctx) { | ||||
|         fprintf(stderr, "qjs: cannot allocate JS context\n"); | ||||
|         exit(2); | ||||
|     } | ||||
|  | ||||
|     /* loader for ES6 modules */ | ||||
|     JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); | ||||
|                             | ||||
|     if (!empty_run) { | ||||
| #ifdef CONFIG_BIGNUM | ||||
|         if (load_jscalc) { | ||||
|             js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0); | ||||
|         } | ||||
| #endif | ||||
|         js_std_add_helpers(ctx, argc - optind, argv + optind); | ||||
|  | ||||
|         /* system modules */ | ||||
|         js_init_module_std(ctx, "std"); | ||||
|         js_init_module_os(ctx, "os"); | ||||
|  | ||||
|         /* make 'std' and 'os' visible to non module code */ | ||||
|         if (load_std) { | ||||
|             const char *str = "import * as std from 'std';\n" | ||||
|                 "import * as os from 'os';\n" | ||||
|                 "globalThis.std = std;\n" | ||||
|                 "globalThis.os = os;\n"; | ||||
|             eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE); | ||||
|         } | ||||
|  | ||||
|         if (expr) { | ||||
|             if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", 0)) | ||||
|                 goto fail; | ||||
|         } else | ||||
|         if (optind >= argc) { | ||||
|             /* interactive mode */ | ||||
|             interactive = 1; | ||||
|         } else { | ||||
|             const char *filename; | ||||
|             filename = argv[optind]; | ||||
|             if (eval_file(ctx, filename, module)) | ||||
|                 goto fail; | ||||
|         } | ||||
|         if (interactive) { | ||||
|             js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0); | ||||
|         } | ||||
|         js_std_loop(ctx); | ||||
|     } | ||||
|      | ||||
|     if (dump_memory) { | ||||
|         JSMemoryUsage stats; | ||||
|         JS_ComputeMemoryUsage(rt, &stats); | ||||
|         JS_DumpMemoryUsage(stdout, &stats, rt); | ||||
|     } | ||||
|     js_std_free_handlers(rt); | ||||
|     JS_FreeContext(ctx); | ||||
|     JS_FreeRuntime(rt); | ||||
|  | ||||
|     if (empty_run && dump_memory) { | ||||
|         clock_t t[5]; | ||||
|         double best[5]; | ||||
|         int i, j; | ||||
|         for (i = 0; i < 100; i++) { | ||||
|             t[0] = clock(); | ||||
|             rt = JS_NewRuntime(); | ||||
|             t[1] = clock(); | ||||
|             ctx = JS_NewContext(rt); | ||||
|             t[2] = clock(); | ||||
|             JS_FreeContext(ctx); | ||||
|             t[3] = clock(); | ||||
|             JS_FreeRuntime(rt); | ||||
|             t[4] = clock(); | ||||
|             for (j = 4; j > 0; j--) { | ||||
|                 double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC; | ||||
|                 if (i == 0 || best[j] > ms) | ||||
|                     best[j] = ms; | ||||
|             } | ||||
|         } | ||||
|         printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n", | ||||
|                best[1] + best[2] + best[3] + best[4], | ||||
|                best[1], best[2], best[3], best[4]); | ||||
|     } | ||||
|     return 0; | ||||
|  fail: | ||||
|     js_std_free_handlers(rt); | ||||
|     JS_FreeContext(ctx); | ||||
|     JS_FreeRuntime(rt); | ||||
|     return 1; | ||||
| } | ||||
							
								
								
									
										696
									
								
								deps/quickjs/qjsc.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										696
									
								
								deps/quickjs/qjsc.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,696 @@ | ||||
| /* | ||||
|  * QuickJS command line compiler | ||||
|  *  | ||||
|  * Copyright (c) 2018-2019 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <inttypes.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
| #if !defined(_WIN32) | ||||
| #include <sys/wait.h> | ||||
| #endif | ||||
|  | ||||
| #include "cutils.h" | ||||
| #include "quickjs-libc.h" | ||||
|  | ||||
| typedef struct { | ||||
|     char *name; | ||||
|     char *short_name; | ||||
|     int flags; | ||||
| } namelist_entry_t; | ||||
|  | ||||
| typedef struct namelist_t { | ||||
|     namelist_entry_t *array; | ||||
|     int count; | ||||
|     int size; | ||||
| } namelist_t; | ||||
|  | ||||
| typedef struct { | ||||
|     const char *option_name; | ||||
|     const char *init_name; | ||||
| } FeatureEntry; | ||||
|  | ||||
| static namelist_t cname_list; | ||||
| static namelist_t cmodule_list; | ||||
| static namelist_t init_module_list; | ||||
| static uint64_t feature_bitmap; | ||||
| static FILE *outfile; | ||||
| static BOOL byte_swap; | ||||
| static BOOL dynamic_export; | ||||
| static const char *c_ident_prefix = "qjsc_"; | ||||
|  | ||||
| #define FE_ALL (-1) | ||||
|  | ||||
| static const FeatureEntry feature_list[] = { | ||||
|     { "date", "Date" }, | ||||
|     { "eval", "Eval" }, | ||||
|     { "string-normalize", "StringNormalize" }, | ||||
|     { "regexp", "RegExp" }, | ||||
|     { "json", "JSON" }, | ||||
|     { "proxy", "Proxy" }, | ||||
|     { "map", "MapSet" }, | ||||
|     { "typedarray", "TypedArrays" }, | ||||
|     { "promise", "Promise" }, | ||||
| #define FE_MODULE_LOADER 9 | ||||
|     { "module-loader", NULL }, | ||||
| }; | ||||
|  | ||||
| void namelist_add(namelist_t *lp, const char *name, const char *short_name, | ||||
|                   int flags) | ||||
| { | ||||
|     namelist_entry_t *e; | ||||
|     if (lp->count == lp->size) { | ||||
|         size_t newsize = lp->size + (lp->size >> 1) + 4; | ||||
|         namelist_entry_t *a = | ||||
|             realloc(lp->array, sizeof(lp->array[0]) * newsize); | ||||
|         /* XXX: check for realloc failure */ | ||||
|         lp->array = a; | ||||
|         lp->size = newsize; | ||||
|     } | ||||
|     e =  &lp->array[lp->count++]; | ||||
|     e->name = strdup(name); | ||||
|     if (short_name) | ||||
|         e->short_name = strdup(short_name); | ||||
|     else | ||||
|         e->short_name = NULL; | ||||
|     e->flags = flags; | ||||
| } | ||||
|  | ||||
| void namelist_free(namelist_t *lp) | ||||
| { | ||||
|     while (lp->count > 0) { | ||||
|         namelist_entry_t *e = &lp->array[--lp->count]; | ||||
|         free(e->name); | ||||
|         free(e->short_name); | ||||
|     } | ||||
|     free(lp->array); | ||||
|     lp->array = NULL; | ||||
|     lp->size = 0; | ||||
| } | ||||
|  | ||||
| namelist_entry_t *namelist_find(namelist_t *lp, const char *name) | ||||
| { | ||||
|     int i; | ||||
|     for(i = 0; i < lp->count; i++) { | ||||
|         namelist_entry_t *e = &lp->array[i]; | ||||
|         if (!strcmp(e->name, name)) | ||||
|             return e; | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| static void get_c_name(char *buf, size_t buf_size, const char *file) | ||||
| { | ||||
|     const char *p, *r; | ||||
|     size_t len, i; | ||||
|     int c; | ||||
|     char *q; | ||||
|      | ||||
|     p = strrchr(file, '/'); | ||||
|     if (!p) | ||||
|         p = file; | ||||
|     else | ||||
|         p++; | ||||
|     r = strrchr(p, '.'); | ||||
|     if (!r) | ||||
|         len = strlen(p); | ||||
|     else | ||||
|         len = r - p; | ||||
|     pstrcpy(buf, buf_size, c_ident_prefix); | ||||
|     q = buf + strlen(buf); | ||||
|     for(i = 0; i < len; i++) { | ||||
|         c = p[i]; | ||||
|         if (!((c >= '0' && c <= '9') || | ||||
|               (c >= 'A' && c <= 'Z') || | ||||
|               (c >= 'a' && c <= 'z'))) { | ||||
|             c = '_'; | ||||
|         } | ||||
|         if ((q - buf) < buf_size - 1) | ||||
|             *q++ = c; | ||||
|     } | ||||
|     *q = '\0'; | ||||
| } | ||||
|  | ||||
| static void dump_hex(FILE *f, const uint8_t *buf, size_t len) | ||||
| { | ||||
|     size_t i, col; | ||||
|     col = 0; | ||||
|     for(i = 0; i < len; i++) { | ||||
|         fprintf(f, " 0x%02x,", buf[i]); | ||||
|         if (++col == 8) { | ||||
|             fprintf(f, "\n"); | ||||
|             col = 0; | ||||
|         } | ||||
|     } | ||||
|     if (col != 0) | ||||
|         fprintf(f, "\n"); | ||||
| } | ||||
|  | ||||
| static void output_object_code(JSContext *ctx, | ||||
|                                FILE *fo, JSValueConst obj, const char *c_name, | ||||
|                                BOOL load_only) | ||||
| { | ||||
|     uint8_t *out_buf; | ||||
|     size_t out_buf_len; | ||||
|     int flags; | ||||
|     flags = JS_WRITE_OBJ_BYTECODE; | ||||
|     if (byte_swap) | ||||
|         flags |= JS_WRITE_OBJ_BSWAP; | ||||
|     out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags); | ||||
|     if (!out_buf) { | ||||
|         js_std_dump_error(ctx); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     namelist_add(&cname_list, c_name, NULL, load_only); | ||||
|      | ||||
|     fprintf(fo, "const uint32_t %s_size = %u;\n\n",  | ||||
|             c_name, (unsigned int)out_buf_len); | ||||
|     fprintf(fo, "const uint8_t %s[%u] = {\n", | ||||
|             c_name, (unsigned int)out_buf_len); | ||||
|     dump_hex(fo, out_buf, out_buf_len); | ||||
|     fprintf(fo, "};\n\n"); | ||||
|  | ||||
|     js_free(ctx, out_buf); | ||||
| } | ||||
|  | ||||
| static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m) | ||||
| { | ||||
|     /* should never be called when compiling JS code */ | ||||
|     abort(); | ||||
| } | ||||
|  | ||||
| static void find_unique_cname(char *cname, size_t cname_size) | ||||
| { | ||||
|     char cname1[1024]; | ||||
|     int suffix_num; | ||||
|     size_t len, max_len; | ||||
|     assert(cname_size >= 32); | ||||
|     /* find a C name not matching an existing module C name by | ||||
|        adding a numeric suffix */ | ||||
|     len = strlen(cname); | ||||
|     max_len = cname_size - 16; | ||||
|     if (len > max_len) | ||||
|         cname[max_len] = '\0'; | ||||
|     suffix_num = 1; | ||||
|     for(;;) { | ||||
|         snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num); | ||||
|         if (!namelist_find(&cname_list, cname1)) | ||||
|             break; | ||||
|         suffix_num++; | ||||
|     } | ||||
|     pstrcpy(cname, cname_size, cname1); | ||||
| } | ||||
|  | ||||
| JSModuleDef *jsc_module_loader(JSContext *ctx, | ||||
|                               const char *module_name, void *opaque) | ||||
| { | ||||
|     JSModuleDef *m; | ||||
|     namelist_entry_t *e; | ||||
|  | ||||
|     /* check if it is a declared C or system module */ | ||||
|     e = namelist_find(&cmodule_list, module_name); | ||||
|     if (e) { | ||||
|         /* add in the static init module list */ | ||||
|         namelist_add(&init_module_list, e->name, e->short_name, 0); | ||||
|         /* create a dummy module */ | ||||
|         m = JS_NewCModule(ctx, module_name, js_module_dummy_init); | ||||
|     } else if (has_suffix(module_name, ".so")) { | ||||
|         fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name); | ||||
|         /* create a dummy module */ | ||||
|         m = JS_NewCModule(ctx, module_name, js_module_dummy_init); | ||||
|         /* the resulting executable will export its symbols for the | ||||
|            dynamic library */ | ||||
|         dynamic_export = TRUE; | ||||
|     } else { | ||||
|         size_t buf_len; | ||||
|         uint8_t *buf; | ||||
|         JSValue func_val; | ||||
|         char cname[1024]; | ||||
|          | ||||
|         buf = js_load_file(ctx, &buf_len, module_name); | ||||
|         if (!buf) { | ||||
|             JS_ThrowReferenceError(ctx, "could not load module filename '%s'", | ||||
|                                    module_name); | ||||
|             return NULL; | ||||
|         } | ||||
|          | ||||
|         /* compile the module */ | ||||
|         func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, | ||||
|                            JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); | ||||
|         js_free(ctx, buf); | ||||
|         if (JS_IsException(func_val)) | ||||
|             return NULL; | ||||
|         get_c_name(cname, sizeof(cname), module_name); | ||||
|         if (namelist_find(&cname_list, cname)) { | ||||
|             find_unique_cname(cname, sizeof(cname)); | ||||
|         } | ||||
|         output_object_code(ctx, outfile, func_val, cname, TRUE); | ||||
|          | ||||
|         /* the module is already referenced, so we must free it */ | ||||
|         m = JS_VALUE_GET_PTR(func_val); | ||||
|         JS_FreeValue(ctx, func_val); | ||||
|     } | ||||
|     return m; | ||||
| } | ||||
|  | ||||
| static void compile_file(JSContext *ctx, FILE *fo, | ||||
|                          const char *filename, | ||||
|                          const char *c_name1, | ||||
|                          int module) | ||||
| { | ||||
|     uint8_t *buf; | ||||
|     char c_name[1024]; | ||||
|     int eval_flags; | ||||
|     JSValue obj; | ||||
|     size_t buf_len; | ||||
|      | ||||
|     buf = js_load_file(ctx, &buf_len, filename); | ||||
|     if (!buf) { | ||||
|         fprintf(stderr, "Could not load '%s'\n", filename); | ||||
|         exit(1); | ||||
|     } | ||||
|     eval_flags = JS_EVAL_FLAG_COMPILE_ONLY; | ||||
|     if (module < 0) { | ||||
|         module = (has_suffix(filename, ".mjs") || | ||||
|                   JS_DetectModule((const char *)buf, buf_len)); | ||||
|     } | ||||
|     if (module) | ||||
|         eval_flags |= JS_EVAL_TYPE_MODULE; | ||||
|     else | ||||
|         eval_flags |= JS_EVAL_TYPE_GLOBAL; | ||||
|     obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags); | ||||
|     if (JS_IsException(obj)) { | ||||
|         js_std_dump_error(ctx); | ||||
|         exit(1); | ||||
|     } | ||||
|     js_free(ctx, buf); | ||||
|     if (c_name1) { | ||||
|         pstrcpy(c_name, sizeof(c_name), c_name1); | ||||
|     } else { | ||||
|         get_c_name(c_name, sizeof(c_name), filename); | ||||
|     } | ||||
|     output_object_code(ctx, fo, obj, c_name, FALSE); | ||||
|     JS_FreeValue(ctx, obj); | ||||
| } | ||||
|  | ||||
| static const char main_c_template1[] = | ||||
|     "int main(int argc, char **argv)\n" | ||||
|     "{\n" | ||||
|     "  JSRuntime *rt;\n" | ||||
|     "  JSContext *ctx;\n" | ||||
|     "  rt = JS_NewRuntime();\n" | ||||
|     ; | ||||
|  | ||||
| static const char main_c_template2[] = | ||||
|     "  js_std_loop(ctx);\n" | ||||
|     "  JS_FreeContext(ctx);\n" | ||||
|     "  JS_FreeRuntime(rt);\n" | ||||
|     "  return 0;\n" | ||||
|     "}\n"; | ||||
|  | ||||
| #ifdef CONFIG_BIGNUM | ||||
| #define PROG_NAME "qjscbn" | ||||
| #else | ||||
| #define PROG_NAME "qjsc" | ||||
| #endif | ||||
|  | ||||
| void help(void) | ||||
| { | ||||
|     printf("QuickJS Compiler version " CONFIG_VERSION "\n" | ||||
|            "usage: " PROG_NAME " [options] [files]\n" | ||||
|            "\n" | ||||
|            "options are:\n" | ||||
|            "-c          only output bytecode in a C file\n" | ||||
|            "-e          output main() and bytecode in a C file (default = executable output)\n" | ||||
|            "-o output   set the output filename\n" | ||||
|            "-N cname    set the C name of the generated data\n" | ||||
|            "-m          compile as Javascript module (default=autodetect)\n" | ||||
|            "-M module_name[,cname] add initialization code for an external C module\n" | ||||
|            "-x          byte swapped output\n" | ||||
|            "-p prefix   set the prefix of the generated C names\n" | ||||
|            ); | ||||
| #ifdef CONFIG_LTO | ||||
|     { | ||||
|         int i; | ||||
|         printf("-flto       use link time optimization\n"); | ||||
|         printf("-fno-["); | ||||
|         for(i = 0; i < countof(feature_list); i++) { | ||||
|             if (i != 0) | ||||
|                 printf("|"); | ||||
|             printf("%s", feature_list[i].option_name); | ||||
|         } | ||||
|         printf("]\n" | ||||
|                "            disable selected language features (smaller code size)\n"); | ||||
|     } | ||||
| #endif | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
| #if defined(CONFIG_CC) && !defined(_WIN32) | ||||
|  | ||||
| int exec_cmd(char **argv) | ||||
| { | ||||
|     int pid, status, ret; | ||||
|  | ||||
|     pid = fork(); | ||||
|     if (pid == 0) { | ||||
|         execvp(argv[0], argv); | ||||
|         exit(1); | ||||
|     }  | ||||
|  | ||||
|     for(;;) { | ||||
|         ret = waitpid(pid, &status, 0); | ||||
|         if (ret == pid && WIFEXITED(status)) | ||||
|             break; | ||||
|     } | ||||
|     return WEXITSTATUS(status); | ||||
| } | ||||
|  | ||||
| static int output_executable(const char *out_filename, const char *cfilename, | ||||
|                              BOOL use_lto, BOOL verbose, const char *exename) | ||||
| { | ||||
|     const char *argv[64]; | ||||
|     const char **arg, *bn_suffix, *lto_suffix; | ||||
|     char libjsname[1024]; | ||||
|     char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p; | ||||
|     int ret; | ||||
|      | ||||
|     /* get the directory of the executable */ | ||||
|     pstrcpy(exe_dir, sizeof(exe_dir), exename); | ||||
|     p = strrchr(exe_dir, '/'); | ||||
|     if (p) { | ||||
|         *p = '\0'; | ||||
|     } else { | ||||
|         pstrcpy(exe_dir, sizeof(exe_dir), "."); | ||||
|     } | ||||
|  | ||||
|     /* if 'quickjs.h' is present at the same path as the executable, we | ||||
|        use it as include and lib directory */ | ||||
|     snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir); | ||||
|     if (access(buf, R_OK) == 0) { | ||||
|         pstrcpy(inc_dir, sizeof(inc_dir), exe_dir); | ||||
|         pstrcpy(lib_dir, sizeof(lib_dir), exe_dir); | ||||
|     } else { | ||||
|         snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX); | ||||
|         snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX); | ||||
|     } | ||||
|      | ||||
|     lto_suffix = ""; | ||||
| #ifdef CONFIG_BIGNUM | ||||
|     bn_suffix = ".bn"; | ||||
| #else | ||||
|     bn_suffix = ""; | ||||
| #endif | ||||
|      | ||||
|     arg = argv; | ||||
|     *arg++ = CONFIG_CC; | ||||
|     *arg++ = "-O2"; | ||||
| #ifdef CONFIG_LTO | ||||
|     if (use_lto) { | ||||
|         *arg++ = "-flto"; | ||||
|         lto_suffix = ".lto"; | ||||
|     } | ||||
| #endif | ||||
|     /* XXX: use the executable path to find the includes files and | ||||
|        libraries */ | ||||
|     *arg++ = "-D"; | ||||
|     *arg++ = "_GNU_SOURCE"; | ||||
|     *arg++ = "-I"; | ||||
|     *arg++ = inc_dir; | ||||
|     *arg++ = "-o"; | ||||
|     *arg++ = out_filename; | ||||
|     if (dynamic_export) | ||||
|         *arg++ = "-rdynamic"; | ||||
|     *arg++ = cfilename; | ||||
|     snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a", | ||||
|              lib_dir, bn_suffix, lto_suffix); | ||||
|     *arg++ = libjsname; | ||||
|     *arg++ = "-lm"; | ||||
|     *arg++ = "-ldl"; | ||||
|     *arg = NULL; | ||||
|      | ||||
|     if (verbose) { | ||||
|         for(arg = argv; *arg != NULL; arg++) | ||||
|             printf("%s ", *arg); | ||||
|         printf("\n"); | ||||
|     } | ||||
|      | ||||
|     ret = exec_cmd((char **)argv); | ||||
|     unlink(cfilename); | ||||
|     return ret; | ||||
| } | ||||
| #else | ||||
| static int output_executable(const char *out_filename, const char *cfilename, | ||||
|                              BOOL use_lto, BOOL verbose, const char *exename) | ||||
| { | ||||
|     fprintf(stderr, "Executable output is not supported for this target\n"); | ||||
|     exit(1); | ||||
|     return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| typedef enum { | ||||
|     OUTPUT_C, | ||||
|     OUTPUT_C_MAIN, | ||||
|     OUTPUT_EXECUTABLE, | ||||
| } OutputTypeEnum; | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     int c, i, verbose; | ||||
|     const char *out_filename, *cname; | ||||
|     char cfilename[1024]; | ||||
|     FILE *fo; | ||||
|     JSRuntime *rt; | ||||
|     JSContext *ctx; | ||||
|     BOOL use_lto; | ||||
|     int module; | ||||
|     OutputTypeEnum output_type; | ||||
|      | ||||
|     out_filename = NULL; | ||||
|     output_type = OUTPUT_EXECUTABLE; | ||||
|     cname = NULL; | ||||
|     feature_bitmap = FE_ALL; | ||||
|     module = -1; | ||||
|     byte_swap = FALSE; | ||||
|     verbose = 0; | ||||
|     use_lto = FALSE; | ||||
|  | ||||
|     /* add system modules */ | ||||
|     namelist_add(&cmodule_list, "std", "std", 0); | ||||
|     namelist_add(&cmodule_list, "os", "os", 0); | ||||
|  | ||||
|     for(;;) { | ||||
|         c = getopt(argc, argv, "ho:cN:f:mxevM:p:"); | ||||
|         if (c == -1) | ||||
|             break; | ||||
|         switch(c) { | ||||
|         case 'h': | ||||
|             help(); | ||||
|         case 'o': | ||||
|             out_filename = optarg; | ||||
|             break; | ||||
|         case 'c': | ||||
|             output_type = OUTPUT_C; | ||||
|             break; | ||||
|         case 'e': | ||||
|             output_type = OUTPUT_C_MAIN; | ||||
|             break; | ||||
|         case 'N': | ||||
|             cname = optarg; | ||||
|             break; | ||||
|         case 'f': | ||||
|             { | ||||
|                 const char *p; | ||||
|                 p = optarg; | ||||
|                 if (!strcmp(optarg, "lto")) { | ||||
|                     use_lto = TRUE; | ||||
|                 } else if (strstart(p, "no-", &p)) { | ||||
|                     use_lto = TRUE; | ||||
|                     for(i = 0; i < countof(feature_list); i++) { | ||||
|                         if (!strcmp(p, feature_list[i].option_name)) { | ||||
|                             feature_bitmap &= ~((uint64_t)1 << i); | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     if (i == countof(feature_list)) | ||||
|                         goto bad_feature; | ||||
|                 } else { | ||||
|                 bad_feature: | ||||
|                     fprintf(stderr, "unsupported feature: %s\n", optarg); | ||||
|                     exit(1); | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|         case 'm': | ||||
|             module = 1; | ||||
|             break; | ||||
|         case 'M': | ||||
|             { | ||||
|                 char *p; | ||||
|                 char path[1024]; | ||||
|                 char cname[1024]; | ||||
|                 pstrcpy(path, sizeof(path), optarg); | ||||
|                 p = strchr(path, ','); | ||||
|                 if (p) { | ||||
|                     *p = '\0'; | ||||
|                     pstrcpy(cname, sizeof(cname), p + 1); | ||||
|                 } else { | ||||
|                     get_c_name(cname, sizeof(cname), path); | ||||
|                 } | ||||
|                 namelist_add(&cmodule_list, path, cname, 0); | ||||
|             } | ||||
|             break; | ||||
|         case 'x': | ||||
|             byte_swap = TRUE; | ||||
|             break; | ||||
|         case 'v': | ||||
|             verbose++; | ||||
|             break; | ||||
|         case 'p': | ||||
|             c_ident_prefix = optarg; | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (optind >= argc) | ||||
|         help(); | ||||
|  | ||||
|     if (!out_filename) { | ||||
|         if (output_type == OUTPUT_EXECUTABLE) { | ||||
|             out_filename = "a.out"; | ||||
|         } else { | ||||
|             out_filename = "out.c"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (output_type == OUTPUT_EXECUTABLE) { | ||||
| #if defined(_WIN32) || defined(__ANDROID__) | ||||
|         /* XXX: find a /tmp directory ? */ | ||||
|         snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid()); | ||||
| #else | ||||
|         snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid()); | ||||
| #endif | ||||
|     } else { | ||||
|         pstrcpy(cfilename, sizeof(cfilename), out_filename); | ||||
|     } | ||||
|      | ||||
|     fo = fopen(cfilename, "w"); | ||||
|     if (!fo) { | ||||
|         perror(cfilename); | ||||
|         exit(1); | ||||
|     } | ||||
|     outfile = fo; | ||||
|      | ||||
|     rt = JS_NewRuntime(); | ||||
|     ctx = JS_NewContextRaw(rt); | ||||
|     JS_AddIntrinsicEval(ctx); | ||||
|     JS_AddIntrinsicRegExpCompiler(ctx); | ||||
|      | ||||
|     /* loader for ES6 modules */ | ||||
|     JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL); | ||||
|  | ||||
|     fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n" | ||||
|             "\n" | ||||
|             ); | ||||
|      | ||||
|     if (output_type != OUTPUT_C) { | ||||
|         fprintf(fo, "#include \"quickjs-libc.h\"\n" | ||||
|                 "\n" | ||||
|                 ); | ||||
|     } else { | ||||
|         fprintf(fo, "#include <inttypes.h>\n" | ||||
|                 "\n" | ||||
|                 ); | ||||
|     } | ||||
|  | ||||
|     for(i = optind; i < argc; i++) { | ||||
|         const char *filename = argv[i]; | ||||
|         compile_file(ctx, fo, filename, cname, module); | ||||
|         cname = NULL; | ||||
|     } | ||||
|  | ||||
|     if (output_type != OUTPUT_C) { | ||||
|         fputs(main_c_template1, fo); | ||||
|         fprintf(fo, "  ctx = JS_NewContextRaw(rt);\n"); | ||||
|  | ||||
|         /* add the module loader if necessary */ | ||||
|         if (feature_bitmap & (1 << FE_MODULE_LOADER)) { | ||||
|             fprintf(fo, "  JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n"); | ||||
|         } | ||||
|          | ||||
|         /* add the basic objects */ | ||||
|          | ||||
|         fprintf(fo, "  JS_AddIntrinsicBaseObjects(ctx);\n"); | ||||
|         for(i = 0; i < countof(feature_list); i++) { | ||||
|             if ((feature_bitmap & ((uint64_t)1 << i)) && | ||||
|                 feature_list[i].init_name) { | ||||
|                 fprintf(fo, "  JS_AddIntrinsic%s(ctx);\n", | ||||
|                         feature_list[i].init_name); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         fprintf(fo, "  js_std_add_helpers(ctx, argc, argv);\n"); | ||||
|  | ||||
|         for(i = 0; i < init_module_list.count; i++) { | ||||
|             namelist_entry_t *e = &init_module_list.array[i]; | ||||
|             /* initialize the static C modules */ | ||||
|              | ||||
|             fprintf(fo, | ||||
|                     "  {\n" | ||||
|                     "    extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n" | ||||
|                     "    js_init_module_%s(ctx, \"%s\");\n" | ||||
|                     "  }\n", | ||||
|                     e->short_name, e->short_name, e->name); | ||||
|         } | ||||
|  | ||||
|         for(i = 0; i < cname_list.count; i++) { | ||||
|             namelist_entry_t *e = &cname_list.array[i]; | ||||
|             fprintf(fo, "  js_std_eval_binary(ctx, %s, %s_size, %s);\n", | ||||
|                     e->name, e->name, | ||||
|                     e->flags ? "1" : "0"); | ||||
|         } | ||||
|         fputs(main_c_template2, fo); | ||||
|     } | ||||
|      | ||||
|     JS_FreeContext(ctx); | ||||
|     JS_FreeRuntime(rt); | ||||
|  | ||||
|     fclose(fo); | ||||
|  | ||||
|     if (output_type == OUTPUT_EXECUTABLE) { | ||||
|         return output_executable(out_filename, cfilename, use_lto, verbose, | ||||
|                                  argv[0]); | ||||
|     } | ||||
|     namelist_free(&cname_list); | ||||
|     namelist_free(&cmodule_list); | ||||
|     namelist_free(&init_module_list); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										2442
									
								
								deps/quickjs/qjscalc.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2442
									
								
								deps/quickjs/qjscalc.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										284
									
								
								deps/quickjs/quickjs-atom.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								deps/quickjs/quickjs-atom.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,284 @@ | ||||
| /* | ||||
|  * QuickJS atom definitions | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * Copyright (c) 2017-2018 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #ifdef DEF | ||||
|  | ||||
| /* Note: first atoms are considered as keywords in the parser */ | ||||
| DEF(null, "null") /* must be first */ | ||||
| DEF(false, "false") | ||||
| DEF(true, "true") | ||||
| DEF(if, "if") | ||||
| DEF(else, "else") | ||||
| DEF(return, "return") | ||||
| DEF(var, "var") | ||||
| DEF(this, "this") | ||||
| DEF(delete, "delete") | ||||
| DEF(void, "void") | ||||
| DEF(typeof, "typeof") | ||||
| DEF(new, "new") | ||||
| DEF(in, "in") | ||||
| DEF(instanceof, "instanceof") | ||||
| DEF(do, "do") | ||||
| DEF(while, "while") | ||||
| DEF(for, "for") | ||||
| DEF(break, "break") | ||||
| DEF(continue, "continue") | ||||
| DEF(switch, "switch") | ||||
| DEF(case, "case") | ||||
| DEF(default, "default") | ||||
| DEF(throw, "throw") | ||||
| DEF(try, "try") | ||||
| DEF(catch, "catch") | ||||
| DEF(finally, "finally") | ||||
| DEF(function, "function") | ||||
| DEF(debugger, "debugger") | ||||
| DEF(with, "with") | ||||
| /* FutureReservedWord */ | ||||
| DEF(class, "class") | ||||
| DEF(const, "const") | ||||
| DEF(enum, "enum") | ||||
| DEF(export, "export") | ||||
| DEF(extends, "extends") | ||||
| DEF(import, "import") | ||||
| DEF(super, "super") | ||||
| /* FutureReservedWords when parsing strict mode code */ | ||||
| DEF(implements, "implements") | ||||
| DEF(interface, "interface") | ||||
| DEF(let, "let") | ||||
| DEF(package, "package") | ||||
| DEF(private, "private") | ||||
| DEF(protected, "protected") | ||||
| DEF(public, "public") | ||||
| DEF(static, "static") | ||||
| DEF(yield, "yield") | ||||
| DEF(await, "await") | ||||
|  | ||||
| /* empty string */ | ||||
| DEF(empty_string, "") | ||||
| /* identifiers */ | ||||
| DEF(length, "length") | ||||
| DEF(fileName, "fileName") | ||||
| DEF(lineNumber, "lineNumber") | ||||
| DEF(message, "message") | ||||
| DEF(stack, "stack") | ||||
| DEF(name, "name") | ||||
| DEF(toString, "toString") | ||||
| DEF(toLocaleString, "toLocaleString") | ||||
| DEF(valueOf, "valueOf") | ||||
| DEF(eval, "eval") | ||||
| DEF(prototype, "prototype") | ||||
| DEF(constructor, "constructor") | ||||
| DEF(configurable, "configurable") | ||||
| DEF(writable, "writable") | ||||
| DEF(enumerable, "enumerable") | ||||
| DEF(value, "value") | ||||
| DEF(get, "get") | ||||
| DEF(set, "set") | ||||
| DEF(of, "of") | ||||
| DEF(__proto__, "__proto__") | ||||
| DEF(undefined, "undefined") | ||||
| DEF(number, "number") | ||||
| DEF(boolean, "boolean") | ||||
| DEF(string, "string") | ||||
| DEF(object, "object") | ||||
| DEF(symbol, "symbol") | ||||
| DEF(integer, "integer") | ||||
| DEF(unknown, "unknown") | ||||
| DEF(arguments, "arguments") | ||||
| DEF(callee, "callee") | ||||
| DEF(caller, "caller") | ||||
| DEF(_eval_, "<eval>") | ||||
| DEF(_ret_, "<ret>") | ||||
| DEF(_var_, "<var>") | ||||
| DEF(_with_, "<with>") | ||||
| DEF(lastIndex, "lastIndex") | ||||
| DEF(target, "target") | ||||
| DEF(index, "index") | ||||
| DEF(input, "input") | ||||
| DEF(defineProperties, "defineProperties") | ||||
| DEF(apply, "apply") | ||||
| DEF(join, "join") | ||||
| DEF(concat, "concat") | ||||
| DEF(split, "split") | ||||
| DEF(construct, "construct") | ||||
| DEF(getPrototypeOf, "getPrototypeOf") | ||||
| DEF(setPrototypeOf, "setPrototypeOf") | ||||
| DEF(isExtensible, "isExtensible") | ||||
| DEF(preventExtensions, "preventExtensions") | ||||
| DEF(has, "has") | ||||
| DEF(deleteProperty, "deleteProperty") | ||||
| DEF(defineProperty, "defineProperty") | ||||
| DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor") | ||||
| DEF(ownKeys, "ownKeys") | ||||
| DEF(add, "add") | ||||
| DEF(done, "done") | ||||
| DEF(next, "next") | ||||
| DEF(values, "values") | ||||
| DEF(source, "source") | ||||
| DEF(flags, "flags") | ||||
| DEF(global, "global") | ||||
| DEF(unicode, "unicode") | ||||
| DEF(raw, "raw") | ||||
| DEF(new_target, "new.target") | ||||
| DEF(this_active_func, "this.active_func") | ||||
| DEF(home_object, "<home_object>") | ||||
| DEF(computed_field, "<computed_field>") | ||||
| DEF(static_computed_field, "<static_computed_field>") /* must come after computed_fields */ | ||||
| DEF(class_fields_init, "<class_fields_init>") | ||||
| DEF(brand, "<brand>") | ||||
| DEF(hash_constructor, "#constructor") | ||||
| DEF(as, "as") | ||||
| DEF(from, "from") | ||||
| DEF(meta, "meta") | ||||
| DEF(_default_, "*default*") | ||||
| DEF(_star_, "*") | ||||
| DEF(Module, "Module") | ||||
| DEF(then, "then") | ||||
| DEF(resolve, "resolve") | ||||
| DEF(reject, "reject") | ||||
| DEF(promise, "promise") | ||||
| DEF(proxy, "proxy") | ||||
| DEF(revoke, "revoke") | ||||
| DEF(async, "async") | ||||
| DEF(exec, "exec") | ||||
| DEF(groups, "groups") | ||||
| DEF(status, "status") | ||||
| DEF(reason, "reason") | ||||
| DEF(globalThis, "globalThis") | ||||
| #ifdef CONFIG_BIGNUM | ||||
| DEF(bigint, "bigint") | ||||
| DEF(bigfloat, "bigfloat") | ||||
| #endif | ||||
| #ifdef CONFIG_ATOMICS | ||||
| DEF(not_equal, "not-equal") | ||||
| DEF(timed_out, "timed-out") | ||||
| DEF(ok, "ok") | ||||
| #endif | ||||
| DEF(toJSON, "toJSON") | ||||
| /* class names */ | ||||
| DEF(Object, "Object") | ||||
| DEF(Array, "Array") | ||||
| DEF(Error, "Error") | ||||
| DEF(Number, "Number") | ||||
| DEF(String, "String") | ||||
| DEF(Boolean, "Boolean") | ||||
| DEF(Symbol, "Symbol") | ||||
| DEF(Arguments, "Arguments") | ||||
| DEF(Math, "Math") | ||||
| DEF(JSON, "JSON") | ||||
| DEF(Date, "Date") | ||||
| DEF(Function, "Function") | ||||
| DEF(GeneratorFunction, "GeneratorFunction") | ||||
| DEF(ForInIterator, "ForInIterator") | ||||
| DEF(RegExp, "RegExp") | ||||
| DEF(ArrayBuffer, "ArrayBuffer") | ||||
| DEF(SharedArrayBuffer, "SharedArrayBuffer") | ||||
| /* must keep same order as class IDs for typed arrays */ | ||||
| DEF(Uint8ClampedArray, "Uint8ClampedArray")  | ||||
| DEF(Int8Array, "Int8Array") | ||||
| DEF(Uint8Array, "Uint8Array") | ||||
| DEF(Int16Array, "Int16Array") | ||||
| DEF(Uint16Array, "Uint16Array") | ||||
| DEF(Int32Array, "Int32Array") | ||||
| DEF(Uint32Array, "Uint32Array") | ||||
| #ifdef CONFIG_BIGNUM | ||||
| DEF(BigInt64Array, "BigInt64Array") | ||||
| DEF(BigUint64Array, "BigUint64Array") | ||||
| #endif | ||||
| DEF(Float32Array, "Float32Array") | ||||
| DEF(Float64Array, "Float64Array") | ||||
| DEF(DataView, "DataView") | ||||
| #ifdef CONFIG_BIGNUM | ||||
| DEF(BigInt, "BigInt") | ||||
| DEF(BigFloat, "BigFloat") | ||||
| DEF(BigFloatEnv, "BigFloatEnv") | ||||
| #endif | ||||
| DEF(Map, "Map") | ||||
| DEF(Set, "Set") /* Map + 1 */ | ||||
| DEF(WeakMap, "WeakMap") /* Map + 2 */ | ||||
| DEF(WeakSet, "WeakSet") /* Map + 3 */ | ||||
| DEF(Map_Iterator, "Map Iterator") | ||||
| DEF(Set_Iterator, "Set Iterator") | ||||
| DEF(Array_Iterator, "Array Iterator") | ||||
| DEF(String_Iterator, "String Iterator") | ||||
| DEF(RegExp_String_Iterator, "RegExp String Iterator") | ||||
| DEF(Generator, "Generator") | ||||
| DEF(Proxy, "Proxy") | ||||
| DEF(Promise, "Promise") | ||||
| DEF(PromiseResolveFunction, "PromiseResolveFunction") | ||||
| DEF(PromiseRejectFunction, "PromiseRejectFunction") | ||||
| DEF(AsyncFunction, "AsyncFunction") | ||||
| DEF(AsyncFunctionResolve, "AsyncFunctionResolve") | ||||
| DEF(AsyncFunctionReject, "AsyncFunctionReject") | ||||
| DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction") | ||||
| DEF(AsyncGenerator, "AsyncGenerator") | ||||
| DEF(EvalError, "EvalError") | ||||
| DEF(RangeError, "RangeError") | ||||
| DEF(ReferenceError, "ReferenceError") | ||||
| DEF(SyntaxError, "SyntaxError") | ||||
| DEF(TypeError, "TypeError") | ||||
| DEF(URIError, "URIError") | ||||
| DEF(InternalError, "InternalError") | ||||
| /* private symbols */ | ||||
| DEF(Private_brand, "<brand>") | ||||
| /* symbols */ | ||||
| DEF(Symbol_toPrimitive, "Symbol.toPrimitive") | ||||
| DEF(Symbol_iterator, "Symbol.iterator") | ||||
| DEF(Symbol_match, "Symbol.match") | ||||
| DEF(Symbol_matchAll, "Symbol.matchAll") | ||||
| DEF(Symbol_replace, "Symbol.replace") | ||||
| DEF(Symbol_search, "Symbol.search") | ||||
| DEF(Symbol_split, "Symbol.split") | ||||
| DEF(Symbol_toStringTag, "Symbol.toStringTag") | ||||
| DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable") | ||||
| DEF(Symbol_hasInstance, "Symbol.hasInstance") | ||||
| DEF(Symbol_species, "Symbol.species") | ||||
| DEF(Symbol_unscopables, "Symbol.unscopables") | ||||
| DEF(Symbol_asyncIterator, "Symbol.asyncIterator") | ||||
| #ifdef CONFIG_BIGNUM | ||||
| DEF(Symbol_operatorOrder, "Symbol.operatorOrder") | ||||
| DEF(Symbol_operatorAdd, "Symbol.operatorAdd") | ||||
| DEF(Symbol_operatorSub, "Symbol.operatorSub") | ||||
| DEF(Symbol_operatorMul, "Symbol.operatorMul") | ||||
| DEF(Symbol_operatorDiv, "Symbol.operatorDiv") | ||||
| DEF(Symbol_operatorMod, "Symbol.operatorMod") | ||||
| DEF(Symbol_operatorPow, "Symbol.operatorPow") | ||||
| DEF(Symbol_operatorShl, "Symbol.operatorShl") | ||||
| DEF(Symbol_operatorShr, "Symbol.operatorShr") | ||||
| DEF(Symbol_operatorAnd, "Symbol.operatorAnd") | ||||
| DEF(Symbol_operatorOr, "Symbol.operatorOr") | ||||
| DEF(Symbol_operatorXor, "Symbol.operatorXor") | ||||
| DEF(Symbol_operatorCmpLT, "Symbol.operatorCmpLT") | ||||
| DEF(Symbol_operatorCmpLE, "Symbol.operatorCmpLE") | ||||
| DEF(Symbol_operatorCmpEQ, "Symbol.operatorCmpEQ") | ||||
| DEF(Symbol_operatorPlus, "Symbol.operatorPlus") | ||||
| DEF(Symbol_operatorNeg, "Symbol.operatorNeg") | ||||
| DEF(Symbol_operatorNot, "Symbol.operatorNot") | ||||
| DEF(Symbol_operatorInc, "Symbol.operatorInc") | ||||
| DEF(Symbol_operatorDec, "Symbol.operatorDec") | ||||
| DEF(Symbol_operatorMathMod, "Symbol.operatorMathMod") | ||||
| #endif | ||||
|  | ||||
| #endif /* DEF */ | ||||
							
								
								
									
										2772
									
								
								deps/quickjs/quickjs-libc.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2772
									
								
								deps/quickjs/quickjs-libc.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										46
									
								
								deps/quickjs/quickjs-libc.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								deps/quickjs/quickjs-libc.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /* | ||||
|  * QuickJS C library | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef QUICKJS_LIBC_H | ||||
| #define QUICKJS_LIBC_H | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "quickjs.h" | ||||
|  | ||||
| JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); | ||||
| JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); | ||||
| void js_std_add_helpers(JSContext *ctx, int argc, char **argv); | ||||
| void js_std_loop(JSContext *ctx); | ||||
| void js_std_free_handlers(JSRuntime *rt); | ||||
| void js_std_dump_error(JSContext *ctx); | ||||
| uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); | ||||
| int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, | ||||
|                               JS_BOOL use_realpath, JS_BOOL is_main); | ||||
| JSModuleDef *js_module_loader(JSContext *ctx, | ||||
|                               const char *module_name, void *opaque); | ||||
| void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, | ||||
|                         int flags); | ||||
|  | ||||
| #endif /* QUICKJS_LIBC_H */ | ||||
							
								
								
									
										370
									
								
								deps/quickjs/quickjs-opcode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								deps/quickjs/quickjs-opcode.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,370 @@ | ||||
| /* | ||||
|  * QuickJS opcode definitions | ||||
|  *  | ||||
|  * Copyright (c) 2017-2018 Fabrice Bellard | ||||
|  * Copyright (c) 2017-2018 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #ifdef FMT | ||||
| FMT(none) | ||||
| FMT(none_int) | ||||
| FMT(none_loc) | ||||
| FMT(none_arg) | ||||
| FMT(none_var_ref) | ||||
| FMT(u8) | ||||
| FMT(i8) | ||||
| FMT(loc8) | ||||
| FMT(const8) | ||||
| FMT(label8) | ||||
| FMT(u16) | ||||
| FMT(i16) | ||||
| FMT(label16) | ||||
| FMT(npop) | ||||
| FMT(npopx) | ||||
| FMT(npop_u16) | ||||
| FMT(loc) | ||||
| FMT(arg) | ||||
| FMT(var_ref) | ||||
| FMT(u32) | ||||
| FMT(i32) | ||||
| FMT(const) | ||||
| FMT(label) | ||||
| FMT(atom) | ||||
| FMT(atom_u8) | ||||
| FMT(atom_u16) | ||||
| FMT(atom_label_u8) | ||||
| FMT(atom_label_u16) | ||||
| FMT(label_u16) | ||||
| #undef FMT | ||||
| #endif /* FMT */ | ||||
|  | ||||
| #ifdef DEF | ||||
|  | ||||
| #ifndef def | ||||
| #define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f) | ||||
| #endif | ||||
|  | ||||
| DEF(invalid, 1, 0, 0, none) /* never emitted */ | ||||
|  | ||||
| /* push values */ | ||||
| DEF(       push_i32, 5, 0, 1, i32) | ||||
| DEF(     push_const, 5, 0, 1, const) | ||||
| DEF(       fclosure, 5, 0, 1, const) /* must follow push_const */ | ||||
| DEF(push_atom_value, 5, 0, 1, atom) | ||||
| DEF( private_symbol, 5, 0, 1, atom) | ||||
| DEF(      undefined, 1, 0, 1, none) | ||||
| DEF(           null, 1, 0, 1, none) | ||||
| DEF(      push_this, 1, 0, 1, none) /* only used at the start of a function */ | ||||
| DEF(     push_false, 1, 0, 1, none) | ||||
| DEF(      push_true, 1, 0, 1, none) | ||||
| DEF(         object, 1, 0, 1, none) | ||||
| DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */ | ||||
| DEF(           rest, 3, 0, 1, u16) /* only used at the start of a function */ | ||||
|  | ||||
| DEF(           drop, 1, 1, 0, none) /* a -> */ | ||||
| DEF(            nip, 1, 2, 1, none) /* a b -> b */ | ||||
| DEF(           nip1, 1, 3, 2, none) /* a b c -> b c */ | ||||
| DEF(            dup, 1, 1, 2, none) /* a -> a a */ | ||||
| DEF(           dup1, 1, 2, 3, none) /* a b -> a a b */ | ||||
| DEF(           dup2, 1, 2, 4, none) /* a b -> a b a b */ | ||||
| DEF(           dup3, 1, 3, 6, none) /* a b c -> a b c a b c */ | ||||
| DEF(        insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */ | ||||
| DEF(        insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */ | ||||
| DEF(        insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */ | ||||
| DEF(          perm3, 1, 3, 3, none) /* obj a b -> a obj b */ | ||||
| DEF(          perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */ | ||||
| DEF(          perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */ | ||||
| DEF(           swap, 1, 2, 2, none) /* a b -> b a */ | ||||
| DEF(          swap2, 1, 4, 4, none) /* a b c d -> c d a b */ | ||||
| DEF(          rot3l, 1, 3, 3, none) /* x a b -> a b x */ | ||||
| DEF(          rot3r, 1, 3, 3, none) /* a b x -> x a b */ | ||||
| DEF(          rot4l, 1, 4, 4, none) /* x a b c -> a b c x */ | ||||
| DEF(          rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */ | ||||
|  | ||||
| DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */ | ||||
| DEF(           call, 3, 1, 1, npop) /* arguments are not counted in n_pop */ | ||||
| DEF(      tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */ | ||||
| DEF(    call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */ | ||||
| DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */ | ||||
| DEF(     array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */ | ||||
| DEF(          apply, 3, 3, 1, u16) | ||||
| DEF(         return, 1, 1, 0, none) | ||||
| DEF(   return_undef, 1, 0, 0, none) | ||||
| DEF(check_ctor_return, 1, 1, 2, none) | ||||
| DEF(     check_ctor, 1, 0, 0, none) | ||||
| DEF(    check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */ | ||||
| DEF(      add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ | ||||
| DEF(   return_async, 1, 1, 0, none) | ||||
| DEF(          throw, 1, 1, 0, none) | ||||
| DEF(      throw_var, 6, 0, 0, atom_u8) | ||||
| DEF(           eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */ | ||||
| DEF(     apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */ | ||||
| DEF(         regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a | ||||
|                                        bytecode string */ | ||||
| DEF( get_super_ctor, 1, 1, 1, none) | ||||
| DEF(      get_super, 1, 1, 1, none) | ||||
| DEF(         import, 1, 1, 1, none) /* dynamic module import */ | ||||
|  | ||||
| DEF(      check_var, 5, 0, 1, atom) /* check if a variable exists */ | ||||
| DEF(  get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */ | ||||
| DEF(        get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */ | ||||
| DEF(        put_var, 5, 1, 0, atom) /* must come after get_var */ | ||||
| DEF(   put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */ | ||||
| DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */ | ||||
|  | ||||
| DEF(  get_ref_value, 1, 2, 3, none) | ||||
| DEF(  put_ref_value, 1, 3, 0, none) | ||||
|  | ||||
| DEF(     define_var, 6, 0, 0, atom_u8) | ||||
| DEF(check_define_var, 6, 0, 0, atom_u8) | ||||
| DEF(    define_func, 6, 1, 0, atom_u8) | ||||
| DEF(      get_field, 5, 1, 1, atom) | ||||
| DEF(     get_field2, 5, 1, 2, atom) | ||||
| DEF(      put_field, 5, 2, 0, atom) | ||||
| DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */ | ||||
| DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */ | ||||
| DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */ | ||||
| DEF(   get_array_el, 1, 2, 1, none) | ||||
| DEF(  get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */ | ||||
| DEF(   put_array_el, 1, 3, 0, none) | ||||
| DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */ | ||||
| DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */ | ||||
| DEF(   define_field, 5, 2, 1, atom) | ||||
| DEF(       set_name, 5, 1, 1, atom) | ||||
| DEF(set_name_computed, 1, 2, 2, none) | ||||
| DEF(      set_proto, 1, 2, 1, none) | ||||
| DEF(set_home_object, 1, 2, 2, none) | ||||
| DEF(define_array_el, 1, 3, 2, none) | ||||
| DEF(         append, 1, 3, 2, none) /* append enumerated object, update length */ | ||||
| DEF(copy_data_properties, 2, 3, 3, u8) | ||||
| DEF(  define_method, 6, 2, 1, atom_u8) | ||||
| DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */ | ||||
| DEF(   define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */ | ||||
| DEF(   define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */ | ||||
|  | ||||
| DEF(        get_loc, 3, 0, 1, loc) | ||||
| DEF(        put_loc, 3, 1, 0, loc) /* must come after get_loc */ | ||||
| DEF(        set_loc, 3, 1, 1, loc) /* must come after put_loc */ | ||||
| DEF(        get_arg, 3, 0, 1, arg) | ||||
| DEF(        put_arg, 3, 1, 0, arg) /* must come after get_arg */ | ||||
| DEF(        set_arg, 3, 1, 1, arg) /* must come after put_arg */ | ||||
| DEF(    get_var_ref, 3, 0, 1, var_ref)  | ||||
| DEF(    put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */ | ||||
| DEF(    set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */ | ||||
| DEF(set_loc_uninitialized, 3, 0, 0, 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_init, 3, 1, 0, loc) | ||||
| 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_init, 3, 1, 0, var_ref) | ||||
| DEF(      close_loc, 3, 0, 0, loc) | ||||
| DEF(       if_false, 5, 1, 0, label) | ||||
| DEF(        if_true, 5, 1, 0, label) /* must come after if_false */ | ||||
| DEF(           goto, 5, 0, 0, label) /* must come after if_true */ | ||||
| DEF(          catch, 5, 0, 1, label) | ||||
| 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(      to_object, 1, 1, 1, none) | ||||
| //DEF(      to_string, 1, 1, 1, none) | ||||
| DEF(     to_propkey, 1, 1, 1, none) | ||||
| DEF(    to_propkey2, 1, 2, 2, none) | ||||
|  | ||||
| DEF(   with_get_var, 10, 1, 0, atom_label_u8)     /* must be in the same order as scope_xxx */ | ||||
| DEF(   with_put_var, 10, 2, 1, atom_label_u8)     /* must be in the same order as scope_xxx */ | ||||
| DEF(with_delete_var, 10, 1, 0, atom_label_u8)     /* must be in the same order as scope_xxx */ | ||||
| DEF(  with_make_ref, 10, 1, 0, atom_label_u8)     /* must be in the same order as scope_xxx */ | ||||
| DEF(   with_get_ref, 10, 1, 0, atom_label_u8)     /* must be in the same order as scope_xxx */ | ||||
| DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8) | ||||
|  | ||||
| DEF(   make_loc_ref, 7, 0, 2, atom_u16) | ||||
| DEF(   make_arg_ref, 7, 0, 2, atom_u16) | ||||
| DEF(make_var_ref_ref, 7, 0, 2, atom_u16) | ||||
| DEF(   make_var_ref, 5, 0, 2, atom) | ||||
|  | ||||
| DEF(   for_in_start, 1, 1, 1, none) | ||||
| DEF(   for_of_start, 1, 1, 3, none) | ||||
| DEF(for_await_of_start, 1, 1, 3, none) | ||||
| DEF(    for_in_next, 1, 1, 3, none) | ||||
| DEF(    for_of_next, 2, 3, 5, u8) | ||||
| DEF(for_await_of_next, 1, 3, 4, none) | ||||
| DEF(iterator_get_value_done, 1, 1, 2, none) | ||||
| DEF( iterator_close, 1, 3, 0, none) | ||||
| DEF(iterator_close_return, 1, 4, 4, none) | ||||
| DEF(async_iterator_close, 1, 3, 2, none) | ||||
| DEF(async_iterator_next, 1, 4, 4, none) | ||||
| DEF(async_iterator_get, 2, 4, 5, u8) | ||||
| DEF(  initial_yield, 1, 0, 0, none) | ||||
| DEF(          yield, 1, 1, 2, none) | ||||
| DEF(     yield_star, 1, 2, 2, none) | ||||
| DEF(async_yield_star, 1, 1, 2, none) | ||||
| DEF(          await, 1, 1, 1, none) | ||||
|  | ||||
| /* arithmetic/logic operations */ | ||||
| DEF(            neg, 1, 1, 1, none) | ||||
| DEF(           plus, 1, 1, 1, none) | ||||
| DEF(            dec, 1, 1, 1, none) | ||||
| DEF(            inc, 1, 1, 1, none) | ||||
| DEF(       post_dec, 1, 1, 2, none) | ||||
| DEF(       post_inc, 1, 1, 2, none) | ||||
| DEF(        dec_loc, 2, 0, 0, loc8) | ||||
| DEF(        inc_loc, 2, 0, 0, loc8) | ||||
| DEF(        add_loc, 2, 1, 0, loc8) | ||||
| DEF(            not, 1, 1, 1, none) | ||||
| DEF(           lnot, 1, 1, 1, none) | ||||
| DEF(         typeof, 1, 1, 1, none) | ||||
| DEF(         delete, 1, 2, 1, none) | ||||
| DEF(     delete_var, 5, 0, 1, atom) | ||||
|  | ||||
| DEF(            mul, 1, 2, 1, none) | ||||
| DEF(            div, 1, 2, 1, none) | ||||
| DEF(            mod, 1, 2, 1, none) | ||||
| DEF(            add, 1, 2, 1, none) | ||||
| DEF(            sub, 1, 2, 1, none) | ||||
| DEF(            pow, 1, 2, 1, none) | ||||
| DEF(            shl, 1, 2, 1, none) | ||||
| DEF(            sar, 1, 2, 1, none) | ||||
| DEF(            shr, 1, 2, 1, none) | ||||
| DEF(             lt, 1, 2, 1, none) | ||||
| DEF(            lte, 1, 2, 1, none) | ||||
| DEF(             gt, 1, 2, 1, none) | ||||
| DEF(            gte, 1, 2, 1, none) | ||||
| DEF(     instanceof, 1, 2, 1, none) | ||||
| DEF(             in, 1, 2, 1, none) | ||||
| DEF(             eq, 1, 2, 1, none) | ||||
| DEF(            neq, 1, 2, 1, none) | ||||
| DEF(      strict_eq, 1, 2, 1, none) | ||||
| DEF(     strict_neq, 1, 2, 1, none) | ||||
| DEF(            and, 1, 2, 1, none) | ||||
| DEF(            xor, 1, 2, 1, none) | ||||
| DEF(             or, 1, 2, 1, none) | ||||
| #ifdef CONFIG_BIGNUM | ||||
| DEF(      mul_pow10, 1, 2, 1, none) | ||||
| DEF(       math_div, 1, 2, 1, none) | ||||
| DEF(       math_mod, 1, 2, 1, none) | ||||
| DEF(       math_pow, 1, 2, 1, none) | ||||
| #endif | ||||
| /* must be the last non short and non temporary opcode */ | ||||
| DEF(            nop, 1, 0, 0, none)  | ||||
|  | ||||
| /* temporary opcodes: never emitted in the final bytecode */ | ||||
|  | ||||
| def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */ | ||||
|  | ||||
| def(close_var_object, 1, 0, 0, none) /* emitted in phase 1, removed in phase 2 */ | ||||
| def(    enter_scope, 3, 0, 0, u16)  /* emitted in phase 1, removed in phase 2 */ | ||||
| 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(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_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ | ||||
| def(scope_delete_var, 7, 0, 1, atom_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_put_var_init, 7, 0, 2, atom_u16) /* 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_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, 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 */ | ||||
|  | ||||
| #if SHORT_OPCODES | ||||
| DEF(    push_minus1, 1, 0, 1, none_int) | ||||
| DEF(         push_0, 1, 0, 1, none_int) | ||||
| DEF(         push_1, 1, 0, 1, none_int) | ||||
| DEF(         push_2, 1, 0, 1, none_int) | ||||
| DEF(         push_3, 1, 0, 1, none_int) | ||||
| DEF(         push_4, 1, 0, 1, none_int) | ||||
| DEF(         push_5, 1, 0, 1, none_int) | ||||
| DEF(         push_6, 1, 0, 1, none_int) | ||||
| DEF(         push_7, 1, 0, 1, none_int) | ||||
| DEF(        push_i8, 2, 0, 1, i8) | ||||
| DEF(       push_i16, 3, 0, 1, i16) | ||||
| DEF(    push_const8, 2, 0, 1, const8) | ||||
| DEF(      fclosure8, 2, 0, 1, const8) /* must follow push_const8 */ | ||||
| DEF(push_empty_string, 1, 0, 1, none) | ||||
|  | ||||
| DEF(       get_loc8, 2, 0, 1, loc8) | ||||
| DEF(       put_loc8, 2, 1, 0, loc8) | ||||
| DEF(       set_loc8, 2, 1, 1, loc8) | ||||
|  | ||||
| DEF(       get_loc0, 1, 0, 1, none_loc) | ||||
| DEF(       get_loc1, 1, 0, 1, none_loc) | ||||
| DEF(       get_loc2, 1, 0, 1, none_loc) | ||||
| DEF(       get_loc3, 1, 0, 1, none_loc) | ||||
| DEF(       put_loc0, 1, 1, 0, none_loc) | ||||
| DEF(       put_loc1, 1, 1, 0, none_loc) | ||||
| DEF(       put_loc2, 1, 1, 0, none_loc) | ||||
| DEF(       put_loc3, 1, 1, 0, none_loc) | ||||
| DEF(       set_loc0, 1, 1, 1, none_loc) | ||||
| DEF(       set_loc1, 1, 1, 1, none_loc) | ||||
| DEF(       set_loc2, 1, 1, 1, none_loc) | ||||
| DEF(       set_loc3, 1, 1, 1, none_loc) | ||||
| DEF(       get_arg0, 1, 0, 1, none_arg) | ||||
| DEF(       get_arg1, 1, 0, 1, none_arg) | ||||
| DEF(       get_arg2, 1, 0, 1, none_arg) | ||||
| DEF(       get_arg3, 1, 0, 1, none_arg) | ||||
| DEF(       put_arg0, 1, 1, 0, none_arg) | ||||
| DEF(       put_arg1, 1, 1, 0, none_arg) | ||||
| DEF(       put_arg2, 1, 1, 0, none_arg) | ||||
| DEF(       put_arg3, 1, 1, 0, none_arg) | ||||
| DEF(       set_arg0, 1, 1, 1, none_arg) | ||||
| DEF(       set_arg1, 1, 1, 1, none_arg) | ||||
| DEF(       set_arg2, 1, 1, 1, none_arg) | ||||
| DEF(       set_arg3, 1, 1, 1, none_arg) | ||||
| DEF(   get_var_ref0, 1, 0, 1, none_var_ref) | ||||
| DEF(   get_var_ref1, 1, 0, 1, none_var_ref) | ||||
| DEF(   get_var_ref2, 1, 0, 1, none_var_ref) | ||||
| DEF(   get_var_ref3, 1, 0, 1, none_var_ref) | ||||
| DEF(   put_var_ref0, 1, 1, 0, none_var_ref) | ||||
| DEF(   put_var_ref1, 1, 1, 0, none_var_ref) | ||||
| DEF(   put_var_ref2, 1, 1, 0, none_var_ref) | ||||
| DEF(   put_var_ref3, 1, 1, 0, none_var_ref) | ||||
| DEF(   set_var_ref0, 1, 1, 1, none_var_ref) | ||||
| DEF(   set_var_ref1, 1, 1, 1, none_var_ref) | ||||
| DEF(   set_var_ref2, 1, 1, 1, none_var_ref) | ||||
| DEF(   set_var_ref3, 1, 1, 1, none_var_ref) | ||||
|  | ||||
| DEF(     get_length, 1, 1, 1, none) | ||||
|  | ||||
| DEF(      if_false8, 2, 1, 0, label8) | ||||
| DEF(       if_true8, 2, 1, 0, label8) /* must come after if_false8 */ | ||||
| DEF(          goto8, 2, 0, 0, label8) /* must come after if_true8 */ | ||||
| DEF(         goto16, 3, 0, 0, label16) | ||||
|  | ||||
| DEF(          call0, 1, 1, 1, npopx) | ||||
| DEF(          call1, 1, 1, 1, npopx) | ||||
| DEF(          call2, 1, 1, 1, npopx) | ||||
| DEF(          call3, 1, 1, 1, npopx) | ||||
|  | ||||
| DEF(   is_undefined, 1, 1, 1, none) | ||||
| DEF(        is_null, 1, 1, 1, none) | ||||
| DEF(    is_function, 1, 1, 1, none) | ||||
| #endif | ||||
|  | ||||
| #undef DEF | ||||
| #undef def | ||||
| #endif  /* DEF */ | ||||
							
								
								
									
										50241
									
								
								deps/quickjs/quickjs.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50241
									
								
								deps/quickjs/quickjs.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										914
									
								
								deps/quickjs/quickjs.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										914
									
								
								deps/quickjs/quickjs.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,914 @@ | ||||
| /* | ||||
|  * QuickJS Javascript Engine | ||||
|  * | ||||
|  * Copyright (c) 2017-2019 Fabrice Bellard | ||||
|  * Copyright (c) 2017-2019 Charlie Gordon | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef QUICKJS_H | ||||
| #define QUICKJS_H | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #if defined(__GNUC__) || defined(__clang__) | ||||
| #define js_likely(x)          __builtin_expect(!!(x), 1) | ||||
| #define js_unlikely(x)        __builtin_expect(!!(x), 0) | ||||
| #define js_force_inline       inline __attribute__((always_inline)) | ||||
| #define __js_printf_like(f, a)   __attribute__((format(printf, f, a))) | ||||
| #else | ||||
| #define js_likely(x)     (x) | ||||
| #define js_unlikely(x)   (x) | ||||
| #define js_force_inline  inline | ||||
| #define __js_printf_like(a, b) | ||||
| #endif | ||||
|  | ||||
| #define JS_BOOL int | ||||
|  | ||||
| typedef struct JSRuntime JSRuntime; | ||||
| typedef struct JSContext JSContext; | ||||
| typedef struct JSObject JSObject; | ||||
| typedef struct JSClass JSClass; | ||||
| typedef uint32_t JSClassID; | ||||
| typedef uint32_t JSAtom; | ||||
|  | ||||
| #if defined(__x86_64__) || defined(__aarch64__) | ||||
| #define JS_PTR64 | ||||
| #define JS_PTR64_DEF(a) a | ||||
| #else | ||||
| #define JS_PTR64_DEF(a) | ||||
| #endif | ||||
|  | ||||
| #ifndef JS_PTR64 | ||||
| #define JS_NAN_BOXING | ||||
| #endif | ||||
|  | ||||
| enum { | ||||
|     /* all tags with a reference count are negative */ | ||||
|     JS_TAG_FIRST       = -10, /* first negative tag */ | ||||
|     JS_TAG_BIG_INT     = -10, | ||||
|     JS_TAG_BIG_FLOAT   = -9, | ||||
|     JS_TAG_SYMBOL      = -8, | ||||
|     JS_TAG_STRING      = -7, | ||||
|     JS_TAG_SHAPE       = -6, /* used internally during GC */ | ||||
|     JS_TAG_ASYNC_FUNCTION = -5, /* used internally during GC */ | ||||
|     JS_TAG_VAR_REF     = -4, /* used internally during GC */ | ||||
|     JS_TAG_MODULE      = -3, /* used internally */ | ||||
|     JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ | ||||
|     JS_TAG_OBJECT      = -1, | ||||
|  | ||||
|     JS_TAG_INT         = 0, | ||||
|     JS_TAG_BOOL        = 1, | ||||
|     JS_TAG_NULL        = 2, | ||||
|     JS_TAG_UNDEFINED   = 3, | ||||
|     JS_TAG_UNINITIALIZED = 4, | ||||
|     JS_TAG_CATCH_OFFSET = 5, | ||||
|     JS_TAG_EXCEPTION   = 6, | ||||
|     JS_TAG_FLOAT64     = 7, | ||||
|     /* any larger tag is FLOAT64 if JS_NAN_BOXING */ | ||||
| }; | ||||
|  | ||||
| typedef struct JSRefCountHeader { | ||||
|     int ref_count; | ||||
| } JSRefCountHeader; | ||||
|  | ||||
| #define JS_FLOAT64_NAN NAN | ||||
|  | ||||
| #ifdef CONFIG_CHECK_JSVALUE | ||||
| /* JSValue consistency : it is not possible to run the code in this | ||||
|    mode, but it is useful to detect simple reference counting | ||||
|    errors. It would be interesting to modify a static C analyzer to | ||||
|    handle specific annotations (clang has such annotations but only | ||||
|    for objective C) */ | ||||
| typedef struct __JSValue *JSValue; | ||||
| typedef const struct __JSValue *JSValueConst; | ||||
|  | ||||
| #define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf) | ||||
| /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ | ||||
| #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) | ||||
| #define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4) | ||||
| #define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v) | ||||
| #define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v) | ||||
| #define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf) | ||||
|  | ||||
| #define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag)) | ||||
| #define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag)) | ||||
|  | ||||
| #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) | ||||
|  | ||||
| #define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1) | ||||
|  | ||||
| static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) | ||||
| { | ||||
|     return JS_MKVAL(JS_TAG_FLOAT64, (int)d); | ||||
| } | ||||
|  | ||||
| #elif defined(JS_NAN_BOXING) | ||||
|  | ||||
| typedef uint64_t JSValue; | ||||
|  | ||||
| #define JSValueConst JSValue | ||||
|  | ||||
| #define JS_VALUE_GET_TAG(v) (int)((v) >> 32) | ||||
| #define JS_VALUE_GET_INT(v) (int)(v) | ||||
| #define JS_VALUE_GET_BOOL(v) (int)(v) | ||||
| #define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v) | ||||
|  | ||||
| #define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val)) | ||||
| #define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr)) | ||||
|  | ||||
| #define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */ | ||||
|  | ||||
| static inline double JS_VALUE_GET_FLOAT64(JSValue v) | ||||
| { | ||||
|     union { | ||||
|         JSValue v; | ||||
|         double d; | ||||
|     } u; | ||||
|     u.v = v; | ||||
|     u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32; | ||||
|     return u.d; | ||||
| } | ||||
|  | ||||
| #define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) | ||||
|  | ||||
| static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) | ||||
| { | ||||
|     union { | ||||
|         double d; | ||||
|         uint64_t u64; | ||||
|     } u; | ||||
|     JSValue v; | ||||
|     u.d = d; | ||||
|     /* normalize NaN */ | ||||
|     if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)) | ||||
|         v = JS_NAN; | ||||
|     else | ||||
|         v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); | ||||
|     return v; | ||||
| } | ||||
|  | ||||
| #define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST)) | ||||
|  | ||||
| /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ | ||||
| static inline int JS_VALUE_GET_NORM_TAG(JSValue v) | ||||
| { | ||||
|     uint32_t tag; | ||||
|     tag = JS_VALUE_GET_TAG(v); | ||||
|     if (JS_TAG_IS_FLOAT64(tag)) | ||||
|         return JS_TAG_FLOAT64; | ||||
|     else | ||||
|         return tag; | ||||
| } | ||||
|  | ||||
| #else /* !JS_NAN_BOXING */ | ||||
|  | ||||
| typedef union JSValueUnion { | ||||
|     int32_t int32; | ||||
|     double float64; | ||||
|     void *ptr; | ||||
| } JSValueUnion; | ||||
|  | ||||
| typedef struct JSValue { | ||||
|     JSValueUnion u; | ||||
|     int64_t tag; | ||||
| } JSValue; | ||||
|  | ||||
| #define JSValueConst JSValue | ||||
|  | ||||
| #define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag) | ||||
| /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ | ||||
| #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) | ||||
| #define JS_VALUE_GET_INT(v) ((v).u.int32) | ||||
| #define JS_VALUE_GET_BOOL(v) ((v).u.int32) | ||||
| #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) | ||||
| #define JS_VALUE_GET_PTR(v) ((v).u.ptr) | ||||
|  | ||||
| #define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } | ||||
| #define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } | ||||
|  | ||||
| #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) | ||||
|  | ||||
| #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 } | ||||
|  | ||||
| static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) | ||||
| { | ||||
|     JSValue v; | ||||
|     v.tag = JS_TAG_FLOAT64; | ||||
|     v.u.float64 = d; | ||||
|     return v; | ||||
| } | ||||
|  | ||||
| #endif /* !JS_NAN_BOXING */ | ||||
|  | ||||
| #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) | ||||
| #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) | ||||
|  | ||||
| #define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) | ||||
| #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) | ||||
| #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) | ||||
|  | ||||
| /* special values */ | ||||
| #define JS_NULL      JS_MKVAL(JS_TAG_NULL, 0) | ||||
| #define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0) | ||||
| #define JS_FALSE     JS_MKVAL(JS_TAG_BOOL, 0) | ||||
| #define JS_TRUE      JS_MKVAL(JS_TAG_BOOL, 1) | ||||
| #define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0) | ||||
| #define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0) | ||||
|  | ||||
| /* flags for object properties */ | ||||
| #define JS_PROP_CONFIGURABLE  (1 << 0) | ||||
| #define JS_PROP_WRITABLE      (1 << 1) | ||||
| #define JS_PROP_ENUMERABLE    (1 << 2) | ||||
| #define JS_PROP_C_W_E         (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE) | ||||
| #define JS_PROP_LENGTH        (1 << 3) /* used internally in Arrays */ | ||||
| #define JS_PROP_TMASK         (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */ | ||||
| #define JS_PROP_NORMAL         (0 << 4) | ||||
| #define JS_PROP_GETSET         (1 << 4) | ||||
| #define JS_PROP_VARREF         (2 << 4) /* used internally */ | ||||
| #define JS_PROP_AUTOINIT       (3 << 4) /* used internally */ | ||||
|  | ||||
| /* flags for JS_DefineProperty */ | ||||
| #define JS_PROP_HAS_SHIFT        8 | ||||
| #define JS_PROP_HAS_CONFIGURABLE (1 << 8) | ||||
| #define JS_PROP_HAS_WRITABLE     (1 << 9) | ||||
| #define JS_PROP_HAS_ENUMERABLE   (1 << 10) | ||||
| #define JS_PROP_HAS_GET          (1 << 11) | ||||
| #define JS_PROP_HAS_SET          (1 << 12) | ||||
| #define JS_PROP_HAS_VALUE        (1 << 13) | ||||
|  | ||||
| /* throw an exception if false would be returned | ||||
|    (JS_DefineProperty/JS_SetProperty) */ | ||||
| #define JS_PROP_THROW            (1 << 14) | ||||
| /* throw an exception if false would be returned in strict mode | ||||
|    (JS_SetProperty) */ | ||||
| #define JS_PROP_THROW_STRICT     (1 << 15) | ||||
|  | ||||
| #define JS_PROP_NO_ADD           (1 << 16) /* internal use */ | ||||
| #define JS_PROP_NO_EXOTIC        (1 << 17) /* internal use */ | ||||
|  | ||||
| #define JS_DEFAULT_STACK_SIZE (256 * 1024) | ||||
|  | ||||
| /* JS_Eval() flags */ | ||||
| #define JS_EVAL_TYPE_GLOBAL   (0 << 0) /* global code (default) */ | ||||
| #define JS_EVAL_TYPE_MODULE   (1 << 0) /* module code */ | ||||
| #define JS_EVAL_TYPE_DIRECT   (2 << 0) /* direct call (internal use) */ | ||||
| #define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */ | ||||
| #define JS_EVAL_TYPE_MASK     (3 << 0) | ||||
|  | ||||
| #define JS_EVAL_FLAG_STRICT   (1 << 3) /* force 'strict' mode */ | ||||
| #define JS_EVAL_FLAG_STRIP    (1 << 4) /* force 'strip' mode */ | ||||
| /* compile but do not run. The result is an object with a | ||||
|    JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed | ||||
|    with JS_EvalFunction(). */ | ||||
| #define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) | ||||
|  | ||||
| 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 JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data); | ||||
|  | ||||
| typedef struct JSMallocState { | ||||
|     size_t malloc_count; | ||||
|     size_t malloc_size; | ||||
|     size_t malloc_limit; | ||||
|     void *opaque; /* user opaque */ | ||||
| } JSMallocState; | ||||
|  | ||||
| typedef struct JSMallocFunctions { | ||||
|     void *(*js_malloc)(JSMallocState *s, size_t size); | ||||
|     void (*js_free)(JSMallocState *s, void *ptr); | ||||
|     void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size); | ||||
|     size_t (*js_malloc_usable_size)(const void *ptr); | ||||
| } JSMallocFunctions; | ||||
|  | ||||
| JSRuntime *JS_NewRuntime(void); | ||||
| /* info lifetime must exceed that of rt */ | ||||
| void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); | ||||
| void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); | ||||
| void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold); | ||||
| JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); | ||||
| void JS_FreeRuntime(JSRuntime *rt); | ||||
| typedef void JS_MarkFunc(JSRuntime *rt, JSValueConst val); | ||||
| void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); | ||||
| void JS_RunGC(JSRuntime *rt); | ||||
| JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj); | ||||
| JS_BOOL JS_IsInGCSweep(JSRuntime *rt); | ||||
|  | ||||
| JSContext *JS_NewContext(JSRuntime *rt); | ||||
| void JS_FreeContext(JSContext *s); | ||||
| void *JS_GetContextOpaque(JSContext *ctx); | ||||
| void JS_SetContextOpaque(JSContext *ctx, void *opaque); | ||||
| JSRuntime *JS_GetRuntime(JSContext *ctx); | ||||
| void JS_SetMaxStackSize(JSContext *ctx, size_t stack_size); | ||||
| void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj); | ||||
| JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); | ||||
|  | ||||
| /* the following functions are used to select the intrinsic object to | ||||
|    save memory */ | ||||
| JSContext *JS_NewContextRaw(JSRuntime *rt); | ||||
| void JS_AddIntrinsicBaseObjects(JSContext *ctx); | ||||
| void JS_AddIntrinsicDate(JSContext *ctx); | ||||
| void JS_AddIntrinsicEval(JSContext *ctx); | ||||
| void JS_AddIntrinsicStringNormalize(JSContext *ctx); | ||||
| void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); | ||||
| void JS_AddIntrinsicRegExp(JSContext *ctx); | ||||
| void JS_AddIntrinsicJSON(JSContext *ctx); | ||||
| void JS_AddIntrinsicProxy(JSContext *ctx); | ||||
| void JS_AddIntrinsicMapSet(JSContext *ctx); | ||||
| void JS_AddIntrinsicTypedArrays(JSContext *ctx); | ||||
| void JS_AddIntrinsicPromise(JSContext *ctx); | ||||
| JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, | ||||
|                                  int argc, JSValueConst *argv); | ||||
|  | ||||
| void *js_malloc_rt(JSRuntime *rt, size_t size); | ||||
| void js_free_rt(JSRuntime *rt, void *ptr); | ||||
| void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size); | ||||
| size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr); | ||||
| void *js_mallocz_rt(JSRuntime *rt, size_t size); | ||||
|  | ||||
| void *js_malloc(JSContext *ctx, size_t size); | ||||
| void js_free(JSContext *ctx, void *ptr); | ||||
| void *js_realloc(JSContext *ctx, void *ptr, size_t size); | ||||
| size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); | ||||
| void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); | ||||
| void *js_mallocz(JSContext *ctx, size_t size); | ||||
| char *js_strdup(JSContext *ctx, const char *str); | ||||
| char *js_strndup(JSContext *ctx, const char *s, size_t n); | ||||
|  | ||||
| typedef struct JSMemoryUsage { | ||||
|     int64_t malloc_size, malloc_limit, memory_used_size; | ||||
|     int64_t malloc_count; | ||||
|     int64_t memory_used_count; | ||||
|     int64_t atom_count, atom_size; | ||||
|     int64_t str_count, str_size; | ||||
|     int64_t obj_count, obj_size; | ||||
|     int64_t prop_count, prop_size; | ||||
|     int64_t shape_count, shape_size; | ||||
|     int64_t js_func_count, js_func_size, js_func_code_size; | ||||
|     int64_t js_func_pc2line_count, js_func_pc2line_size; | ||||
|     int64_t c_func_count, array_count; | ||||
|     int64_t fast_array_count, fast_array_elements; | ||||
|     int64_t binary_object_count, binary_object_size; | ||||
| } JSMemoryUsage; | ||||
|  | ||||
| void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); | ||||
| void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt); | ||||
|  | ||||
| /* atom support */ | ||||
| JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); | ||||
| JSAtom JS_NewAtom(JSContext *ctx, const char *str); | ||||
| JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); | ||||
| JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); | ||||
| void JS_FreeAtom(JSContext *ctx, JSAtom v); | ||||
| void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); | ||||
| JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); | ||||
| JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); | ||||
| const char *JS_AtomToCString(JSContext *ctx, JSAtom atom); | ||||
| JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); | ||||
|  | ||||
| /* object class support */ | ||||
|  | ||||
| typedef struct JSPropertyEnum { | ||||
|     JS_BOOL is_enumerable; | ||||
|     JSAtom atom; | ||||
| } JSPropertyEnum; | ||||
|  | ||||
| typedef struct JSPropertyDescriptor { | ||||
|     int flags; | ||||
|     JSValue value; | ||||
|     JSValue getter; | ||||
|     JSValue setter; | ||||
| } JSPropertyDescriptor; | ||||
|  | ||||
| typedef struct JSClassExoticMethods { | ||||
|     /* Return -1 if exception (can only happen in case of Proxy object), | ||||
|        FALSE if the property does not exists, TRUE if it exists. If 1 is | ||||
|        returned, the property descriptor 'desc' is filled if != NULL. */ | ||||
|     int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, | ||||
|                              JSValueConst obj, JSAtom prop); | ||||
|     /* '*ptab' should hold the '*plen' property keys. Return 0 if OK, | ||||
|        -1 if exception. The 'is_enumerable' field is ignored. | ||||
|     */ | ||||
|     int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab, | ||||
|                                   uint32_t *plen, | ||||
|                                   JSValueConst obj); | ||||
|     /* return < 0 if exception, or TRUE/FALSE */ | ||||
|     int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); | ||||
|     /* return < 0 if exception or TRUE/FALSE */ | ||||
|     int (*define_own_property)(JSContext *ctx, JSValueConst this_obj, | ||||
|                                JSAtom prop, JSValueConst val, | ||||
|                                JSValueConst getter, JSValueConst setter, | ||||
|                                int flags); | ||||
|     /* The following methods can be emulated with the previous ones, | ||||
|        so they are usually not needed */ | ||||
|     /* return < 0 if exception or TRUE/FALSE */ | ||||
|     int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom); | ||||
|     JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, | ||||
|                             JSValueConst receiver); | ||||
|     /* return < 0 if exception or TRUE/FALSE */ | ||||
|     int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, | ||||
|                         JSValueConst value, JSValueConst receiver, int flags); | ||||
| } JSClassExoticMethods; | ||||
|  | ||||
| typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); | ||||
| typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, | ||||
|                            JS_MarkFunc *mark_func); | ||||
| typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj, | ||||
|                             JSValueConst this_val, int argc, JSValueConst *argv); | ||||
|  | ||||
| typedef struct JSClassDef { | ||||
|     const char *class_name; | ||||
|     JSClassFinalizer *finalizer; | ||||
|     JSClassGCMark *gc_mark; | ||||
|     JSClassCall *call; | ||||
|     /* XXX: suppress this indirection ? It is here only to save memory | ||||
|        because only a few classes need these methods */ | ||||
|     JSClassExoticMethods *exotic; | ||||
| } JSClassDef; | ||||
|  | ||||
| JSClassID JS_NewClassID(JSClassID *pclass_id); | ||||
| int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); | ||||
| int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); | ||||
|  | ||||
| /* value handling */ | ||||
|  | ||||
| static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) | ||||
| { | ||||
|     return JS_MKVAL(JS_TAG_BOOL, val); | ||||
| } | ||||
|  | ||||
| static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) | ||||
| { | ||||
|     return JS_MKVAL(JS_TAG_INT, val); | ||||
| } | ||||
|  | ||||
| static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) | ||||
| { | ||||
|     return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); | ||||
| } | ||||
|  | ||||
| JSValue JS_NewInt64(JSContext *ctx, int64_t v); | ||||
| JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); | ||||
| JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); | ||||
|  | ||||
| static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d) | ||||
| { | ||||
|     JSValue v; | ||||
|     int32_t val; | ||||
|     union { | ||||
|         double d; | ||||
|         uint64_t u; | ||||
|     } u, t; | ||||
|     u.d = d; | ||||
|     val = (int32_t)d; | ||||
|     t.d = val; | ||||
|     /* -0 cannot be represented as integer, so we compare the bit | ||||
|         representation */ | ||||
|     if (u.u == t.u) { | ||||
|         v = JS_MKVAL(JS_TAG_INT, val); | ||||
|     } else { | ||||
|         v = __JS_NewFloat64(ctx, d); | ||||
|     } | ||||
|     return v; | ||||
| } | ||||
|  | ||||
| JS_BOOL JS_IsNumber(JSValueConst v); | ||||
|  | ||||
| static inline JS_BOOL JS_IsInteger(JSValueConst v) | ||||
| { | ||||
|     int tag = JS_VALUE_GET_TAG(v); | ||||
|     return tag == JS_TAG_INT || tag == JS_TAG_BIG_INT; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsBigFloat(JSValueConst v) | ||||
| { | ||||
|     int tag = JS_VALUE_GET_TAG(v); | ||||
|     return tag == JS_TAG_BIG_FLOAT; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsBool(JSValueConst v) | ||||
| { | ||||
|     return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsNull(JSValueConst v) | ||||
| { | ||||
|     return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsUndefined(JSValueConst v) | ||||
| { | ||||
|     return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsException(JSValueConst v) | ||||
| { | ||||
|     return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION); | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsUninitialized(JSValueConst v) | ||||
| { | ||||
|     return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED); | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsString(JSValueConst v) | ||||
| { | ||||
|     return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsSymbol(JSValueConst v) | ||||
| { | ||||
|     return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; | ||||
| } | ||||
|  | ||||
| static inline JS_BOOL JS_IsObject(JSValueConst v) | ||||
| { | ||||
|     return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; | ||||
| } | ||||
|  | ||||
| JSValue JS_Throw(JSContext *ctx, JSValue obj); | ||||
| JSValue JS_GetException(JSContext *ctx); | ||||
| JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val); | ||||
| void JS_EnableIsErrorProperty(JSContext *ctx, JS_BOOL enable); | ||||
| void JS_ResetUncatchableError(JSContext *ctx); | ||||
| JSValue JS_NewError(JSContext *ctx); | ||||
| JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...); | ||||
| JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...); | ||||
| JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...); | ||||
| JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...); | ||||
| JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); | ||||
| JSValue JS_ThrowOutOfMemory(JSContext *ctx); | ||||
|  | ||||
| void __JS_FreeValue(JSContext *ctx, JSValue v); | ||||
| static inline void JS_FreeValue(JSContext *ctx, JSValue v) | ||||
| { | ||||
|     if (JS_VALUE_HAS_REF_COUNT(v)) { | ||||
|         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); | ||||
|         if (--p->ref_count <= 0) { | ||||
|             __JS_FreeValue(ctx, v); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| void __JS_FreeValueRT(JSRuntime *rt, JSValue v); | ||||
| static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) | ||||
| { | ||||
|     if (JS_VALUE_HAS_REF_COUNT(v)) { | ||||
|         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); | ||||
|         if (--p->ref_count <= 0) { | ||||
|             __JS_FreeValueRT(rt, v); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) | ||||
| { | ||||
|     if (JS_VALUE_HAS_REF_COUNT(v)) { | ||||
|         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); | ||||
|         p->ref_count++; | ||||
|     } | ||||
|     return (JSValue)v; | ||||
| } | ||||
|  | ||||
| static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) | ||||
| { | ||||
|     if (JS_VALUE_HAS_REF_COUNT(v)) { | ||||
|         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); | ||||
|         p->ref_count++; | ||||
|     } | ||||
|     return (JSValue)v; | ||||
| } | ||||
|  | ||||
| int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ | ||||
| int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val); | ||||
| static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) | ||||
| { | ||||
|     return JS_ToInt32(ctx, (int32_t*)pres, val); | ||||
| } | ||||
| int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val); | ||||
| int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val); | ||||
| int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val); | ||||
| int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); | ||||
|  | ||||
| JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); | ||||
| JSValue JS_NewString(JSContext *ctx, const char *str); | ||||
| JSValue JS_NewAtomString(JSContext *ctx, const char *str); | ||||
| JSValue JS_ToString(JSContext *ctx, JSValueConst val); | ||||
| JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val); | ||||
| const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8); | ||||
| static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1) | ||||
| { | ||||
|     return JS_ToCStringLen2(ctx, plen, val1, 0); | ||||
| } | ||||
| static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) | ||||
| { | ||||
|     return JS_ToCStringLen2(ctx, NULL, val1, 0); | ||||
| } | ||||
| void JS_FreeCString(JSContext *ctx, const char *ptr); | ||||
|  | ||||
| JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id); | ||||
| JSValue JS_NewObjectClass(JSContext *ctx, int class_id); | ||||
| JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto); | ||||
| JSValue JS_NewObject(JSContext *ctx); | ||||
|  | ||||
| JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val); | ||||
| JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val); | ||||
|  | ||||
| JSValue JS_NewArray(JSContext *ctx); | ||||
| int JS_IsArray(JSContext *ctx, JSValueConst val); | ||||
|  | ||||
| JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, | ||||
|                                JSAtom prop, JSValueConst receiver, | ||||
|                                JS_BOOL throw_ref_error); | ||||
| static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj, | ||||
|                                               JSAtom prop) | ||||
| { | ||||
|     return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0); | ||||
| } | ||||
| JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, | ||||
|                           const char *prop); | ||||
| JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, | ||||
|                              uint32_t idx); | ||||
|  | ||||
| int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, | ||||
|                            JSAtom prop, JSValue val, | ||||
|                            int flags); | ||||
| static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, | ||||
|                                  JSAtom prop, JSValue val) | ||||
| { | ||||
|     return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW); | ||||
| } | ||||
| int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, | ||||
|                          uint32_t idx, JSValue val); | ||||
| int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, | ||||
|                         int64_t idx, JSValue val); | ||||
| int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, | ||||
|                       const char *prop, JSValue val); | ||||
| int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); | ||||
| int JS_IsExtensible(JSContext *ctx, JSValueConst obj); | ||||
| int JS_PreventExtensions(JSContext *ctx, JSValueConst obj); | ||||
| int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); | ||||
| int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); | ||||
| JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val); | ||||
|  | ||||
| #define JS_GPN_STRING_MASK  (1 << 0) | ||||
| #define JS_GPN_SYMBOL_MASK  (1 << 1) | ||||
| #define JS_GPN_PRIVATE_MASK (1 << 2) | ||||
| /* only include the enumerable properties */ | ||||
| #define JS_GPN_ENUM_ONLY    (1 << 4) | ||||
| /* set theJSPropertyEnum.is_enumerable field */ | ||||
| #define JS_GPN_SET_ENUM     (1 << 5) | ||||
|  | ||||
| int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, | ||||
|                            uint32_t *plen, JSValueConst obj, int flags); | ||||
| int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, | ||||
|                       JSValueConst obj, JSAtom prop); | ||||
|  | ||||
| JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, | ||||
|                      const char *filename); | ||||
| JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, | ||||
|                 int argc, JSValueConst *argv); | ||||
| JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom, | ||||
|                   int argc, JSValueConst *argv); | ||||
| JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, | ||||
|                            int argc, JSValueConst *argv); | ||||
| JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, | ||||
|                             JSValueConst new_target, | ||||
|                             int argc, JSValueConst *argv); | ||||
| JS_BOOL JS_DetectModule(const char *input, size_t input_len); | ||||
| JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, | ||||
|                 const char *filename, int eval_flags); | ||||
| JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); | ||||
| JSValue JS_GetGlobalObject(JSContext *ctx); | ||||
| int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); | ||||
| int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, | ||||
|                       JSAtom prop, JSValueConst val, | ||||
|                       JSValueConst getter, JSValueConst setter, int flags); | ||||
| int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, | ||||
|                            JSAtom prop, JSValue val, int flags); | ||||
| int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, | ||||
|                                  uint32_t idx, JSValue val, int flags); | ||||
| int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, | ||||
|                               const char *prop, JSValue val, int flags); | ||||
| int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, | ||||
|                             JSAtom prop, JSValue getter, JSValue setter, | ||||
|                             int flags); | ||||
| void JS_SetOpaque(JSValue obj, void *opaque); | ||||
| void *JS_GetOpaque(JSValueConst obj, JSClassID class_id); | ||||
| void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id); | ||||
|  | ||||
| typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); | ||||
| JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, | ||||
|                           JSFreeArrayBufferDataFunc *free_func, void *opaque, | ||||
|                           JS_BOOL is_shared); | ||||
| JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); | ||||
| void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); | ||||
| uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); | ||||
|  | ||||
| JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); | ||||
|  | ||||
| /* return != 0 if the JS code needs to be interrupted */ | ||||
| typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); | ||||
| void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); | ||||
| /* if can_block is TRUE, Atomics.wait() can be used */ | ||||
| void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); | ||||
|  | ||||
| typedef struct JSModuleDef JSModuleDef; | ||||
|  | ||||
| /* return the module specifier (allocated with js_malloc()) or NULL if | ||||
|    exception */ | ||||
| typedef char *JSModuleNormalizeFunc(JSContext *ctx, | ||||
|                                     const char *module_base_name, | ||||
|                                     const char *module_name, void *opaque); | ||||
| typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, | ||||
|                                         const char *module_name, void *opaque); | ||||
|  | ||||
| /* module_normalize = NULL is allowed and invokes the default module | ||||
|    filename normalizer */ | ||||
| void JS_SetModuleLoaderFunc(JSRuntime *rt, | ||||
|                             JSModuleNormalizeFunc *module_normalize, | ||||
|                             JSModuleLoaderFunc *module_loader, void *opaque); | ||||
| /* return the import.meta object of a module */ | ||||
| JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); | ||||
| JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); | ||||
|  | ||||
| /* JS Job support */ | ||||
|  | ||||
| typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv); | ||||
| int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv); | ||||
|  | ||||
| JS_BOOL JS_IsJobPending(JSRuntime *rt); | ||||
| int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); | ||||
|  | ||||
| /* Object Writer/Reader (currently only used to handle precompiled code) */ | ||||
| #define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */ | ||||
| #define JS_WRITE_OBJ_BSWAP    (1 << 1) /* byte swapped output */ | ||||
| uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, | ||||
|                         int flags); | ||||
| #define JS_READ_OBJ_BYTECODE  (1 << 0) /* allow function/module */ | ||||
| #define JS_READ_OBJ_ROM_DATA  (1 << 1) /* avoid duplicating 'buf' data */ | ||||
| JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, | ||||
|                       int flags); | ||||
| /* load the dependencies of the module 'obj'. Useful when JS_ReadObject() | ||||
|    returns a module. */ | ||||
| int JS_ResolveModule(JSContext *ctx, JSValueConst obj); | ||||
|  | ||||
| /* C function definition */ | ||||
| typedef enum JSCFunctionEnum {  /* XXX: should rename for namespace isolation */ | ||||
|     JS_CFUNC_generic, | ||||
|     JS_CFUNC_generic_magic, | ||||
|     JS_CFUNC_constructor, | ||||
|     JS_CFUNC_constructor_magic, | ||||
|     JS_CFUNC_constructor_or_func, | ||||
|     JS_CFUNC_constructor_or_func_magic, | ||||
|     JS_CFUNC_f_f, | ||||
|     JS_CFUNC_f_f_f, | ||||
|     JS_CFUNC_getter, | ||||
|     JS_CFUNC_setter, | ||||
|     JS_CFUNC_getter_magic, | ||||
|     JS_CFUNC_setter_magic, | ||||
|     JS_CFUNC_iterator_next, | ||||
| } JSCFunctionEnum; | ||||
|  | ||||
| typedef union JSCFunctionType { | ||||
|     JSCFunction *generic; | ||||
|     JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); | ||||
|     JSCFunction *constructor; | ||||
|     JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); | ||||
|     JSCFunction *constructor_or_func; | ||||
|     double (*f_f)(double); | ||||
|     double (*f_f_f)(double, double); | ||||
|     JSValue (*getter)(JSContext *ctx, JSValueConst this_val); | ||||
|     JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val); | ||||
|     JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic); | ||||
|     JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic); | ||||
|     JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val, | ||||
|                              int argc, JSValueConst *argv, int *pdone, int magic); | ||||
| } JSCFunctionType; | ||||
|  | ||||
| JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, | ||||
|                          const char *name, | ||||
|                          int length, JSCFunctionEnum cproto, int magic); | ||||
| JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, | ||||
|                             int length, int magic, int data_len, | ||||
|                             JSValueConst *data); | ||||
|  | ||||
| static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, | ||||
|                                       int length) | ||||
| { | ||||
|     return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0); | ||||
| } | ||||
|  | ||||
| static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, | ||||
|                                            const char *name, | ||||
|                                            int length, JSCFunctionEnum cproto, int magic) | ||||
| { | ||||
|     return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic); | ||||
| } | ||||
|  | ||||
| /* C property definition */ | ||||
|  | ||||
| typedef struct JSCFunctionListEntry { | ||||
|     const char *name; | ||||
|     uint8_t prop_flags; | ||||
|     uint8_t def_type; | ||||
|     int16_t magic; | ||||
|     union { | ||||
|         struct { | ||||
|             uint8_t length; /* XXX: should move outside union */ | ||||
|             uint8_t cproto; /* XXX: should move outside union */ | ||||
|             JSCFunctionType cfunc; | ||||
|         } func; | ||||
|         struct { | ||||
|             JSCFunctionType get; | ||||
|             JSCFunctionType set; | ||||
|         } getset; | ||||
|         struct { | ||||
|             const char *name; | ||||
|             int base; | ||||
|         } alias; | ||||
|         struct { | ||||
|             const struct JSCFunctionListEntry *tab; | ||||
|             int len; | ||||
|         } prop_list; | ||||
|         const char *str; | ||||
|         int32_t i32; | ||||
|         int64_t i64; | ||||
|         double f64; | ||||
|     } u; | ||||
| } JSCFunctionListEntry; | ||||
|  | ||||
| #define JS_DEF_CFUNC          0 | ||||
| #define JS_DEF_CGETSET        1 | ||||
| #define JS_DEF_CGETSET_MAGIC  2 | ||||
| #define JS_DEF_PROP_STRING    3 | ||||
| #define JS_DEF_PROP_INT32     4 | ||||
| #define JS_DEF_PROP_INT64     5 | ||||
| #define JS_DEF_PROP_DOUBLE    6 | ||||
| #define JS_DEF_PROP_UNDEFINED  7 | ||||
| #define JS_DEF_OBJECT         8 | ||||
| #define JS_DEF_ALIAS          9 | ||||
|  | ||||
| #define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u.func = { length, JS_CFUNC_generic, { .generic = func1 } } } | ||||
| #define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u.func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } | ||||
| #define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u.func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } | ||||
| #define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u.func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } | ||||
| #define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u.getset.get.getter = fgetter, .u.getset.set.setter = fsetter } | ||||
| #define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u.getset.get.getter_magic = fgetter, .u.getset.set.setter_magic = fsetter } | ||||
| #define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u.str = cstr } | ||||
| #define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u.i32 = val } | ||||
| #define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u.i64 = val } | ||||
| #define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u.f64 = val } | ||||
| #define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u.i32 = 0 } | ||||
| #define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u.prop_list = { tab, len } } | ||||
| #define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u.alias = { from, -1 } } | ||||
| #define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u.alias = { from, base } } | ||||
|  | ||||
| void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, | ||||
|                                 const JSCFunctionListEntry *tab, | ||||
|                                 int len); | ||||
|  | ||||
| /* C module definition */ | ||||
|  | ||||
| typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m); | ||||
|  | ||||
| JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, | ||||
|                            JSModuleInitFunc *func); | ||||
| /* can only be called before the module is instantiated */ | ||||
| int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); | ||||
| int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, | ||||
|                            const JSCFunctionListEntry *tab, int len); | ||||
| /* can only be called after the module is instantiated */ | ||||
| int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, | ||||
|                        JSValue val); | ||||
| int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, | ||||
|                            const JSCFunctionListEntry *tab, int len); | ||||
|  | ||||
| #undef js_unlikely | ||||
| #undef js_force_inline | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" { */ | ||||
| #endif | ||||
|  | ||||
| #endif /* QUICKJS_H */ | ||||
							
								
								
									
										1
									
								
								deps/quickjs/readme.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								deps/quickjs/readme.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| The main documentation is in doc/quickjs.pdf or doc/quickjs.html. | ||||
							
								
								
									
										131
									
								
								deps/quickjs/release.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										131
									
								
								deps/quickjs/release.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| #!/bin/sh | ||||
| # Release the QuickJS source code | ||||
|  | ||||
| set -e | ||||
|  | ||||
| version=`cat VERSION` | ||||
|  | ||||
| if [ "$1" = "-h" ] ; then | ||||
|     echo "release.sh [all]" | ||||
|     echo "" | ||||
|     echo "all: build all the archives. Otherwise only build the quickjs source archive." | ||||
|     exit 1 | ||||
| fi | ||||
|  | ||||
| unicode="no" | ||||
| tests="no" | ||||
| binary="no" | ||||
| quickjs="no" | ||||
|  | ||||
| if [ "$1" = "all" ] ; then | ||||
|     unicode="yes" | ||||
|     tests="yes" | ||||
|     binary="yes" | ||||
|     quickjs="yes" | ||||
| elif [ "$1" = "binary" ] ; then | ||||
|     binary="yes" | ||||
| else | ||||
|     quickjs="yes" | ||||
| fi | ||||
|  | ||||
| #################################################" | ||||
| # unicode data | ||||
|  | ||||
| if [ "$unicode" = "yes" ] ; then | ||||
|  | ||||
| d="quickjs-${version}" | ||||
| name="quickjs-unicode-data-${version}" | ||||
| outdir="/tmp/${d}" | ||||
|  | ||||
| rm -rf $outdir | ||||
| mkdir -p $outdir $outdir/unicode | ||||
|  | ||||
| cp unicode/* $outdir/unicode | ||||
|  | ||||
| ( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} ) | ||||
|  | ||||
| fi | ||||
|  | ||||
| #################################################" | ||||
| # all tests | ||||
|  | ||||
| if [ "$tests" = "yes" ] ; then | ||||
|  | ||||
| d="quickjs-${version}" | ||||
| name="quickjs-tests-${version}" | ||||
| outdir="/tmp/${d}" | ||||
|  | ||||
| rm -rf $outdir | ||||
| mkdir -p $outdir $outdir/test262o $outdir/test262 $outdir/tests  | ||||
|  | ||||
| cp -a test262o/test $outdir/test262o | ||||
|  | ||||
| cp -a test262/test test262/harness $outdir/test262 | ||||
|  | ||||
| cp -a tests/bench-v8 $outdir/tests | ||||
|  | ||||
| ( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} ) | ||||
|  | ||||
| fi | ||||
|  | ||||
| #################################################" | ||||
| # binary release | ||||
|  | ||||
| if [ "$binary" = "yes" ] ; then | ||||
|  | ||||
| d="quickjs-linux-x86_64-${version}" | ||||
| name="quickjs-linux-x86_64-${version}" | ||||
| outdir="/tmp/${d}" | ||||
|  | ||||
| rm -rf $outdir | ||||
| mkdir -p $outdir | ||||
|  | ||||
| files="qjs qjsbn run-test262 run-test262-bn" | ||||
|  | ||||
| make -j4 $files | ||||
|  | ||||
| strip $files | ||||
| cp $files $outdir | ||||
|  | ||||
| ( cd /tmp/$d && rm -f ../${name}.zip && zip -r ../${name}.zip . ) | ||||
|  | ||||
| fi | ||||
|  | ||||
| #################################################" | ||||
| # quickjs | ||||
|  | ||||
| if [ "$quickjs" = "yes" ] ; then | ||||
|  | ||||
| make build_doc | ||||
|  | ||||
| d="quickjs-${version}" | ||||
| outdir="/tmp/${d}" | ||||
|  | ||||
| rm -rf $outdir | ||||
| mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples | ||||
|  | ||||
| cp Makefile VERSION TODO Changelog readme.txt release.sh unicode_download.sh \ | ||||
|    qjs.c qjsc.c qjscalc.js repl.js \ | ||||
|    quickjs.c quickjs.h quickjs-atom.h \ | ||||
|    quickjs-libc.c quickjs-libc.h quickjs-opcode.h \ | ||||
|    cutils.c cutils.h list.h \ | ||||
|    libregexp.c libregexp.h libregexp-opcode.h \ | ||||
|    libunicode.c libunicode.h libunicode-table.h \ | ||||
|    libbf.c libbf.h \ | ||||
|    jscompress.c unicode_gen.c unicode_gen_def.h \ | ||||
|    bjson.c \ | ||||
|    run-test262.c test262o.conf test262.conf test262bn.conf \ | ||||
|    test262o_errors.txt test262_errors.txt test262bn_errors.txt \ | ||||
|    $outdir | ||||
|  | ||||
| cp tests/*.js tests/*.patch $outdir/tests | ||||
|  | ||||
| cp examples/*.js examples/*.c $outdir/examples | ||||
|  | ||||
| cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \ | ||||
|    doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \ | ||||
|    $outdir/doc  | ||||
|  | ||||
| ( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} ) | ||||
|  | ||||
| fi | ||||
							
								
								
									
										1507
									
								
								deps/quickjs/repl.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1507
									
								
								deps/quickjs/repl.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2105
									
								
								deps/quickjs/run-test262.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2105
									
								
								deps/quickjs/run-test262.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										179
									
								
								deps/quickjs/test262.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								deps/quickjs/test262.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| [config] | ||||
| # general settings for test262 ES6 version | ||||
|  | ||||
| # framework style: old, new | ||||
| style=new | ||||
|  | ||||
| # handle tests tagged as [noStrict]: yes, no, skip | ||||
| nostrict=yes | ||||
|  | ||||
| # handle tests tagged as [strictOnly]: yes, no, skip | ||||
| strict=yes | ||||
|  | ||||
| # test mode: default, default-nostrict, default-strict, strict, nostrict, both, all | ||||
| mode=default | ||||
|  | ||||
| # handle tests flagged as [async]: yes, no, skip | ||||
| # for these, load 'harness/doneprintHandle.js' prior to test | ||||
| # and expect `print('Test262:AsyncTestComplete')` to be called for  | ||||
| # successful termination | ||||
| async=yes | ||||
|  | ||||
| # handle tests flagged as [module]: yes, no, skip | ||||
| module=yes | ||||
|  | ||||
| # output error messages: yes, no | ||||
| verbose=yes | ||||
|  | ||||
| # load harness files from this directory | ||||
| harnessdir=test262/harness | ||||
|  | ||||
| # names of harness include files to skip | ||||
| #harnessexclude= | ||||
|  | ||||
| # name of the error file for known errors | ||||
| errorfile=test262_errors.txt | ||||
|  | ||||
| # exclude tests enumerated in this file (see also [exclude] section) | ||||
| #excludefile=test262_exclude.txt | ||||
|  | ||||
| # report test results to this file | ||||
| reportfile=test262_report.txt | ||||
|  | ||||
| # enumerate tests from this directory | ||||
| testdir=test262/test | ||||
|  | ||||
| [features] | ||||
| # Standard language features and proposed extensions | ||||
| # list the features that are included | ||||
| # skipped features are tagged as such to avoid warnings | ||||
|  | ||||
| Array.prototype.flat | ||||
| Array.prototype.flatMap | ||||
| Array.prototype.flatten | ||||
| Array.prototype.values | ||||
| ArrayBuffer | ||||
| arrow-function | ||||
| async-functions | ||||
| async-iteration | ||||
| Atomics | ||||
| BigInt=skip | ||||
| caller | ||||
| class | ||||
| class-fields-private | ||||
| class-fields-public | ||||
| class-methods-private | ||||
| class-static-fields-public | ||||
| class-static-fields-private | ||||
| class-static-methods-private | ||||
| computed-property-names | ||||
| const | ||||
| cross-realm=skip | ||||
| DataView | ||||
| DataView.prototype.getFloat32 | ||||
| DataView.prototype.getFloat64 | ||||
| DataView.prototype.getInt16 | ||||
| DataView.prototype.getInt32 | ||||
| DataView.prototype.getInt8 | ||||
| DataView.prototype.getUint16 | ||||
| DataView.prototype.getUint32 | ||||
| DataView.prototype.setUint8 | ||||
| default-arg | ||||
| default-parameters | ||||
| destructuring-assignment | ||||
| destructuring-binding | ||||
| dynamic-import | ||||
| export-star-as-namespace-from-module | ||||
| FinalizationGroup=skip | ||||
| Float32Array | ||||
| Float64Array | ||||
| for-of | ||||
| generators | ||||
| globalThis | ||||
| hashbang | ||||
| host-gc-required=skip | ||||
| import.meta | ||||
| Int32Array | ||||
| Int8Array | ||||
| IsHTMLDDA=skip | ||||
| json-superset | ||||
| let | ||||
| Map | ||||
| new.target | ||||
| numeric-separator-literal | ||||
| object-rest | ||||
| object-spread | ||||
| Object.fromEntries | ||||
| Object.is | ||||
| optional-catch-binding | ||||
| optional-chaining=skip | ||||
| Promise.allSettled | ||||
| Promise.prototype.finally | ||||
| Proxy | ||||
| proxy-missing-checks | ||||
| Reflect | ||||
| Reflect.construct | ||||
| Reflect.set | ||||
| Reflect.setPrototypeOf | ||||
| regexp-dotall | ||||
| regexp-lookbehind | ||||
| regexp-named-groups | ||||
| regexp-unicode-property-escapes | ||||
| rest-parameters | ||||
| Set | ||||
| SharedArrayBuffer | ||||
| string-trimming | ||||
| String.fromCodePoint | ||||
| String.prototype.endsWith | ||||
| String.prototype.includes | ||||
| String.prototype.matchAll | ||||
| String.prototype.trimEnd | ||||
| String.prototype.trimStart | ||||
| super | ||||
| Symbol | ||||
| Symbol.asyncIterator | ||||
| Symbol.hasInstance | ||||
| Symbol.isConcatSpreadable | ||||
| Symbol.iterator | ||||
| Symbol.match | ||||
| Symbol.matchAll | ||||
| Symbol.prototype.description | ||||
| Symbol.replace | ||||
| Symbol.search | ||||
| Symbol.species | ||||
| Symbol.split | ||||
| Symbol.toPrimitive | ||||
| Symbol.toStringTag | ||||
| Symbol.unscopables | ||||
| tail-call-optimization=skip | ||||
| template | ||||
| top-level-await=skip | ||||
| TypedArray | ||||
| u180e | ||||
| Uint16Array | ||||
| Uint8Array | ||||
| Uint8ClampedArray | ||||
| WeakMap | ||||
| WeakRef=skip | ||||
| WeakSet | ||||
| well-formed-json-stringify | ||||
|  | ||||
| [exclude] | ||||
| # list excluded tests and directories here | ||||
|  | ||||
| # intl not supported | ||||
| test262/test/intl402/ | ||||
|  | ||||
| # these builtins are not supported: | ||||
| test262/test/built-ins/BigInt/ | ||||
|  | ||||
| # incompatible with the "caller" feature | ||||
| test262/test/built-ins/Function/prototype/restricted-property-caller.js | ||||
| test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js | ||||
|  | ||||
| # slow tests | ||||
| #test262/test/built-ins/RegExp/CharacterClassEscapes/ | ||||
| #test262/test/built-ins/RegExp/property-escapes/ | ||||
|  | ||||
| [tests] | ||||
| # list test files or use config.testdir | ||||
							
								
								
									
										2
									
								
								deps/quickjs/test262_errors.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								deps/quickjs/test262_errors.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| 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 | ||||
							
								
								
									
										177
									
								
								deps/quickjs/test262bn.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								deps/quickjs/test262bn.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| [config] | ||||
| # general settings for test262 ES6 bignum version | ||||
|  | ||||
| # framework style: old, new | ||||
| style=new | ||||
|  | ||||
| # handle tests tagged as [noStrict]: yes, no, skip | ||||
| nostrict=yes | ||||
|  | ||||
| # handle tests tagged as [strictOnly]: yes, no, skip | ||||
| strict=yes | ||||
|  | ||||
| # test mode: default, default-nostrict, default-strict, strict, nostrict, both, all | ||||
| mode=default | ||||
|  | ||||
| # handle tests flagged as [async]: yes, no, skip | ||||
| # for these, load 'harness/doneprintHandle.js' prior to test | ||||
| # and expect `print('Test262:AsyncTestComplete')` to be called for  | ||||
| # successful termination | ||||
| async=yes | ||||
|  | ||||
| # handle tests flagged as [module]: yes, no, skip | ||||
| module=yes | ||||
|  | ||||
| # output error messages: yes, no | ||||
| verbose=yes | ||||
|  | ||||
| # load harness files from this directory | ||||
| harnessdir=test262/harness | ||||
|  | ||||
| # names of harness include files to skip | ||||
| # bignum version does not support Atomics | ||||
| harnessexclude=testAtomics.js | ||||
|  | ||||
| # name of the error file for known errors | ||||
| errorfile=test262bn_errors.txt | ||||
|  | ||||
| # exclude tests enumerated in this file (see also [exclude] section) | ||||
| #excludefile=test262bn_exclude.txt | ||||
|  | ||||
| # report test results to this file | ||||
| reportfile=test262bn_report.txt | ||||
|  | ||||
| # enumerate tests from this directory | ||||
| testdir=test262/test | ||||
|  | ||||
| [features] | ||||
| # Standard language features and proposed extensions | ||||
| # list the features that are included | ||||
| # skipped features are tagged as such to avoid warnings | ||||
|  | ||||
| Array.prototype.flat | ||||
| Array.prototype.flatMap | ||||
| Array.prototype.flatten | ||||
| Array.prototype.values | ||||
| ArrayBuffer | ||||
| arrow-function | ||||
| async-functions | ||||
| async-iteration | ||||
| Atomics | ||||
| BigInt | ||||
| caller | ||||
| class | ||||
| class-fields-private | ||||
| class-fields-public | ||||
| class-methods-private | ||||
| class-static-fields-public | ||||
| class-static-fields-private | ||||
| class-static-methods-private | ||||
| computed-property-names | ||||
| const | ||||
| cross-realm=skip | ||||
| DataView | ||||
| DataView.prototype.getFloat32 | ||||
| DataView.prototype.getFloat64 | ||||
| DataView.prototype.getInt16 | ||||
| DataView.prototype.getInt32 | ||||
| DataView.prototype.getInt8 | ||||
| DataView.prototype.getUint16 | ||||
| DataView.prototype.getUint32 | ||||
| DataView.prototype.setUint8 | ||||
| default-arg | ||||
| default-parameters | ||||
| destructuring-assignment | ||||
| destructuring-binding | ||||
| dynamic-import | ||||
| export-star-as-namespace-from-module | ||||
| FinalizationGroup=skip | ||||
| Float32Array | ||||
| Float64Array | ||||
| for-of | ||||
| generators | ||||
| globalThis=skip | ||||
| hashbang | ||||
| host-gc-required=skip | ||||
| import.meta | ||||
| Int32Array | ||||
| Int8Array | ||||
| IsHTMLDDA=skip | ||||
| json-superset | ||||
| let | ||||
| Map | ||||
| new.target | ||||
| numeric-separator-literal | ||||
| object-rest | ||||
| object-spread | ||||
| Object.fromEntries | ||||
| Object.is | ||||
| optional-catch-binding | ||||
| optional-chaining=skip | ||||
| Promise.allSettled | ||||
| Promise.prototype.finally | ||||
| Proxy | ||||
| proxy-missing-checks | ||||
| Reflect | ||||
| Reflect.construct | ||||
| Reflect.set | ||||
| Reflect.setPrototypeOf | ||||
| regexp-dotall | ||||
| regexp-lookbehind | ||||
| regexp-named-groups | ||||
| regexp-unicode-property-escapes | ||||
| rest-parameters | ||||
| Set | ||||
| SharedArrayBuffer | ||||
| string-trimming | ||||
| String.fromCodePoint | ||||
| String.prototype.endsWith | ||||
| String.prototype.includes | ||||
| String.prototype.matchAll | ||||
| String.prototype.trimEnd | ||||
| String.prototype.trimStart | ||||
| super | ||||
| Symbol | ||||
| Symbol.asyncIterator | ||||
| Symbol.hasInstance | ||||
| Symbol.isConcatSpreadable | ||||
| Symbol.iterator | ||||
| Symbol.match | ||||
| Symbol.matchAll | ||||
| Symbol.prototype.description | ||||
| Symbol.replace | ||||
| Symbol.search | ||||
| Symbol.species | ||||
| Symbol.split | ||||
| Symbol.toPrimitive | ||||
| Symbol.toStringTag | ||||
| Symbol.unscopables | ||||
| tail-call-optimization=skip | ||||
| template | ||||
| top-level-await=skip | ||||
| TypedArray | ||||
| u180e | ||||
| Uint16Array | ||||
| Uint8Array | ||||
| Uint8ClampedArray | ||||
| WeakMap | ||||
| WeakRef=skip | ||||
| WeakSet | ||||
| well-formed-json-stringify | ||||
|  | ||||
| [exclude] | ||||
| # list excluded tests and directories here | ||||
|  | ||||
| # intl not supported | ||||
| test262/test/intl402/ | ||||
|  | ||||
| # incompatible with the "caller" feature | ||||
| test262/test/built-ins/Function/prototype/restricted-property-caller.js | ||||
| test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js | ||||
|  | ||||
| # slow tests | ||||
| #test262/test/built-ins/RegExp/CharacterClassEscapes/ | ||||
| #test262/test/built-ins/RegExp/property-escapes/ | ||||
|  | ||||
| [tests] | ||||
| # list test files or use config.testdir | ||||
							
								
								
									
										2
									
								
								deps/quickjs/test262bn_errors.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								deps/quickjs/test262bn_errors.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| 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 | ||||
							
								
								
									
										410
									
								
								deps/quickjs/test262o.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								deps/quickjs/test262o.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,410 @@ | ||||
| [config] | ||||
| # general settings for test262 ES5 version | ||||
|  | ||||
| # framework style: old, new | ||||
| style=old | ||||
|  | ||||
| # handle tests tagged as @noStrict: yes, no, skip | ||||
| nostrict=yes | ||||
|  | ||||
| # handle tests tagged as @strictOnly: yes, no, skip | ||||
| strict=yes | ||||
|  | ||||
| # test mode: default, default-nostrict, default-strict, strict, nostrict, both, all | ||||
| mode=default | ||||
|  | ||||
| # output error messages: yes, no | ||||
| verbose=yes | ||||
|  | ||||
| # load harness files this directory | ||||
| harnessdir=test262o/test/harness | ||||
|  | ||||
| # name of the error file for known errors | ||||
| errorfile=test262o_errors.txt | ||||
|  | ||||
| # exclude tests enumerated in this file | ||||
| #excludefile=test262o_excluded.txt | ||||
|  | ||||
| # report test results to this file | ||||
| reportfile=test262o_report.txt | ||||
|  | ||||
| # enumerate tests from this directory | ||||
| testdir=test262o/test/suite | ||||
|  | ||||
| [exclude] | ||||
| # list excluded tests and directories here | ||||
|  | ||||
| # intl not supported | ||||
| test262o/test/suite/intl402/ | ||||
|  | ||||
| # ES6 != ES5: block scoped function definitions allowed in strict mode | ||||
| test262o/test/suite/bestPractice/Sbp_A1_T1.js | ||||
| test262o/test/suite/bestPractice/Sbp_A2_T1.js | ||||
| test262o/test/suite/bestPractice/Sbp_A2_T2.js | ||||
| test262o/test/suite/bestPractice/Sbp_A3_T1.js | ||||
| test262o/test/suite/bestPractice/Sbp_A3_T2.js | ||||
| test262o/test/suite/bestPractice/Sbp_A4_T1.js | ||||
| test262o/test/suite/bestPractice/Sbp_A4_T2.js | ||||
| test262o/test/suite/bestPractice/Sbp_A5_T2.js | ||||
|  | ||||
| # ES6 != ES5: `y={x};` is shorthand for `y={x:x}` | ||||
| test262o/test/suite/ch12/12.1/S12.1_A4_T2.js | ||||
| test262o/test/suite/ch12/12.6/12.6.4/S12.6.4_A15.js | ||||
|  | ||||
| # ES6 != ES5: function length property is configurable | ||||
| test262o/test/suite/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-15-1.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.1/S15.1.2.1_A4.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A9.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A7.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.4/S15.1.2.4_A2.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.5/S15.1.2.5_A2.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A5.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A5.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A5.2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A5.2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-186.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-187.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-191.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-194.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-201.js | ||||
| test262o/test/suite/ch15/15.2/15.2.4/15.2.4.2/S15.2.4.2_A9.js | ||||
| test262o/test/suite/ch15/15.2/15.2.4/15.2.4.3/S15.2.4.3_A9.js | ||||
| test262o/test/suite/ch15/15.2/15.2.4/15.2.4.4/S15.2.4.4_A9.js | ||||
| test262o/test/suite/ch15/15.2/15.2.4/15.2.4.5/S15.2.4.5_A9.js | ||||
| test262o/test/suite/ch15/15.2/15.2.4/15.2.4.6/S15.2.4.6_A9.js | ||||
| test262o/test/suite/ch15/15.2/15.2.4/15.2.4.7/S15.2.4.7_A9.js | ||||
| test262o/test/suite/ch15/15.3/15.3.3/15.3.3.2/15.3.3.2-1.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.2/S15.3.4.2_A9.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.3/S15.3.4.3_A9.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.4/S15.3.4.4_A9.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-15-2.js | ||||
| test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T1.js | ||||
| test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T2.js | ||||
| test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.3/S15.4.3_A2.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.2/S15.4.4.2_A4.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.3/S15.4.4.3_A4.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.4/S15.4.4.4_A4.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A6.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A5.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A6.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A5.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A5.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A5.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A7.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A5.2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A5.2.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.4/S15.5.4.4_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.5/S15.5.4.5_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.6/S15.5.4.6_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.8/S15.5.4.8_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.9/S15.5.4.9_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.10/S15.5.4.10_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.11/S15.5.4.11_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.12/S15.5.4.12_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.13/S15.5.4.13_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.16/S15.5.4.16_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.17/S15.5.4.17_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.18/S15.5.4.18_A9.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.19/S15.5.4.19_A9.js | ||||
| test262o/test/suite/ch15/15.9/15.9.4/15.9.4.2/S15.9.4.2_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.4/15.9.4.3/S15.9.4.3_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.1/S15.9.5.1_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.2/S15.9.5.2_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.3/S15.9.5.3_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.4/S15.9.5.4_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.5/S15.9.5.5_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.6/S15.9.5.6_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.7/S15.9.5.7_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.8/S15.9.5.8_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.9/S15.9.5.9_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.10/S15.9.5.10_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.11/S15.9.5.11_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.12/S15.9.5.12_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.13/S15.9.5.13_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.14/S15.9.5.14_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.15/S15.9.5.15_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.16/S15.9.5.16_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.17/S15.9.5.17_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.18/S15.9.5.18_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.19/S15.9.5.19_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.20/S15.9.5.20_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.21/S15.9.5.21_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.22/S15.9.5.22_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.23/S15.9.5.23_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.24/S15.9.5.24_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.25/S15.9.5.25_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.26/S15.9.5.26_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.27/S15.9.5.27_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.28/S15.9.5.28_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.29/S15.9.5.29_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.30/S15.9.5.30_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.31/S15.9.5.31_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.32/S15.9.5.32_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.33/S15.9.5.33_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.34/S15.9.5.34_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.35/S15.9.5.35_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.36/S15.9.5.36_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.37/S15.9.5.37_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.38/S15.9.5.38_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.39/S15.9.5.39_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/S15.9.5.40_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.41/S15.9.5.41_A3_T2.js | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.42/S15.9.5.42_A3_T2.js | ||||
| test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A9.js | ||||
| test262o/test/suite/ch15/15.10/15.10.6/15.10.6.3/S15.10.6.3_A9.js | ||||
| test262o/test/suite/ch15/15.10/15.10.6/15.10.6.4/S15.10.6.4_A9.js | ||||
|  | ||||
| # ES6 != ES5: object literals may have duplicates | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5-4-4-a-1-s.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-1.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-2.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-1.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-2.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-1.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-2.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-3.js | ||||
| test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-4.js | ||||
|  | ||||
| # ES6 != ES5: Date.prototype is no longer an instance of Date | ||||
| test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/15.9.5.40_1.js | ||||
|  | ||||
| # ES6 != ES5: Object.getPrototypeOf converts argument to object | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.getPrototypeOf(NativeError) | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-12.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-13.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-14.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-15.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-16.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-17.js | ||||
|  | ||||
| # ES6 != ES5: Object.getOwnPropertyDescriptor converts argument to object | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.getOwnPropertyNames converts argument to object | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-5.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.seal accepts all types | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-1.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.freeze accepts all types | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-1.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.preventExtensions accepts all types | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-1.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.isSealed accepts all types | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.11/15.2.3.11-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.isFrozen accepts all types | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-1.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.isExtensible accepts all types | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-1.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-3.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-4.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1.js | ||||
|  | ||||
| # ES6 != ES5: Object.keys converts argument to object | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-1.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-2.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-3.js | ||||
|  | ||||
| # ES6 != ES5: source and other properties of RegExp.prototype are not own properties | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214.js | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215.js | ||||
|  | ||||
| # ES6 != ES5: String numeric object properties are enumerated first | ||||
| test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-44.js | ||||
|  | ||||
| # ES6: new RegExp(regex, flags) is valid | ||||
| test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T2.js | ||||
| test262o/test/suite/ch15/15.10/15.10.4/15.10.4.1/15.10.4.1-1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T2.js | ||||
|  | ||||
| # ES6 != ES5: RegExp.prototype.test behavior | ||||
| test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A5_T3.js | ||||
|  | ||||
| # ES6 != ES5: source, global, ignoreCase, multiline, lastIndex are not data properties | ||||
| # of RegExp objects and RegExp.prototype is not a RegExp object | ||||
| test262o/test/suite/ch15/15.10/15.10.6/15.10.6.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-2.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A8.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A9.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A10.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-2.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A8.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A9.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A10.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-2.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A8.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A9.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A10.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-2.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A8.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A9.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A10.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-2.js | ||||
|  | ||||
| # ES6 != ES5: Error.prototype is a normal object | ||||
| test262o/test/suite/ch15/15.11/15.11.4/S15.11.4_A2.js | ||||
|  | ||||
| # ES6 different ToLength() semantics | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A4_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A2_T2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T1.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A2_T2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T1.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A3_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A3_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T1.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A4_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T1.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T3.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A3_T2.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-8.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-28.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-29.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-28.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-8.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-29.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-8.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-28.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-29.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-8.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-28.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-29.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-25.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-7.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-12.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-25.js | ||||
|  | ||||
| # ES6 different ToLength() semantics causes near infinite runtime | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-14.js | ||||
| test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-14.js | ||||
|  | ||||
| # ES6 arguments/caller changes | ||||
| test262o/test/suite/ch10/10.6/10.6-13-b-1-s.js | ||||
| test262o/test/suite/ch10/10.6/10.6-13-b-2-s.js | ||||
| test262o/test/suite/ch10/10.6/10.6-13-b-3-s.js | ||||
| test262o/test/suite/ch10/10.6/10.6-14-1-s.js | ||||
| test262o/test/suite/ch10/10.6/10.6-14-b-1-s.js | ||||
| test262o/test/suite/ch10/10.6/10.6-14-b-4-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-29-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-30-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-31-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-32-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-33-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-34-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-35-s.js | ||||
| test262o/test/suite/ch13/13.2/13.2-36-s.js | ||||
| test262o/test/suite/ch13/13.2/S13.2.3_A1.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-1.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-4.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-5.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-1.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-4.js | ||||
| test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-5.js | ||||
|  | ||||
| # u180e is no longer considered as a space | ||||
| test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A2.js | ||||
| test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T1.js | ||||
| test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T2.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A2_T10.js | ||||
| test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A2_T10.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-2.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-3.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-4.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-5.js | ||||
| test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-6.js | ||||
| test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A1_T1.js | ||||
| test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A2_T1.js | ||||
|  | ||||
| # E6 eval return value is different | ||||
| test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.js | ||||
| test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.1.js | ||||
|  | ||||
| # ECMA 2019 optional-catch-binding feature allows try{}catch{} | ||||
| test262o/test/suite/ch12/12.14/S12.14_A16_T4.js | ||||
|  | ||||
| # Syntax error instead of ReferenceError in ES2020 | ||||
| test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-1.js | ||||
| test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-2.js | ||||
| test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-3.js | ||||
| test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-4.js | ||||
|  | ||||
| [tests] | ||||
| # list test files or use config.testdir | ||||
							
								
								
									
										0
									
								
								deps/quickjs/test262o_errors.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								deps/quickjs/test262o_errors.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										1004
									
								
								deps/quickjs/tests/microbench.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1004
									
								
								deps/quickjs/tests/microbench.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										71
									
								
								deps/quickjs/tests/test262.patch
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								deps/quickjs/tests/test262.patch
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| diff --git a/harness/atomicsHelper.js b/harness/atomicsHelper.js | ||||
| index 135c16e..b19f2ef 100644 | ||||
| --- a/harness/atomicsHelper.js | ||||
| +++ b/harness/atomicsHelper.js | ||||
| @@ -222,10 +222,14 @@ $262.agent.waitUntil = function(typedArray, index, expected) { | ||||
|   *   } | ||||
|   */ | ||||
|  $262.agent.timeouts = { | ||||
| -  yield: 100, | ||||
| -  small: 200, | ||||
| -  long: 1000, | ||||
| -  huge: 10000, | ||||
| +//  yield: 100, | ||||
| +//  small: 200, | ||||
| +//  long: 1000, | ||||
| +//  huge: 10000, | ||||
| +  yield: 20, | ||||
| +  small: 20, | ||||
| +  long: 100, | ||||
| +  huge: 1000, | ||||
|  }; | ||||
|   | ||||
|  /** | ||||
| diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js | ||||
| index 2abfee3..e7c07b1 100644 | ||||
| --- a/harness/regExpUtils.js | ||||
| +++ b/harness/regExpUtils.js | ||||
| @@ -5,24 +5,27 @@ description: | | ||||
|      Collection of functions used to assert the correctness of RegExp objects. | ||||
|  ---*/ | ||||
|   | ||||
| +if ($262 && typeof $262.codePointRange === "function") { | ||||
| +    /* use C function to build the codePointRange (much faster with | ||||
| +       slow JS engines) */ | ||||
| +    codePointRange = $262.codePointRange; | ||||
| +} else { | ||||
| +    codePointRange = function codePointRange(start, end) { | ||||
| +        const codePoints = []; | ||||
| +        let length = 0; | ||||
| +        for (codePoint = start; codePoint < end; codePoint++) { | ||||
| +            codePoints[length++] = codePoint; | ||||
| +        } | ||||
| +        return String.fromCodePoint.apply(null, codePoints); | ||||
| +    } | ||||
| +} | ||||
| + | ||||
|  function buildString({ loneCodePoints, ranges }) { | ||||
| -  const CHUNK_SIZE = 10000; | ||||
| -  let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints); | ||||
| -  for (let i = 0; i < ranges.length; i++) { | ||||
| -    const range = ranges[i]; | ||||
| -    const start = range[0]; | ||||
| -    const end = range[1]; | ||||
| -    const codePoints = []; | ||||
| -    for (let length = 0, codePoint = start; codePoint <= end; codePoint++) { | ||||
| -      codePoints[length++] = codePoint; | ||||
| -      if (length === CHUNK_SIZE) { | ||||
| -        result += Reflect.apply(String.fromCodePoint, null, codePoints); | ||||
| -        codePoints.length = length = 0; | ||||
| -      } | ||||
| +    let result = String.fromCodePoint.apply(null, loneCodePoints); | ||||
| +    for (const [start, end] of ranges) { | ||||
| +        result += codePointRange(start, end + 1); | ||||
|      } | ||||
| -    result += Reflect.apply(String.fromCodePoint, null, codePoints); | ||||
| -  } | ||||
| -  return result; | ||||
| +    return result; | ||||
|  } | ||||
|   | ||||
|  function testPropertyEscapes(regex, string, expression) { | ||||
							
								
								
									
										269
									
								
								deps/quickjs/tests/test_bignum.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								deps/quickjs/tests/test_bignum.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,269 @@ | ||||
| "use math"; | ||||
| "use strict"; | ||||
|  | ||||
| function assert(actual, expected, message) { | ||||
|     if (arguments.length == 1) | ||||
|         expected = true; | ||||
|  | ||||
|     if (actual === expected) | ||||
|         return; | ||||
|  | ||||
|     if (actual !== null && expected !== null | ||||
|     &&  typeof actual == 'object' && typeof expected == 'object' | ||||
|     &&  actual.toString() === expected.toString()) | ||||
|         return; | ||||
|  | ||||
|     throw Error("assertion failed: got |" + actual + "|" + | ||||
|                 ", expected |" + expected + "|" + | ||||
|                 (message ? " (" + message + ")" : "")); | ||||
| } | ||||
|  | ||||
| // load more elaborate version of assert if available | ||||
| try { __loadScript("test_assert.js"); } catch(e) {} | ||||
|  | ||||
| /*----------------*/ | ||||
|  | ||||
| function pow(a, n) | ||||
| { | ||||
|     var r, i; | ||||
|     r = 1; | ||||
|     for(i = 0; i < n; i++) | ||||
|         r *= a; | ||||
|     return r; | ||||
| } | ||||
|  | ||||
| function test_integer() | ||||
| { | ||||
|     var a, r; | ||||
|     a = pow(3, 100); | ||||
|     assert((a - 1) != a); | ||||
|     assert(a == 515377520732011331036461129765621272702107522001); | ||||
|     assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1); | ||||
|     assert(Integer.isInteger(1) === true); | ||||
|     assert(Integer.isInteger(1.0) === false); | ||||
|  | ||||
|     assert(Integer.floorLog2(0) === -1); | ||||
|     assert(Integer.floorLog2(7) === 2); | ||||
|  | ||||
|     r = 1 << 31; | ||||
|     assert(r, 2147483648, "1 << 31 === 2147483648"); | ||||
|      | ||||
|     r = 1 << 32; | ||||
|     assert(r, 4294967296, "1 << 32 === 4294967296"); | ||||
|      | ||||
|     r = (1 << 31) < 0; | ||||
|     assert(r, false, "(1 << 31) < 0 === false"); | ||||
| } | ||||
|  | ||||
| function test_divrem(div1, a, b, q) | ||||
| { | ||||
|     var div, divrem, t; | ||||
|     div = Integer[div1]; | ||||
|     divrem = Integer[div1 + "rem"]; | ||||
|     assert(div(a, b) == q); | ||||
|     t = divrem(a, b); | ||||
|     assert(t[0] == q); | ||||
|     assert(a == b * q + t[1]); | ||||
| } | ||||
|  | ||||
| function test_idiv1(div, a, b, r) | ||||
| { | ||||
|     test_divrem(div, a, b, r[0]); | ||||
|     test_divrem(div, -a, b, r[1]); | ||||
|     test_divrem(div, a, -b, r[2]); | ||||
|     test_divrem(div, -a, -b, r[3]); | ||||
| } | ||||
|  | ||||
| function test_idiv() | ||||
| { | ||||
|     test_idiv1("tdiv", 3, 2, [1, -1, -1, 1]); | ||||
|     test_idiv1("fdiv", 3, 2, [1, -2, -2, 1]); | ||||
|     test_idiv1("cdiv", 3, 2, [2, -1, -1, 2]); | ||||
|     test_idiv1("ediv", 3, 2, [1, -2, -1, 2]); | ||||
| } | ||||
|  | ||||
| function test_float() | ||||
| { | ||||
|     var e, a, b, sqrt2; | ||||
|      | ||||
|     assert(typeof 1 === "bigint"); | ||||
|     assert(typeof 1.0 === "bigfloat"); | ||||
|     assert(1 == 1.0); | ||||
|     assert(1 !== 1.0); | ||||
|      | ||||
|     e = new BigFloatEnv(128); | ||||
|     assert(e.prec == 128); | ||||
|     a = BigFloat.sqrt(2, e); | ||||
|     assert(a == BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e)); | ||||
|     assert(e.inexact === true); | ||||
|     assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcd); | ||||
|      | ||||
|     b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128); | ||||
|     assert(a == b); | ||||
| } | ||||
|  | ||||
| /* jscalc tests */ | ||||
|  | ||||
| function test_modulo() | ||||
| { | ||||
|     var i, p, a, b; | ||||
|  | ||||
|     /* Euclidian modulo operator */ | ||||
|     assert((-3) % 2 == 1); | ||||
|     assert(3 % (-2) == 1); | ||||
|  | ||||
|     p = 101; | ||||
|     for(i = 1; i < p; i++) { | ||||
|         a = Integer.invmod(i, p); | ||||
|         assert(a >= 0 && a < p); | ||||
|         assert((i * a) % p == 1); | ||||
|     } | ||||
|  | ||||
|     assert(Integer.isPrime(2^107-1)); | ||||
|     assert(!Integer.isPrime((2^107-1) * (2^89-1))); | ||||
|     a = Integer.factor((2^89-1)*2^3*11*13^2*1009); | ||||
|     assert(a == [ 2,2,2,11,13,13,1009,618970019642690137449562111 ]); | ||||
| } | ||||
|  | ||||
| function test_mod() | ||||
| { | ||||
|     var a, b, p; | ||||
|      | ||||
|     a = Mod(3, 101); | ||||
|     b = Mod(-1, 101); | ||||
|     assert((a + b) == Mod(2, 101)); | ||||
|     assert(a ^ 100 == Mod(1, 101)); | ||||
|  | ||||
|     p = 2 ^ 607 - 1; /* mersenne prime */ | ||||
|     a = Mod(3, p) ^ (p - 1); | ||||
|     assert(a == Mod(1, p)); | ||||
| } | ||||
|  | ||||
| function test_polynomial() | ||||
| { | ||||
|     var a, b, q, r, t, i; | ||||
|     a = (1 + X) ^ 4; | ||||
|     assert(a == X^4+4*X^3+6*X^2+4*X+1); | ||||
|      | ||||
|     r = (1 + X); | ||||
|     q = (1+X+X^2); | ||||
|     b = (1 - X^2); | ||||
|     a = q * b + r; | ||||
|     t = Polynomial.divrem(a, b); | ||||
|     assert(t[0] == q); | ||||
|     assert(t[1] == r); | ||||
|  | ||||
|     a = 1 + 2*X + 3*X^2; | ||||
|     assert(a.apply(0.1) == 1.23); | ||||
|  | ||||
|     a = 1-2*X^2+2*X^3; | ||||
|     assert(deriv(a) == (6*X^2-4*X)); | ||||
|     assert(deriv(integ(a)) == a); | ||||
|  | ||||
|     a = (X-1)*(X-2)*(X-3)*(X-4)*(X-0.1); | ||||
|     r = polroots(a); | ||||
|     for(i = 0; i < r.length; i++) { | ||||
|         b = abs(a.apply(r[i])); | ||||
|         assert(b <= 1e-13); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function test_poly_mod() | ||||
| { | ||||
|     var a, p; | ||||
|  | ||||
|     /* modulo using polynomials */ | ||||
|     p = X^2 + X + 1; | ||||
|     a = PolyMod(3+X, p) ^ 10; | ||||
|     assert(a == PolyMod(-3725*X-18357, p)); | ||||
|  | ||||
|     a = PolyMod(1/X, 1+X^2); | ||||
|     assert(a == PolyMod(-X, X^2+1)); | ||||
| } | ||||
|  | ||||
| function test_rfunc() | ||||
| { | ||||
|     var a; | ||||
|     a = (X+1)/((X+1)*(X-1)); | ||||
|     assert(a == 1/(X-1)); | ||||
|     a = (X + 2) / (X - 2); | ||||
|     assert(a.apply(1/3) == -7/5); | ||||
|  | ||||
|     assert(deriv((X^2-X+1)/(X-1)) == (X^2-2*X)/(X^2-2*X+1)); | ||||
| } | ||||
|  | ||||
| function test_series() | ||||
| { | ||||
|     var a, b; | ||||
|     a = 1+X+O(X^5); | ||||
|     b = a.inverse(); | ||||
|     assert(b == 1-X+X^2-X^3+X^4+O(X^5)); | ||||
|     assert(deriv(b) == -1+2*X-3*X^2+4*X^3+O(X^4)); | ||||
|     assert(deriv(integ(b)) == b); | ||||
|  | ||||
|     a = Series(1/(1-X), 5); | ||||
|     assert(a == 1+X+X^2+X^3+X^4+O(X^5)); | ||||
|     b = a.apply(0.1); | ||||
|     assert(b == 1.1111); | ||||
|  | ||||
|     assert(exp(3*X^2+O(X^10)) == 1+3*X^2+9/2*X^4+9/2*X^6+27/8*X^8+O(X^10)); | ||||
|     assert(sin(X+O(X^6)) == X-1/6*X^3+1/120*X^5+O(X^6)); | ||||
|     assert(cos(X+O(X^6)) == 1-1/2*X^2+1/24*X^4+O(X^6)); | ||||
|     assert(tan(X+O(X^8)) == X+1/3*X^3+2/15*X^5+17/315*X^7+O(X^8)); | ||||
|     assert((1+X+O(X^6))^(2+X) == 1+2*X+2*X^2+3/2*X^3+5/6*X^4+5/12*X^5+O(X^6)); | ||||
| } | ||||
|  | ||||
| function test_matrix() | ||||
| { | ||||
|     var a, b, r; | ||||
|     a = [[1, 2],[3, 4]]; | ||||
|     b = [3, 4]; | ||||
|     r = a * b; | ||||
|     assert(r == [11, 25]); | ||||
|     r = (a^-1) * 2; | ||||
|     assert(r == [[-4, 2],[3, -1]]); | ||||
|  | ||||
|     assert(norm2([1,2,3]) == 14); | ||||
|  | ||||
|     assert(diag([1,2,3]) == [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]); | ||||
|     assert(trans(a) == [ [ 1, 3 ], [ 2, 4 ] ]); | ||||
|     assert(trans([1,2,3]) == [[1,2,3]]); | ||||
|     assert(trace(a) == 5); | ||||
|  | ||||
|     assert(charpoly(Matrix.hilbert(4)) == X^4-176/105*X^3+3341/12600*X^2-41/23625*X+1/6048000); | ||||
|     assert(det(Matrix.hilbert(4)) == 1/6048000); | ||||
|  | ||||
|     a = [[1,2,1],[-2,-3,1],[3,5,0]]; | ||||
|     assert(rank(a) == 2); | ||||
|     assert(ker(a) == [ [ 5 ], [ -3 ], [ 1 ] ]); | ||||
|  | ||||
|     assert(dp([1, 2, 3], [3, -4, -7]) === -26); | ||||
|     assert(cp([1, 2, 3], [3, -4, -7]) == [ -2, 16, -10 ]); | ||||
| } | ||||
|  | ||||
| function assert_eq(a, ref) | ||||
| { | ||||
|     assert(abs(a / ref - 1.0) <= 1e-15); | ||||
| } | ||||
|  | ||||
| function test_trig() | ||||
| { | ||||
|     assert_eq(sin(1/2), 0.479425538604203); | ||||
|     assert_eq(sin(2+3*I), 9.154499146911428-4.168906959966565*I); | ||||
|     assert_eq(cos(2+3*I), -4.189625690968807-9.109227893755337*I); | ||||
|     assert_eq((2+0.5*I)^(1.1-0.5*I), 2.494363021357619-0.23076804554558092*I); | ||||
|     assert_eq(sqrt(2*I), 1 + I); | ||||
| } | ||||
|  | ||||
| test_integer(); | ||||
| test_idiv(); | ||||
| test_float(); | ||||
|  | ||||
| test_modulo(); | ||||
| test_mod(); | ||||
| test_polynomial(); | ||||
| test_poly_mod(); | ||||
| test_rfunc(); | ||||
| test_series(); | ||||
| test_matrix(); | ||||
| test_trig(); | ||||
							
								
								
									
										119
									
								
								deps/quickjs/tests/test_bjson.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								deps/quickjs/tests/test_bjson.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| import * as bjson from "../bjson.so"; | ||||
|  | ||||
| function assert(b, str) | ||||
| { | ||||
|     if (b) { | ||||
|         return; | ||||
|     } else { | ||||
|         throw Error("assertion failed: " + str); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function toHex(a) | ||||
| { | ||||
|     var i, s = "", tab, v; | ||||
|     tab = new Uint8Array(a); | ||||
|     for(i = 0; i < tab.length; i++) { | ||||
|         v = tab[i].toString(16); | ||||
|         if (v.length < 2) | ||||
|             v = "0" + v; | ||||
|         if (i !== 0) | ||||
|             s += " "; | ||||
|         s += v; | ||||
|     } | ||||
|     return s; | ||||
| } | ||||
|  | ||||
| function toStr(a) | ||||
| { | ||||
|     var s, i, props, prop; | ||||
|  | ||||
|     switch(typeof(a)) { | ||||
|     case "object": | ||||
|         if (a === null) | ||||
|             return "null"; | ||||
|         if (Array.isArray(a)) { | ||||
|             s = "["; | ||||
|             for(i = 0; i < a.length; i++) { | ||||
|                 if (i != 0) | ||||
|                     s += ","; | ||||
|                 s += toStr(a[i]); | ||||
|             } | ||||
|             s += "]"; | ||||
|         } else { | ||||
|             props = Object.keys(a); | ||||
|             s = "{"; | ||||
|             for(i = 0; i < props.length; i++) { | ||||
|                 if (i != 0) | ||||
|                     s += ","; | ||||
|                 prop = props[i]; | ||||
|                 s += prop + ":" + toStr(a[prop]); | ||||
|             } | ||||
|             s += "}"; | ||||
|         } | ||||
|         return s; | ||||
|     case "undefined": | ||||
|         return "undefined"; | ||||
|     case "string": | ||||
|         return a.__quote(); | ||||
|     case "number": | ||||
|     case "bigfloat": | ||||
|         if (a == 0 && 1 / a < 0) | ||||
|             return "-0"; | ||||
|         else | ||||
|             return a.toString(); | ||||
|         break; | ||||
|     default: | ||||
|         return a.toString(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function bjson_test(a) | ||||
| { | ||||
|     var buf, r, a_str, r_str; | ||||
|     a_str = toStr(a); | ||||
|     buf = bjson.write(a); | ||||
|     if (0) { | ||||
|         print(a_str, "->", toHex(buf)); | ||||
|     } | ||||
|     r = bjson.read(buf, 0, buf.byteLength); | ||||
|     r_str = toStr(r); | ||||
|     if (a_str != r_str) { | ||||
|         print(a_str); | ||||
|         print(r_str); | ||||
|         assert(false); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function bjson_test_all() | ||||
| { | ||||
|     var obj; | ||||
|      | ||||
|     bjson_test({x:1, y:2, if:3}); | ||||
|     bjson_test([1, 2, 3]); | ||||
|     bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]); | ||||
|     if (typeof BigInt !== "undefined") { | ||||
|         bjson_test([BigInt("1"), -BigInt("0x123456789"), | ||||
|                BigInt("0x123456789abcdef123456789abcdef")]); | ||||
|     } | ||||
|     if (typeof BigFloat !== "undefined") { | ||||
|         BigFloatEnv.setPrec(function () { | ||||
|             bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"), | ||||
|                    BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"), | ||||
|                    0.0 / BigFloat("0"), BigFloat.MAX_VALUE, | ||||
|                    BigFloat.MIN_VALUE]); | ||||
|         }, 113, 15); | ||||
|     } | ||||
|  | ||||
|     /* tested with a circular reference */ | ||||
|     obj = {}; | ||||
|     obj.x = obj; | ||||
|     try { | ||||
|         bjson.write(obj); | ||||
|         assert(false); | ||||
|     } catch(e) { | ||||
|         assert(e instanceof TypeError); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bjson_test_all(); | ||||
							
								
								
									
										644
									
								
								deps/quickjs/tests/test_builtin.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										644
									
								
								deps/quickjs/tests/test_builtin.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,644 @@ | ||||
| "use strict"; | ||||
|  | ||||
| function assert(actual, expected, message) { | ||||
|     if (arguments.length == 1) | ||||
|         expected = true; | ||||
|  | ||||
|     if (actual === expected) | ||||
|         return; | ||||
|  | ||||
|     if (actual !== null && expected !== null | ||||
|     &&  typeof actual == 'object' && typeof expected == 'object' | ||||
|     &&  actual.toString() === expected.toString()) | ||||
|         return; | ||||
|  | ||||
|     throw Error("assertion failed: got |" + actual + "|" + | ||||
|                 ", expected |" + expected + "|" + | ||||
|                 (message ? " (" + message + ")" : "")); | ||||
| } | ||||
|  | ||||
| // load more elaborate version of assert if available | ||||
| try { __loadScript("test_assert.js"); } catch(e) {} | ||||
|  | ||||
| /*----------------*/ | ||||
|  | ||||
| function my_func(a, b) | ||||
| { | ||||
|     return a + b; | ||||
| } | ||||
|  | ||||
| function test_function() | ||||
| { | ||||
|     function f(a, b) { | ||||
|         var i, tab = []; | ||||
|         tab.push(this); | ||||
|         for(i = 0; i < arguments.length; i++) | ||||
|             tab.push(arguments[i]); | ||||
|         return tab; | ||||
|     } | ||||
|     function constructor1(a) { | ||||
|         this.x = a; | ||||
|     } | ||||
|      | ||||
|     var r, g; | ||||
|      | ||||
|     r = my_func.call(null, 1, 2); | ||||
|     assert(r, 3, "call"); | ||||
|  | ||||
|     r = my_func.apply(null, [1, 2]); | ||||
|     assert(r, 3, "apply"); | ||||
|  | ||||
|     r = new Function("a", "b", "return a + b;"); | ||||
|     assert(r(2,3), 5, "function"); | ||||
|      | ||||
|     g = f.bind(1, 2); | ||||
|     assert(g.length, 1); | ||||
|     assert(g.name, "bound f"); | ||||
|     assert(g(3), [1,2,3]); | ||||
|  | ||||
|     g = constructor1.bind(null, 1); | ||||
|     r = new g(); | ||||
|     assert(r.x, 1); | ||||
| } | ||||
|  | ||||
| function test() | ||||
| { | ||||
|     var r, a, b, c, err; | ||||
|  | ||||
|     r = Error("hello"); | ||||
|     assert(r.message, "hello", "Error"); | ||||
|  | ||||
|     a = new Object(); | ||||
|     a.x = 1; | ||||
|     assert(a.x, 1, "Object"); | ||||
|  | ||||
|     assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf"); | ||||
|     Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true }); | ||||
|     assert(a.y, 3, "defineProperty"); | ||||
|  | ||||
|     Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true }); | ||||
|     assert(a.z, 4, "get"); | ||||
|     a.z = 5; | ||||
|     assert(a.z_val, 5, "set"); | ||||
|      | ||||
|     a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; | ||||
|     assert(a.z, 4, "get"); | ||||
|     a.z = 5; | ||||
|     assert(a.z_val, 5, "set"); | ||||
|  | ||||
|     b = Object.create(a); | ||||
|     assert(Object.getPrototypeOf(b), a, "create"); | ||||
|     c = {u:2}; | ||||
|     /* XXX: refcount bug in 'b' instead of 'a' */ | ||||
|     Object.setPrototypeOf(a, c); | ||||
|     assert(Object.getPrototypeOf(a), c, "setPrototypeOf"); | ||||
|  | ||||
|     a = {}; | ||||
|     assert(a.toString(), "[object Object]", "toString"); | ||||
|  | ||||
|     a = {x:1}; | ||||
|     assert(Object.isExtensible(a), true, "extensible"); | ||||
|     Object.preventExtensions(a); | ||||
|  | ||||
|     err = false; | ||||
|     try { | ||||
|         a.y = 2; | ||||
|     } catch(e) { | ||||
|         err = true; | ||||
|     } | ||||
|     assert(Object.isExtensible(a), false, "extensible"); | ||||
|     assert(typeof a.y, "undefined", "extensible"); | ||||
|     assert(err, true, "extensible"); | ||||
| } | ||||
|  | ||||
| function test_enum() | ||||
| { | ||||
|     var a, tab; | ||||
|     a = {x:1, | ||||
|          "18014398509481984": 1, | ||||
|          "9007199254740992": 1, | ||||
|          "9007199254740991": 1, | ||||
|          "4294967296": 1, | ||||
|          "4294967295": 1, | ||||
|          y:1, | ||||
|          "4294967294": 1, | ||||
|          "1": 2}; | ||||
|     tab = Object.keys(a); | ||||
| //    console.log("tab=" + tab.toString()); | ||||
|     assert(tab, ["1","4294967294","x","18014398509481984","9007199254740992","9007199254740991","4294967296","4294967295","y"], "keys"); | ||||
| } | ||||
|  | ||||
| function test_array() | ||||
| { | ||||
|     var a, err; | ||||
|  | ||||
|     a = [1, 2, 3]; | ||||
|     assert(a.length, 3, "array"); | ||||
|     assert(a[2], 3, "array1"); | ||||
|  | ||||
|     a = new Array(10); | ||||
|     assert(a.length, 10, "array2"); | ||||
|  | ||||
|     a = new Array(1, 2); | ||||
|     assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3"); | ||||
|  | ||||
|     a = [1, 2, 3]; | ||||
|     a.length = 2; | ||||
|     assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4"); | ||||
|  | ||||
|     a = []; | ||||
|     a[1] = 10; | ||||
|     a[4] = 3; | ||||
|     assert(a.length, 5); | ||||
|  | ||||
|     a = [1,2]; | ||||
|     a.length = 5; | ||||
|     a[4] = 1; | ||||
|     a.length = 4; | ||||
|     assert(a[4] !== 1, true, "array5"); | ||||
|  | ||||
|     a = [1,2]; | ||||
|     a.push(3,4); | ||||
|     assert(a.join(), "1,2,3,4", "join"); | ||||
|  | ||||
|     a = [1,2,3,4,5]; | ||||
|     Object.defineProperty(a, "3", { configurable: false }); | ||||
|     err = false; | ||||
|     try { | ||||
|         a.length = 2; | ||||
|     } catch(e) { | ||||
|         err = true; | ||||
|     } | ||||
|     assert(err && a.toString() === "1,2,3,4"); | ||||
| } | ||||
|  | ||||
| function test_string() | ||||
| { | ||||
|     var a; | ||||
|     a = String("abc"); | ||||
|     assert(a.length, 3, "string"); | ||||
|     assert(a[1], "b", "string"); | ||||
|     assert(a.charCodeAt(1), 0x62, "string"); | ||||
|     assert(String.fromCharCode(65), "A", "string"); | ||||
|     assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string"); | ||||
|     assert(a.charAt(1), "b"); | ||||
|     assert(a.charAt(-1), ""); | ||||
|     assert(a.charAt(3), ""); | ||||
|      | ||||
|     a = "abcd"; | ||||
|     assert(a.substring(1, 3), "bc", "substring"); | ||||
|     a = String.fromCharCode(0x20ac); | ||||
|     assert(a.charCodeAt(0), 0x20ac, "unicode"); | ||||
|     assert(a, "€", "unicode"); | ||||
|     assert(a, "\u20ac", "unicode"); | ||||
|     assert(a, "\u{20ac}", "unicode"); | ||||
|     assert("a", "\x61", "unicode"); | ||||
|          | ||||
|     a = "\u{10ffff}"; | ||||
|     assert(a.length, 2, "unicode"); | ||||
|     assert(a, "\u{dbff}\u{dfff}", "unicode"); | ||||
|     assert(a.codePointAt(0), 0x10ffff); | ||||
|     assert(String.fromCodePoint(0x10ffff), a); | ||||
|  | ||||
|     assert("a".concat("b", "c"), "abc"); | ||||
|  | ||||
|     assert("abcabc".indexOf("cab"), 2); | ||||
|     assert("abcabc".indexOf("cab2"), -1); | ||||
|     assert("abc".indexOf("c"), 2); | ||||
|  | ||||
|     assert("aaa".indexOf("a"), 0); | ||||
|     assert("aaa".indexOf("a", NaN), 0); | ||||
|     assert("aaa".indexOf("a", -Infinity), 0); | ||||
|     assert("aaa".indexOf("a", -1), 0); | ||||
|     assert("aaa".indexOf("a", -0), 0); | ||||
|     assert("aaa".indexOf("a", 0), 0); | ||||
|     assert("aaa".indexOf("a", 1), 1); | ||||
|     assert("aaa".indexOf("a", 2), 2); | ||||
|     assert("aaa".indexOf("a", 3), -1); | ||||
|     assert("aaa".indexOf("a", 4), -1); | ||||
|     assert("aaa".indexOf("a", Infinity), -1); | ||||
|  | ||||
|     assert("aaa".indexOf(""), 0); | ||||
|     assert("aaa".indexOf("", NaN), 0); | ||||
|     assert("aaa".indexOf("", -Infinity), 0); | ||||
|     assert("aaa".indexOf("", -1), 0); | ||||
|     assert("aaa".indexOf("", -0), 0); | ||||
|     assert("aaa".indexOf("", 0), 0); | ||||
|     assert("aaa".indexOf("", 1), 1); | ||||
|     assert("aaa".indexOf("", 2), 2); | ||||
|     assert("aaa".indexOf("", 3), 3); | ||||
|     assert("aaa".indexOf("", 4), 3); | ||||
|     assert("aaa".indexOf("", Infinity), 3); | ||||
|  | ||||
|     assert("aaa".lastIndexOf("a"), 2); | ||||
|     assert("aaa".lastIndexOf("a", NaN), 2); | ||||
|     assert("aaa".lastIndexOf("a", -Infinity), 0); | ||||
|     assert("aaa".lastIndexOf("a", -1), 0); | ||||
|     assert("aaa".lastIndexOf("a", -0), 0); | ||||
|     assert("aaa".lastIndexOf("a", 0), 0); | ||||
|     assert("aaa".lastIndexOf("a", 1), 1); | ||||
|     assert("aaa".lastIndexOf("a", 2), 2); | ||||
|     assert("aaa".lastIndexOf("a", 3), 2); | ||||
|     assert("aaa".lastIndexOf("a", 4), 2); | ||||
|     assert("aaa".lastIndexOf("a", Infinity), 2); | ||||
|  | ||||
|     assert("aaa".lastIndexOf(""), 3); | ||||
|     assert("aaa".lastIndexOf("", NaN), 3); | ||||
|     assert("aaa".lastIndexOf("", -Infinity), 0); | ||||
|     assert("aaa".lastIndexOf("", -1), 0); | ||||
|     assert("aaa".lastIndexOf("", -0), 0); | ||||
|     assert("aaa".lastIndexOf("", 0), 0); | ||||
|     assert("aaa".lastIndexOf("", 1), 1); | ||||
|     assert("aaa".lastIndexOf("", 2), 2); | ||||
|     assert("aaa".lastIndexOf("", 3), 3); | ||||
|     assert("aaa".lastIndexOf("", 4), 3); | ||||
|     assert("aaa".lastIndexOf("", Infinity), 3); | ||||
|  | ||||
|     assert("a,b,c".split(","), ["a","b","c"]); | ||||
|     assert(",b,c".split(","), ["","b","c"]); | ||||
|     assert("a,b,".split(","), ["a","b",""]); | ||||
|  | ||||
|     assert("aaaa".split(), [ "aaaa" ]); | ||||
|     assert("aaaa".split(undefined, 0), [ ]); | ||||
|     assert("aaaa".split(""), [ "a", "a", "a", "a" ]); | ||||
|     assert("aaaa".split("", 0), [ ]); | ||||
|     assert("aaaa".split("", 1), [ "a" ]); | ||||
|     assert("aaaa".split("", 2), [ "a", "a" ]); | ||||
|     assert("aaaa".split("a"), [ "", "", "", "", "" ]); | ||||
|     assert("aaaa".split("a", 2), [ "", "" ]); | ||||
|     assert("aaaa".split("aa"), [ "", "", "" ]); | ||||
|     assert("aaaa".split("aa", 0), [ ]); | ||||
|     assert("aaaa".split("aa", 1), [ "" ]); | ||||
|     assert("aaaa".split("aa", 2), [ "", "" ]); | ||||
|     assert("aaaa".split("aaa"), [ "", "a" ]); | ||||
|     assert("aaaa".split("aaaa"), [ "", "" ]); | ||||
|     assert("aaaa".split("aaaaa"), [ "aaaa" ]); | ||||
|     assert("aaaa".split("aaaaa", 0), [  ]); | ||||
|     assert("aaaa".split("aaaaa", 1), [ "aaaa" ]); | ||||
|  | ||||
|     assert(eval('"\0"'), "\0"); | ||||
| } | ||||
|  | ||||
| function test_math() | ||||
| { | ||||
|     var a; | ||||
|     a = 1.4; | ||||
|     assert(Math.floor(a), 1); | ||||
|     assert(Math.ceil(a), 2); | ||||
|     assert(Math.imul(0x12345678, 123), -1088058456); | ||||
|     assert(Math.fround(0.1), 0.10000000149011612); | ||||
| } | ||||
|  | ||||
| function test_number() | ||||
| { | ||||
|     assert(parseInt("123"), 123); | ||||
|     assert(parseInt("  123r"), 123); | ||||
|     assert(parseInt("0x123"), 0x123); | ||||
|     assert(parseInt("0o123"), 0); | ||||
|     assert(+"  123   ", 123); | ||||
|     assert(+"0b111", 7); | ||||
|     assert(+"0o123", 83); | ||||
|     assert(parseFloat("0x1234"), 0); | ||||
|     assert(parseFloat("Infinity"), Infinity); | ||||
|     assert(parseFloat("-Infinity"), -Infinity); | ||||
|     assert(parseFloat("123.2"), 123.2); | ||||
|     assert(parseFloat("123.2e3"), 123200); | ||||
|  | ||||
|     assert((25).toExponential(0), "3e+1"); | ||||
|     assert((-25).toExponential(0), "-3e+1"); | ||||
|     assert((2.5).toPrecision(1), "3"); | ||||
|     assert((-2.5).toPrecision(1), "-3"); | ||||
|     assert((1.125).toFixed(2), "1.13"); | ||||
|     assert((-1.125).toFixed(2), "-1.13"); | ||||
| } | ||||
|  | ||||
| function test_eval2() | ||||
| { | ||||
|     var g_call_count = 0; | ||||
|     /* force non strict mode for f1 and f2 */ | ||||
|     var f1 = new Function("eval", "eval(1, 2)"); | ||||
|     var f2 = new Function("eval", "eval(...[1, 2])"); | ||||
|     function g(a, b) { | ||||
|         assert(a, 1); | ||||
|         assert(b, 2); | ||||
|         g_call_count++; | ||||
|     } | ||||
|     f1(g); | ||||
|     f2(g); | ||||
|     assert(g_call_count, 2); | ||||
| } | ||||
|  | ||||
| function test_eval() | ||||
| { | ||||
|     function f(b) { | ||||
|         var x = 1; | ||||
|         return eval(b); | ||||
|     } | ||||
|     var r, a; | ||||
|  | ||||
|     r = eval("1+1;"); | ||||
|     assert(r, 2, "eval"); | ||||
|  | ||||
|     r = eval("var my_var=2; my_var;"); | ||||
|     assert(r, 2, "eval"); | ||||
|     assert(typeof my_var, "undefined"); | ||||
|  | ||||
|     assert(eval("if (1) 2; else 3;"), 2); | ||||
|     assert(eval("if (0) 2; else 3;"), 3); | ||||
|  | ||||
|     assert(f.call(1, "this"), 1); | ||||
|      | ||||
|     a = 2; | ||||
|     assert(eval("a"), 2); | ||||
|  | ||||
|     eval("a = 3"); | ||||
|     assert(a, 3); | ||||
|  | ||||
|     assert(f("arguments.length", 1), 2); | ||||
|     assert(f("arguments[1]", 1), 1); | ||||
|  | ||||
|     a = 4; | ||||
|     assert(f("a"), 4); | ||||
|     f("a=3"); | ||||
|     assert(a, 3); | ||||
|  | ||||
|     test_eval2(); | ||||
| } | ||||
|  | ||||
| function test_typed_array() | ||||
| { | ||||
|     var buffer, a, i; | ||||
|  | ||||
|     a = new Uint8Array(4); | ||||
|     assert(a.length, 4); | ||||
|     for(i = 0; i < a.length; i++) | ||||
|         a[i] = i; | ||||
|     assert(a.join(","), "0,1,2,3"); | ||||
|     a[0] = -1; | ||||
|     assert(a[0], 255); | ||||
|  | ||||
|     a = new Int8Array(3); | ||||
|     a[0] = 255; | ||||
|     assert(a[0], -1); | ||||
|  | ||||
|     a = new Int32Array(3); | ||||
|     a[0] = Math.pow(2, 32) - 1; | ||||
|     assert(a[0], -1); | ||||
|     assert(a.BYTES_PER_ELEMENT, 4); | ||||
|  | ||||
|     a = new Uint8ClampedArray(4); | ||||
|     a[0] = -100; | ||||
|     a[1] = 1.5; | ||||
|     a[2] = 0.5; | ||||
|     a[3] = 1233.5; | ||||
|     assert(a.toString(), "0,2,0,255"); | ||||
|      | ||||
|     buffer = new ArrayBuffer(16); | ||||
|     assert(buffer.byteLength, 16); | ||||
|     a = new Uint32Array(buffer, 12, 1); | ||||
|     assert(a.length, 1); | ||||
|     a[0] = -1; | ||||
|  | ||||
|     a = new Uint16Array(buffer, 2); | ||||
|     a[0] = -1; | ||||
|  | ||||
|     a = new Float32Array(buffer, 8, 1); | ||||
|     a[0] = 1; | ||||
|      | ||||
|     a = new Uint8Array(buffer); | ||||
|      | ||||
|     assert(a.toString(), "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255"); | ||||
|  | ||||
|     assert(a.buffer, buffer); | ||||
|  | ||||
|     a = new Uint8Array([1, 2, 3, 4]); | ||||
|     assert(a.toString(), "1,2,3,4"); | ||||
|     a.set([10, 11], 2); | ||||
|     assert(a.toString(), "1,2,10,11"); | ||||
| } | ||||
|  | ||||
| function test_json() | ||||
| { | ||||
|     var a, s; | ||||
|     s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}'; | ||||
|     a = JSON.parse(s); | ||||
|     assert(a.x, 1); | ||||
|     assert(a.y, true); | ||||
|     assert(a.z, null); | ||||
|     assert(JSON.stringify(a), s); | ||||
|  | ||||
|     /* indentation test */ | ||||
|     assert(JSON.stringify([[{x:1,y:{},z:[]},2,3]],undefined,1), | ||||
| `[ | ||||
|  [ | ||||
|   { | ||||
|    "x": 1, | ||||
|    "y": {}, | ||||
|    "z": [] | ||||
|   }, | ||||
|   2, | ||||
|   3 | ||||
|  ] | ||||
| ]`); | ||||
| } | ||||
|  | ||||
| function test_date() | ||||
| { | ||||
|     var d = new Date(1506098258091), a, s; | ||||
|     assert(d.toISOString(), "2017-09-22T16:37:38.091Z"); | ||||
|     d.setUTCHours(18, 10, 11); | ||||
|     assert(d.toISOString(), "2017-09-22T18:10:11.091Z"); | ||||
|     a = Date.parse(d.toISOString()); | ||||
|     assert((new Date(a)).toISOString(), d.toISOString()); | ||||
|     s = new Date("2020-01-01T01:01:01.1Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:01.100Z"); | ||||
|     s = new Date("2020-01-01T01:01:01.12Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:01.120Z"); | ||||
|     s = new Date("2020-01-01T01:01:01.123Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:01.123Z"); | ||||
|     s = new Date("2020-01-01T01:01:01.1234Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:01.123Z"); | ||||
|     s = new Date("2020-01-01T01:01:01.12345Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:01.123Z"); | ||||
|     s = new Date("2020-01-01T01:01:01.1235Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:01.124Z"); | ||||
|     s = new Date("2020-01-01T01:01:01.9999Z").toISOString(); | ||||
|     assert(s ==  "2020-01-01T01:01:02.000Z"); | ||||
| } | ||||
|  | ||||
| function test_regexp() | ||||
| { | ||||
|     var a, str; | ||||
|     str = "abbbbbc"; | ||||
|     a = /(b+)c/.exec(str); | ||||
|     assert(a[0], "bbbbbc"); | ||||
|     assert(a[1], "bbbbb"); | ||||
|     assert(a.index, 1); | ||||
|     assert(a.input, str); | ||||
|     a = /(b+)c/.test(str); | ||||
|     assert(a, true); | ||||
|     assert(/\x61/.exec("a")[0], "a"); | ||||
|     assert(/\u0061/.exec("a")[0], "a"); | ||||
|     assert(/\ca/.exec("\x01")[0], "\x01"); | ||||
|     assert(/\\a/.exec("\\a")[0], "\\a"); | ||||
|     assert(/\c0/.exec("\\c0")[0], "\\c0"); | ||||
|  | ||||
|     a = /(\.(?=com|org)|\/)/.exec("ah.com"); | ||||
|     assert(a.index === 2 && a[0] === "."); | ||||
|  | ||||
|     a = /(\.(?!com|org)|\/)/.exec("ah.com"); | ||||
|     assert(a, null); | ||||
|      | ||||
|     a = /(?=(a+))/.exec("baaabac"); | ||||
|     assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); | ||||
|  | ||||
|     a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); | ||||
|     assert(a, ["zaacbbbcac","z","ac","a",,"c"]); | ||||
|  | ||||
|     a = eval("/\0a/"); | ||||
|     assert(a.toString(), "/\0a/"); | ||||
|     assert(a.exec("\0a")[0], "\0a"); | ||||
| } | ||||
|  | ||||
| function test_symbol() | ||||
| { | ||||
|     var a, b, obj, c; | ||||
|     a = Symbol("abc"); | ||||
|     obj = {}; | ||||
|     obj[a] = 2; | ||||
|     assert(obj[a], 2); | ||||
|     assert(typeof obj["abc"], "undefined"); | ||||
|     assert(String(a), "Symbol(abc)"); | ||||
|     b = Symbol("abc"); | ||||
|     assert(a == a); | ||||
|     assert(a === a); | ||||
|     assert(a != b); | ||||
|     assert(a !== b); | ||||
|  | ||||
|     b = Symbol.for("abc"); | ||||
|     c = Symbol.for("abc"); | ||||
|     assert(b === c); | ||||
|     assert(b !== a); | ||||
|  | ||||
|     assert(Symbol.keyFor(b), "abc"); | ||||
|     assert(Symbol.keyFor(a), undefined); | ||||
|  | ||||
|     a = Symbol("aaa"); | ||||
|     assert(a.valueOf(), a); | ||||
|     assert(a.toString(), "Symbol(aaa)"); | ||||
|  | ||||
|     b = Object(a); | ||||
|     assert(b.valueOf(), a); | ||||
|     assert(b.toString(), "Symbol(aaa)"); | ||||
| } | ||||
|  | ||||
| function test_map() | ||||
| { | ||||
|     var a, i, n, tab, o, v; | ||||
|     n = 1000; | ||||
|     a = new Map(); | ||||
|     tab = []; | ||||
|     for(i = 0; i < n; i++) { | ||||
|         v = { }; | ||||
|         o = { id: i }; | ||||
|         tab[i] = [o, v]; | ||||
|         a.set(o, v); | ||||
|     } | ||||
|  | ||||
|     assert(a.size, n); | ||||
|     for(i = 0; i < n; i++) { | ||||
|         assert(a.get(tab[i][0]), tab[i][1]); | ||||
|     } | ||||
|  | ||||
|     i = 0; | ||||
|     a.forEach(function (v, o) {  | ||||
|         assert(o, tab[i++][0]); | ||||
|         assert(a.has(o)); | ||||
|         assert(a.delete(o)); | ||||
|         assert(!a.has(o)); | ||||
|     }); | ||||
|  | ||||
|     assert(a.size, 0); | ||||
| } | ||||
|  | ||||
| function test_weak_map() | ||||
| { | ||||
|     var a, i, n, tab, o, v, n2; | ||||
|     a = new WeakMap(); | ||||
|     n = 10; | ||||
|     tab = []; | ||||
|     for(i = 0; i < n; i++) { | ||||
|         v = { }; | ||||
|         o = { id: i }; | ||||
|         tab[i] = [o, v]; | ||||
|         a.set(o, v); | ||||
|     } | ||||
|     o = null; | ||||
|      | ||||
|     n2 = n >> 1; | ||||
|     for(i = 0; i < n2; i++) { | ||||
|         a.delete(tab[i][0]); | ||||
|     } | ||||
|     for(i = n2; i < n; i++) { | ||||
|         tab[i][0] = null; /* should remove the object from the WeakMap too */ | ||||
|     } | ||||
|     /* the WeakMap should be empty here */ | ||||
| } | ||||
|  | ||||
| function test_generator() | ||||
| { | ||||
|     function *f() { | ||||
|         var ret; | ||||
|         yield 1; | ||||
|         ret = yield 2; | ||||
|         assert(ret, "next_arg"); | ||||
|         return 3; | ||||
|     } | ||||
|     function *f2() { | ||||
|         yield 1; | ||||
|         yield 2; | ||||
|         return "ret_val"; | ||||
|     } | ||||
|     function *f1() { | ||||
|         var ret = yield *f2(); | ||||
|         assert(ret, "ret_val"); | ||||
|         return 3; | ||||
|     } | ||||
|     var g, v; | ||||
|     g = f(); | ||||
|     v = g.next(); | ||||
|     assert(v.value === 1 && v.done === false); | ||||
|     v = g.next(); | ||||
|     assert(v.value === 2 && v.done === false); | ||||
|     v = g.next("next_arg"); | ||||
|     assert(v.value === 3 && v.done === true); | ||||
|     v = g.next(); | ||||
|     assert(v.value === undefined && v.done === true); | ||||
|  | ||||
|     g = f1(); | ||||
|     v = g.next(); | ||||
|     assert(v.value === 1 && v.done === false); | ||||
|     v = g.next(); | ||||
|     assert(v.value === 2 && v.done === false); | ||||
|     v = g.next(); | ||||
|     assert(v.value === 3 && v.done === true); | ||||
|     v = g.next(); | ||||
|     assert(v.value === undefined && v.done === true); | ||||
| } | ||||
|  | ||||
| test(); | ||||
| test_function(); | ||||
| test_enum(); | ||||
| test_array(); | ||||
| test_string(); | ||||
| test_math(); | ||||
| test_number(); | ||||
| test_eval(); | ||||
| test_typed_array(); | ||||
| test_json(); | ||||
| test_date(); | ||||
| test_regexp(); | ||||
| test_symbol(); | ||||
| test_map(); | ||||
| test_weak_map(); | ||||
| test_generator(); | ||||
							
								
								
									
										221
									
								
								deps/quickjs/tests/test_closure.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								deps/quickjs/tests/test_closure.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,221 @@ | ||||
| function assert(actual, expected, message) { | ||||
|     if (arguments.length == 1) | ||||
|         expected = true; | ||||
|  | ||||
|     if (actual === expected) | ||||
|         return; | ||||
|  | ||||
|     if (actual !== null && expected !== null | ||||
|     &&  typeof actual == 'object' && typeof expected == 'object' | ||||
|     &&  actual.toString() === expected.toString()) | ||||
|         return; | ||||
|  | ||||
|     throw Error("assertion failed: got |" + actual + "|" + | ||||
|                 ", expected |" + expected + "|" + | ||||
|                 (message ? " (" + message + ")" : "")); | ||||
| } | ||||
|  | ||||
| // load more elaborate version of assert if available | ||||
| try { __loadScript("test_assert.js"); } catch(e) {} | ||||
|  | ||||
| /*----------------*/ | ||||
|  | ||||
| var log_str = ""; | ||||
|  | ||||
| function log(str) | ||||
| { | ||||
|     log_str += str + ","; | ||||
| } | ||||
|  | ||||
| function f(a, b, c) | ||||
| { | ||||
|     var x = 10; | ||||
|     log("a="+a); | ||||
|     function g(d) { | ||||
|         function h() { | ||||
|             log("d=" + d); | ||||
|             log("x=" + x); | ||||
|         } | ||||
|         log("b=" + b); | ||||
|         log("c=" + c); | ||||
|         h(); | ||||
|     } | ||||
|     g(4); | ||||
|     return g; | ||||
| } | ||||
|  | ||||
| var g1 = f(1, 2, 3); | ||||
| g1(5); | ||||
|  | ||||
| assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1"); | ||||
|  | ||||
| function test_closure1() | ||||
| { | ||||
|     function f2() | ||||
|     { | ||||
|         var val = 1; | ||||
|          | ||||
|         function set(a) { | ||||
|             val = a; | ||||
|         } | ||||
|         function get(a) { | ||||
|             return val; | ||||
|         } | ||||
|         return { "set": set, "get": get }; | ||||
|     } | ||||
|      | ||||
|     var obj = f2(); | ||||
|     obj.set(10); | ||||
|     var r; | ||||
|     r = obj.get(); | ||||
|     assert(r, 10, "closure2"); | ||||
| } | ||||
|  | ||||
| function test_closure2() | ||||
| { | ||||
|     var expr_func = function myfunc1(n) { | ||||
|         function myfunc2(n) { | ||||
|             return myfunc1(n - 1); | ||||
|         } | ||||
|         if (n == 0) | ||||
|             return 0; | ||||
|         else | ||||
|             return myfunc2(n); | ||||
|     }; | ||||
|     var r; | ||||
|     r = expr_func(1); | ||||
|     assert(r, 0, "expr_func"); | ||||
| } | ||||
|  | ||||
| function test_closure3() | ||||
| { | ||||
|     function fib(n) | ||||
|     { | ||||
|         if (n <= 0) | ||||
|             return 0; | ||||
|         else if (n == 1) | ||||
|             return 1; | ||||
|         else | ||||
|             return fib(n - 1) + fib(n - 2); | ||||
|     } | ||||
|  | ||||
|     var fib_func = function fib1(n) | ||||
|     { | ||||
|         if (n <= 0) | ||||
|             return 0; | ||||
|         else if (n == 1) | ||||
|             return 1; | ||||
|         else | ||||
|             return fib1(n - 1) + fib1(n - 2); | ||||
|     }; | ||||
|  | ||||
|     assert(fib(6), 8, "fib"); | ||||
|     assert(fib_func(6), 8, "fib_func"); | ||||
| } | ||||
|  | ||||
| function test_arrow_function() | ||||
| { | ||||
|     "use strict"; | ||||
|  | ||||
|     function f1() { | ||||
|         return (() => arguments)(); | ||||
|     } | ||||
|     function f2() { | ||||
|         return (() => this)(); | ||||
|     } | ||||
|     function f3() { | ||||
|         return (() => eval("this"))(); | ||||
|     } | ||||
|     function f4() { | ||||
|         return (() => eval("new.target"))(); | ||||
|     } | ||||
|     var a; | ||||
|  | ||||
|     a = f1(1, 2); | ||||
|     assert(a.length, 2); | ||||
|     assert(a[0] === 1 && a[1] === 2); | ||||
|  | ||||
|     assert(f2.call("this_val") === "this_val"); | ||||
|     assert(f3.call("this_val") === "this_val"); | ||||
|     assert(new f4() === f4); | ||||
|  | ||||
|     var o1 = { f() { return this; } }; | ||||
|     var o2 = { f() { | ||||
|         return (() => eval("super.f()"))(); | ||||
|     } }; | ||||
|     o2.__proto__ = o1; | ||||
|  | ||||
|     assert(o2.f() === o2); | ||||
| } | ||||
|  | ||||
| function test_with() | ||||
| { | ||||
|     var o1 = { x: "o1", y: "o1" }; | ||||
|     var x = "local"; | ||||
|     eval('var z="var_obj";'); | ||||
|     assert(z === "var_obj"); | ||||
|     with (o1) { | ||||
|         assert(x === "o1"); | ||||
|         assert(eval("x") === "o1"); | ||||
|         var f = function () { | ||||
|             o2 = { x: "o2" }; | ||||
|             with (o2) { | ||||
|                 assert(x === "o2"); | ||||
|                 assert(y === "o1"); | ||||
|                 assert(z === "var_obj"); | ||||
|                 assert(eval("x") === "o2"); | ||||
|                 assert(eval("y") === "o1"); | ||||
|                 assert(eval("z") === "var_obj"); | ||||
|                 assert(eval('eval("x")') === "o2"); | ||||
|             } | ||||
|         }; | ||||
|         f(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function test_eval_closure() | ||||
| { | ||||
|     var tab; | ||||
|  | ||||
|     tab = []; | ||||
|     for(let i = 0; i < 3; i++) { | ||||
|         eval("tab.push(function g1() { return i; })"); | ||||
|     } | ||||
|     for(let i = 0; i < 3; i++) { | ||||
|         assert(tab[i]() === i); | ||||
|     } | ||||
|  | ||||
|     tab = []; | ||||
|     for(let i = 0; i < 3; i++) { | ||||
|         let f = function f() { | ||||
|             eval("tab.push(function g2() { return i; })"); | ||||
|         }; | ||||
|         f(); | ||||
|     } | ||||
|     for(let i = 0; i < 3; i++) { | ||||
|         assert(tab[i]() === i); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function test_eval_const() | ||||
| { | ||||
|     const a = 1; | ||||
|     var success = false; | ||||
|     var f = function () { | ||||
|         eval("a = 1"); | ||||
|     }; | ||||
|     try { | ||||
|         f(); | ||||
|     } catch(e) { | ||||
|         success = (e instanceof TypeError); | ||||
|     } | ||||
|     assert(success); | ||||
| } | ||||
|  | ||||
| test_closure1(); | ||||
| test_closure2(); | ||||
| test_closure3(); | ||||
| test_arrow_function(); | ||||
| test_with(); | ||||
| test_eval_closure(); | ||||
| test_eval_const(); | ||||
							
								
								
									
										368
									
								
								deps/quickjs/tests/test_loop.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								deps/quickjs/tests/test_loop.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,368 @@ | ||||
| function assert(actual, expected, message) { | ||||
|     if (arguments.length == 1) | ||||
|         expected = true; | ||||
|  | ||||
|     if (actual === expected) | ||||
|         return; | ||||
|  | ||||
|     if (actual !== null && expected !== null | ||||
|     &&  typeof actual == 'object' && typeof expected == 'object' | ||||
|     &&  actual.toString() === expected.toString()) | ||||
|         return; | ||||
|  | ||||
|     throw Error("assertion failed: got |" + actual + "|" + | ||||
|                 ", expected |" + expected + "|" + | ||||
|                 (message ? " (" + message + ")" : "")); | ||||
| } | ||||
|  | ||||
| // load more elaborate version of assert if available | ||||
| try { __loadScript("test_assert.js"); } catch(e) {} | ||||
|  | ||||
| /*----------------*/ | ||||
|  | ||||
| function test_while() | ||||
| { | ||||
|     var i, c; | ||||
|     i = 0; | ||||
|     c = 0; | ||||
|     while (i < 3) { | ||||
|         c++; | ||||
|         i++; | ||||
|     } | ||||
|     assert(c === 3); | ||||
| } | ||||
|  | ||||
| function test_while_break() | ||||
| { | ||||
|     var i, c; | ||||
|     i = 0; | ||||
|     c = 0; | ||||
|     while (i < 3) { | ||||
|         c++; | ||||
|         if (i == 1) | ||||
|             break; | ||||
|         i++; | ||||
|     } | ||||
|     assert(c === 2 && i === 1); | ||||
| } | ||||
|  | ||||
| function test_do_while() | ||||
| { | ||||
|     var i, c; | ||||
|     i = 0; | ||||
|     c = 0; | ||||
|     do { | ||||
|         c++; | ||||
|         i++; | ||||
|     } while (i < 3); | ||||
|     assert(c === 3 && i === 3); | ||||
| } | ||||
|  | ||||
| function test_for() | ||||
| { | ||||
|     var i, c; | ||||
|     c = 0; | ||||
|     for(i = 0; i < 3; i++) { | ||||
|         c++; | ||||
|     } | ||||
|     assert(c === 3 && i === 3); | ||||
|  | ||||
|     c = 0; | ||||
|     for(var j = 0; j < 3; j++) { | ||||
|         c++; | ||||
|     } | ||||
|     assert(c === 3 && j === 3); | ||||
| } | ||||
|  | ||||
| function test_for_in() | ||||
| { | ||||
|     var i, tab, a, b; | ||||
|  | ||||
|     tab = []; | ||||
|     for(i in {x:1, y: 2}) { | ||||
|         tab.push(i); | ||||
|     } | ||||
|     assert(tab.toString(), "x,y", "for_in"); | ||||
|  | ||||
|     /* prototype chain test */ | ||||
|     a = {x:2, y: 2, "1": 3}; | ||||
|     b = {"4" : 3 }; | ||||
|     Object.setPrototypeOf(a, b); | ||||
|     tab = []; | ||||
|     for(i in a) { | ||||
|         tab.push(i); | ||||
|     } | ||||
|     assert(tab.toString(), "1,x,y,4", "for_in"); | ||||
|  | ||||
|     /* non enumerable properties hide enumerables ones in the | ||||
|        prototype chain */ | ||||
|     a = {y: 2, "1": 3}; | ||||
|     Object.defineProperty(a, "x", { value: 1 }); | ||||
|     b = {"x" : 3 }; | ||||
|     Object.setPrototypeOf(a, b); | ||||
|     tab = []; | ||||
|     for(i in a) { | ||||
|         tab.push(i); | ||||
|     } | ||||
|     assert(tab.toString(), "1,y", "for_in"); | ||||
|  | ||||
|     /* array optimization */ | ||||
|     a = []; | ||||
|     for(i = 0; i < 10; i++) | ||||
|         a.push(i); | ||||
|     tab = []; | ||||
|     for(i in a) { | ||||
|         tab.push(i); | ||||
|     } | ||||
|     assert(tab.toString(), "0,1,2,3,4,5,6,7,8,9", "for_in"); | ||||
|  | ||||
|     /* iterate with a field */ | ||||
|     a={x:0}; | ||||
|     tab = []; | ||||
|     for(a.x in {x:1, y: 2}) { | ||||
|         tab.push(a.x); | ||||
|     } | ||||
|     assert(tab.toString(), "x,y", "for_in"); | ||||
|  | ||||
|     /* iterate with a variable field */ | ||||
|     a=[0]; | ||||
|     tab = []; | ||||
|     for(a[0] in {x:1, y: 2}) { | ||||
|         tab.push(a[0]); | ||||
|     } | ||||
|     assert(tab.toString(), "x,y", "for_in"); | ||||
|  | ||||
|     /* variable definition in the for in */ | ||||
|     tab = []; | ||||
|     for(var j in {x:1, y: 2}) { | ||||
|         tab.push(j); | ||||
|     } | ||||
|     assert(tab.toString(), "x,y", "for_in"); | ||||
|  | ||||
|     /* variable assigment in the for in */ | ||||
|     tab = []; | ||||
|     for(var k = 2 in {x:1, y: 2}) { | ||||
|         tab.push(k); | ||||
|     } | ||||
|     assert(tab.toString(), "x,y", "for_in"); | ||||
| } | ||||
|  | ||||
| function test_for_in2() | ||||
| { | ||||
|     var i; | ||||
|     tab = []; | ||||
|     for(i in {x:1, y: 2, z:3}) { | ||||
|         if (i === "y") | ||||
|             continue; | ||||
|         tab.push(i); | ||||
|     } | ||||
|     assert(tab.toString() == "x,z"); | ||||
|  | ||||
|     tab = []; | ||||
|     for(i in {x:1, y: 2, z:3}) { | ||||
|         if (i === "z") | ||||
|             break; | ||||
|         tab.push(i); | ||||
|     } | ||||
|     assert(tab.toString() == "x,y"); | ||||
| } | ||||
|  | ||||
| function test_for_break() | ||||
| { | ||||
|     var i, c; | ||||
|     c = 0; | ||||
|     L1: for(i = 0; i < 3; i++) { | ||||
|         c++; | ||||
|         if (i == 0) | ||||
|             continue; | ||||
|         while (1) { | ||||
|             break L1; | ||||
|         } | ||||
|     } | ||||
|     assert(c === 2 && i === 1); | ||||
| } | ||||
|  | ||||
| function test_switch1() | ||||
| { | ||||
|     var i, a, s; | ||||
|     s = ""; | ||||
|     for(i = 0; i < 3; i++) { | ||||
|         a = "?"; | ||||
|         switch(i) { | ||||
|         case 0: | ||||
|             a = "a"; | ||||
|             break; | ||||
|         case 1: | ||||
|             a = "b"; | ||||
|             break; | ||||
|         default: | ||||
|             a = "c"; | ||||
|             break; | ||||
|         } | ||||
|         s += a; | ||||
|     } | ||||
|     assert(s === "abc" && i === 3); | ||||
| } | ||||
|  | ||||
| function test_switch2() | ||||
| { | ||||
|     var i, a, s; | ||||
|     s = ""; | ||||
|     for(i = 0; i < 4; i++) { | ||||
|         a = "?"; | ||||
|         switch(i) { | ||||
|         case 0: | ||||
|             a = "a"; | ||||
|             break; | ||||
|         case 1: | ||||
|             a = "b"; | ||||
|             break; | ||||
|         case 2: | ||||
|             continue; | ||||
|         default: | ||||
|             a = "" + i; | ||||
|             break; | ||||
|         } | ||||
|         s += a; | ||||
|     } | ||||
|     assert(s === "ab3" && i === 4); | ||||
| } | ||||
|  | ||||
| function test_try_catch1() | ||||
| { | ||||
|     try { | ||||
|         throw "hello"; | ||||
|     } catch (e) { | ||||
|         assert(e, "hello", "catch"); | ||||
|         return; | ||||
|     } | ||||
|     assert(false, "catch"); | ||||
| } | ||||
|  | ||||
| function test_try_catch2() | ||||
| { | ||||
|     var a; | ||||
|     try { | ||||
|         a = 1; | ||||
|     } catch (e) { | ||||
|         a = 2; | ||||
|     } | ||||
|     assert(a, 1, "catch"); | ||||
| } | ||||
|  | ||||
| function test_try_catch3() | ||||
| { | ||||
|     var s; | ||||
|     s = ""; | ||||
|     try { | ||||
|         s += "t"; | ||||
|     } catch (e) { | ||||
|         s += "c"; | ||||
|     } finally { | ||||
|         s += "f"; | ||||
|     } | ||||
|     assert(s, "tf", "catch"); | ||||
| } | ||||
|  | ||||
| function test_try_catch4() | ||||
| { | ||||
|     var s; | ||||
|     s = ""; | ||||
|     try { | ||||
|         s += "t"; | ||||
|         throw "c"; | ||||
|     } catch (e) { | ||||
|         s += e; | ||||
|     } finally { | ||||
|         s += "f"; | ||||
|     } | ||||
|     assert(s, "tcf", "catch"); | ||||
| } | ||||
|  | ||||
| function test_try_catch5() | ||||
| { | ||||
|     var s; | ||||
|     s = ""; | ||||
|     for(;;) { | ||||
|         try { | ||||
|             s += "t"; | ||||
|             break; | ||||
|             s += "b"; | ||||
|         } finally { | ||||
|             s += "f"; | ||||
|         } | ||||
|     } | ||||
|     assert(s, "tf", "catch"); | ||||
| } | ||||
|  | ||||
| function test_try_catch6() | ||||
| { | ||||
|     function f() { | ||||
|         try { | ||||
|             s += 't'; | ||||
|             return 1; | ||||
|         } finally { | ||||
|             s += "f"; | ||||
|         } | ||||
|     } | ||||
|     var s = ""; | ||||
|     assert(f() === 1); | ||||
|     assert(s, "tf", "catch6"); | ||||
| } | ||||
|  | ||||
| function test_try_catch7() | ||||
| { | ||||
|     var s; | ||||
|     s = ""; | ||||
|  | ||||
|     try { | ||||
|         try { | ||||
|             s += "t"; | ||||
|             throw "a"; | ||||
|         } finally { | ||||
|             s += "f"; | ||||
|         } | ||||
|     } catch(e) { | ||||
|         s += e; | ||||
|     } finally { | ||||
|         s += "g"; | ||||
|     } | ||||
|     assert(s, "tfag", "catch"); | ||||
| } | ||||
|  | ||||
| function test_try_catch8() | ||||
| { | ||||
|     var i, s; | ||||
|      | ||||
|     s = ""; | ||||
|     for(var i in {x:1, y:2}) { | ||||
|         try { | ||||
|             s += i; | ||||
|             throw "a"; | ||||
|         } catch (e) { | ||||
|             s += e; | ||||
|         } finally { | ||||
|             s += "f"; | ||||
|         } | ||||
|     } | ||||
|     assert(s === "xafyaf"); | ||||
| } | ||||
|  | ||||
| test_while(); | ||||
| test_while_break(); | ||||
| test_do_while(); | ||||
| test_for(); | ||||
| test_for_break(); | ||||
| test_switch1(); | ||||
| test_switch2(); | ||||
| test_for_in(); | ||||
| test_for_in2(); | ||||
|  | ||||
| test_try_catch1(); | ||||
| test_try_catch2(); | ||||
| test_try_catch3(); | ||||
| test_try_catch4(); | ||||
| test_try_catch5(); | ||||
| test_try_catch6(); | ||||
| test_try_catch7(); | ||||
| test_try_catch8(); | ||||
							
								
								
									
										352
									
								
								deps/quickjs/tests/test_op.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								deps/quickjs/tests/test_op.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,352 @@ | ||||
| function assert(actual, expected, message) { | ||||
|     if (arguments.length == 1) | ||||
|         expected = true; | ||||
|  | ||||
|     if (actual === expected) | ||||
|         return; | ||||
|  | ||||
|     if (actual !== null && expected !== null | ||||
|     &&  typeof actual == 'object' && typeof expected == 'object' | ||||
|     &&  actual.toString() === expected.toString()) | ||||
|         return; | ||||
|  | ||||
|     throw Error("assertion failed: got |" + actual + "|" + | ||||
|                 ", expected |" + expected + "|" + | ||||
|                 (message ? " (" + message + ")" : "")); | ||||
| } | ||||
|  | ||||
| // load more elaborate version of assert if available | ||||
| try { __loadScript("test_assert.js"); } catch(e) {} | ||||
|  | ||||
| /*----------------*/ | ||||
|  | ||||
| function test_op1() | ||||
| { | ||||
|     var r, a; | ||||
|     r = 1 + 2; | ||||
|     assert(r, 3, "1 + 2 === 3"); | ||||
|  | ||||
|     r = 1 - 2; | ||||
|     assert(r, -1, "1 - 2 === -1"); | ||||
|  | ||||
|     r = -1; | ||||
|     assert(r, -1, "-1 === -1"); | ||||
|  | ||||
|     r = +2; | ||||
|     assert(r, 2, "+2 === 2"); | ||||
|  | ||||
|     r = 2 * 3; | ||||
|     assert(r, 6, "2 * 3 === 6"); | ||||
|  | ||||
|     r = 4 / 2; | ||||
|     assert(r, 2, "4 / 2 === 2"); | ||||
|  | ||||
|     r = 4 % 3; | ||||
|     assert(r, 1, "4 % 3 === 3"); | ||||
|  | ||||
|     r = 4 << 2; | ||||
|     assert(r, 16, "4 << 2 === 16"); | ||||
|  | ||||
|     r = 1 << 0; | ||||
|     assert(r, 1, "1 << 0 === 1"); | ||||
|  | ||||
|     r = 1 << 31; | ||||
|     assert(r, -2147483648, "1 << 31 === -2147483648"); | ||||
|      | ||||
|     r = 1 << 32; | ||||
|     assert(r, 1, "1 << 32 === 1"); | ||||
|      | ||||
|     r = (1 << 31) < 0; | ||||
|     assert(r, true, "(1 << 31) < 0 === true"); | ||||
|  | ||||
|     r = -4 >> 1; | ||||
|     assert(r, -2, "-4 >> 1 === -2"); | ||||
|  | ||||
|     r = -4 >>> 1; | ||||
|     assert(r, 0x7ffffffe, "-4 >>> 1 === 0x7ffffffe"); | ||||
|  | ||||
|     r = 1 & 1; | ||||
|     assert(r, 1, "1 & 1 === 1"); | ||||
|  | ||||
|     r = 0 | 1; | ||||
|     assert(r, 1, "0 | 1 === 1"); | ||||
|  | ||||
|     r = 1 ^ 1; | ||||
|     assert(r, 0, "1 ^ 1 === 0"); | ||||
|  | ||||
|     r = ~1; | ||||
|     assert(r, -2, "~1 === -2"); | ||||
|  | ||||
|     r = !1; | ||||
|     assert(r, false, "!1 === false"); | ||||
|  | ||||
|     assert((1 < 2), true, "(1 < 2) === true"); | ||||
|  | ||||
|     assert((2 > 1), true, "(2 > 1) === true"); | ||||
|  | ||||
|     assert(('b' > 'a'), true, "('b' > 'a') === true"); | ||||
|  | ||||
|     assert(2 ** 8, 256, "2 ** 8 === 256"); | ||||
| } | ||||
|  | ||||
| function test_cvt() | ||||
| { | ||||
|     assert((NaN | 0) === 0); | ||||
|     assert((Infinity | 0) === 0); | ||||
|     assert(((-Infinity) | 0) === 0); | ||||
|     assert(("12345" | 0) === 12345); | ||||
|     assert(("0x12345" | 0) === 0x12345); | ||||
|     assert(((4294967296 * 3 - 4) | 0) === -4); | ||||
|      | ||||
|     assert(("12345" >>> 0) === 12345); | ||||
|     assert(("0x12345" >>> 0) === 0x12345); | ||||
|     assert((NaN >>> 0) === 0); | ||||
|     assert((Infinity >>> 0) === 0); | ||||
|     assert(((-Infinity) >>> 0) === 0); | ||||
|     assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4)); | ||||
| } | ||||
|  | ||||
| function test_eq() | ||||
| { | ||||
|     assert(null == undefined); | ||||
|     assert(undefined == null); | ||||
|     assert(true == 1); | ||||
|     assert(0 == false); | ||||
|     assert("" == 0); | ||||
|     assert("123" == 123); | ||||
|     assert("122" != 123); | ||||
|     assert((new Number(1)) == 1); | ||||
|     assert(2 == (new Number(2))); | ||||
|     assert((new String("abc")) == "abc"); | ||||
|     assert({} != "abc"); | ||||
| } | ||||
|  | ||||
| function test_inc_dec() | ||||
| { | ||||
|     var a, r; | ||||
|      | ||||
|     a = 1; | ||||
|     r = a++; | ||||
|     assert(r === 1 && a === 2, true, "++"); | ||||
|  | ||||
|     a = 1; | ||||
|     r = ++a; | ||||
|     assert(r === 2 && a === 2, true, "++"); | ||||
|  | ||||
|     a = 1; | ||||
|     r = a--; | ||||
|     assert(r === 1 && a === 0, true, "--"); | ||||
|  | ||||
|     a = 1; | ||||
|     r = --a; | ||||
|     assert(r === 0 && a === 0, true, "--"); | ||||
|  | ||||
|     a = {x:true}; | ||||
|     a.x++; | ||||
|     assert(a.x, 2, "++"); | ||||
|  | ||||
|     a = {x:true}; | ||||
|     a.x--; | ||||
|     assert(a.x, 0, "--"); | ||||
|  | ||||
|     a = [true]; | ||||
|     a[0]++; | ||||
|     assert(a[0], 2, "++"); | ||||
|      | ||||
|     a = {x:true}; | ||||
|     r = a.x++; | ||||
|     assert(r === 1 && a.x === 2, true, "++"); | ||||
|      | ||||
|     a = {x:true}; | ||||
|     r = a.x--; | ||||
|     assert(r === 1 && a.x === 0, true, "--"); | ||||
|      | ||||
|     a = [true]; | ||||
|     r = a[0]++; | ||||
|     assert(r === 1 && a[0] === 2, true, "++"); | ||||
|      | ||||
|     a = [true]; | ||||
|     r = a[0]--; | ||||
|     assert(r === 1 && a[0] === 0, true, "--"); | ||||
| } | ||||
|  | ||||
| function F(x) | ||||
| { | ||||
|     this.x = x; | ||||
| } | ||||
|  | ||||
| function test_op2() | ||||
| { | ||||
|     var a, b; | ||||
|     a = new Object; | ||||
|     a.x = 1; | ||||
|     assert(a.x, 1, "new"); | ||||
|     b = new F(2); | ||||
|     assert(b.x, 2, "new"); | ||||
|  | ||||
|     a = {x : 2}; | ||||
|     assert(("x" in a), true, "in"); | ||||
|     assert(("y" in a), false, "in"); | ||||
|  | ||||
|     a = {}; | ||||
|     assert((a instanceof Object), true, "instanceof"); | ||||
|     assert((a instanceof String), false, "instanceof"); | ||||
|  | ||||
|     assert((typeof 1), "number", "typeof"); | ||||
|     assert((typeof Object), "function", "typeof"); | ||||
|     assert((typeof null), "object", "typeof"); | ||||
|     assert((typeof unknown_var), "undefined", "typeof"); | ||||
|      | ||||
|     a = {x: 1, if: 2, async: 3}; | ||||
|     assert(a.if === 2); | ||||
|     assert(a.async === 3); | ||||
| } | ||||
|  | ||||
| function test_delete() | ||||
| { | ||||
|     var a, err; | ||||
|  | ||||
|     a = {x: 1, y: 1}; | ||||
|     assert((delete a.x), true, "delete"); | ||||
|     assert(("x" in a), false, "delete"); | ||||
|      | ||||
|     /* the following are not tested by test262 */ | ||||
|     assert(delete "abc"[100], true); | ||||
|  | ||||
|     err = false; | ||||
|     try { | ||||
|         delete null.a; | ||||
|     } catch(e) { | ||||
|         err = (e instanceof TypeError); | ||||
|     } | ||||
|     assert(err, true, "delete"); | ||||
|  | ||||
|     err = false; | ||||
|     try { | ||||
|         a = { f() { delete super.a; } }; | ||||
|         a.f(); | ||||
|     } catch(e) { | ||||
|         err = (e instanceof ReferenceError); | ||||
|     } | ||||
|     assert(err, true, "delete"); | ||||
| } | ||||
|  | ||||
| function test_prototype() | ||||
| { | ||||
|     function f() { } | ||||
|     assert(f.prototype.constructor, f, "prototype"); | ||||
| } | ||||
|  | ||||
| function test_arguments() | ||||
| { | ||||
|     function f2() { | ||||
|         assert(arguments.length, 2, "arguments"); | ||||
|         assert(arguments[0], 1, "arguments"); | ||||
|         assert(arguments[1], 3, "arguments"); | ||||
|     } | ||||
|     f2(1, 3); | ||||
| } | ||||
|  | ||||
| function test_class() | ||||
| { | ||||
|     var o; | ||||
|     class C { | ||||
|         constructor() { | ||||
|             this.x = 10; | ||||
|         } | ||||
|         f() { | ||||
|             return 1; | ||||
|         } | ||||
|         static F() { | ||||
|             return -1; | ||||
|         } | ||||
|         get y() { | ||||
|             return 12; | ||||
|         } | ||||
|     }; | ||||
|     class D extends C { | ||||
|         constructor() { | ||||
|             super(); | ||||
|             this.z = 20; | ||||
|         } | ||||
|         g() { | ||||
|             return 2; | ||||
|         } | ||||
|         static G() { | ||||
|             return -2; | ||||
|         } | ||||
|         h() { | ||||
|             return super.f(); | ||||
|         } | ||||
|         static H() { | ||||
|             return super["F"](); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     assert(C.F() === -1); | ||||
|     assert(Object.getOwnPropertyDescriptor(C.prototype, "y").get.name === "get y"); | ||||
|  | ||||
|     o = new C(); | ||||
|     assert(o.f() === 1); | ||||
|     assert(o.x === 10); | ||||
|      | ||||
|     assert(D.F() === -1); | ||||
|     assert(D.G() === -2); | ||||
|     assert(D.H() === -1); | ||||
|  | ||||
|     o = new D(); | ||||
|     assert(o.f() === 1); | ||||
|     assert(o.g() === 2); | ||||
|     assert(o.x === 10); | ||||
|     assert(o.z === 20); | ||||
|     assert(o.h() === 1); | ||||
|  | ||||
|     /* test class name scope */ | ||||
|     var E1 = class E { static F() { return E; } }; | ||||
|     assert(E1 === E1.F()); | ||||
| }; | ||||
|  | ||||
| function test_template() | ||||
| { | ||||
|     var a, b; | ||||
|     b = 123; | ||||
|     a = `abc${b}d`; | ||||
|     assert(a === "abc123d"); | ||||
|  | ||||
|     a = String.raw `abc${b}d`; | ||||
|     assert(a === "abc123d"); | ||||
| } | ||||
|  | ||||
| function test_object_literal() | ||||
| { | ||||
|     var x = 0, get = 1, set = 2; async = 3; | ||||
|     a = { get: 2, set: 3, async: 4 }; | ||||
|     assert(JSON.stringify(a), '{"get":2,"set":3,"async":4}'); | ||||
|  | ||||
|     a = { x, get, set, async }; | ||||
|     assert(JSON.stringify(a), '{"x":0,"get":1,"set":2,"async":3}'); | ||||
| } | ||||
|  | ||||
| function test_regexp_skip() | ||||
| { | ||||
|     var a, b; | ||||
|     [a, b = /abc\(/] = [1]; | ||||
|     assert(a === 1); | ||||
|      | ||||
|     [a, b =/abc\(/] = [2]; | ||||
|     assert(a === 2); | ||||
| } | ||||
|  | ||||
| test_op1(); | ||||
| test_cvt(); | ||||
| test_eq(); | ||||
| test_inc_dec(); | ||||
| test_op2(); | ||||
| test_delete(); | ||||
| test_prototype(); | ||||
| test_arguments(); | ||||
| test_class(); | ||||
| test_template(); | ||||
| test_object_literal(); | ||||
| test_regexp_skip(); | ||||
|  | ||||
							
								
								
									
										247
									
								
								deps/quickjs/tests/test_std.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								deps/quickjs/tests/test_std.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| import * as std from "std"; | ||||
| import * as os from "os"; | ||||
|  | ||||
| function assert(actual, expected, message) { | ||||
|     if (arguments.length == 1) | ||||
|         expected = true; | ||||
|  | ||||
|     if (actual === expected) | ||||
|         return; | ||||
|  | ||||
|     if (actual !== null && expected !== null | ||||
|     &&  typeof actual == 'object' && typeof expected == 'object' | ||||
|     &&  actual.toString() === expected.toString()) | ||||
|         return; | ||||
|  | ||||
|     throw Error("assertion failed: got |" + actual + "|" + | ||||
|                 ", expected |" + expected + "|" + | ||||
|                 (message ? " (" + message + ")" : "")); | ||||
| } | ||||
|  | ||||
| // load more elaborate version of assert if available | ||||
| try { std.loadScript("test_assert.js"); } catch(e) {} | ||||
|  | ||||
| /*----------------*/ | ||||
|  | ||||
| function test_printf() | ||||
| { | ||||
|     assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc"); | ||||
| } | ||||
|  | ||||
| function test_file1() | ||||
| { | ||||
|     var f, len, str, size, buf, ret, i, str1; | ||||
|  | ||||
|     f = std.tmpfile(); | ||||
|     str = "hello world\n"; | ||||
|     f.puts(str); | ||||
|  | ||||
|     f.seek(0, std.SEEK_SET); | ||||
|     str1 = f.readAsString(); | ||||
|     assert(str1 === str); | ||||
|      | ||||
|     f.seek(0, std.SEEK_END); | ||||
|     size = f.tell(); | ||||
|     assert(size === str.length); | ||||
|  | ||||
|     f.seek(0, std.SEEK_SET); | ||||
|  | ||||
|     buf = new Uint8Array(size); | ||||
|     ret = f.read(buf.buffer, 0, size); | ||||
|     assert(ret === size); | ||||
|     for(i = 0; i < size; i++) | ||||
|         assert(buf[i] === str.charCodeAt(i)); | ||||
|  | ||||
|     f.close(); | ||||
| } | ||||
|  | ||||
| function test_file2() | ||||
| { | ||||
|     var f, str, i, size; | ||||
|     f = std.tmpfile(); | ||||
|     str = "hello world\n"; | ||||
|     size = str.length; | ||||
|     for(i = 0; i < size; i++) | ||||
|         f.putByte(str.charCodeAt(i)); | ||||
|     f.seek(0, std.SEEK_SET); | ||||
|     for(i = 0; i < size; i++) { | ||||
|         assert(str.charCodeAt(i) === f.getByte()); | ||||
|     } | ||||
|     assert(f.getByte() === -1); | ||||
|     f.close(); | ||||
| } | ||||
|  | ||||
| function test_getline() | ||||
| { | ||||
|     var f, line, line_count, lines, i; | ||||
|      | ||||
|     lines = ["hello world", "line 1", "line 2" ]; | ||||
|     f = std.tmpfile(); | ||||
|     for(i = 0; i < lines.length; i++) { | ||||
|         f.puts(lines[i], "\n"); | ||||
|     } | ||||
|  | ||||
|     f.seek(0, std.SEEK_SET); | ||||
|     assert(!f.eof()); | ||||
|     line_count = 0; | ||||
|     for(;;) { | ||||
|         line = f.getline(); | ||||
|         if (line === null) | ||||
|             break; | ||||
|         assert(line == lines[line_count]); | ||||
|         line_count++; | ||||
|     } | ||||
|     assert(f.eof()); | ||||
|     assert(line_count === lines.length); | ||||
|  | ||||
|     f.close(); | ||||
| } | ||||
|   | ||||
| function test_popen() | ||||
| { | ||||
|     var str, f, fname = "tmp_file.txt"; | ||||
|     var content = "hello world"; | ||||
|  | ||||
|     f = std.open(fname, "w"); | ||||
|     f.puts(content); | ||||
|     f.close(); | ||||
|  | ||||
|     /* execute the 'cat' shell command */ | ||||
|     f = std.popen("cat " + fname, "r"); | ||||
|     str = f.readAsString(); | ||||
|     f.close(); | ||||
|  | ||||
|     assert(str, content); | ||||
|  | ||||
|     os.remove(fname); | ||||
| } | ||||
|  | ||||
| function test_os() | ||||
| { | ||||
|     var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; | ||||
|  | ||||
|     assert(os.isatty(0)); | ||||
|  | ||||
|     fdir = "test_tmp_dir"; | ||||
|     fname = "tmp_file.txt"; | ||||
|     fpath = fdir + "/" + fname; | ||||
|     link_path = fdir + "/test_link"; | ||||
|      | ||||
|     os.remove(link_path); | ||||
|     os.remove(fpath); | ||||
|     os.remove(fdir); | ||||
|  | ||||
|     err = os.mkdir(fdir, 0o755); | ||||
|     assert(err === 0); | ||||
|      | ||||
|     fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC); | ||||
|     assert(fd >= 0); | ||||
|      | ||||
|     buf = new Uint8Array(10); | ||||
|     for(i = 0; i < buf.length; i++) | ||||
|         buf[i] = i; | ||||
|     assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length); | ||||
|  | ||||
|     assert(os.seek(fd, 0, os.SEEK_SET) === 0); | ||||
|     buf2 = new Uint8Array(buf.length); | ||||
|     assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length); | ||||
|      | ||||
|     for(i = 0; i < buf.length; i++) | ||||
|         assert(buf[i] == buf2[i]); | ||||
|      | ||||
|     assert(os.close(fd) === 0); | ||||
|  | ||||
|     [files, err] = os.readdir(fdir); | ||||
|     assert(err, 0); | ||||
|     assert(files.indexOf(fname) >= 0); | ||||
|  | ||||
|     fdate = 10000; | ||||
|  | ||||
|     err = os.utimes(fpath, fdate, fdate); | ||||
|     assert(err, 0); | ||||
|      | ||||
|     [st, err] = os.stat(fpath); | ||||
|     assert(err, 0); | ||||
|     assert(st.mode & os.S_IFMT, os.S_IFREG); | ||||
|     assert(st.mtime, fdate); | ||||
|  | ||||
|     err = os.symlink(fname, link_path); | ||||
|     assert(err === 0); | ||||
|      | ||||
|     [st, err] = os.lstat(link_path); | ||||
|     assert(err, 0); | ||||
|     assert(st.mode & os.S_IFMT, os.S_IFLNK); | ||||
|  | ||||
|     [buf, err] = os.readlink(link_path); | ||||
|     assert(err, 0); | ||||
|     assert(buf, fname); | ||||
|      | ||||
|     assert(os.remove(link_path) === 0); | ||||
|  | ||||
|     [buf, err] = os.getcwd(); | ||||
|     assert(err, 0); | ||||
|  | ||||
|     [buf2, err] = os.realpath("."); | ||||
|     assert(err, 0); | ||||
|  | ||||
|     assert(buf, buf2); | ||||
|      | ||||
|     assert(os.remove(fpath) === 0); | ||||
|  | ||||
|     fd = os.open(fpath, os.O_RDONLY); | ||||
|     assert(fd < 0); | ||||
|  | ||||
|     assert(os.remove(fdir) === 0); | ||||
| } | ||||
|  | ||||
| function test_os_exec() | ||||
| { | ||||
|     var ret, fds, pid, f, status; | ||||
|  | ||||
|     ret = os.exec(["true"]); | ||||
|     assert(ret, 0); | ||||
|  | ||||
|     ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false }); | ||||
|     assert(ret, 1); | ||||
|      | ||||
|     fds = os.pipe(); | ||||
|     pid = os.exec(["echo", "hello"], { stdout: fds[1], block: false } ); | ||||
|     assert(pid >= 0); | ||||
|     os.close(fds[1]); /* close the write end (as it is only in the child)  */ | ||||
|     f = std.fdopen(fds[0], "r"); | ||||
|     assert(f.getline(), "hello"); | ||||
|     assert(f.getline(), null); | ||||
|     f.close(); | ||||
|     [ret, status] = os.waitpid(pid, 0); | ||||
|     assert(ret, pid); | ||||
|     assert(status & 0x7f, 0); /* exited */ | ||||
|     assert(status >> 8, 0); /* exit code */ | ||||
|  | ||||
|     pid = os.exec(["cat"], { block: false } ); | ||||
|     assert(pid >= 0); | ||||
|     os.kill(pid, os.SIGQUIT); | ||||
|     [ret, status] = os.waitpid(pid, 0); | ||||
|     assert(ret, pid); | ||||
|     assert(status & 0x7f, os.SIGQUIT); | ||||
| } | ||||
|  | ||||
| function test_timer() | ||||
| { | ||||
|     var th, i; | ||||
|  | ||||
|     /* just test that a timer can be inserted and removed */ | ||||
|     th = []; | ||||
|     for(i = 0; i < 3; i++) | ||||
|         th[i] = os.setTimeout(function () { }, 1000); | ||||
|     for(i = 0; i < 3; i++) | ||||
|         os.clearTimeout(th[i]); | ||||
| } | ||||
|  | ||||
| test_printf(); | ||||
| test_file1(); | ||||
| test_file2(); | ||||
| test_getline(); | ||||
| test_popen(); | ||||
| test_os(); | ||||
| test_os_exec(); | ||||
| test_timer(); | ||||
							
								
								
									
										19
									
								
								deps/quickjs/unicode_download.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										19
									
								
								deps/quickjs/unicode_download.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| #!/bin/sh | ||||
| set -e | ||||
|  | ||||
| url="ftp://ftp.unicode.org/Public/12.1.0/ucd" | ||||
| emoji_url="ftp://ftp.unicode.org/Public/emoji/12.0/emoji-data.txt" | ||||
|  | ||||
| files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ | ||||
| SpecialCasing.txt CompositionExclusions.txt ScriptExtensions.txt \ | ||||
| UnicodeData.txt DerivedCoreProperties.txt NormalizationTest.txt Scripts.txt \ | ||||
| PropertyValueAliases.txt" | ||||
|  | ||||
| mkdir -p unicode | ||||
|  | ||||
| for f in $files; do | ||||
|     g="${url}/${f}" | ||||
|     wget $g -O unicode/$f | ||||
| done | ||||
|      | ||||
| wget $emoji_url -O unicode/emoji-data.txt | ||||
							
								
								
									
										3056
									
								
								deps/quickjs/unicode_gen.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3056
									
								
								deps/quickjs/unicode_gen.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										280
									
								
								deps/quickjs/unicode_gen_def.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								deps/quickjs/unicode_gen_def.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,280 @@ | ||||
| #ifdef UNICODE_GENERAL_CATEGORY | ||||
| DEF(Cn, "Unassigned") /* must be zero */ | ||||
| DEF(Lu, "Uppercase_Letter") | ||||
| DEF(Ll, "Lowercase_Letter") | ||||
| DEF(Lt, "Titlecase_Letter") | ||||
| DEF(Lm, "Modifier_Letter") | ||||
| DEF(Lo, "Other_Letter") | ||||
| DEF(Mn, "Nonspacing_Mark") | ||||
| DEF(Mc, "Spacing_Mark") | ||||
| DEF(Me, "Enclosing_Mark") | ||||
| DEF(Nd, "Decimal_Number,digit") | ||||
| DEF(Nl, "Letter_Number") | ||||
| DEF(No, "Other_Number") | ||||
| DEF(Sm, "Math_Symbol") | ||||
| DEF(Sc, "Currency_Symbol") | ||||
| DEF(Sk, "Modifier_Symbol") | ||||
| DEF(So, "Other_Symbol") | ||||
| DEF(Pc, "Connector_Punctuation") | ||||
| DEF(Pd, "Dash_Punctuation") | ||||
| DEF(Ps, "Open_Punctuation") | ||||
| DEF(Pe, "Close_Punctuation") | ||||
| DEF(Pi, "Initial_Punctuation") | ||||
| DEF(Pf, "Final_Punctuation") | ||||
| DEF(Po, "Other_Punctuation") | ||||
| DEF(Zs, "Space_Separator") | ||||
| DEF(Zl, "Line_Separator") | ||||
| DEF(Zp, "Paragraph_Separator") | ||||
| DEF(Cc, "Control,cntrl") | ||||
| DEF(Cf, "Format") | ||||
| DEF(Cs, "Surrogate") | ||||
| DEF(Co, "Private_Use") | ||||
| /* synthetic properties */ | ||||
| DEF(LC, "Cased_Letter") | ||||
| DEF(L, "Letter") | ||||
| DEF(M, "Mark,Combining_Mark") | ||||
| DEF(N, "Number") | ||||
| DEF(S, "Symbol") | ||||
| DEF(P, "Punctuation,punct") | ||||
| DEF(Z, "Separator") | ||||
| DEF(C, "Other") | ||||
| #endif | ||||
|  | ||||
| #ifdef UNICODE_SCRIPT | ||||
| /* scripts aliases names in PropertyValueAliases.txt */ | ||||
| DEF(Unknown, "Zzzz") | ||||
| DEF(Adlam, "Adlm") | ||||
| DEF(Ahom, "Ahom") | ||||
| DEF(Anatolian_Hieroglyphs, "Hluw") | ||||
| DEF(Arabic, "Arab") | ||||
| DEF(Armenian, "Armn") | ||||
| DEF(Avestan, "Avst") | ||||
| DEF(Balinese, "Bali") | ||||
| DEF(Bamum, "Bamu") | ||||
| DEF(Bassa_Vah, "Bass") | ||||
| DEF(Batak, "Batk") | ||||
| DEF(Bengali, "Beng") | ||||
| DEF(Bhaiksuki, "Bhks") | ||||
| DEF(Bopomofo, "Bopo") | ||||
| DEF(Brahmi, "Brah") | ||||
| DEF(Braille, "Brai") | ||||
| DEF(Buginese, "Bugi") | ||||
| DEF(Buhid, "Buhd") | ||||
| DEF(Canadian_Aboriginal, "Cans") | ||||
| DEF(Carian, "Cari") | ||||
| DEF(Caucasian_Albanian, "Aghb") | ||||
| DEF(Chakma, "Cakm") | ||||
| DEF(Cham, "Cham") | ||||
| DEF(Cherokee, "Cher") | ||||
| DEF(Common, "Zyyy") | ||||
| DEF(Coptic, "Copt,Qaac") | ||||
| DEF(Cuneiform, "Xsux") | ||||
| DEF(Cypriot, "Cprt") | ||||
| DEF(Cyrillic, "Cyrl") | ||||
| DEF(Deseret, "Dsrt") | ||||
| DEF(Devanagari, "Deva") | ||||
| DEF(Dogra, "Dogr") | ||||
| DEF(Duployan, "Dupl") | ||||
| DEF(Egyptian_Hieroglyphs, "Egyp") | ||||
| DEF(Elbasan, "Elba") | ||||
| DEF(Elymaic, "Elym") | ||||
| DEF(Ethiopic, "Ethi") | ||||
| DEF(Georgian, "Geor") | ||||
| DEF(Glagolitic, "Glag") | ||||
| DEF(Gothic, "Goth") | ||||
| DEF(Grantha, "Gran") | ||||
| DEF(Greek, "Grek") | ||||
| DEF(Gujarati, "Gujr") | ||||
| DEF(Gunjala_Gondi, "Gong") | ||||
| DEF(Gurmukhi, "Guru") | ||||
| DEF(Han, "Hani") | ||||
| DEF(Hangul, "Hang") | ||||
| DEF(Hanifi_Rohingya, "Rohg") | ||||
| DEF(Hanunoo, "Hano") | ||||
| DEF(Hatran, "Hatr") | ||||
| DEF(Hebrew, "Hebr") | ||||
| DEF(Hiragana, "Hira") | ||||
| DEF(Imperial_Aramaic, "Armi") | ||||
| DEF(Inherited, "Zinh,Qaai") | ||||
| DEF(Inscriptional_Pahlavi, "Phli") | ||||
| DEF(Inscriptional_Parthian, "Prti") | ||||
| DEF(Javanese, "Java") | ||||
| DEF(Kaithi, "Kthi") | ||||
| DEF(Kannada, "Knda") | ||||
| DEF(Katakana, "Kana") | ||||
| DEF(Kayah_Li, "Kali") | ||||
| DEF(Kharoshthi, "Khar") | ||||
| DEF(Khmer, "Khmr") | ||||
| DEF(Khojki, "Khoj") | ||||
| DEF(Khudawadi, "Sind") | ||||
| DEF(Lao, "Laoo") | ||||
| DEF(Latin, "Latn") | ||||
| DEF(Lepcha, "Lepc") | ||||
| DEF(Limbu, "Limb") | ||||
| DEF(Linear_A, "Lina") | ||||
| DEF(Linear_B, "Linb") | ||||
| DEF(Lisu, "Lisu") | ||||
| DEF(Lycian, "Lyci") | ||||
| DEF(Lydian, "Lydi") | ||||
| DEF(Makasar, "Maka") | ||||
| DEF(Mahajani, "Mahj") | ||||
| DEF(Malayalam, "Mlym") | ||||
| DEF(Mandaic, "Mand") | ||||
| DEF(Manichaean, "Mani") | ||||
| DEF(Marchen, "Marc") | ||||
| DEF(Masaram_Gondi, "Gonm") | ||||
| DEF(Medefaidrin, "Medf") | ||||
| DEF(Meetei_Mayek, "Mtei") | ||||
| DEF(Mende_Kikakui, "Mend") | ||||
| DEF(Meroitic_Cursive, "Merc") | ||||
| DEF(Meroitic_Hieroglyphs, "Mero") | ||||
| DEF(Miao, "Plrd") | ||||
| DEF(Modi, "Modi") | ||||
| DEF(Mongolian, "Mong") | ||||
| DEF(Mro, "Mroo") | ||||
| DEF(Multani, "Mult") | ||||
| DEF(Myanmar, "Mymr") | ||||
| DEF(Nabataean, "Nbat") | ||||
| DEF(Nandinagari, "Nand") | ||||
| DEF(New_Tai_Lue, "Talu") | ||||
| DEF(Newa, "Newa") | ||||
| DEF(Nko, "Nkoo") | ||||
| DEF(Nushu, "Nshu") | ||||
| DEF(Nyiakeng_Puachue_Hmong, "Hmnp") | ||||
| DEF(Ogham, "Ogam") | ||||
| DEF(Ol_Chiki, "Olck") | ||||
| DEF(Old_Hungarian, "Hung") | ||||
| DEF(Old_Italic, "Ital") | ||||
| DEF(Old_North_Arabian, "Narb") | ||||
| DEF(Old_Permic, "Perm") | ||||
| DEF(Old_Persian, "Xpeo") | ||||
| DEF(Old_Sogdian, "Sogo") | ||||
| DEF(Old_South_Arabian, "Sarb") | ||||
| DEF(Old_Turkic, "Orkh") | ||||
| DEF(Oriya, "Orya") | ||||
| DEF(Osage, "Osge") | ||||
| DEF(Osmanya, "Osma") | ||||
| DEF(Pahawh_Hmong, "Hmng") | ||||
| DEF(Palmyrene, "Palm") | ||||
| DEF(Pau_Cin_Hau, "Pauc") | ||||
| DEF(Phags_Pa, "Phag") | ||||
| DEF(Phoenician, "Phnx") | ||||
| DEF(Psalter_Pahlavi, "Phlp") | ||||
| DEF(Rejang, "Rjng") | ||||
| DEF(Runic, "Runr") | ||||
| DEF(Samaritan, "Samr") | ||||
| DEF(Saurashtra, "Saur") | ||||
| DEF(Sharada, "Shrd") | ||||
| DEF(Shavian, "Shaw") | ||||
| DEF(Siddham, "Sidd") | ||||
| DEF(SignWriting, "Sgnw") | ||||
| DEF(Sinhala, "Sinh") | ||||
| DEF(Sogdian, "Sogd") | ||||
| DEF(Sora_Sompeng, "Sora") | ||||
| DEF(Soyombo, "Soyo") | ||||
| DEF(Sundanese, "Sund") | ||||
| DEF(Syloti_Nagri, "Sylo") | ||||
| DEF(Syriac, "Syrc") | ||||
| DEF(Tagalog, "Tglg") | ||||
| DEF(Tagbanwa, "Tagb") | ||||
| DEF(Tai_Le, "Tale") | ||||
| DEF(Tai_Tham, "Lana") | ||||
| DEF(Tai_Viet, "Tavt") | ||||
| DEF(Takri, "Takr") | ||||
| DEF(Tamil, "Taml") | ||||
| DEF(Tangut, "Tang") | ||||
| DEF(Telugu, "Telu") | ||||
| DEF(Thaana, "Thaa") | ||||
| DEF(Thai, "Thai") | ||||
| DEF(Tibetan, "Tibt") | ||||
| DEF(Tifinagh, "Tfng") | ||||
| DEF(Tirhuta, "Tirh") | ||||
| DEF(Ugaritic, "Ugar") | ||||
| DEF(Vai, "Vaii") | ||||
| DEF(Wancho, "Wcho") | ||||
| DEF(Warang_Citi, "Wara") | ||||
| DEF(Yi, "Yiii") | ||||
| DEF(Zanabazar_Square, "Zanb") | ||||
| #endif | ||||
|  | ||||
| #ifdef UNICODE_PROP_LIST | ||||
| /* Prop list not exported to regexp */ | ||||
| DEF(Hyphen, "") | ||||
| DEF(Other_Math, "") | ||||
| DEF(Other_Alphabetic, "") | ||||
| DEF(Other_Lowercase, "") | ||||
| DEF(Other_Uppercase, "") | ||||
| DEF(Other_Grapheme_Extend, "") | ||||
| DEF(Other_Default_Ignorable_Code_Point, "") | ||||
| DEF(Other_ID_Start, "") | ||||
| DEF(Other_ID_Continue, "") | ||||
| DEF(Prepended_Concatenation_Mark, "") | ||||
| /* additional computed properties for smaller tables */ | ||||
| DEF(ID_Continue1, "") | ||||
| DEF(XID_Start1, "") | ||||
| DEF(XID_Continue1, "") | ||||
| DEF(Changes_When_Titlecased1, "") | ||||
| DEF(Changes_When_Casefolded1, "") | ||||
| DEF(Changes_When_NFKC_Casefolded1, "") | ||||
|  | ||||
| /* Prop list exported to JS */ | ||||
| DEF(ASCII_Hex_Digit, "AHex") | ||||
| DEF(Bidi_Control, "Bidi_C") | ||||
| DEF(Dash, "") | ||||
| DEF(Deprecated, "Dep") | ||||
| DEF(Diacritic, "Dia") | ||||
| DEF(Extender, "Ext") | ||||
| DEF(Hex_Digit, "Hex") | ||||
| DEF(IDS_Binary_Operator, "IDSB") | ||||
| DEF(IDS_Trinary_Operator, "IDST") | ||||
| DEF(Ideographic, "Ideo") | ||||
| DEF(Join_Control, "Join_C") | ||||
| DEF(Logical_Order_Exception, "LOE") | ||||
| DEF(Noncharacter_Code_Point, "NChar") | ||||
| DEF(Pattern_Syntax, "Pat_Syn") | ||||
| DEF(Pattern_White_Space, "Pat_WS") | ||||
| DEF(Quotation_Mark, "QMark") | ||||
| DEF(Radical, "") | ||||
| DEF(Regional_Indicator, "RI") | ||||
| DEF(Sentence_Terminal, "STerm") | ||||
| DEF(Soft_Dotted, "SD") | ||||
| DEF(Terminal_Punctuation, "Term") | ||||
| DEF(Unified_Ideograph, "UIdeo") | ||||
| DEF(Variation_Selector, "VS") | ||||
| DEF(White_Space, "space") | ||||
| DEF(Bidi_Mirrored, "Bidi_M") | ||||
| DEF(Emoji, "") | ||||
| DEF(Emoji_Component, "") | ||||
| DEF(Emoji_Modifier, "") | ||||
| DEF(Emoji_Modifier_Base, "") | ||||
| DEF(Emoji_Presentation, "") | ||||
| DEF(Extended_Pictographic, "") | ||||
| DEF(Default_Ignorable_Code_Point, "DI") | ||||
| DEF(ID_Start, "IDS") | ||||
| DEF(Case_Ignorable, "CI") | ||||
|  | ||||
| /* other binary properties */ | ||||
| DEF(ASCII,"") | ||||
| DEF(Alphabetic, "Alpha") | ||||
| DEF(Any, "") | ||||
| DEF(Assigned,"") | ||||
| DEF(Cased, "") | ||||
| DEF(Changes_When_Casefolded, "CWCF") | ||||
| DEF(Changes_When_Casemapped, "CWCM") | ||||
| DEF(Changes_When_Lowercased, "CWL") | ||||
| DEF(Changes_When_NFKC_Casefolded, "CWKCF") | ||||
| DEF(Changes_When_Titlecased, "CWT") | ||||
| DEF(Changes_When_Uppercased, "CWU") | ||||
| DEF(Grapheme_Base, "Gr_Base") | ||||
| DEF(Grapheme_Extend, "Gr_Ext") | ||||
| DEF(ID_Continue, "IDC") | ||||
| DEF(Lowercase, "Lower") | ||||
| DEF(Math, "") | ||||
| DEF(Uppercase, "Upper") | ||||
| DEF(XID_Continue, "XIDC") | ||||
| DEF(XID_Start, "XIDS") | ||||
|  | ||||
| /* internal tables with index */ | ||||
| DEF(Cased1, "") | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										39
									
								
								src/quickjstest.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/quickjstest.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #include "quickjs.h" | ||||
| #include "quickjs-libc.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| int main() | ||||
| { | ||||
| 	JSRuntime* runtime = JS_NewRuntime(); | ||||
| 	JSContext* context = JS_NewContext(runtime); | ||||
| 	js_init_module_std(context, "std"); | ||||
| 	const char* import = "import * as std from 'std';\nglobalThis.std = std;\n"; | ||||
| 	JS_Eval(context, import, strlen(import), "<input>", JS_EVAL_TYPE_MODULE); | ||||
|  | ||||
| 	js_std_add_helpers(context, 0, NULL); | ||||
| 	const char* js = "std.out.puts(\"hello\"); 5+4"; | ||||
| 	JSValue result = JS_Eval(context, js, strlen(js), "test.js", 0); | ||||
| 	if (JS_IsError(context, result)) | ||||
| 	{ | ||||
| 		printf("got an error\n"); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		printf("not an error\n"); | ||||
| 	} | ||||
| 	if (JS_IsException(result)) | ||||
| 	{ | ||||
| 		js_std_dump_error(context); | ||||
| 	} | ||||
| 	const char* c = JS_ToCString(context, JS_ToString(context, result)); | ||||
| 	printf("c = %p\n", c); | ||||
| 	if (c) | ||||
| 	{ | ||||
| 		printf("%s\n", c); | ||||
| 	} | ||||
| 	JS_FreeContext(context); | ||||
| 	JS_FreeRuntime(runtime); | ||||
| 	return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user