├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── TODO ├── VERSION ├── bjson.c ├── cutils.c ├── cutils.h ├── doc ├── jsbignum.html ├── jsbignum.pdf ├── jsbignum.texi ├── quickjs.html ├── quickjs.pdf └── quickjs.texi ├── examples ├── c_module.js ├── fib.c ├── fib_module.js ├── hello.js ├── hello_module.js └── pi.js ├── jscompress.c ├── libbf.c ├── libbf.h ├── libregexp-opcode.h ├── libregexp.c ├── libregexp.h ├── libunicode-table.h ├── libunicode.c ├── libunicode.h ├── list.h ├── node_test.js ├── qjs.c ├── qjsc.c ├── qjscalc.js ├── quickjs-atom.h ├── quickjs-libc.c ├── quickjs-libc.h ├── quickjs-opcode.h ├── quickjs.c ├── quickjs.h ├── readme.txt ├── release.sh ├── repl.js ├── run-test262.c ├── test262.conf ├── test262_errors.txt ├── test262bn.conf ├── test262bn_errors.txt ├── test262o.conf ├── test262o_errors.txt ├── tests ├── microbench.js ├── test262.patch ├── test_bignum.js ├── test_bjson.js ├── test_builtin.js ├── test_closure.js ├── test_loop.js ├── test_op.js └── test_std.js ├── unicode_gen.c └── unicode_gen_def.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | .obj 3 | .DS_Store 4 | quickjs-2019-07-09_bkp 5 | Session.vim 6 | .undodir 7 | node_test 8 | examples 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Carlos Castaño 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # QuickJS Javascript Engine 3 | # 4 | # Copyright (c) 2017-2019 Fabrice Bellard 5 | # Copyright (c) 2017-2019 Charlie Gordon 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | ifeq ($(shell uname -s),Darwin) 26 | CONFIG_DARWIN=y 27 | endif 28 | # Windows cross compilation from Linux 29 | #CONFIG_WIN32=y 30 | # use link time optimization (smaller and faster executables but slower build) 31 | CONFIG_LTO=y 32 | # consider warnings as errors (for development) 33 | #CONFIG_WERROR=y 34 | 35 | ifndef CONFIG_WIN32 36 | # force 32 bit build for some utilities 37 | CONFIG_M32=y 38 | endif 39 | ifdef CONFIG_DARWIN 40 | # use clang instead of gcc 41 | CONFIG_CLANG=y 42 | CONFIG_DEFAULT_AR=y 43 | endif 44 | 45 | # installation directory 46 | prefix=/usr/local 47 | 48 | # use the gprof profiler 49 | #CONFIG_PROFILE=y 50 | # use address sanitizer 51 | #CONFIG_ASAN=y 52 | 53 | OBJDIR=.obj 54 | 55 | ifdef CONFIG_WIN32 56 | CROSS_PREFIX=i686-w64-mingw32- 57 | EXE=.exe 58 | else 59 | CROSS_PREFIX= 60 | EXE= 61 | endif 62 | ifdef CONFIG_CLANG 63 | CC=$(CROSS_PREFIX)clang 64 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d 65 | CFLAGS += -Wextra 66 | CFLAGS += -Wno-sign-compare 67 | CFLAGS += -Wno-missing-field-initializers 68 | CFLAGS += -Wundef -Wuninitialized 69 | CFLAGS += -Wunused -Wno-unused-parameter 70 | CFLAGS += -Wwrite-strings 71 | CFLAGS += -Wchar-subscripts -funsigned-char 72 | CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d 73 | ifdef CONFIG_DEFAULT_AR 74 | AR=$(CROSS_PREFIX)ar 75 | else 76 | ifdef CONFIG_LTO 77 | AR=$(CROSS_PREFIX)llvm-ar 78 | else 79 | AR=$(CROSS_PREFIX)ar 80 | endif 81 | endif 82 | else 83 | CC=$(CROSS_PREFIX)gcc 84 | CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d 85 | CFLAGS += -Wno-array-bounds 86 | ifdef CONFIG_LTO 87 | AR=$(CROSS_PREFIX)gcc-ar 88 | else 89 | AR=$(CROSS_PREFIX)ar 90 | endif 91 | endif 92 | ifdef CONFIG_WERROR 93 | CFLAGS+=-Werror 94 | endif 95 | DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\" 96 | CFLAGS+=$(DEFINES) 97 | CFLAGS_DEBUG=$(CFLAGS) -O0 98 | CFLAGS_SMALL=$(CFLAGS) -Os 99 | CFLAGS_OPT=$(CFLAGS) -O2 100 | CFLAGS_NOLTO:=$(CFLAGS_OPT) 101 | LDFLAGS=-g 102 | ifdef CONFIG_LTO 103 | CFLAGS_SMALL+=-flto 104 | CFLAGS_OPT+=-flto 105 | LDFLAGS+=-flto 106 | endif 107 | ifdef CONFIG_PROFILE 108 | CFLAGS+=-p 109 | LDFLAGS+=-p 110 | endif 111 | ifdef CONFIG_ASAN 112 | CFLAGS+=-fsanitize=address 113 | LDFLAGS+=-fsanitize=address 114 | endif 115 | ifdef CONFIG_WIN32 116 | LDEXPORT= 117 | else 118 | LDEXPORT=-rdynamic 119 | endif 120 | 121 | PROGS=qjs$(EXE) qjsbn$(EXE) qjsc qjsbnc run-test262 run-test262-bn 122 | ifndef CONFIG_WIN32 123 | PROGS+=qjscalc 124 | endif 125 | ifdef CONFIG_M32 126 | PROGS+=qjs32 qjs32_s qjsbn32 127 | endif 128 | PROGS+=libquickjs.a libquickjs.bn.a 129 | ifdef CONFIG_LTO 130 | PROGS+=libquickjs.lto.a libquickjs.bn.lto.a 131 | endif 132 | # examples 133 | ifdef CONFIG_ASAN 134 | PROGS+= 135 | else ifdef CONFIG_WIN32 136 | PROGS+= 137 | else 138 | PROGS+=examples/hello examples/hello_module examples/c_module 139 | endif 140 | 141 | all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS) 142 | 143 | QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o 144 | 145 | QJSBN_LIB_OBJS=$(patsubst %.o, %.bn.o, $(QJS_LIB_OBJS)) $(OBJDIR)/libbf.bn.o 146 | 147 | QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS) 148 | 149 | QJSBN_OBJS=$(OBJDIR)/qjs.bn.o $(OBJDIR)/repl-bn.bn.o $(OBJDIR)/qjscalc.bn.o $(QJSBN_LIB_OBJS) 150 | 151 | LIBS=-lm 152 | ifndef CONFIG_WIN32 153 | LIBS+=-ldl 154 | endif 155 | 156 | $(OBJDIR): 157 | mkdir -p $(OBJDIR) 158 | 159 | qjs$(EXE): $(QJS_OBJS) 160 | $(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) 161 | 162 | qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS)) 163 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 164 | 165 | qjsc: $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS) 166 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 167 | 168 | qjsbnc: $(OBJDIR)/qjsc.bn.o $(QJSBN_LIB_OBJS) 169 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 170 | 171 | 172 | QJSC_DEFINES:=-DCONFIG_CC=\"$(CC)\" 173 | ifdef CONFIG_LTO 174 | QJSC_DEFINES+=-DCONFIG_LTO 175 | endif 176 | QJSC_DEFINES+=-DCONFIG_PREFIX=\"$(prefix)\" 177 | 178 | $(OBJDIR)/qjsc.o $(OBJDIR)/qjsc.bn.o: CFLAGS+=$(QJSC_DEFINES) 179 | 180 | qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS)) 181 | $(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) 182 | 183 | qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS)) 184 | $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) 185 | @size $@ 186 | 187 | qjsbn$(EXE): $(QJSBN_OBJS) 188 | $(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) 189 | 190 | qjsbn32: $(patsubst %.o, %.m32.o, $(QJSBN_OBJS)) 191 | $(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS) 192 | 193 | qjscalc: qjsbn 194 | ln -sf $< $@ 195 | 196 | qjsbn-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJSBN_OBJS)) 197 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 198 | 199 | ifdef CONFIG_LTO 200 | LTOEXT=.lto 201 | else 202 | LTOEXT= 203 | endif 204 | 205 | libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS) 206 | $(AR) rcs $@ $^ 207 | 208 | libquickjs.bn$(LTOEXT).a: $(QJSBN_LIB_OBJS) 209 | $(AR) rcs $@ $^ 210 | 211 | ifdef CONFIG_LTO 212 | libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS)) 213 | $(AR) rcs $@ $^ 214 | 215 | libquickjs.bn.a: $(patsubst %.o, %.nolto.o, $(QJSBN_LIB_OBJS)) 216 | $(AR) rcs $@ $^ 217 | endif # CONFIG_LTO 218 | 219 | repl.c: qjsc repl.js 220 | ./qjsc -c -o $@ -m repl.js 221 | 222 | repl-bn.c: qjsbnc repl.js 223 | ./qjsbnc -c -o $@ -m repl.js 224 | 225 | qjscalc.c: qjsbnc qjscalc.js 226 | ./qjsbnc -c -o $@ qjscalc.js 227 | 228 | ifneq ($(wildcard unicode/UnicodeData.txt),) 229 | $(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o $(OBJDIR)/libunicode.bn.o \ 230 | $(OBJDIR)/libunicode.nolto.o $(OBJDIR)/libunicode.bn.nolto.o: libunicode-table.h 231 | 232 | libunicode-table.h: unicode_gen 233 | ./unicode_gen unicode $@ 234 | endif 235 | 236 | run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS) 237 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread 238 | 239 | run-test262-bn: $(OBJDIR)/run-test262.bn.o $(QJSBN_LIB_OBJS) 240 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread 241 | 242 | run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) 243 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread 244 | 245 | run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)) 246 | $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread 247 | 248 | run-test262-bn32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.bn.o $(QJSBN_LIB_OBJS)) 249 | $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread 250 | 251 | # object suffix order: bn, nolto, [m32|m32s] 252 | 253 | $(OBJDIR)/%.o: %.c | $(OBJDIR) 254 | $(CC) $(CFLAGS_OPT) -c -o $@ $< 255 | 256 | $(OBJDIR)/%.pic.o: %.c | $(OBJDIR) 257 | $(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $< 258 | 259 | $(OBJDIR)/%.bn.o: %.c | $(OBJDIR) 260 | $(CC) $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $< 261 | 262 | $(OBJDIR)/%.nolto.o: %.c | $(OBJDIR) 263 | $(CC) $(CFLAGS_NOLTO) -c -o $@ $< 264 | 265 | $(OBJDIR)/%.bn.nolto.o: %.c | $(OBJDIR) 266 | $(CC) $(CFLAGS_NOLTO) -DCONFIG_BIGNUM -c -o $@ $< 267 | 268 | $(OBJDIR)/%.m32.o: %.c | $(OBJDIR) 269 | $(CC) -m32 $(CFLAGS_OPT) -c -o $@ $< 270 | 271 | $(OBJDIR)/%.m32s.o: %.c | $(OBJDIR) 272 | $(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $< 273 | 274 | $(OBJDIR)/%.bn.m32.o: %.c | $(OBJDIR) 275 | $(CC) -m32 $(CFLAGS_OPT) -DCONFIG_BIGNUM -c -o $@ $< 276 | 277 | $(OBJDIR)/%.debug.o: %.c | $(OBJDIR) 278 | $(CC) $(CFLAGS_DEBUG) -c -o $@ $< 279 | 280 | $(OBJDIR)/%.bn.debug.o: %.c | $(OBJDIR) 281 | $(CC) $(CFLAGS_DEBUG) -DCONFIG_BIGNUM -c -o $@ $< 282 | 283 | $(OBJDIR)/%.check.o: %.c | $(OBJDIR) 284 | $(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $< 285 | 286 | regexp_test: libregexp.c libunicode.c cutils.c 287 | $(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS) 288 | 289 | jscompress: jscompress.c 290 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c 291 | 292 | unicode_gen: unicode_gen.c cutils.c libunicode.c 293 | $(CC) $(LDFLAGS) $(CFLAGS) -o $@ unicode_gen.c cutils.c 294 | 295 | clean: 296 | rm -f repl.c repl-bn.c qjscalc.c out.c 297 | rm -f *.a *.so *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS) 298 | rm -f hello.c hello_module.c c_module.c 299 | rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug qjsbn-debug 300 | rm -rf run-test262-debug run-test262-32 run-test262-bn32 301 | 302 | install: all 303 | mkdir -p "$(prefix)/bin" 304 | install -m755 -s qjs qjsc qjsbn qjsbnc "$(prefix)/bin" 305 | ln -sf qjsbn "$(prefix)/bin/qjscalc" 306 | mkdir -p "$(prefix)/lib/quickjs" 307 | install -m755 libquickjs.a libquickjs.bn.a "$(prefix)/lib/quickjs" 308 | ifdef CONFIG_LTO 309 | install -m755 libquickjs.lto.a libquickjs.bn.lto.a "$(prefix)/lib/quickjs" 310 | endif 311 | mkdir -p "$(prefix)/include/quickjs" 312 | install -m755 quickjs.h quickjs-libc.h "$(prefix)/include/quickjs" 313 | 314 | 315 | ############################################################################### 316 | # examples 317 | 318 | # example of static JS compilation 319 | HELLO_SRCS=examples/hello.js 320 | HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ 321 | -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy 322 | 323 | hello.c: qjsc $(HELLO_SRCS) 324 | ./qjsc -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS) 325 | 326 | ifdef CONFIG_M32 327 | examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS)) 328 | $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) 329 | else 330 | examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS) 331 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 332 | endif 333 | 334 | # example of static JS compilation with modules 335 | HELLO_MODULE_SRCS=examples/hello_module.js 336 | HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ 337 | -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy -m 338 | examples/hello_module: qjsc libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS) 339 | ./qjsc $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS) 340 | 341 | # use of an external C module (static compilation) 342 | 343 | c_module.c: qjsc examples/c_module.js 344 | ./qjsc -e -M examples/fib.so,fib -m -o $@ examples/c_module.js 345 | 346 | examples/c_module: $(OBJDIR)/c_module.o $(OBJDIR)/fib.o libquickjs$(LTOEXT).a 347 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 348 | 349 | $(OBJDIR)/fib.o: examples/fib.c 350 | $(CC) $(CFLAGS_OPT) -c -o $@ $< 351 | 352 | ############################################################################### 353 | # documentation 354 | 355 | DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html 356 | 357 | build_doc: $(DOCS) 358 | 359 | clean_doc: 360 | rm -f $(DOCS) 361 | 362 | doc/%.pdf: doc/%.texi 363 | texi2pdf --clean -o $@ -q $< 364 | 365 | doc/%.html: doc/%.texi 366 | makeinfo --html --no-headers --no-split --number-sections -o $@ $< 367 | 368 | ############################################################################### 369 | # tests 370 | 371 | ifndef CONFIG_DARWIN 372 | test: bjson.so 373 | endif 374 | 375 | test: qjs qjsbn 376 | ./qjs tests/test_closure.js 377 | ./qjs tests/test_op.js 378 | ./qjs tests/test_builtin.js 379 | ./qjs tests/test_loop.js 380 | ./qjs -m tests/test_std.js 381 | ifndef CONFIG_DARWIN 382 | ./qjs -m tests/test_bjson.js 383 | endif 384 | ./qjsbn tests/test_closure.js 385 | ./qjsbn tests/test_op.js 386 | ./qjsbn tests/test_builtin.js 387 | ./qjsbn tests/test_loop.js 388 | ./qjsbn -m tests/test_std.js 389 | ./qjsbn --qjscalc tests/test_bignum.js 390 | 391 | test-32: qjs32 qjsbn32 392 | ./qjs32 tests/test_closure.js 393 | ./qjs32 tests/test_op.js 394 | ./qjs32 tests/test_builtin.js 395 | ./qjs32 tests/test_loop.js 396 | ./qjs32 -m tests/test_std.js 397 | ./qjsbn32 tests/test_closure.js 398 | ./qjsbn32 tests/test_op.js 399 | ./qjsbn32 tests/test_builtin.js 400 | ./qjsbn32 tests/test_loop.js 401 | ./qjsbn32 -m tests/test_std.js 402 | ./qjsbn32 --qjscalc tests/test_bignum.js 403 | 404 | stats: qjs qjs32 405 | ./qjs -qd 406 | ./qjs32 -qd 407 | 408 | microbench: qjs 409 | ./qjs tests/microbench.js 410 | 411 | microbench-32: qjs32 412 | ./qjs32 tests/microbench.js 413 | 414 | # ES5 tests (obsolete) 415 | test2o: run-test262 416 | time ./run-test262 -m -c test262o.conf 417 | 418 | test2o-32: run-test262-32 419 | time ./run-test262-32 -m -c test262o.conf 420 | 421 | test2o-update: run-test262 422 | ./run-test262 -u -c test262o.conf 423 | 424 | # Test262 tests 425 | test2-default: run-test262 426 | time ./run-test262 -m -c test262.conf 427 | 428 | test2: run-test262 429 | time ./run-test262 -m -c test262.conf -a 430 | 431 | test2-32: run-test262-32 432 | time ./run-test262-32 -m -c test262.conf -a 433 | 434 | test2-update: run-test262 435 | ./run-test262 -u -c test262.conf -a 436 | 437 | test2-check: run-test262 438 | time ./run-test262 -m -c test262.conf -E -a 439 | 440 | # Test262 + BigInt tests 441 | test2bn-default: run-test262-bn 442 | time ./run-test262-bn -m -c test262bn.conf 443 | 444 | test2bn: run-test262-bn 445 | time ./run-test262-bn -m -c test262bn.conf -a 446 | 447 | test2bn-32: run-test262-bn32 448 | time ./run-test262-bn32 -m -c test262bn.conf -a 449 | 450 | testall: all test microbench test2o test2 test2bn 451 | 452 | testall-32: all test-32 microbench-32 test2o-32 test2-32 test2bn-32 453 | 454 | testall-complete: testall testall-32 455 | 456 | bench-v8: qjs qjs32 457 | make -C tests/bench-v8 458 | ./qjs -d tests/bench-v8/combined.js 459 | 460 | bjson.so: $(OBJDIR)/bjson.pic.o 461 | $(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS) 462 | 463 | -include $(wildcard $(OBJDIR)/*.d) 464 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic NodeJS APIs for the QuickJS Javascript Engine 2 | This project is based on QuickJS Engine and add some of the most common methods or global objects used in NodeJS 3 | 4 | # Getting started 5 | This was tested in Linux (Ubuntu), install the following dependencies before to compile: 6 | - `apt-get install build-essential` 7 | - `apt-get install gcc-multilib` 8 | 9 | Then run: 10 | ``` 11 | make 12 | ``` 13 | 14 | To use compiler: 15 | ``` 16 | ./qjsc -o myBinary myCode.js 17 | ./myBinary 18 | ``` 19 | 20 | With modules: 21 | ``` 22 | ./qjsc -m -o myBinary myCode.js 23 | ``` 24 | 25 | To use the interpreter: 26 | ``` 27 | ./qjs 28 | ``` 29 | or 30 | ``` 31 | ./qjs myCode.js 32 | ``` 33 | Find out more here https://bellard.org/quickjs/ 34 | 35 | 36 | # What's new here? 37 | 38 | ## Console global object 39 | - `console.error(...)` 40 | - `console.warn(...)` 41 | 42 | ## Process global object 43 | - `process.platform` 44 | - `process.cwd()` 45 | - `process.argv` 46 | - `process.EOL` 47 | 48 | ## Path global object 49 | - `path.basename(...)` 50 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - 64-bit atoms in 64-bit mode? 2 | - rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ? 3 | - unify coding style and naming conventions 4 | - use names from the ECMA spec in library implementation 5 | - modules: if no ".", use a well known module loading path ? 6 | - use JSHoistedDef only for global variables (JSHoistedDef.var_name != JS_ATOM_NULL) 7 | - add index in JSVarDef and is_arg flag to merge args and vars in JSFunctionDef 8 | - replace most JSVarDef flags with var_type enumeration 9 | - use byte code emitters with typed arguments (for clarity) 10 | - use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing 11 | and use the same wrappers in all phases 12 | - use more generic method for line numbers in resolve_variables and resolve_labels 13 | - bignum: 14 | - fix div/pow div by zero exception in doc & code in bigint mode 15 | - fix Atomics support 16 | 17 | Memory: 18 | - test border cases for max number of atoms, object properties, string length 19 | - add emergency malloc mode for out of memory exceptions. 20 | - test all DynBuf memory errors 21 | - test all js_realloc memory errors 22 | - bignum: handle memory errors 23 | - use memory pools for objects, etc? 24 | - improve JS_ComputeMemoryUsage() with more info 25 | 26 | Optimizations: 27 | - use auto-init properties for more global objects 28 | - reuse stack slots for disjoint scopes, if strip 29 | - optimize `for of` iterator for built-in array objects 30 | - add heuristic to avoid some cycles in closures 31 | - small String (0-2 charcodes) with immediate storage 32 | - perform static string concatenation at compile time 33 | - optimize string concatenation with ropes or miniropes? 34 | - add implicit numeric strings for Uint32 numbers? 35 | - optimize `s += a + b`, `s += a.b` and similar simple expressions 36 | - ensure string canonical representation and optimise comparisons and hashes? 37 | - remove JSObject.first_weak_ref, use bit+context based hashed array for weak references 38 | - optimize function storage with length and name accessors? 39 | - property access optimization on the global object, functions, 40 | prototypes and special non extensible objects. 41 | - create object literals with the correct length by backpatching length argument 42 | - remove redundant set_loc_uninitialized/check_uninitialized opcodes 43 | - peephole optim: push_atom_value, to_propkey -> push_atom_value 44 | - peephole optim: put_loc x, get_loc_check x -> set_loc x 45 | - comparative performance benchmark 46 | - use variable name when throwing uninitialized exception if available 47 | - convert slow array to fast array when all properties != length are numeric 48 | - optimize destructuring assignments for global and local variables 49 | - implement some form of tail-call-optimization 50 | - debugger keyword support 51 | - optmize OP_apply 52 | - optimize f(...b) 53 | 54 | Extensions: 55 | - support more features in [features] section 56 | - add TC39 stage 3 proposals: String.prototype.matchAll, Symbol.matchAll 57 | - fix preprocessor bug if nested #ifdef in jscompress.c 58 | - add built-in preprocessor in compiler, get rid of jscompress 59 | handle #if, #ifdef, #line, limited support for #define 60 | - limited support for web assembly 61 | - get rid of __loadScript, use more common name 62 | - BSD sockets 63 | - Process or thread control 64 | - use custom printf to avoid C library compatibility issues 65 | - use custom timezone support to avoid C library compatibility issues 66 | 67 | REPL: 68 | - strip internal functions from stack trace 69 | - readline: support MS Windows terminal 70 | - readline: handle dynamic terminal resizing 71 | - multiline editing 72 | - debugger 73 | - runtime object and function inspectors 74 | - interactive object browser 75 | - use more generic approach to display evaluation results 76 | - improve directive handling: dispatch, colorize, completion... 77 | - save history 78 | - close all predefined methods in repl.js and jscalc.js 79 | 80 | Test262o: 0/11266 errors, 459 excluded 81 | Test262: 0/55855 errors, 504 excluded, 1559 skipped 82 | Test262bn: 0/57176 errors, 724 excluded, 675 skipped 83 | test262 commit: 94b1e80ab3440413df916cd56d29c5a2fa2ac451 84 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2019-07-09 2 | -------------------------------------------------------------------------------- /bjson.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS: binary JSON module (test only) 3 | * 4 | * Copyright (c) 2017-2019 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include "quickjs-libc.h" 25 | #include "cutils.h" 26 | 27 | static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, 28 | int argc, JSValueConst *argv) 29 | { 30 | uint8_t *buf; 31 | uint64_t pos, len; 32 | JSValue obj; 33 | size_t size; 34 | 35 | if (JS_ToIndex(ctx, &pos, argv[1])) 36 | return JS_EXCEPTION; 37 | if (JS_ToIndex(ctx, &len, argv[2])) 38 | return JS_EXCEPTION; 39 | buf = JS_GetArrayBuffer(ctx, &size, argv[0]); 40 | if (!buf) 41 | return JS_EXCEPTION; 42 | if (pos + len > size) 43 | return JS_ThrowRangeError(ctx, "array buffer overflow"); 44 | obj = JS_ReadObject(ctx, buf + pos, len, 0); 45 | return obj; 46 | } 47 | 48 | static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, 49 | int argc, JSValueConst *argv) 50 | { 51 | size_t len; 52 | uint8_t *buf; 53 | JSValue array; 54 | 55 | buf = JS_WriteObject(ctx, &len, argv[0], 0); 56 | if (!buf) 57 | return JS_EXCEPTION; 58 | array = JS_NewArrayBufferCopy(ctx, buf, len); 59 | js_free(ctx, buf); 60 | return array; 61 | } 62 | 63 | static const JSCFunctionListEntry js_bjson_funcs[] = { 64 | JS_CFUNC_DEF("read", 3, js_bjson_read ), 65 | JS_CFUNC_DEF("write", 1, js_bjson_write ), 66 | }; 67 | 68 | static int js_bjson_init(JSContext *ctx, JSModuleDef *m) 69 | { 70 | return JS_SetModuleExportList(ctx, m, js_bjson_funcs, 71 | countof(js_bjson_funcs)); 72 | } 73 | 74 | #ifdef JS_SHARED_LIBRARY 75 | #define JS_INIT_MODULE js_init_module 76 | #else 77 | #define JS_INIT_MODULE js_init_module_bjson 78 | #endif 79 | 80 | JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) 81 | { 82 | JSModuleDef *m; 83 | m = JS_NewCModule(ctx, module_name, js_bjson_init); 84 | if (!m) 85 | return NULL; 86 | JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs)); 87 | return m; 88 | } 89 | -------------------------------------------------------------------------------- /cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * Copyright (c) 2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "cutils.h" 31 | 32 | void pstrcpy(char *buf, int buf_size, const char *str) 33 | { 34 | int c; 35 | char *q = buf; 36 | 37 | if (buf_size <= 0) 38 | return; 39 | 40 | for(;;) { 41 | c = *str++; 42 | if (c == 0 || q >= buf + buf_size - 1) 43 | break; 44 | *q++ = c; 45 | } 46 | *q = '\0'; 47 | } 48 | 49 | /* strcat and truncate. */ 50 | char *pstrcat(char *buf, int buf_size, const char *s) 51 | { 52 | int len; 53 | len = strlen(buf); 54 | if (len < buf_size) 55 | pstrcpy(buf + len, buf_size - len, s); 56 | return buf; 57 | } 58 | 59 | int strstart(const char *str, const char *val, const char **ptr) 60 | { 61 | const char *p, *q; 62 | p = str; 63 | q = val; 64 | while (*q != '\0') { 65 | if (*p != *q) 66 | return 0; 67 | p++; 68 | q++; 69 | } 70 | if (ptr) 71 | *ptr = p; 72 | return 1; 73 | } 74 | 75 | int has_suffix(const char *str, const char *suffix) 76 | { 77 | size_t len = strlen(str); 78 | size_t slen = strlen(suffix); 79 | return (len >= slen && !memcmp(str + len - slen, suffix, slen)); 80 | } 81 | 82 | /* Dynamic buffer package */ 83 | 84 | static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) 85 | { 86 | return realloc(ptr, size); 87 | } 88 | 89 | void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) 90 | { 91 | memset(s, 0, sizeof(*s)); 92 | if (!realloc_func) 93 | realloc_func = dbuf_default_realloc; 94 | s->opaque = opaque; 95 | s->realloc_func = realloc_func; 96 | } 97 | 98 | void dbuf_init(DynBuf *s) 99 | { 100 | dbuf_init2(s, NULL, NULL); 101 | } 102 | 103 | /* return < 0 if error */ 104 | int dbuf_realloc(DynBuf *s, size_t new_size) 105 | { 106 | size_t size; 107 | uint8_t *new_buf; 108 | if (new_size > s->allocated_size) { 109 | if (s->error) 110 | return -1; 111 | size = s->allocated_size * 3 / 2; 112 | if (size > new_size) 113 | new_size = size; 114 | new_buf = s->realloc_func(s->opaque, s->buf, new_size); 115 | if (!new_buf) { 116 | s->error = TRUE; 117 | return -1; 118 | } 119 | s->buf = new_buf; 120 | s->allocated_size = new_size; 121 | } 122 | return 0; 123 | } 124 | 125 | int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) 126 | { 127 | size_t end; 128 | end = offset + len; 129 | if (dbuf_realloc(s, end)) 130 | return -1; 131 | memcpy(s->buf + offset, data, len); 132 | if (end > s->size) 133 | s->size = end; 134 | return 0; 135 | } 136 | 137 | int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) 138 | { 139 | if (unlikely((s->size + len) > s->allocated_size)) { 140 | if (dbuf_realloc(s, s->size + len)) 141 | return -1; 142 | } 143 | memcpy(s->buf + s->size, data, len); 144 | s->size += len; 145 | return 0; 146 | } 147 | 148 | int dbuf_put_self(DynBuf *s, size_t offset, size_t len) 149 | { 150 | if (unlikely((s->size + len) > s->allocated_size)) { 151 | if (dbuf_realloc(s, s->size + len)) 152 | return -1; 153 | } 154 | memcpy(s->buf + s->size, s->buf + offset, len); 155 | s->size += len; 156 | return 0; 157 | } 158 | 159 | int dbuf_putc(DynBuf *s, uint8_t c) 160 | { 161 | return dbuf_put(s, &c, 1); 162 | } 163 | 164 | int dbuf_putstr(DynBuf *s, const char *str) 165 | { 166 | return dbuf_put(s, (const uint8_t *)str, strlen(str)); 167 | } 168 | 169 | int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, 170 | const char *fmt, ...) 171 | { 172 | va_list ap; 173 | char buf[128]; 174 | int len; 175 | 176 | va_start(ap, fmt); 177 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 178 | va_end(ap); 179 | if (len < sizeof(buf)) { 180 | /* fast case */ 181 | return dbuf_put(s, (uint8_t *)buf, len); 182 | } else { 183 | if (dbuf_realloc(s, s->size + len + 1)) 184 | return -1; 185 | va_start(ap, fmt); 186 | vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, 187 | fmt, ap); 188 | va_end(ap); 189 | s->size += len; 190 | } 191 | return 0; 192 | } 193 | 194 | void dbuf_free(DynBuf *s) 195 | { 196 | /* we test s->buf as a fail safe to avoid crashing if dbuf_free() 197 | is called twice */ 198 | if (s->buf) { 199 | s->realloc_func(s->opaque, s->buf, 0); 200 | } 201 | memset(s, 0, sizeof(*s)); 202 | } 203 | 204 | /* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes 205 | are output. */ 206 | int unicode_to_utf8(uint8_t *buf, unsigned int c) 207 | { 208 | uint8_t *q = buf; 209 | 210 | if (c < 0x80) { 211 | *q++ = c; 212 | } else { 213 | if (c < 0x800) { 214 | *q++ = (c >> 6) | 0xc0; 215 | } else { 216 | if (c < 0x10000) { 217 | *q++ = (c >> 12) | 0xe0; 218 | } else { 219 | if (c < 0x00200000) { 220 | *q++ = (c >> 18) | 0xf0; 221 | } else { 222 | if (c < 0x04000000) { 223 | *q++ = (c >> 24) | 0xf8; 224 | } else if (c < 0x80000000) { 225 | *q++ = (c >> 30) | 0xfc; 226 | *q++ = ((c >> 24) & 0x3f) | 0x80; 227 | } else { 228 | return 0; 229 | } 230 | *q++ = ((c >> 18) & 0x3f) | 0x80; 231 | } 232 | *q++ = ((c >> 12) & 0x3f) | 0x80; 233 | } 234 | *q++ = ((c >> 6) & 0x3f) | 0x80; 235 | } 236 | *q++ = (c & 0x3f) | 0x80; 237 | } 238 | return q - buf; 239 | } 240 | 241 | static const unsigned int utf8_min_code[5] = { 242 | 0x80, 0x800, 0x10000, 0x00200000, 0x04000000, 243 | }; 244 | 245 | static const unsigned char utf8_first_code_mask[5] = { 246 | 0x1f, 0xf, 0x7, 0x3, 0x1, 247 | }; 248 | 249 | /* return -1 if error. *pp is not updated in this case. max_len must 250 | be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */ 251 | int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp) 252 | { 253 | int l, c, b, i; 254 | 255 | c = *p++; 256 | if (c < 0x80) { 257 | *pp = p; 258 | return c; 259 | } 260 | switch(c) { 261 | case 0xc0 ... 0xdf: 262 | l = 1; 263 | break; 264 | case 0xe0 ... 0xef: 265 | l = 2; 266 | break; 267 | case 0xf0 ... 0xf7: 268 | l = 3; 269 | break; 270 | case 0xf8 ... 0xfb: 271 | l = 4; 272 | break; 273 | case 0xfc ... 0xfd: 274 | l = 5; 275 | break; 276 | default: 277 | return -1; 278 | } 279 | /* check that we have enough characters */ 280 | if (l > (max_len - 1)) 281 | return -1; 282 | c &= utf8_first_code_mask[l - 1]; 283 | for(i = 0; i < l; i++) { 284 | b = *p++; 285 | if (b < 0x80 || b >= 0xc0) 286 | return -1; 287 | c = (c << 6) | (b & 0x3f); 288 | } 289 | if (c < utf8_min_code[l - 1]) 290 | return -1; 291 | *pp = p; 292 | return c; 293 | } 294 | 295 | #if 0 296 | 297 | #if defined(EMSCRIPTEN) || defined(__ANDROID__) 298 | 299 | static void *rqsort_arg; 300 | static int (*rqsort_cmp)(const void *, const void *, void *); 301 | 302 | static int rqsort_cmp2(const void *p1, const void *p2) 303 | { 304 | return rqsort_cmp(p1, p2, rqsort_arg); 305 | } 306 | 307 | /* not reentrant, but not needed with emscripten */ 308 | void rqsort(void *base, size_t nmemb, size_t size, 309 | int (*cmp)(const void *, const void *, void *), 310 | void *arg) 311 | { 312 | rqsort_arg = arg; 313 | rqsort_cmp = cmp; 314 | qsort(base, nmemb, size, rqsort_cmp2); 315 | } 316 | 317 | #endif 318 | 319 | #else 320 | 321 | typedef void (*exchange_f)(void *a, void *b, size_t size); 322 | typedef int (*cmp_f)(const void *, const void *, void *opaque); 323 | 324 | static void exchange_bytes(void *a, void *b, size_t size) { 325 | uint8_t *ap = (uint8_t *)a; 326 | uint8_t *bp = (uint8_t *)b; 327 | 328 | while (size-- != 0) { 329 | uint8_t t = *ap; 330 | *ap++ = *bp; 331 | *bp++ = t; 332 | } 333 | } 334 | 335 | static void exchange_one_byte(void *a, void *b, size_t size) { 336 | uint8_t *ap = (uint8_t *)a; 337 | uint8_t *bp = (uint8_t *)b; 338 | uint8_t t = *ap; 339 | *ap = *bp; 340 | *bp = t; 341 | } 342 | 343 | static void exchange_int16s(void *a, void *b, size_t size) { 344 | uint16_t *ap = (uint16_t *)a; 345 | uint16_t *bp = (uint16_t *)b; 346 | 347 | for (size /= sizeof(uint16_t); size-- != 0;) { 348 | uint16_t t = *ap; 349 | *ap++ = *bp; 350 | *bp++ = t; 351 | } 352 | } 353 | 354 | static void exchange_one_int16(void *a, void *b, size_t size) { 355 | uint16_t *ap = (uint16_t *)a; 356 | uint16_t *bp = (uint16_t *)b; 357 | uint16_t t = *ap; 358 | *ap = *bp; 359 | *bp = t; 360 | } 361 | 362 | static void exchange_int32s(void *a, void *b, size_t size) { 363 | uint32_t *ap = (uint32_t *)a; 364 | uint32_t *bp = (uint32_t *)b; 365 | 366 | for (size /= sizeof(uint32_t); size-- != 0;) { 367 | uint32_t t = *ap; 368 | *ap++ = *bp; 369 | *bp++ = t; 370 | } 371 | } 372 | 373 | static void exchange_one_int32(void *a, void *b, size_t size) { 374 | uint32_t *ap = (uint32_t *)a; 375 | uint32_t *bp = (uint32_t *)b; 376 | uint32_t t = *ap; 377 | *ap = *bp; 378 | *bp = t; 379 | } 380 | 381 | static void exchange_int64s(void *a, void *b, size_t size) { 382 | uint64_t *ap = (uint64_t *)a; 383 | uint64_t *bp = (uint64_t *)b; 384 | 385 | for (size /= sizeof(uint64_t); size-- != 0;) { 386 | uint64_t t = *ap; 387 | *ap++ = *bp; 388 | *bp++ = t; 389 | } 390 | } 391 | 392 | static void exchange_one_int64(void *a, void *b, size_t size) { 393 | uint64_t *ap = (uint64_t *)a; 394 | uint64_t *bp = (uint64_t *)b; 395 | uint64_t t = *ap; 396 | *ap = *bp; 397 | *bp = t; 398 | } 399 | 400 | static void exchange_int128s(void *a, void *b, size_t size) { 401 | uint64_t *ap = (uint64_t *)a; 402 | uint64_t *bp = (uint64_t *)b; 403 | 404 | for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { 405 | uint64_t t = ap[0]; 406 | uint64_t u = ap[1]; 407 | ap[0] = bp[0]; 408 | ap[1] = bp[1]; 409 | bp[0] = t; 410 | bp[1] = u; 411 | } 412 | } 413 | 414 | static void exchange_one_int128(void *a, void *b, size_t size) { 415 | uint64_t *ap = (uint64_t *)a; 416 | uint64_t *bp = (uint64_t *)b; 417 | uint64_t t = ap[0]; 418 | uint64_t u = ap[1]; 419 | ap[0] = bp[0]; 420 | ap[1] = bp[1]; 421 | bp[0] = t; 422 | bp[1] = u; 423 | } 424 | 425 | static inline exchange_f exchange_func(const void *base, size_t size) { 426 | switch (((uintptr_t)base | (uintptr_t)size) & 15) { 427 | case 0: 428 | if (size == sizeof(uint64_t) * 2) 429 | return exchange_one_int128; 430 | else 431 | return exchange_int128s; 432 | case 8: 433 | if (size == sizeof(uint64_t)) 434 | return exchange_one_int64; 435 | else 436 | return exchange_int64s; 437 | case 4: 438 | case 12: 439 | if (size == sizeof(uint32_t)) 440 | return exchange_one_int32; 441 | else 442 | return exchange_int32s; 443 | case 2: 444 | case 6: 445 | case 10: 446 | case 14: 447 | if (size == sizeof(uint16_t)) 448 | return exchange_one_int16; 449 | else 450 | return exchange_int16s; 451 | default: 452 | if (size == 1) 453 | return exchange_one_byte; 454 | else 455 | return exchange_bytes; 456 | } 457 | } 458 | 459 | static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) 460 | { 461 | uint8_t *basep = (uint8_t *)base; 462 | size_t i, n, c, r; 463 | exchange_f swap = exchange_func(base, size); 464 | 465 | if (nmemb > 1) { 466 | i = (nmemb / 2) * size; 467 | n = nmemb * size; 468 | 469 | while (i > 0) { 470 | i -= size; 471 | for (r = i; (c = r * 2 + size) < n; r = c) { 472 | if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) 473 | c += size; 474 | if (cmp(basep + r, basep + c, opaque) > 0) 475 | break; 476 | swap(basep + r, basep + c, size); 477 | } 478 | } 479 | for (i = n - size; i > 0; i -= size) { 480 | swap(basep, basep + i, size); 481 | 482 | for (r = 0; (c = r * 2 + size) < i; r = c) { 483 | if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) 484 | c += size; 485 | if (cmp(basep + r, basep + c, opaque) > 0) 486 | break; 487 | swap(basep + r, basep + c, size); 488 | } 489 | } 490 | } 491 | } 492 | 493 | static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) 494 | { 495 | return cmp(a, b, opaque) < 0 ? 496 | (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : 497 | (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); 498 | } 499 | 500 | /* pointer based version with local stack and insertion sort threshhold */ 501 | void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) 502 | { 503 | struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; 504 | uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; 505 | size_t m4, i, lt, gt, span, span2; 506 | int c, depth; 507 | exchange_f swap = exchange_func(base, size); 508 | exchange_f swap_block = exchange_func(base, size | 128); 509 | 510 | if (nmemb < 2 || size <= 0) 511 | return; 512 | 513 | sp->base = (uint8_t *)base; 514 | sp->count = nmemb; 515 | sp->depth = 0; 516 | sp++; 517 | 518 | while (sp > stack) { 519 | sp--; 520 | ptr = sp->base; 521 | nmemb = sp->count; 522 | depth = sp->depth; 523 | 524 | while (nmemb > 6) { 525 | if (++depth > 50) { 526 | /* depth check to ensure worst case logarithmic time */ 527 | heapsortx(ptr, nmemb, size, cmp, opaque); 528 | nmemb = 0; 529 | break; 530 | } 531 | /* select median of 3 from 1/4, 1/2, 3/4 positions */ 532 | /* should use median of 5 or 9? */ 533 | m4 = (nmemb >> 2) * size; 534 | m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); 535 | swap(ptr, m, size); /* move the pivot to the start or the array */ 536 | i = lt = 1; 537 | pi = plt = ptr + size; 538 | gt = nmemb; 539 | pj = pgt = top = ptr + nmemb * size; 540 | for (;;) { 541 | while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { 542 | if (c == 0) { 543 | swap(plt, pi, size); 544 | lt++; 545 | plt += size; 546 | } 547 | i++; 548 | pi += size; 549 | } 550 | while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { 551 | if (c == 0) { 552 | gt--; 553 | pgt -= size; 554 | swap(pgt, pj, size); 555 | } 556 | } 557 | if (pi >= pj) 558 | break; 559 | swap(pi, pj, size); 560 | i++; 561 | pi += size; 562 | } 563 | /* array has 4 parts: 564 | * from 0 to lt excluded: elements identical to pivot 565 | * from lt to pi excluded: elements smaller than pivot 566 | * from pi to gt excluded: elements greater than pivot 567 | * from gt to n excluded: elements identical to pivot 568 | */ 569 | /* move elements identical to pivot in the middle of the array: */ 570 | /* swap values in ranges [0..lt[ and [i-lt..i[ 571 | swapping the smallest span between lt and i-lt is sufficient 572 | */ 573 | span = plt - ptr; 574 | span2 = pi - plt; 575 | plt = pi - span; 576 | lt = i - lt; 577 | if (span > span2) 578 | span = span2; 579 | swap_block(ptr, pi - span, span); 580 | /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ 581 | swapping the smallest span between top-gt and gt-i is sufficient 582 | */ 583 | span = top - pgt; 584 | span2 = pgt - pi; 585 | pgt = top - span2; 586 | gt = nmemb - (gt - i); 587 | if (span > span2) 588 | span = span2; 589 | swap_block(pi, top - span, span); 590 | 591 | /* now array has 3 parts: 592 | * from 0 to lt excluded: elements smaller than pivot 593 | * from lt to gt excluded: elements identical to pivot 594 | * from gt to n excluded: elements greater than pivot 595 | */ 596 | /* stack the larger segment and keep processing the smaller one 597 | to minimize stack use for pathological distributions */ 598 | if (lt > nmemb - gt) { 599 | sp->base = ptr; 600 | sp->count = lt; 601 | sp->depth = depth; 602 | sp++; 603 | ptr = pgt; 604 | nmemb -= gt; 605 | } else { 606 | sp->base = pgt; 607 | sp->count = nmemb - gt; 608 | sp->depth = depth; 609 | sp++; 610 | nmemb = lt; 611 | } 612 | } 613 | /* Use insertion sort for small fragments */ 614 | for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { 615 | for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) 616 | swap(pj, pj - size, size); 617 | } 618 | } 619 | } 620 | 621 | #endif 622 | -------------------------------------------------------------------------------- /cutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * Copyright (c) 2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #ifndef CUTILS_H 26 | #define CUTILS_H 27 | 28 | #include 29 | #include 30 | 31 | /* set if CPU is big endian */ 32 | #undef WORDS_BIGENDIAN 33 | 34 | #define likely(x) __builtin_expect(!!(x), 1) 35 | #define unlikely(x) __builtin_expect(!!(x), 0) 36 | #define force_inline inline __attribute__((always_inline)) 37 | #define no_inline __attribute__((noinline)) 38 | 39 | #define xglue(x, y) x ## y 40 | #define glue(x, y) xglue(x, y) 41 | #define stringify(s) tostring(s) 42 | #define tostring(s) #s 43 | 44 | #ifndef offsetof 45 | #define offsetof(type, field) ((size_t) &((type *)0)->field) 46 | #endif 47 | #ifndef countof 48 | #define countof(x) (sizeof(x) / sizeof((x)[0])) 49 | #endif 50 | 51 | typedef int BOOL; 52 | 53 | #ifndef FALSE 54 | enum { 55 | FALSE = 0, 56 | TRUE = 1, 57 | }; 58 | #endif 59 | 60 | void pstrcpy(char *buf, int buf_size, const char *str); 61 | char *pstrcat(char *buf, int buf_size, const char *s); 62 | int strstart(const char *str, const char *val, const char **ptr); 63 | int has_suffix(const char *str, const char *suffix); 64 | 65 | static inline int max_int(int a, int b) 66 | { 67 | if (a > b) 68 | return a; 69 | else 70 | return b; 71 | } 72 | 73 | static inline int min_int(int a, int b) 74 | { 75 | if (a < b) 76 | return a; 77 | else 78 | return b; 79 | } 80 | 81 | static inline uint32_t max_uint32(uint32_t a, uint32_t b) 82 | { 83 | if (a > b) 84 | return a; 85 | else 86 | return b; 87 | } 88 | 89 | static inline uint32_t min_uint32(uint32_t a, uint32_t b) 90 | { 91 | if (a < b) 92 | return a; 93 | else 94 | return b; 95 | } 96 | 97 | static inline int64_t max_int64(int64_t a, int64_t b) 98 | { 99 | if (a > b) 100 | return a; 101 | else 102 | return b; 103 | } 104 | 105 | static inline int64_t min_int64(int64_t a, int64_t b) 106 | { 107 | if (a < b) 108 | return a; 109 | else 110 | return b; 111 | } 112 | 113 | /* WARNING: undefined if a = 0 */ 114 | static inline int clz32(unsigned int a) 115 | { 116 | return __builtin_clz(a); 117 | } 118 | 119 | /* WARNING: undefined if a = 0 */ 120 | static inline int clz64(uint64_t a) 121 | { 122 | return __builtin_clzll(a); 123 | } 124 | 125 | /* WARNING: undefined if a = 0 */ 126 | static inline int ctz32(unsigned int a) 127 | { 128 | return __builtin_ctz(a); 129 | } 130 | 131 | /* WARNING: undefined if a = 0 */ 132 | static inline int ctz64(uint64_t a) 133 | { 134 | return __builtin_ctzll(a); 135 | } 136 | 137 | struct __attribute__((packed)) packed_u64 { 138 | uint64_t v; 139 | }; 140 | 141 | struct __attribute__((packed)) packed_u32 { 142 | uint32_t v; 143 | }; 144 | 145 | struct __attribute__((packed)) packed_u16 { 146 | uint16_t v; 147 | }; 148 | 149 | static inline uint64_t get_u64(const uint8_t *tab) 150 | { 151 | return ((const struct packed_u64 *)tab)->v; 152 | } 153 | 154 | static inline int64_t get_i64(const uint8_t *tab) 155 | { 156 | return (int64_t)((const struct packed_u64 *)tab)->v; 157 | } 158 | 159 | static inline void put_u64(uint8_t *tab, uint64_t val) 160 | { 161 | ((struct packed_u64 *)tab)->v = val; 162 | } 163 | 164 | static inline uint32_t get_u32(const uint8_t *tab) 165 | { 166 | return ((const struct packed_u32 *)tab)->v; 167 | } 168 | 169 | static inline int32_t get_i32(const uint8_t *tab) 170 | { 171 | return (int32_t)((const struct packed_u32 *)tab)->v; 172 | } 173 | 174 | static inline void put_u32(uint8_t *tab, uint32_t val) 175 | { 176 | ((struct packed_u32 *)tab)->v = val; 177 | } 178 | 179 | static inline uint32_t get_u16(const uint8_t *tab) 180 | { 181 | return ((const struct packed_u16 *)tab)->v; 182 | } 183 | 184 | static inline int32_t get_i16(const uint8_t *tab) 185 | { 186 | return (int16_t)((const struct packed_u16 *)tab)->v; 187 | } 188 | 189 | static inline void put_u16(uint8_t *tab, uint16_t val) 190 | { 191 | ((struct packed_u16 *)tab)->v = val; 192 | } 193 | 194 | static inline uint32_t get_u8(const uint8_t *tab) 195 | { 196 | return *tab; 197 | } 198 | 199 | static inline int32_t get_i8(const uint8_t *tab) 200 | { 201 | return (int8_t)*tab; 202 | } 203 | 204 | static inline void put_u8(uint8_t *tab, uint8_t val) 205 | { 206 | *tab = val; 207 | } 208 | 209 | static inline uint16_t bswap16(uint16_t x) 210 | { 211 | return (x >> 8) | (x << 8); 212 | } 213 | 214 | static inline uint32_t bswap32(uint32_t v) 215 | { 216 | return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) | 217 | ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24); 218 | } 219 | 220 | static inline uint64_t bswap64(uint64_t v) 221 | { 222 | return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) | 223 | ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) | 224 | ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) | 225 | ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) | 226 | ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) | 227 | ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) | 228 | ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) | 229 | ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8)); 230 | } 231 | 232 | /* XXX: should take an extra argument to pass slack information to the caller */ 233 | typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size); 234 | 235 | typedef struct DynBuf { 236 | uint8_t *buf; 237 | size_t size; 238 | size_t allocated_size; 239 | BOOL error; /* true if a memory allocation error occurred */ 240 | DynBufReallocFunc *realloc_func; 241 | void *opaque; /* for realloc_func */ 242 | } DynBuf; 243 | 244 | void dbuf_init(DynBuf *s); 245 | void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); 246 | int dbuf_realloc(DynBuf *s, size_t new_size); 247 | int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); 248 | int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); 249 | int dbuf_put_self(DynBuf *s, size_t offset, size_t len); 250 | int dbuf_putc(DynBuf *s, uint8_t c); 251 | int dbuf_putstr(DynBuf *s, const char *str); 252 | static inline int dbuf_put_u16(DynBuf *s, uint16_t val) 253 | { 254 | return dbuf_put(s, (uint8_t *)&val, 2); 255 | } 256 | static inline int dbuf_put_u32(DynBuf *s, uint32_t val) 257 | { 258 | return dbuf_put(s, (uint8_t *)&val, 4); 259 | } 260 | static inline int dbuf_put_u64(DynBuf *s, uint64_t val) 261 | { 262 | return dbuf_put(s, (uint8_t *)&val, 8); 263 | } 264 | int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, 265 | const char *fmt, ...); 266 | void dbuf_free(DynBuf *s); 267 | static inline BOOL dbuf_error(DynBuf *s) { 268 | return s->error; 269 | } 270 | 271 | #define UTF8_CHAR_LEN_MAX 6 272 | 273 | int unicode_to_utf8(uint8_t *buf, unsigned int c); 274 | int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp); 275 | 276 | static inline int from_hex(int c) 277 | { 278 | if (c >= '0' && c <= '9') 279 | return c - '0'; 280 | else if (c >= 'A' && c <= 'F') 281 | return c - 'A' + 10; 282 | else if (c >= 'a' && c <= 'f') 283 | return c - 'a' + 10; 284 | else 285 | return -1; 286 | } 287 | 288 | void rqsort(void *base, size_t nmemb, size_t size, 289 | int (*cmp)(const void *, const void *, void *), 290 | void *arg); 291 | 292 | #endif /* CUTILS_H */ 293 | -------------------------------------------------------------------------------- /doc/jsbignum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calbertts/qnode/27bd7e7fd124aba8fac2216e60fe735612b377bb/doc/jsbignum.pdf -------------------------------------------------------------------------------- /doc/quickjs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calbertts/qnode/27bd7e7fd124aba8fac2216e60fe735612b377bb/doc/quickjs.pdf -------------------------------------------------------------------------------- /examples/c_module.js: -------------------------------------------------------------------------------- 1 | /* example of JS module importing a C module */ 2 | 3 | import { fib } from "./fib.so"; 4 | 5 | console.log("Hello World"); 6 | console.log("fib(10)=", fib(10)); 7 | -------------------------------------------------------------------------------- /examples/fib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS: Example of C module 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include "../quickjs.h" 25 | 26 | #define countof(x) (sizeof(x) / sizeof((x)[0])) 27 | 28 | static int fib(int n) 29 | { 30 | if (n <= 0) 31 | return 0; 32 | else if (n == 1) 33 | return 1; 34 | else 35 | return fib(n - 1) + fib(n - 2); 36 | } 37 | 38 | static JSValue js_fib(JSContext *ctx, JSValueConst this_val, 39 | int argc, JSValueConst *argv) 40 | { 41 | int n, res; 42 | if (JS_ToInt32(ctx, &n, argv[0])) 43 | return JS_EXCEPTION; 44 | res = fib(n); 45 | return JS_NewInt32(ctx, res); 46 | } 47 | 48 | static const JSCFunctionListEntry js_fib_funcs[] = { 49 | JS_CFUNC_DEF("fib", 1, js_fib ), 50 | }; 51 | 52 | static int js_fib_init(JSContext *ctx, JSModuleDef *m) 53 | { 54 | return JS_SetModuleExportList(ctx, m, js_fib_funcs, 55 | countof(js_fib_funcs)); 56 | } 57 | 58 | #ifdef JS_SHARED_LIBRARY 59 | #define JS_INIT_MODULE js_init_module 60 | #else 61 | #define JS_INIT_MODULE js_init_module_fib 62 | #endif 63 | 64 | JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) 65 | { 66 | JSModuleDef *m; 67 | m = JS_NewCModule(ctx, module_name, js_fib_init); 68 | if (!m) 69 | return NULL; 70 | JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs)); 71 | return m; 72 | } 73 | -------------------------------------------------------------------------------- /examples/fib_module.js: -------------------------------------------------------------------------------- 1 | /* fib module */ 2 | export function fib(n) 3 | { 4 | if (n <= 0) 5 | return 0; 6 | else if (n == 1) 7 | return 1; 8 | else 9 | return fib(n - 1) + fib(n - 2); 10 | } 11 | -------------------------------------------------------------------------------- /examples/hello.js: -------------------------------------------------------------------------------- 1 | console.log("Hello World"); 2 | -------------------------------------------------------------------------------- /examples/hello_module.js: -------------------------------------------------------------------------------- 1 | /* example of JS module */ 2 | 3 | import { fib } from "./fib_module.js"; 4 | 5 | console.log("Hello World"); 6 | console.log("fib(10)=", fib(10)); 7 | -------------------------------------------------------------------------------- /examples/pi.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PI computation in Javascript using the QuickJS bignum extensions 3 | */ 4 | "use strict"; 5 | "use bigint"; 6 | 7 | /* compute PI with a precision of 'prec' bits */ 8 | function calc_pi(prec) { 9 | const CHUD_A = 13591409; 10 | const CHUD_B = 545140134; 11 | const CHUD_C = 640320; 12 | const CHUD_C3 = 10939058860032000; /* C^3/24 */ 13 | const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ 14 | 15 | /* return [P, Q, G] */ 16 | function chud_bs(a, b, need_G) { 17 | var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; 18 | if (a == (b - 1)) { 19 | G = (2 * b - 1) * (6 * b - 1) * (6 * b - 5); 20 | P = BigFloat(G * (CHUD_B * b + CHUD_A)); 21 | if (b & 1) 22 | P = -P; 23 | G = BigFloat(G); 24 | Q = BigFloat(b * b * b * CHUD_C3); 25 | } else { 26 | c = (a + b) >> 1; 27 | [P1, Q1, G1] = chud_bs(a, c, true); 28 | [P2, Q2, G2] = chud_bs(c, b, need_G); 29 | P = P1 * Q2 + P2 * G1; 30 | Q = Q1 * Q2; 31 | if (need_G) 32 | G = G1 * G2; 33 | else 34 | G = 0; 35 | } 36 | return [P, Q, G]; 37 | } 38 | 39 | var n, P, Q, G; 40 | /* number of serie terms */ 41 | n = Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM) + 10; 42 | [P, Q, G] = chud_bs(0, n, false); 43 | Q = Q / (P + Q * CHUD_A); 44 | G = (CHUD_C / 12) * BigFloat.sqrt(CHUD_C); 45 | return Q * G; 46 | } 47 | 48 | (function() { 49 | var r, n_digits, n_bits; 50 | if (typeof scriptArgs != "undefined") { 51 | if (scriptArgs.length < 2) { 52 | print("usage: pi n_digits"); 53 | return; 54 | } 55 | n_digits = scriptArgs[1]; 56 | } else { 57 | n_digits = 1000; 58 | } 59 | n_bits = Math.ceil(n_digits * Math.log2(10)); 60 | /* we add more bits to reduce the probability of bad rounding for 61 | the last digits */ 62 | BigFloatEnv.setPrec( () => { 63 | r = calc_pi(); 64 | print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); 65 | }, n_bits + 32); 66 | })(); 67 | -------------------------------------------------------------------------------- /libbf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny arbitrary precision floating point library 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIBBF_H 25 | #define LIBBF_H 26 | 27 | #include 28 | #include 29 | 30 | #if defined(__x86_64__) 31 | #define LIMB_LOG2_BITS 6 32 | #else 33 | #define LIMB_LOG2_BITS 5 34 | #endif 35 | 36 | #define LIMB_BITS (1 << LIMB_LOG2_BITS) 37 | 38 | #if LIMB_BITS == 64 39 | typedef __int128 int128_t; 40 | typedef unsigned __int128 uint128_t; 41 | typedef int64_t slimb_t; 42 | typedef uint64_t limb_t; 43 | typedef uint128_t dlimb_t; 44 | #define EXP_MIN INT64_MIN 45 | #define EXP_MAX INT64_MAX 46 | 47 | #else 48 | 49 | typedef int32_t slimb_t; 50 | typedef uint32_t limb_t; 51 | typedef uint64_t dlimb_t; 52 | #define EXP_MIN INT32_MIN 53 | #define EXP_MAX INT32_MAX 54 | 55 | #endif 56 | 57 | /* in bits */ 58 | #define BF_EXP_BITS_MIN 3 59 | #define BF_EXP_BITS_MAX (LIMB_BITS - 2) 60 | #define BF_PREC_MIN 2 61 | #define BF_PREC_MAX (((limb_t)1 << BF_EXP_BITS_MAX) - 2) 62 | #define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */ 63 | 64 | #if LIMB_BITS == 64 65 | #define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197)) 66 | #else 67 | #define BF_CHKSUM_MOD 975620677U 68 | #endif 69 | 70 | #define BF_EXP_ZERO EXP_MIN 71 | #define BF_EXP_INF (EXP_MAX - 1) 72 | #define BF_EXP_NAN EXP_MAX 73 | 74 | /* +/-zero is represented with expn = BF_EXP_ZERO and len = 0, 75 | +/-infinity is represented with expn = BF_EXP_INF and len = 0, 76 | NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored) 77 | */ 78 | typedef struct { 79 | struct bf_context_t *ctx; 80 | int sign; 81 | slimb_t expn; 82 | limb_t len; 83 | limb_t *tab; 84 | } bf_t; 85 | 86 | typedef enum { 87 | BF_RNDN, /* round to nearest, ties to even */ 88 | BF_RNDZ, /* round to zero */ 89 | BF_RNDD, /* round to -inf */ 90 | BF_RNDU, /* round to +inf */ 91 | BF_RNDNA, /* round to nearest, ties away from zero */ 92 | BF_RNDNU, /* round to nearest, ties to +inf */ 93 | BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU, 94 | inexact flag is always set) */ 95 | } bf_rnd_t; 96 | 97 | /* allow subnormal numbers (only available if the number of exponent 98 | bits is < BF_EXP_BITS_MAX and prec != BF_PREC_INF) */ 99 | #define BF_FLAG_SUBNORMAL (1 << 3) 100 | 101 | #define BF_RND_MASK 0x7 102 | #define BF_EXP_BITS_SHIFT 4 103 | #define BF_EXP_BITS_MASK 0x3f 104 | 105 | /* contains the rounding mode and number of exponents bits */ 106 | typedef uint32_t bf_flags_t; 107 | 108 | typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size); 109 | 110 | typedef struct { 111 | bf_t val; 112 | limb_t prec; 113 | } BFConstCache; 114 | 115 | typedef struct bf_context_t { 116 | void *realloc_opaque; 117 | bf_realloc_func_t *realloc_func; 118 | BFConstCache log2_cache; 119 | BFConstCache pi_cache; 120 | struct BFNTTState *ntt_state; 121 | } bf_context_t; 122 | 123 | static inline int bf_get_exp_bits(bf_flags_t flags) 124 | { 125 | return BF_EXP_BITS_MAX - ((flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK); 126 | } 127 | 128 | static inline bf_flags_t bf_set_exp_bits(int n) 129 | { 130 | return (BF_EXP_BITS_MAX - n) << BF_EXP_BITS_SHIFT; 131 | } 132 | 133 | /* returned status */ 134 | #define BF_ST_INVALID_OP (1 << 0) 135 | #define BF_ST_DIVIDE_ZERO (1 << 1) 136 | #define BF_ST_OVERFLOW (1 << 2) 137 | #define BF_ST_UNDERFLOW (1 << 3) 138 | #define BF_ST_INEXACT (1 << 4) 139 | /* not used yet, indicate that a memory allocation error occured. NaN 140 | is returned */ 141 | #define BF_ST_MEM_ERROR (1 << 5) 142 | 143 | #define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */ 144 | 145 | static inline slimb_t bf_max(slimb_t a, slimb_t b) 146 | { 147 | if (a > b) 148 | return a; 149 | else 150 | return b; 151 | } 152 | 153 | static inline slimb_t bf_min(slimb_t a, slimb_t b) 154 | { 155 | if (a < b) 156 | return a; 157 | else 158 | return b; 159 | } 160 | 161 | void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func, 162 | void *realloc_opaque); 163 | void bf_context_end(bf_context_t *s); 164 | /* free memory allocated for the bf cache data */ 165 | void bf_clear_cache(bf_context_t *s); 166 | 167 | static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size) 168 | { 169 | return s->realloc_func(s->realloc_opaque, ptr, size); 170 | } 171 | 172 | void bf_init(bf_context_t *s, bf_t *r); 173 | 174 | static inline void bf_delete(bf_t *r) 175 | { 176 | bf_context_t *s = r->ctx; 177 | /* we accept to delete a zeroed bf_t structure */ 178 | if (s) { 179 | bf_realloc(s, r->tab, 0); 180 | } 181 | } 182 | 183 | static inline void bf_neg(bf_t *r) 184 | { 185 | r->sign ^= 1; 186 | } 187 | 188 | static inline int bf_is_finite(const bf_t *a) 189 | { 190 | return (a->expn < BF_EXP_INF); 191 | } 192 | 193 | static inline int bf_is_nan(const bf_t *a) 194 | { 195 | return (a->expn == BF_EXP_NAN); 196 | } 197 | 198 | static inline int bf_is_zero(const bf_t *a) 199 | { 200 | return (a->expn == BF_EXP_ZERO); 201 | } 202 | 203 | void bf_set_ui(bf_t *r, uint64_t a); 204 | void bf_set_si(bf_t *r, int64_t a); 205 | void bf_set_nan(bf_t *r); 206 | void bf_set_zero(bf_t *r, int is_neg); 207 | void bf_set_inf(bf_t *r, int is_neg); 208 | void bf_set(bf_t *r, const bf_t *a); 209 | void bf_move(bf_t *r, bf_t *a); 210 | int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode); 211 | void bf_set_float64(bf_t *a, double d); 212 | 213 | int bf_cmpu(const bf_t *a, const bf_t *b); 214 | int bf_cmp_full(const bf_t *a, const bf_t *b); 215 | int bf_cmp_eq(const bf_t *a, const bf_t *b); 216 | int bf_cmp_le(const bf_t *a, const bf_t *b); 217 | int bf_cmp_lt(const bf_t *a, const bf_t *b); 218 | int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); 219 | int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); 220 | int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags); 221 | int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); 222 | int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags); 223 | int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, 224 | bf_flags_t flags); 225 | int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags); 226 | int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags); 227 | #define BF_DIVREM_EUCLIDIAN BF_RNDF 228 | int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, 229 | limb_t prec, bf_flags_t flags, int rnd_mode); 230 | int bf_fmod(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, 231 | bf_flags_t flags); 232 | int bf_remainder(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, 233 | bf_flags_t flags); 234 | int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, 235 | bf_flags_t flags); 236 | int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec, 237 | bf_flags_t flags); 238 | int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b, limb_t prec, bf_flags_t flags); 239 | int bf_rint(bf_t *r, limb_t prec, bf_flags_t flags); 240 | int bf_round(bf_t *r, limb_t prec, bf_flags_t flags); 241 | int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a); 242 | int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 243 | slimb_t bf_get_exp_min(const bf_t *a); 244 | void bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b); 245 | void bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b); 246 | void bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b); 247 | 248 | /* additional flags for bf_atof */ 249 | /* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */ 250 | #define BF_ATOF_NO_HEX (1 << 16) 251 | /* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */ 252 | #define BF_ATOF_BIN_OCT (1 << 17) 253 | /* Only accept integers (no decimal point, no exponent, no infinity nor NaN */ 254 | #define BF_ATOF_INT_ONLY (1 << 18) 255 | /* Do not accept radix prefix after sign */ 256 | #define BF_ATOF_NO_PREFIX_AFTER_SIGN (1 << 19) 257 | /* Do not parse NaN and parse case sensitive 'Infinity' */ 258 | #define BF_ATOF_JS_QUIRKS (1 << 20) 259 | /* Do not round integers to the indicated precision */ 260 | #define BF_ATOF_INT_PREC_INF (1 << 21) 261 | /* Support legacy octal syntax for well formed numbers */ 262 | #define BF_ATOF_LEGACY_OCTAL (1 << 22) 263 | /* accept _ between digits as a digit separator */ 264 | #define BF_ATOF_UNDERSCORE_SEP (1 << 23) 265 | /* if a 'n' suffix is present, force integer parsing (XXX: remove) */ 266 | #define BF_ATOF_INT_N_SUFFIX (1 << 24) 267 | /* if set return NaN if empty number string (instead of 0) */ 268 | #define BF_ATOF_NAN_IF_EMPTY (1 << 25) 269 | /* only accept decimal floating point if radix = 0 */ 270 | #define BF_ATOF_ONLY_DEC_FLOAT (1 << 26) 271 | 272 | /* one more return flag: indicate that the parsed number is an integer 273 | (only set when the flags BF_ATOF_INT_PREC_INF or 274 | BF_ATOF_INT_N_SUFFIX are used) */ 275 | #define BF_ATOF_ST_INTEGER (1 << 5) 276 | 277 | int bf_atof(bf_t *a, const char *str, const char **pnext, int radix, 278 | limb_t prec, bf_flags_t flags); 279 | /* this version accepts prec = BF_PREC_INF and returns the radix 280 | exponent */ 281 | int bf_atof2(bf_t *r, slimb_t *pexponent, 282 | const char *str, const char **pnext, int radix, 283 | limb_t prec, bf_flags_t flags); 284 | int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix, 285 | slimb_t expn, limb_t prec, bf_flags_t flags); 286 | 287 | #define BF_FTOA_FORMAT_MASK (3 << 16) 288 | /* fixed format: prec significant digits rounded with (flags & 289 | BF_RND_MASK). Exponential notation is used if too many zeros are 290 | needed. */ 291 | #define BF_FTOA_FORMAT_FIXED (0 << 16) 292 | /* fractional format: prec digits after the decimal point rounded with 293 | (flags & BF_RND_MASK) */ 294 | #define BF_FTOA_FORMAT_FRAC (1 << 16) 295 | /* free format: use as many digits as necessary so that bf_atof() 296 | return the same number when using precision 'prec', rounding to 297 | nearest and the subnormal+exponent configuration of 'flags'. The 298 | result is meaningful only if 'a' is already rounded to the wanted 299 | precision. 300 | 301 | Infinite precision (BF_PREC_INF) is supported when the radix is a 302 | power of two. */ 303 | #define BF_FTOA_FORMAT_FREE (2 << 16) 304 | /* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits 305 | (takes more computation time). */ 306 | #define BF_FTOA_FORMAT_FREE_MIN (3 << 16) 307 | 308 | /* force exponential notation for fixed or free format */ 309 | #define BF_FTOA_FORCE_EXP (1 << 20) 310 | /* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for 311 | base 2 if non zero value */ 312 | #define BF_FTOA_ADD_PREFIX (1 << 21) 313 | #define BF_FTOA_JS_QUIRKS (1 << 22) 314 | 315 | size_t bf_ftoa(char **pbuf, const bf_t *a, int radix, limb_t prec, 316 | bf_flags_t flags); 317 | 318 | /* modulo 2^n instead of saturation. NaN and infinity return 0 */ 319 | #define BF_GET_INT_MOD (1 << 0) 320 | int bf_get_int32(int *pres, const bf_t *a, int flags); 321 | int bf_get_int64(int64_t *pres, const bf_t *a, int flags); 322 | 323 | /* the following functions are exported for testing only. */ 324 | void bf_print_str(const char *str, const bf_t *a); 325 | void bf_resize(bf_t *r, limb_t len); 326 | int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len); 327 | void bf_recip(bf_t *r, const bf_t *a, limb_t prec); 328 | void bf_rsqrt(bf_t *a, const bf_t *x, limb_t prec); 329 | int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags); 330 | int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k); 331 | slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, 332 | int is_ceil1); 333 | 334 | /* transcendental functions */ 335 | int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags); 336 | int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags); 337 | int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 338 | int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 339 | #define BF_POW_JS_QUICKS (1 << 16) 340 | int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags); 341 | int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 342 | int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 343 | int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 344 | int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 345 | int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x, 346 | limb_t prec, bf_flags_t flags); 347 | int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 348 | int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags); 349 | 350 | #endif /* LIBBF_H */ 351 | -------------------------------------------------------------------------------- /libregexp-opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Regular Expression Engine 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifdef DEF 26 | 27 | DEF(invalid, 1) /* never used */ 28 | DEF(char, 3) 29 | DEF(char32, 5) 30 | DEF(dot, 1) 31 | DEF(any, 1) /* same as dot but match any character including line terminator */ 32 | DEF(line_start, 1) 33 | DEF(line_end, 1) 34 | DEF(goto, 5) 35 | DEF(split_goto_first, 5) 36 | DEF(split_next_first, 5) 37 | DEF(match, 1) 38 | DEF(save_start, 2) /* save start position */ 39 | DEF(save_end, 2) /* save end position, must come after saved_start */ 40 | DEF(save_reset, 3) /* reset save positions */ 41 | DEF(loop, 5) /* decrement the top the stack and goto if != 0 */ 42 | DEF(push_i32, 5) /* push integer on the stack */ 43 | DEF(drop, 1) 44 | DEF(word_boundary, 1) 45 | DEF(not_word_boundary, 1) 46 | DEF(back_reference, 2) 47 | DEF(backward_back_reference, 2) /* must come after back_reference */ 48 | DEF(range, 3) /* variable length */ 49 | DEF(range32, 3) /* variable length */ 50 | DEF(lookahead, 5) 51 | DEF(negative_lookahead, 5) 52 | DEF(push_char_pos, 1) /* push the character position on the stack */ 53 | DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character 54 | position */ 55 | DEF(prev, 1) /* go to the previous char */ 56 | DEF(simple_greedy_quant, 17) 57 | 58 | #endif /* DEF */ 59 | -------------------------------------------------------------------------------- /libregexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Regular Expression Engine 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIBREGEXP_H 25 | #define LIBREGEXP_H 26 | 27 | #include 28 | 29 | #include "libunicode.h" 30 | 31 | #define LRE_BOOL int /* for documentation purposes */ 32 | 33 | #define LRE_FLAG_GLOBAL (1 << 0) 34 | #define LRE_FLAG_IGNORECASE (1 << 1) 35 | #define LRE_FLAG_MULTILINE (1 << 2) 36 | #define LRE_FLAG_DOTALL (1 << 3) 37 | #define LRE_FLAG_UTF16 (1 << 4) 38 | #define LRE_FLAG_STICKY (1 << 5) 39 | 40 | #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */ 41 | 42 | uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, 43 | const char *buf, size_t buf_len, int re_flags, 44 | void *opaque); 45 | int lre_get_capture_count(const uint8_t *bc_buf); 46 | int lre_get_flags(const uint8_t *bc_buf); 47 | int lre_exec(uint8_t **capture, 48 | const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen, 49 | int cbuf_type, void *opaque); 50 | 51 | int lre_parse_escape(const uint8_t **pp, int allow_utf16); 52 | LRE_BOOL lre_is_space(int c); 53 | 54 | /* must be provided by the user */ 55 | LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); 56 | void *lre_realloc(void *opaque, void *ptr, size_t size); 57 | 58 | /* JS identifier test */ 59 | extern uint32_t const lre_id_start_table_ascii[4]; 60 | extern uint32_t const lre_id_continue_table_ascii[4]; 61 | 62 | static inline int lre_js_is_ident_first(int c) 63 | { 64 | if ((uint32_t)c < 128) { 65 | return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1; 66 | } else { 67 | #ifdef CONFIG_ALL_UNICODE 68 | return lre_is_id_start(c); 69 | #else 70 | return !lre_is_space(c); 71 | #endif 72 | } 73 | } 74 | 75 | static inline int lre_js_is_ident_next(int c) 76 | { 77 | if ((uint32_t)c < 128) { 78 | return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; 79 | } else { 80 | /* ZWNJ and ZWJ are accepted in identifiers */ 81 | #ifdef CONFIG_ALL_UNICODE 82 | return lre_is_id_continue(c) || c == 0x200C || c == 0x200D; 83 | #else 84 | return !lre_is_space(c) || c == 0x200C || c == 0x200D; 85 | #endif 86 | } 87 | } 88 | 89 | #undef LRE_BOOL 90 | 91 | #endif /* LIBREGEXP_H */ 92 | -------------------------------------------------------------------------------- /libunicode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Unicode utilities 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIBUNICODE_H 25 | #define LIBUNICODE_H 26 | 27 | #include 28 | 29 | #define LRE_BOOL int /* for documentation purposes */ 30 | 31 | /* define it to include all the unicode tables (40KB larger) */ 32 | #define CONFIG_ALL_UNICODE 33 | 34 | #define LRE_CC_RES_LEN_MAX 3 35 | 36 | typedef enum { 37 | UNICODE_NFC, 38 | UNICODE_NFD, 39 | UNICODE_NFKC, 40 | UNICODE_NFKD, 41 | } UnicodeNormalizationEnum; 42 | 43 | int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); 44 | LRE_BOOL lre_is_cased(uint32_t c); 45 | LRE_BOOL lre_is_case_ignorable(uint32_t c); 46 | 47 | /* char ranges */ 48 | 49 | typedef struct { 50 | int len; /* in points, always even */ 51 | int size; 52 | uint32_t *points; /* points sorted by increasing value */ 53 | void *mem_opaque; 54 | void *(*realloc_func)(void *opaque, void *ptr, size_t size); 55 | } CharRange; 56 | 57 | typedef enum { 58 | CR_OP_UNION, 59 | CR_OP_INTER, 60 | CR_OP_XOR, 61 | } CharRangeOpEnum; 62 | 63 | void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); 64 | void cr_free(CharRange *cr); 65 | int cr_realloc(CharRange *cr, int size); 66 | int cr_copy(CharRange *cr, const CharRange *cr1); 67 | 68 | static inline int cr_add_point(CharRange *cr, uint32_t v) 69 | { 70 | if (cr->len >= cr->size) { 71 | if (cr_realloc(cr, cr->len + 1)) 72 | return -1; 73 | } 74 | cr->points[cr->len++] = v; 75 | return 0; 76 | } 77 | 78 | static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2) 79 | { 80 | if ((cr->len + 2) > cr->size) { 81 | if (cr_realloc(cr, cr->len + 2)) 82 | return -1; 83 | } 84 | cr->points[cr->len++] = c1; 85 | cr->points[cr->len++] = c2; 86 | return 0; 87 | } 88 | 89 | int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len); 90 | 91 | static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2) 92 | { 93 | uint32_t b_pt[2]; 94 | b_pt[0] = c1; 95 | b_pt[1] = c2 + 1; 96 | return cr_union1(cr, b_pt, 2); 97 | } 98 | 99 | int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, 100 | const uint32_t *b_pt, int b_len, int op); 101 | 102 | int cr_invert(CharRange *cr); 103 | 104 | #ifdef CONFIG_ALL_UNICODE 105 | 106 | LRE_BOOL lre_is_id_start(uint32_t c); 107 | LRE_BOOL lre_is_id_continue(uint32_t c); 108 | 109 | int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, 110 | UnicodeNormalizationEnum n_type, 111 | void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); 112 | 113 | /* Unicode character range functions */ 114 | 115 | int unicode_script(CharRange *cr, 116 | const char *script_name, LRE_BOOL is_ext); 117 | int unicode_general_category(CharRange *cr, const char *gc_name); 118 | int unicode_prop(CharRange *cr, const char *prop_name); 119 | 120 | #endif /* CONFIG_ALL_UNICODE */ 121 | 122 | #undef LRE_BOOL 123 | 124 | #endif /* LIBUNICODE_H */ 125 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux klist like system 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIST_H 25 | #define LIST_H 26 | 27 | #ifndef NULL 28 | #include 29 | #endif 30 | 31 | struct list_head { 32 | struct list_head *prev; 33 | struct list_head *next; 34 | }; 35 | 36 | #define LIST_HEAD_INIT(el) { &(el), &(el) } 37 | 38 | /* return the pointer of type 'type *' containing 'el' as field 'member' */ 39 | #define list_entry(el, type, member) \ 40 | ((type *)((uint8_t *)(el) - offsetof(type, member))) 41 | 42 | static inline void init_list_head(struct list_head *head) 43 | { 44 | head->prev = head; 45 | head->next = head; 46 | } 47 | 48 | /* insert 'el' between 'prev' and 'next' */ 49 | static inline void __list_add(struct list_head *el, 50 | struct list_head *prev, struct list_head *next) 51 | { 52 | prev->next = el; 53 | el->prev = prev; 54 | el->next = next; 55 | next->prev = el; 56 | } 57 | 58 | /* add 'el' at the head of the list 'head' (= after element head) */ 59 | static inline void list_add(struct list_head *el, struct list_head *head) 60 | { 61 | __list_add(el, head, head->next); 62 | } 63 | 64 | /* add 'el' at the end of the list 'head' (= before element head) */ 65 | static inline void list_add_tail(struct list_head *el, struct list_head *head) 66 | { 67 | __list_add(el, head->prev, head); 68 | } 69 | 70 | static inline void list_del(struct list_head *el) 71 | { 72 | struct list_head *prev, *next; 73 | prev = el->prev; 74 | next = el->next; 75 | prev->next = next; 76 | next->prev = prev; 77 | el->prev = NULL; /* fail safe */ 78 | el->next = NULL; /* fail safe */ 79 | } 80 | 81 | static inline int list_empty(struct list_head *el) 82 | { 83 | return el->next == el; 84 | } 85 | 86 | #define list_for_each(el, head) \ 87 | for(el = (head)->next; el != (head); el = el->next) 88 | 89 | #define list_for_each_safe(el, el1, head) \ 90 | for(el = (head)->next, el1 = el->next; el != (head); \ 91 | el = el1, el1 = el->next) 92 | 93 | #define list_for_each_prev(el, head) \ 94 | for(el = (head)->prev; el != (head); el = el->prev) 95 | 96 | #define list_for_each_prev_safe(el, el1, head) \ 97 | for(el = (head)->prev, el1 = el->prev; el != (head); \ 98 | el = el1, el1 = el->prev) 99 | 100 | #endif /* LIST_H */ 101 | -------------------------------------------------------------------------------- /node_test.js: -------------------------------------------------------------------------------- 1 | console.error('Error') 2 | console.warn('Warning') 3 | 4 | console.log(process.platform) 5 | console.log(process.cwd()) 6 | console.log(process.argv) 7 | console.log(process.EOL) 8 | 9 | console.log(path.basename('/one/two/three')) 10 | -------------------------------------------------------------------------------- /qjs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS stand alone interpreter 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * Copyright (c) 2017-2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #if defined(__APPLE__) 36 | #include 37 | #elif defined(__linux__) 38 | #include 39 | #endif 40 | 41 | #include "cutils.h" 42 | #include "quickjs-libc.h" 43 | 44 | extern const uint8_t repl[]; 45 | extern const uint32_t repl_size; 46 | #ifdef CONFIG_BIGNUM 47 | extern const uint8_t qjscalc[]; 48 | extern const uint32_t qjscalc_size; 49 | #endif 50 | 51 | static int eval_buf(JSContext *ctx, const void *buf, int buf_len, 52 | const char *filename, int eval_flags) 53 | { 54 | JSValue val; 55 | int ret; 56 | 57 | val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); 58 | if (JS_IsException(val)) { 59 | js_std_dump_error(ctx); 60 | ret = -1; 61 | } else { 62 | ret = 0; 63 | } 64 | JS_FreeValue(ctx, val); 65 | return ret; 66 | } 67 | 68 | static int eval_file(JSContext *ctx, const char *filename, int eval_flags) 69 | { 70 | uint8_t *buf; 71 | int ret; 72 | size_t buf_len; 73 | 74 | buf = js_load_file(ctx, &buf_len, filename); 75 | if (!buf) { 76 | perror(filename); 77 | exit(1); 78 | } 79 | ret = eval_buf(ctx, buf, buf_len, filename, eval_flags); 80 | js_free(ctx, buf); 81 | return ret; 82 | } 83 | 84 | #if defined(__APPLE__) 85 | #define MALLOC_OVERHEAD 0 86 | #else 87 | #define MALLOC_OVERHEAD 8 88 | #endif 89 | 90 | struct trace_malloc_data { 91 | uint8_t *base; 92 | }; 93 | 94 | static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr, 95 | struct trace_malloc_data *dp) 96 | { 97 | return ptr - dp->base; 98 | } 99 | 100 | /* default memory allocation functions with memory limitation */ 101 | static inline size_t js_trace_malloc_usable_size(void *ptr) 102 | { 103 | #if defined(__APPLE__) 104 | return malloc_size(ptr); 105 | #elif defined(_WIN32) 106 | return _msize(ptr); 107 | #elif defined(EMSCRIPTEN) 108 | return 0; 109 | #elif defined(__linux__) 110 | return malloc_usable_size(ptr); 111 | #else 112 | /* change this to `return 0;` if compilation fails */ 113 | return malloc_usable_size(ptr); 114 | #endif 115 | } 116 | 117 | static void __attribute__((format(printf, 2, 3))) 118 | js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...) 119 | { 120 | va_list ap; 121 | int c; 122 | 123 | va_start(ap, fmt); 124 | while ((c = *fmt++) != '\0') { 125 | if (c == '%') { 126 | /* only handle %p and %zd */ 127 | if (*fmt == 'p') { 128 | uint8_t *ptr = va_arg(ap, void *); 129 | if (ptr == NULL) { 130 | printf("NULL"); 131 | } else { 132 | printf("H%+06lld.%zd", 133 | js_trace_malloc_ptr_offset(ptr, s->opaque), 134 | js_trace_malloc_usable_size(ptr)); 135 | } 136 | fmt++; 137 | continue; 138 | } 139 | if (fmt[0] == 'z' && fmt[1] == 'd') { 140 | size_t sz = va_arg(ap, size_t); 141 | printf("%zd", sz); 142 | fmt += 2; 143 | continue; 144 | } 145 | } 146 | putc(c, stdout); 147 | } 148 | va_end(ap); 149 | } 150 | 151 | static void js_trace_malloc_init(struct trace_malloc_data *s) 152 | { 153 | free(s->base = malloc(8)); 154 | } 155 | 156 | static void *js_trace_malloc(JSMallocState *s, size_t size) 157 | { 158 | void *ptr; 159 | 160 | /* Do not allocate zero bytes: behavior is platform dependent */ 161 | assert(size != 0); 162 | 163 | if (unlikely(s->malloc_size + size > s->malloc_limit)) 164 | return NULL; 165 | ptr = malloc(size); 166 | js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr); 167 | if (ptr) { 168 | s->malloc_count++; 169 | s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; 170 | } 171 | return ptr; 172 | } 173 | 174 | static void js_trace_free(JSMallocState *s, void *ptr) 175 | { 176 | if (!ptr) 177 | return; 178 | 179 | js_trace_malloc_printf(s, "F %p\n", ptr); 180 | s->malloc_count--; 181 | s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; 182 | free(ptr); 183 | } 184 | 185 | static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size) 186 | { 187 | size_t old_size; 188 | 189 | if (!ptr) { 190 | if (size == 0) 191 | return NULL; 192 | return js_trace_malloc(s, size); 193 | } 194 | old_size = js_trace_malloc_usable_size(ptr); 195 | if (size == 0) { 196 | js_trace_malloc_printf(s, "R %zd %p\n", size, ptr); 197 | s->malloc_count--; 198 | s->malloc_size -= old_size + MALLOC_OVERHEAD; 199 | free(ptr); 200 | return NULL; 201 | } 202 | if (s->malloc_size + size - old_size > s->malloc_limit) 203 | return NULL; 204 | 205 | js_trace_malloc_printf(s, "R %zd %p", size, ptr); 206 | 207 | ptr = realloc(ptr, size); 208 | js_trace_malloc_printf(s, " -> %p\n", ptr); 209 | if (ptr) { 210 | s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size; 211 | } 212 | return ptr; 213 | } 214 | 215 | static const JSMallocFunctions trace_mf = { 216 | js_trace_malloc, 217 | js_trace_free, 218 | js_trace_realloc, 219 | #if defined(__APPLE__) 220 | malloc_size, 221 | #elif defined(_WIN32) 222 | (size_t (*)(const void *))_msize, 223 | #elif defined(EMSCRIPTEN) 224 | NULL, 225 | #elif defined(__linux__) 226 | (size_t (*)(const void *))malloc_usable_size, 227 | #else 228 | /* change this to `NULL,` if compilation fails */ 229 | malloc_usable_size, 230 | #endif 231 | }; 232 | 233 | #ifdef CONFIG_BIGNUM 234 | #define PROG_NAME "qjsbn" 235 | #else 236 | #define PROG_NAME "qjs" 237 | #endif 238 | 239 | void help(void) 240 | { 241 | printf("QuickJS version " CONFIG_VERSION "\n" 242 | "usage: " PROG_NAME " [options] [files]\n" 243 | "-h --help list options\n" 244 | "-e --eval EXPR evaluate EXPR\n" 245 | "-i --interactive go to interactive mode\n" 246 | "-m --module load as ES6 module (default if .mjs file extension)\n" 247 | #ifdef CONFIG_BIGNUM 248 | " --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n" 249 | #endif 250 | "-T --trace trace memory allocation\n" 251 | "-d --dump dump the memory usage stats\n" 252 | "-q --quit just instantiate the interpreter and quit\n"); 253 | exit(1); 254 | } 255 | 256 | int main(int argc, char **argv) 257 | { 258 | JSRuntime *rt; 259 | JSContext *ctx; 260 | struct trace_malloc_data trace_data = { NULL }; 261 | int optind; 262 | char *expr = NULL; 263 | int interactive = 0; 264 | int dump_memory = 0; 265 | int trace_memory = 0; 266 | int empty_run = 0; 267 | int module = 0; 268 | int load_std = 1; 269 | #ifdef CONFIG_BIGNUM 270 | int load_jscalc; 271 | #endif 272 | 273 | #ifdef CONFIG_BIGNUM 274 | /* load jscalc runtime if invoked as 'qjscalc' */ 275 | { 276 | const char *p, *exename; 277 | exename = argv[0]; 278 | p = strrchr(exename, '/'); 279 | if (p) 280 | exename = p + 1; 281 | load_jscalc = !strcmp(exename, "qjscalc"); 282 | } 283 | #endif 284 | 285 | /* cannot use getopt because we want to pass the command line to 286 | the script */ 287 | optind = 1; 288 | while (optind < argc && *argv[optind] == '-') { 289 | char *arg = argv[optind] + 1; 290 | const char *longopt = ""; 291 | /* a single - is not an option, it also stops argument scanning */ 292 | if (!*arg) 293 | break; 294 | optind++; 295 | if (*arg == '-') { 296 | longopt = arg + 1; 297 | arg += strlen(arg); 298 | /* -- stops argument scanning */ 299 | if (!*longopt) 300 | break; 301 | } 302 | for (; *arg || *longopt; longopt = "") { 303 | char opt = *arg; 304 | if (opt) 305 | arg++; 306 | if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { 307 | help(); 308 | continue; 309 | } 310 | if (opt == 'e' || !strcmp(longopt, "eval")) { 311 | if (*arg) { 312 | expr = arg; 313 | break; 314 | } 315 | if (optind < argc) { 316 | expr = argv[optind++]; 317 | break; 318 | } 319 | fprintf(stderr, "qjs: missing expression for -e\n"); 320 | exit(2); 321 | } 322 | if (opt == 'i' || !strcmp(longopt, "interactive")) { 323 | interactive++; 324 | continue; 325 | } 326 | if (opt == 'm' || !strcmp(longopt, "module")) { 327 | module = 1; 328 | continue; 329 | } 330 | if (opt == 'd' || !strcmp(longopt, "dump")) { 331 | dump_memory++; 332 | continue; 333 | } 334 | if (opt == 'T' || !strcmp(longopt, "trace")) { 335 | trace_memory++; 336 | continue; 337 | } 338 | if (!strcmp(longopt, "nostd")) { 339 | load_std = 0; 340 | continue; 341 | } 342 | #ifdef CONFIG_BIGNUM 343 | if (!strcmp(longopt, "qjscalc")) { 344 | load_jscalc = 1; 345 | continue; 346 | } 347 | #endif 348 | if (opt == 'q' || !strcmp(longopt, "quit")) { 349 | empty_run++; 350 | continue; 351 | } 352 | if (opt) { 353 | fprintf(stderr, "qjs: unknown option '-%c'\n", opt); 354 | } else { 355 | fprintf(stderr, "qjs: unknown option '--%s'\n", longopt); 356 | } 357 | help(); 358 | } 359 | } 360 | 361 | if (trace_memory) { 362 | js_trace_malloc_init(&trace_data); 363 | rt = JS_NewRuntime2(&trace_mf, &trace_data); 364 | } else { 365 | rt = JS_NewRuntime(); 366 | } 367 | if (!rt) { 368 | fprintf(stderr, "qjs: cannot allocate JS runtime\n"); 369 | exit(2); 370 | } 371 | ctx = JS_NewContext(rt); 372 | if (!ctx) { 373 | fprintf(stderr, "qjs: cannot allocate JS context\n"); 374 | exit(2); 375 | } 376 | 377 | /* loader for ES6 modules */ 378 | JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); 379 | 380 | if (!empty_run) { 381 | #ifdef CONFIG_BIGNUM 382 | if (load_jscalc) { 383 | js_std_eval_binary(ctx, qjscalc, qjscalc_size, 0); 384 | } 385 | #endif 386 | js_std_add_helpers(ctx, argc - optind, argv + optind); 387 | //js_path_add_helpers(ctx, argc - optind, argv + optind); 388 | 389 | /* system modules */ 390 | js_init_module_std(ctx, "std"); 391 | js_init_module_os(ctx, "os"); 392 | 393 | /* make 'std' and 'os' visible to non module code */ 394 | if (load_std) { 395 | const char *str = "import * as std from 'std';\n" 396 | "import * as os from 'os';\n" 397 | "std.global.std = std;\n" 398 | "std.global.os = os;\n"; 399 | eval_buf(ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE); 400 | } 401 | 402 | if (expr) { 403 | if (eval_buf(ctx, expr, strlen(expr), "", 0)) 404 | goto fail; 405 | } else 406 | if (optind >= argc) { 407 | /* interactive mode */ 408 | interactive = 1; 409 | } else { 410 | int eval_flags; 411 | const char *filename; 412 | filename = argv[optind]; 413 | 414 | if (module || has_suffix(filename, ".mjs")) 415 | eval_flags = JS_EVAL_TYPE_MODULE; 416 | else 417 | eval_flags = JS_EVAL_TYPE_GLOBAL; 418 | eval_flags |= JS_EVAL_FLAG_SHEBANG; 419 | if (eval_file(ctx, filename, eval_flags)) 420 | goto fail; 421 | } 422 | if (interactive) { 423 | js_std_eval_binary(ctx, repl, repl_size, 0); 424 | } 425 | js_std_loop(ctx); 426 | } 427 | 428 | if (dump_memory) { 429 | JSMemoryUsage stats; 430 | JS_ComputeMemoryUsage(rt, &stats); 431 | JS_DumpMemoryUsage(stdout, &stats, rt); 432 | } 433 | js_std_free_handlers(rt); 434 | JS_FreeContext(ctx); 435 | JS_FreeRuntime(rt); 436 | 437 | if (empty_run && dump_memory) { 438 | clock_t t[5]; 439 | double best[5]; 440 | int i, j; 441 | for (i = 0; i < 100; i++) { 442 | t[0] = clock(); 443 | rt = JS_NewRuntime(); 444 | t[1] = clock(); 445 | ctx = JS_NewContext(rt); 446 | t[2] = clock(); 447 | JS_FreeContext(ctx); 448 | t[3] = clock(); 449 | JS_FreeRuntime(rt); 450 | t[4] = clock(); 451 | for (j = 4; j > 0; j--) { 452 | double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC; 453 | if (i == 0 || best[j] > ms) 454 | best[j] = ms; 455 | } 456 | } 457 | printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n", 458 | best[1] + best[2] + best[3] + best[4], 459 | best[1], best[2], best[3], best[4]); 460 | } 461 | return 0; 462 | fail: 463 | js_std_free_handlers(rt); 464 | JS_FreeContext(ctx); 465 | JS_FreeRuntime(rt); 466 | return 1; 467 | } 468 | -------------------------------------------------------------------------------- /qjsc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS command line compiler 3 | * 4 | * Copyright (c) 2018-2019 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #if !defined(_WIN32) 33 | #include 34 | #endif 35 | 36 | #include "cutils.h" 37 | #include "quickjs-libc.h" 38 | 39 | typedef struct { 40 | char *name; 41 | char *short_name; 42 | int flags; 43 | } namelist_entry_t; 44 | 45 | typedef struct namelist_t { 46 | namelist_entry_t *array; 47 | int count; 48 | int size; 49 | } namelist_t; 50 | 51 | typedef struct { 52 | const char *option_name; 53 | const char *init_name; 54 | } FeatureEntry; 55 | 56 | #define FE_ALL (-1) 57 | 58 | static namelist_t cname_list; 59 | static namelist_t cmodule_list; 60 | static namelist_t init_module_list; 61 | static uint64_t feature_bitmap; 62 | static FILE *outfile; 63 | static BOOL byte_swap; 64 | 65 | static const FeatureEntry feature_list[] = { 66 | { "eval", "Eval" }, 67 | { "string-normalize", "StringNormalize" }, 68 | { "regexp", "RegExp" }, 69 | { "json", "JSON" }, 70 | { "proxy", "Proxy" }, 71 | { "map", "MapSet" }, 72 | { "typedarray", "TypedArrays" }, 73 | { "promise", "Promise" }, 74 | }; 75 | 76 | void namelist_add(namelist_t *lp, const char *name, const char *short_name, 77 | int flags) 78 | { 79 | namelist_entry_t *e; 80 | if (lp->count == lp->size) { 81 | size_t newsize = lp->size + (lp->size >> 1) + 4; 82 | namelist_entry_t *a = 83 | realloc(lp->array, sizeof(lp->array[0]) * newsize); 84 | /* XXX: check for realloc failure */ 85 | lp->array = a; 86 | lp->size = newsize; 87 | } 88 | e = &lp->array[lp->count++]; 89 | e->name = strdup(name); 90 | if (short_name) 91 | e->short_name = strdup(short_name); 92 | else 93 | e->short_name = NULL; 94 | e->flags = flags; 95 | } 96 | 97 | void namelist_free(namelist_t *lp) 98 | { 99 | while (lp->count > 0) { 100 | namelist_entry_t *e = &lp->array[--lp->count]; 101 | free(e->name); 102 | free(e->short_name); 103 | } 104 | free(lp->array); 105 | lp->array = NULL; 106 | lp->size = 0; 107 | } 108 | 109 | namelist_entry_t *namelist_find(namelist_t *lp, const char *name) 110 | { 111 | int i; 112 | for(i = 0; i < lp->count; i++) { 113 | namelist_entry_t *e = &lp->array[i]; 114 | if (!strcmp(e->name, name)) 115 | return e; 116 | } 117 | return NULL; 118 | } 119 | 120 | 121 | static void get_c_name(char *buf, int buf_size, const char *file) 122 | { 123 | const char *p, *r; 124 | size_t len; 125 | 126 | p = strrchr(file, '/'); 127 | if (!p) 128 | p = file; 129 | else 130 | p++; 131 | r = strrchr(p, '.'); 132 | if (!r) 133 | r = p + strlen(p); 134 | len = r - p; 135 | if (len > buf_size - 1) 136 | len = buf_size - 1; 137 | memcpy(buf, p, len); 138 | buf[len] = '\0'; 139 | } 140 | 141 | static void dump_hex(FILE *f, const uint8_t *buf, size_t len) 142 | { 143 | size_t i, col; 144 | col = 0; 145 | for(i = 0; i < len; i++) { 146 | fprintf(f, " 0x%02x,", buf[i]); 147 | if (++col == 8) { 148 | fprintf(f, "\n"); 149 | col = 0; 150 | } 151 | } 152 | if (col != 0) 153 | fprintf(f, "\n"); 154 | } 155 | 156 | static void output_object_code(JSContext *ctx, 157 | FILE *fo, JSValueConst obj, const char *c_name, 158 | BOOL load_only) 159 | { 160 | uint8_t *out_buf; 161 | size_t out_buf_len; 162 | int flags; 163 | flags = JS_WRITE_OBJ_BYTECODE; 164 | if (byte_swap) 165 | flags |= JS_WRITE_OBJ_BSWAP; 166 | out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags); 167 | if (!out_buf) { 168 | js_std_dump_error(ctx); 169 | exit(1); 170 | } 171 | 172 | namelist_add(&cname_list, c_name, NULL, load_only); 173 | 174 | fprintf(fo, "const uint32_t %s_size = %u;\n\n", 175 | c_name, (unsigned int)out_buf_len); 176 | fprintf(fo, "const uint8_t %s[%u] = {\n", 177 | c_name, (unsigned int)out_buf_len); 178 | dump_hex(fo, out_buf, out_buf_len); 179 | fprintf(fo, "};\n\n"); 180 | 181 | js_free(ctx, out_buf); 182 | } 183 | 184 | static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m) 185 | { 186 | /* should never be called when compiling JS code */ 187 | abort(); 188 | } 189 | 190 | JSModuleDef *jsc_module_loader(JSContext *ctx, 191 | const char *module_name, void *opaque) 192 | { 193 | JSModuleDef *m; 194 | namelist_entry_t *e; 195 | 196 | /* check if it is a declared C or system module */ 197 | e = namelist_find(&cmodule_list, module_name); 198 | if (e) { 199 | /* add in the static init module list */ 200 | namelist_add(&init_module_list, e->name, e->short_name, 0); 201 | /* create a dummy module */ 202 | m = JS_NewCModule(ctx, module_name, js_module_dummy_init); 203 | } else if (has_suffix(module_name, ".so")) { 204 | fprintf(stderr, "Warning: binary module '%s' is not compiled\n", module_name); 205 | /* create a dummy module */ 206 | m = JS_NewCModule(ctx, module_name, js_module_dummy_init); 207 | } else { 208 | size_t buf_len; 209 | uint8_t *buf; 210 | JSValue func_val; 211 | char cname[1024]; 212 | 213 | buf = js_load_file(ctx, &buf_len, module_name); 214 | if (!buf) { 215 | JS_ThrowReferenceError(ctx, "could not load module filename '%s'", 216 | module_name); 217 | return NULL; 218 | } 219 | 220 | /* compile the module */ 221 | func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, 222 | JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); 223 | js_free(ctx, buf); 224 | if (JS_IsException(func_val)) 225 | return NULL; 226 | get_c_name(cname, sizeof(cname), module_name); 227 | output_object_code(ctx, outfile, func_val, cname, TRUE); 228 | 229 | /* the module is already referenced, so we must free it */ 230 | m = JS_VALUE_GET_PTR(func_val); 231 | JS_FreeValue(ctx, func_val); 232 | } 233 | return m; 234 | } 235 | 236 | static void compile_file(JSContext *ctx, FILE *fo, 237 | const char *filename, 238 | const char *c_name1, 239 | BOOL is_module) 240 | { 241 | uint8_t *buf; 242 | char c_name[1024]; 243 | int eval_flags; 244 | JSValue obj; 245 | size_t buf_len; 246 | 247 | buf = js_load_file(ctx, &buf_len, filename); 248 | if (!buf) { 249 | fprintf(stderr, "Could not load '%s'\n", filename); 250 | exit(1); 251 | } 252 | eval_flags = JS_EVAL_FLAG_SHEBANG | JS_EVAL_FLAG_COMPILE_ONLY; 253 | if (is_module) 254 | eval_flags |= JS_EVAL_TYPE_MODULE; 255 | else 256 | eval_flags |= JS_EVAL_TYPE_GLOBAL; 257 | obj = JS_Eval(ctx, (char *)buf, buf_len, filename, eval_flags); 258 | if (JS_IsException(obj)) { 259 | js_std_dump_error(ctx); 260 | exit(1); 261 | } 262 | js_free(ctx, buf); 263 | if (c_name1) { 264 | pstrcpy(c_name, sizeof(c_name), c_name1); 265 | } else { 266 | get_c_name(c_name, sizeof(c_name), filename); 267 | } 268 | output_object_code(ctx, fo, obj, c_name, FALSE); 269 | JS_FreeValue(ctx, obj); 270 | } 271 | 272 | static const char main_c_template1[] = 273 | "int main(int argc, char **argv)\n" 274 | "{\n" 275 | " JSRuntime *rt;\n" 276 | " JSContext *ctx;\n" 277 | " rt = JS_NewRuntime();\n" 278 | ; 279 | 280 | static const char main_c_template2[] = 281 | " js_std_loop(ctx);\n" 282 | " JS_FreeContext(ctx);\n" 283 | " JS_FreeRuntime(rt);\n" 284 | " return 0;\n" 285 | "}\n"; 286 | 287 | #ifdef CONFIG_BIGNUM 288 | #define PROG_NAME "qjscbn" 289 | #else 290 | #define PROG_NAME "qjsc" 291 | #endif 292 | 293 | void help(void) 294 | { 295 | printf("QuickJS Compiler version " CONFIG_VERSION "\n" 296 | "usage: " PROG_NAME " [options] [files]\n" 297 | "\n" 298 | "options are:\n" 299 | "-c only output bytecode in a C file\n" 300 | "-e output main() and bytecode in a C file (default = executable output)\n" 301 | "-o output set the output filename\n" 302 | "-N cname set the C name of the generated data\n" 303 | "-m compile as Javascript module\n" 304 | "-M module_name[,cname] add initialization code for an external C module\n" 305 | "-x byte swapped output\n" 306 | ); 307 | #ifdef CONFIG_LTO 308 | { 309 | int i; 310 | printf("-flto use link time optimization\n"); 311 | printf("-fno-["); 312 | for(i = 0; i < countof(feature_list); i++) { 313 | if (i != 0) 314 | printf("|"); 315 | printf("%s", feature_list[i].option_name); 316 | } 317 | printf("]\n" 318 | " disable selected language features (smaller code size)\n"); 319 | } 320 | #endif 321 | exit(1); 322 | } 323 | 324 | #if defined(CONFIG_CC) && !defined(_WIN32) 325 | 326 | int exec_cmd(char **argv) 327 | { 328 | int pid, status, ret; 329 | 330 | pid = fork(); 331 | if (pid == 0) { 332 | execvp(argv[0], argv); 333 | exit(1); 334 | } 335 | 336 | for(;;) { 337 | ret = waitpid(pid, &status, 0); 338 | if (ret == pid && WIFEXITED(status)) 339 | break; 340 | } 341 | return WEXITSTATUS(status); 342 | } 343 | 344 | static int output_executable(const char *out_filename, const char *cfilename, 345 | BOOL use_lto, BOOL verbose, const char *exename) 346 | { 347 | const char *argv[64]; 348 | const char **arg, *bn_suffix, *lto_suffix; 349 | char libjsname[1024]; 350 | char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p; 351 | int ret; 352 | 353 | /* get the directory of the executable */ 354 | pstrcpy(exe_dir, sizeof(exe_dir), exename); 355 | p = strrchr(exe_dir, '/'); 356 | if (p) { 357 | *p = '\0'; 358 | } else { 359 | pstrcpy(exe_dir, sizeof(exe_dir), "."); 360 | } 361 | 362 | /* if 'quickjs.h' is present at the same path as the executable, we 363 | use it as include and lib directory */ 364 | snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir); 365 | if (access(buf, R_OK) == 0) { 366 | pstrcpy(inc_dir, sizeof(inc_dir), exe_dir); 367 | pstrcpy(lib_dir, sizeof(lib_dir), exe_dir); 368 | } else { 369 | snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX); 370 | snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX); 371 | } 372 | 373 | lto_suffix = ""; 374 | #ifdef CONFIG_BIGNUM 375 | bn_suffix = ".bn"; 376 | #else 377 | bn_suffix = ""; 378 | #endif 379 | 380 | arg = argv; 381 | *arg++ = CONFIG_CC; 382 | *arg++ = "-O2"; 383 | #ifdef CONFIG_LTO 384 | if (use_lto) { 385 | *arg++ = "-flto"; 386 | lto_suffix = ".lto"; 387 | } 388 | #endif 389 | /* XXX: use the executable path to find the includes files and 390 | libraries */ 391 | *arg++ = "-D"; 392 | *arg++ = "_GNU_SOURCE"; 393 | *arg++ = "-I"; 394 | *arg++ = inc_dir; 395 | *arg++ = "-o"; 396 | *arg++ = out_filename; 397 | *arg++ = cfilename; 398 | snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a", 399 | lib_dir, bn_suffix, lto_suffix); 400 | *arg++ = libjsname; 401 | *arg++ = "-lm"; 402 | *arg++ = "-ldl"; 403 | *arg = NULL; 404 | 405 | if (verbose) { 406 | for(arg = argv; *arg != NULL; arg++) 407 | printf("%s ", *arg); 408 | printf("\n"); 409 | } 410 | 411 | ret = exec_cmd((char **)argv); 412 | unlink(cfilename); 413 | return ret; 414 | } 415 | #else 416 | static int output_executable(const char *out_filename, const char *cfilename, 417 | BOOL use_lto, BOOL verbose, const char *exename) 418 | { 419 | fprintf(stderr, "Executable output is not supported for this target\n"); 420 | exit(1); 421 | return 0; 422 | } 423 | #endif 424 | 425 | 426 | typedef enum { 427 | OUTPUT_C, 428 | OUTPUT_C_MAIN, 429 | OUTPUT_EXECUTABLE, 430 | } OutputTypeEnum; 431 | 432 | int main(int argc, char **argv) 433 | { 434 | int c, i, verbose; 435 | const char *out_filename, *cname; 436 | char cfilename[1024]; 437 | FILE *fo; 438 | JSRuntime *rt; 439 | JSContext *ctx; 440 | BOOL module, use_lto; 441 | OutputTypeEnum output_type; 442 | 443 | out_filename = NULL; 444 | output_type = OUTPUT_EXECUTABLE; 445 | cname = NULL; 446 | feature_bitmap = FE_ALL; 447 | module = FALSE; 448 | byte_swap = FALSE; 449 | verbose = 0; 450 | use_lto = FALSE; 451 | 452 | /* add system modules */ 453 | namelist_add(&cmodule_list, "std", "std", 0); 454 | namelist_add(&cmodule_list, "os", "os", 0); 455 | 456 | for(;;) { 457 | c = getopt(argc, argv, "ho:cN:f:mxevM:"); 458 | if (c == -1) 459 | break; 460 | switch(c) { 461 | case 'h': 462 | help(); 463 | case 'o': 464 | out_filename = optarg; 465 | break; 466 | case 'c': 467 | output_type = OUTPUT_C; 468 | break; 469 | case 'e': 470 | output_type = OUTPUT_C_MAIN; 471 | break; 472 | case 'N': 473 | cname = optarg; 474 | break; 475 | case 'f': 476 | { 477 | const char *p; 478 | p = optarg; 479 | if (!strcmp(optarg, "lto")) { 480 | use_lto = TRUE; 481 | } else if (strstart(p, "no-", &p)) { 482 | use_lto = TRUE; 483 | for(i = 0; i < countof(feature_list); i++) { 484 | if (!strcmp(p, feature_list[i].option_name)) { 485 | feature_bitmap &= ~((uint64_t)1 << i); 486 | break; 487 | } 488 | } 489 | if (i == countof(feature_list)) 490 | goto bad_feature; 491 | } else { 492 | bad_feature: 493 | fprintf(stderr, "unsupported feature: %s\n", optarg); 494 | exit(1); 495 | } 496 | } 497 | break; 498 | case 'm': 499 | module = TRUE; 500 | break; 501 | case 'M': 502 | { 503 | char *p; 504 | char path[1024]; 505 | char cname[1024]; 506 | pstrcpy(path, sizeof(path), optarg); 507 | p = strchr(path, ','); 508 | if (p) { 509 | *p = '\0'; 510 | pstrcpy(cname, sizeof(cname), p + 1); 511 | } else { 512 | get_c_name(cname, sizeof(cname), path); 513 | } 514 | namelist_add(&cmodule_list, path, cname, 0); 515 | } 516 | break; 517 | case 'x': 518 | byte_swap = TRUE; 519 | break; 520 | case 'v': 521 | verbose++; 522 | break; 523 | default: 524 | break; 525 | } 526 | } 527 | 528 | if (optind >= argc) 529 | help(); 530 | 531 | if (!out_filename) { 532 | if (output_type == OUTPUT_EXECUTABLE) { 533 | out_filename = "a.out"; 534 | } else { 535 | out_filename = "out.c"; 536 | } 537 | } 538 | 539 | if (output_type == OUTPUT_EXECUTABLE) { 540 | #if defined(_WIN32) || defined(__ANDROID__) 541 | /* XXX: find a /tmp directory ? */ 542 | snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid()); 543 | #else 544 | snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid()); 545 | #endif 546 | } else { 547 | pstrcpy(cfilename, sizeof(cfilename), out_filename); 548 | } 549 | 550 | fo = fopen(cfilename, "w"); 551 | if (!fo) { 552 | perror(cfilename); 553 | exit(1); 554 | } 555 | outfile = fo; 556 | 557 | rt = JS_NewRuntime(); 558 | ctx = JS_NewContextRaw(rt); 559 | JS_AddIntrinsicEval(ctx); 560 | JS_AddIntrinsicRegExpCompiler(ctx); 561 | 562 | /* loader for ES6 modules */ 563 | JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL); 564 | 565 | fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n" 566 | "\n" 567 | ); 568 | 569 | if (output_type != OUTPUT_C) { 570 | fprintf(fo, "#include \"quickjs-libc.h\"\n" 571 | "\n" 572 | ); 573 | } else { 574 | fprintf(fo, "#include \n" 575 | "\n" 576 | ); 577 | } 578 | 579 | for(i = optind; i < argc; i++) { 580 | const char *filename = argv[i]; 581 | BOOL module1 = module || has_suffix(filename, ".mjs"); 582 | compile_file(ctx, fo, filename, cname, module1); 583 | cname = NULL; 584 | } 585 | 586 | if (output_type != OUTPUT_C) { 587 | fputs(main_c_template1, fo); 588 | fprintf(fo, " ctx = JS_NewContextRaw(rt);\n"); 589 | 590 | /* add the basic objects */ 591 | 592 | fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n"); 593 | for(i = 0; i < countof(feature_list); i++) { 594 | if (feature_bitmap & ((uint64_t)1 << i)) { 595 | fprintf(fo, " JS_AddIntrinsic%s(ctx);\n", 596 | feature_list[i].init_name); 597 | } 598 | } 599 | 600 | fprintf(fo, " js_std_add_helpers(ctx, argc, argv);\n"); 601 | 602 | for(i = 0; i < init_module_list.count; i++) { 603 | namelist_entry_t *e = &init_module_list.array[i]; 604 | /* initialize the static C modules */ 605 | 606 | fprintf(fo, 607 | " {\n" 608 | " extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n" 609 | " js_init_module_%s(ctx, \"%s\");\n" 610 | " }\n", 611 | e->short_name, e->short_name, e->name); 612 | } 613 | 614 | for(i = 0; i < cname_list.count; i++) { 615 | namelist_entry_t *e = &cname_list.array[i]; 616 | fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, %s);\n", 617 | e->name, e->name, 618 | e->flags ? "JS_EVAL_BINARY_LOAD_ONLY" : "0"); 619 | } 620 | fputs(main_c_template2, fo); 621 | } 622 | 623 | JS_FreeContext(ctx); 624 | JS_FreeRuntime(rt); 625 | 626 | fclose(fo); 627 | 628 | if (output_type == OUTPUT_EXECUTABLE) { 629 | return output_executable(out_filename, cfilename, use_lto, verbose, 630 | argv[0]); 631 | } 632 | namelist_free(&cname_list); 633 | namelist_free(&cmodule_list); 634 | namelist_free(&init_module_list); 635 | return 0; 636 | } 637 | -------------------------------------------------------------------------------- /quickjs-atom.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS atom definitions 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * Copyright (c) 2017-2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifdef DEF 27 | 28 | /* Note: first atoms are considered as keywords in the parser */ 29 | DEF(null, "null") /* must be first */ 30 | DEF(false, "false") 31 | DEF(true, "true") 32 | DEF(if, "if") 33 | DEF(else, "else") 34 | DEF(return, "return") 35 | DEF(var, "var") 36 | DEF(this, "this") 37 | DEF(delete, "delete") 38 | DEF(void, "void") 39 | DEF(typeof, "typeof") 40 | DEF(new, "new") 41 | DEF(in, "in") 42 | DEF(instanceof, "instanceof") 43 | DEF(do, "do") 44 | DEF(while, "while") 45 | DEF(for, "for") 46 | DEF(break, "break") 47 | DEF(continue, "continue") 48 | DEF(switch, "switch") 49 | DEF(case, "case") 50 | DEF(default, "default") 51 | DEF(throw, "throw") 52 | DEF(try, "try") 53 | DEF(catch, "catch") 54 | DEF(finally, "finally") 55 | DEF(function, "function") 56 | DEF(debugger, "debugger") 57 | DEF(with, "with") 58 | /* FutureReservedWord */ 59 | DEF(class, "class") 60 | DEF(const, "const") 61 | DEF(enum, "enum") 62 | DEF(export, "export") 63 | DEF(extends, "extends") 64 | DEF(import, "import") 65 | DEF(super, "super") 66 | /* FutureReservedWords when parsing strict mode code */ 67 | DEF(implements, "implements") 68 | DEF(interface, "interface") 69 | DEF(let, "let") 70 | DEF(package, "package") 71 | DEF(private, "private") 72 | DEF(protected, "protected") 73 | DEF(public, "public") 74 | DEF(static, "static") 75 | DEF(yield, "yield") 76 | DEF(await, "await") 77 | 78 | /* empty string */ 79 | DEF(empty_string, "") 80 | /* identifiers */ 81 | DEF(length, "length") 82 | DEF(fileName, "fileName") 83 | DEF(lineNumber, "lineNumber") 84 | DEF(message, "message") 85 | DEF(stack, "stack") 86 | DEF(name, "name") 87 | DEF(toString, "toString") 88 | DEF(toLocaleString, "toLocaleString") 89 | DEF(valueOf, "valueOf") 90 | DEF(eval, "eval") 91 | DEF(prototype, "prototype") 92 | DEF(constructor, "constructor") 93 | DEF(configurable, "configurable") 94 | DEF(writable, "writable") 95 | DEF(enumerable, "enumerable") 96 | DEF(value, "value") 97 | DEF(get, "get") 98 | DEF(set, "set") 99 | DEF(of, "of") 100 | DEF(__proto__, "__proto__") 101 | DEF(undefined, "undefined") 102 | DEF(number, "number") 103 | DEF(boolean, "boolean") 104 | DEF(string, "string") 105 | DEF(object, "object") 106 | DEF(symbol, "symbol") 107 | DEF(integer, "integer") 108 | DEF(unknown, "unknown") 109 | DEF(arguments, "arguments") 110 | DEF(callee, "callee") 111 | DEF(caller, "caller") 112 | DEF(_eval_, "") 113 | DEF(_ret_, "") 114 | DEF(_var_, "") 115 | DEF(_with_, "") 116 | DEF(lastIndex, "lastIndex") 117 | DEF(target, "target") 118 | DEF(index, "index") 119 | DEF(input, "input") 120 | DEF(defineProperties, "defineProperties") 121 | DEF(apply, "apply") 122 | DEF(join, "join") 123 | DEF(concat, "concat") 124 | DEF(split, "split") 125 | DEF(construct, "construct") 126 | DEF(getPrototypeOf, "getPrototypeOf") 127 | DEF(setPrototypeOf, "setPrototypeOf") 128 | DEF(isExtensible, "isExtensible") 129 | DEF(preventExtensions, "preventExtensions") 130 | DEF(has, "has") 131 | DEF(deleteProperty, "deleteProperty") 132 | DEF(defineProperty, "defineProperty") 133 | DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor") 134 | DEF(ownKeys, "ownKeys") 135 | DEF(add, "add") 136 | DEF(done, "done") 137 | DEF(next, "next") 138 | DEF(values, "values") 139 | DEF(source, "source") 140 | DEF(flags, "flags") 141 | DEF(global, "global") 142 | DEF(unicode, "unicode") 143 | DEF(raw, "raw") 144 | DEF(new_target, "new.target") 145 | DEF(this_active_func, "this.active_func") 146 | DEF(home_object, "") 147 | DEF(as, "as") 148 | DEF(from, "from") 149 | DEF(_default_, "*default*") 150 | DEF(_star_, "*") 151 | DEF(Module, "Module") 152 | DEF(then, "then") 153 | DEF(resolve, "resolve") 154 | DEF(reject, "reject") 155 | DEF(promise, "promise") 156 | DEF(proxy, "proxy") 157 | DEF(revoke, "revoke") 158 | DEF(async, "async") 159 | DEF(exec, "exec") 160 | DEF(groups, "groups") 161 | #ifdef CONFIG_BIGNUM 162 | DEF(bigint, "bigint") 163 | DEF(bigfloat, "bigfloat") 164 | #endif 165 | #ifdef CONFIG_ATOMICS 166 | DEF(not_equal, "not-equal") 167 | DEF(timed_out, "timed-out") 168 | DEF(ok, "ok") 169 | #endif 170 | DEF(toJSON, "toJSON") 171 | /* class names */ 172 | DEF(Object, "Object") 173 | DEF(Array, "Array") 174 | DEF(Error, "Error") 175 | DEF(Number, "Number") 176 | DEF(String, "String") 177 | DEF(Boolean, "Boolean") 178 | DEF(Symbol, "Symbol") 179 | DEF(Arguments, "Arguments") 180 | DEF(Math, "Math") 181 | DEF(JSON, "JSON") 182 | DEF(Date, "Date") 183 | DEF(Function, "Function") 184 | DEF(GeneratorFunction, "GeneratorFunction") 185 | DEF(ForInIterator, "ForInIterator") 186 | DEF(RegExp, "RegExp") 187 | DEF(ArrayBuffer, "ArrayBuffer") 188 | DEF(SharedArrayBuffer, "SharedArrayBuffer") 189 | /* must keep same order as class IDs for typed arrays */ 190 | DEF(Uint8ClampedArray, "Uint8ClampedArray") 191 | DEF(Int8Array, "Int8Array") 192 | DEF(Uint8Array, "Uint8Array") 193 | DEF(Int16Array, "Int16Array") 194 | DEF(Uint16Array, "Uint16Array") 195 | DEF(Int32Array, "Int32Array") 196 | DEF(Uint32Array, "Uint32Array") 197 | #ifdef CONFIG_BIGNUM 198 | DEF(BigInt64Array, "BigInt64Array") 199 | DEF(BigUint64Array, "BigUint64Array") 200 | #endif 201 | DEF(Float32Array, "Float32Array") 202 | DEF(Float64Array, "Float64Array") 203 | DEF(DataView, "DataView") 204 | #ifdef CONFIG_BIGNUM 205 | DEF(BigInt, "BigInt") 206 | DEF(BigFloat, "BigFloat") 207 | DEF(BigFloatEnv, "BigFloatEnv") 208 | #endif 209 | DEF(Map, "Map") 210 | DEF(Set, "Set") /* Map + 1 */ 211 | DEF(WeakMap, "WeakMap") /* Map + 2 */ 212 | DEF(WeakSet, "WeakSet") /* Map + 3 */ 213 | DEF(Map_Iterator, "Map Iterator") 214 | DEF(Set_Iterator, "Set Iterator") 215 | DEF(Array_Iterator, "Array Iterator") 216 | DEF(String_Iterator, "String Iterator") 217 | DEF(Generator, "Generator") 218 | DEF(Proxy, "Proxy") 219 | DEF(Promise, "Promise") 220 | DEF(PromiseResolveFunction, "PromiseResolveFunction") 221 | DEF(PromiseRejectFunction, "PromiseRejectFunction") 222 | DEF(AsyncFunction, "AsyncFunction") 223 | DEF(AsyncFunctionResolve, "AsyncFunctionResolve") 224 | DEF(AsyncFunctionReject, "AsyncFunctionReject") 225 | DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction") 226 | DEF(AsyncGenerator, "AsyncGenerator") 227 | DEF(EvalError, "EvalError") 228 | DEF(RangeError, "RangeError") 229 | DEF(ReferenceError, "ReferenceError") 230 | DEF(SyntaxError, "SyntaxError") 231 | DEF(TypeError, "TypeError") 232 | DEF(URIError, "URIError") 233 | DEF(InternalError, "InternalError") 234 | 235 | /* symbols */ 236 | DEF(Symbol_toPrimitive, "Symbol.toPrimitive") 237 | DEF(Symbol_iterator, "Symbol.iterator") 238 | DEF(Symbol_match, "Symbol.match") 239 | DEF(Symbol_replace, "Symbol.replace") 240 | DEF(Symbol_search, "Symbol.search") 241 | DEF(Symbol_split, "Symbol.split") 242 | DEF(Symbol_toStringTag, "Symbol.toStringTag") 243 | DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable") 244 | DEF(Symbol_hasInstance, "Symbol.hasInstance") 245 | DEF(Symbol_species, "Symbol.species") 246 | DEF(Symbol_unscopables, "Symbol.unscopables") 247 | DEF(Symbol_asyncIterator, "Symbol.asyncIterator") 248 | #ifdef CONFIG_BIGNUM 249 | DEF(Symbol_operatorOrder, "Symbol.operatorOrder") 250 | DEF(Symbol_operatorAdd, "Symbol.operatorAdd") 251 | DEF(Symbol_operatorSub, "Symbol.operatorSub") 252 | DEF(Symbol_operatorMul, "Symbol.operatorMul") 253 | DEF(Symbol_operatorDiv, "Symbol.operatorDiv") 254 | DEF(Symbol_operatorMod, "Symbol.operatorMod") 255 | DEF(Symbol_operatorPow, "Symbol.operatorPow") 256 | DEF(Symbol_operatorShl, "Symbol.operatorShl") 257 | DEF(Symbol_operatorShr, "Symbol.operatorShr") 258 | DEF(Symbol_operatorAnd, "Symbol.operatorAnd") 259 | DEF(Symbol_operatorOr, "Symbol.operatorOr") 260 | DEF(Symbol_operatorXor, "Symbol.operatorXor") 261 | DEF(Symbol_operatorCmpLT, "Symbol.operatorCmpLT") 262 | DEF(Symbol_operatorCmpLE, "Symbol.operatorCmpLE") 263 | DEF(Symbol_operatorCmpEQ, "Symbol.operatorCmpEQ") 264 | DEF(Symbol_operatorPlus, "Symbol.operatorPlus") 265 | DEF(Symbol_operatorNeg, "Symbol.operatorNeg") 266 | DEF(Symbol_operatorNot, "Symbol.operatorNot") 267 | DEF(Symbol_operatorInc, "Symbol.operatorInc") 268 | DEF(Symbol_operatorDec, "Symbol.operatorDec") 269 | DEF(Symbol_operatorMathDiv, "Symbol.operatorMathDiv") 270 | DEF(Symbol_operatorMathMod, "Symbol.operatorMathMod") 271 | DEF(Symbol_operatorMathPow, "Symbol.operatorMathPow") 272 | #endif 273 | 274 | #endif /* DEF */ 275 | -------------------------------------------------------------------------------- /quickjs-libc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS C library 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef QUICKJS_LIBC_H 25 | #define QUICKJS_LIBC_H 26 | 27 | #include 28 | #include 29 | 30 | #include "quickjs.h" 31 | 32 | JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); 33 | JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); 34 | void js_std_add_helpers(JSContext *ctx, int argc, char **argv); 35 | //void js_path_add_helpers(JSContext *ctx, int argc, char **argv); 36 | void js_std_loop(JSContext *ctx); 37 | void js_std_free_handlers(JSRuntime *rt); 38 | void js_std_dump_error(JSContext *ctx); 39 | uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); 40 | JSModuleDef *js_module_loader(JSContext *ctx, 41 | const char *module_name, void *opaque); 42 | void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, 43 | int flags); 44 | 45 | #endif /* QUICKJS_LIBC_H */ 46 | -------------------------------------------------------------------------------- /quickjs-opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS opcode definitions 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * Copyright (c) 2017-2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifdef FMT 27 | FMT(none) 28 | FMT(none_int) 29 | FMT(none_loc) 30 | FMT(none_arg) 31 | FMT(none_var_ref) 32 | FMT(u8) 33 | FMT(i8) 34 | FMT(loc8) 35 | FMT(const8) 36 | FMT(label8) 37 | FMT(u16) 38 | FMT(i16) 39 | FMT(label16) 40 | FMT(npop) 41 | FMT(npopx) 42 | FMT(loc) 43 | FMT(arg) 44 | FMT(var_ref) 45 | FMT(u32) 46 | FMT(i32) 47 | FMT(const) 48 | FMT(label) 49 | FMT(atom) 50 | FMT(atom_u8) 51 | FMT(atom_u16) 52 | FMT(atom_label_u8) 53 | FMT(atom_label_u16) 54 | FMT(label_u16) 55 | #undef FMT 56 | #endif /* FMT */ 57 | 58 | #ifdef DEF 59 | 60 | #ifndef def 61 | #define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f) 62 | #endif 63 | 64 | def(invalid, 1, 0, 0, none) /* never emitted */ 65 | 66 | /* push values */ 67 | DEF( push_i32, 5, 0, 1, i32) 68 | DEF( push_const, 5, 0, 1, const) 69 | DEF( fclosure, 5, 0, 1, const) /* must follow push_const */ 70 | DEF(push_atom_value, 5, 0, 1, atom) 71 | DEF( undefined, 1, 0, 1, none) 72 | DEF( null, 1, 0, 1, none) 73 | DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */ 74 | DEF( push_false, 1, 0, 1, none) 75 | DEF( push_true, 1, 0, 1, none) 76 | DEF( object, 1, 0, 1, none) 77 | DEF( var_object, 1, 0, 1, none) 78 | DEF( this_func, 1, 0, 1, none) /* only used at the start of a function */ 79 | DEF( arguments, 2, 0, 1, none) /* only used at the start of a function */ 80 | DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */ 81 | DEF( new_target, 1, 0, 1, none) /* only used at the start of a function */ 82 | DEF( home_object, 1, 0, 1, none) /* only used at the start of a function */ 83 | 84 | DEF( drop, 1, 1, 0, none) /* a -> */ 85 | DEF( nip, 1, 2, 1, none) /* a b -> b */ 86 | DEF( nip1, 1, 3, 2, none) /* a b c -> b c */ 87 | DEF( dup, 1, 1, 2, none) /* a -> a a */ 88 | DEF( dup1, 1, 2, 3, none) /* a b -> a a b */ 89 | DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */ 90 | DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */ 91 | DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */ 92 | DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */ 93 | DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */ 94 | DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */ 95 | DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */ 96 | DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */ 97 | DEF( swap, 1, 2, 2, none) /* a b -> b a */ 98 | DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */ 99 | DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */ 100 | DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */ 101 | DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */ 102 | DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */ 103 | 104 | DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */ 105 | DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */ 106 | DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */ 107 | DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */ 108 | DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */ 109 | DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */ 110 | DEF( apply, 3, 3, 1, u16) 111 | DEF( return, 1, 1, 0, none) 112 | DEF( return_undef, 1, 0, 0, none) 113 | DEF(check_ctor_return, 1, 1, 2, none) 114 | DEF( check_ctor, 1, 0, 0, none) 115 | DEF( return_async, 1, 1, 0, none) 116 | DEF( throw, 1, 1, 0, none) 117 | DEF( throw_var, 6, 0, 0, atom_u8) 118 | DEF( eval, 3, 1, 1, u16) 119 | DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a 120 | bytecode string */ 121 | DEF( get_super_ctor, 1, 1, 1, none) 122 | DEF( get_super, 1, 1, 1, none) 123 | 124 | DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */ 125 | DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */ 126 | DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */ 127 | DEF( put_var, 5, 1, 0, atom) /* must come after get_var */ 128 | DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */ 129 | DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */ 130 | 131 | DEF( get_ref_value, 1, 2, 3, none) 132 | DEF( put_ref_value, 1, 3, 0, none) 133 | 134 | DEF( define_var, 6, 0, 0, atom_u8) 135 | DEF(check_define_var, 6, 0, 0, atom_u8) 136 | DEF( define_func, 6, 1, 0, atom_u8) 137 | DEF( get_field, 5, 1, 1, atom) 138 | DEF( get_field2, 5, 1, 2, atom) 139 | DEF( put_field, 5, 2, 0, atom) 140 | DEF( get_array_el, 1, 2, 1, none) 141 | DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */ 142 | DEF( put_array_el, 1, 3, 0, none) 143 | DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */ 144 | DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */ 145 | DEF( define_field, 5, 2, 1, atom) 146 | DEF( set_name, 5, 1, 1, atom) 147 | DEF(set_name_computed, 1, 2, 2, none) 148 | DEF( set_proto, 1, 2, 1, none) 149 | DEF(define_array_el, 1, 3, 2, none) 150 | DEF( append, 1, 3, 2, none) /* append enumerated object, update length */ 151 | DEF(copy_data_properties, 2, 3, 3, u8) 152 | DEF( define_method, 6, 2, 1, atom_u8) 153 | DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */ 154 | DEF( define_class, 2, 2, 2, u8) 155 | 156 | DEF( get_loc, 3, 0, 1, loc) 157 | DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */ 158 | DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */ 159 | DEF( get_arg, 3, 0, 1, arg) 160 | DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */ 161 | DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */ 162 | DEF( get_var_ref, 3, 0, 1, var_ref) 163 | DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */ 164 | DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */ 165 | DEF(set_loc_uninitialized, 3, 0, 0, loc) 166 | def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */ 167 | DEF( get_loc_check, 3, 0, 1, loc) 168 | DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */ 169 | DEF( put_loc_check_init, 3, 1, 0, loc) 170 | DEF(get_var_ref_check, 3, 0, 1, var_ref) 171 | DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */ 172 | DEF(put_var_ref_check_init, 3, 1, 0, var_ref) 173 | DEF( close_loc, 3, 0, 0, loc) 174 | def(close_var_object, 1, 0, 0, none) /* emitted in phase 1, removed in phase 2 */ 175 | def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ 176 | def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ 177 | 178 | DEF( if_false, 5, 1, 0, label) 179 | DEF( if_true, 5, 1, 0, label) /* must come after if_false */ 180 | DEF( goto, 5, 0, 0, label) /* must come after if_true */ 181 | def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */ 182 | DEF( catch, 5, 0, 1, label) 183 | DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */ 184 | DEF( ret, 1, 1, 0, none) /* used to return from the finally block */ 185 | 186 | def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ 187 | def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ 188 | def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ 189 | def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ 190 | def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */ 191 | def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ 192 | def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ 193 | 194 | DEF( to_object, 1, 1, 1, none) 195 | //DEF( to_string, 1, 1, 1, none) 196 | DEF( to_propkey, 1, 1, 1, none) 197 | DEF( to_propkey2, 1, 2, 2, none) 198 | 199 | DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 200 | DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */ 201 | DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 202 | DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 203 | DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 204 | DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8) 205 | 206 | DEF( make_loc_ref, 7, 0, 2, atom_u16) 207 | DEF( make_arg_ref, 7, 0, 2, atom_u16) 208 | DEF(make_var_ref_ref, 7, 0, 2, atom_u16) 209 | DEF( make_var_ref, 5, 0, 2, atom) 210 | 211 | def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ 212 | 213 | DEF( for_in_start, 1, 1, 1, none) 214 | DEF( for_of_start, 1, 1, 3, none) 215 | DEF(for_await_of_start, 1, 1, 3, none) 216 | DEF( for_in_next, 1, 1, 3, none) 217 | DEF( for_of_next, 2, 3, 5, u8) 218 | DEF(for_await_of_next, 1, 3, 4, none) 219 | DEF(iterator_get_value_done, 1, 1, 2, none) 220 | DEF( iterator_close, 1, 3, 0, none) 221 | DEF(iterator_close_return, 1, 4, 4, none) 222 | DEF(async_iterator_close, 1, 3, 2, none) 223 | DEF(async_iterator_next, 1, 4, 4, none) 224 | DEF(async_iterator_get, 2, 4, 5, u8) 225 | DEF( initial_yield, 1, 0, 0, none) 226 | DEF( yield, 1, 1, 2, none) 227 | DEF( yield_star, 1, 2, 2, none) 228 | DEF(async_yield_star, 1, 1, 2, none) 229 | DEF( await, 1, 1, 1, none) 230 | 231 | /* arithmetic/logic operations */ 232 | DEF( neg, 1, 1, 1, none) 233 | DEF( plus, 1, 1, 1, none) 234 | DEF( dec, 1, 1, 1, none) 235 | DEF( inc, 1, 1, 1, none) 236 | DEF( post_dec, 1, 1, 2, none) 237 | DEF( post_inc, 1, 1, 2, none) 238 | DEF( dec_loc, 2, 0, 0, loc8) 239 | DEF( inc_loc, 2, 0, 0, loc8) 240 | DEF( add_loc, 2, 1, 0, loc8) 241 | DEF( not, 1, 1, 1, none) 242 | DEF( lnot, 1, 1, 1, none) 243 | DEF( typeof, 1, 1, 1, none) 244 | DEF( delete, 1, 2, 1, none) 245 | DEF( delete_var, 5, 0, 1, atom) 246 | 247 | DEF( mul, 1, 2, 1, none) 248 | DEF( div, 1, 2, 1, none) 249 | DEF( mod, 1, 2, 1, none) 250 | DEF( add, 1, 2, 1, none) 251 | DEF( sub, 1, 2, 1, none) 252 | DEF( pow, 1, 2, 1, none) 253 | DEF( shl, 1, 2, 1, none) 254 | DEF( sar, 1, 2, 1, none) 255 | DEF( shr, 1, 2, 1, none) 256 | DEF( lt, 1, 2, 1, none) 257 | DEF( lte, 1, 2, 1, none) 258 | DEF( gt, 1, 2, 1, none) 259 | DEF( gte, 1, 2, 1, none) 260 | DEF( instanceof, 1, 2, 1, none) 261 | DEF( in, 1, 2, 1, none) 262 | DEF( eq, 1, 2, 1, none) 263 | DEF( neq, 1, 2, 1, none) 264 | DEF( strict_eq, 1, 2, 1, none) 265 | DEF( strict_neq, 1, 2, 1, none) 266 | DEF( and, 1, 2, 1, none) 267 | DEF( xor, 1, 2, 1, none) 268 | DEF( or, 1, 2, 1, none) 269 | #ifdef CONFIG_BIGNUM 270 | DEF( mul_pow10, 1, 2, 1, none) 271 | DEF( math_div, 1, 2, 1, none) 272 | DEF( math_mod, 1, 2, 1, none) 273 | DEF( math_pow, 1, 2, 1, none) 274 | #endif 275 | 276 | #if SHORT_OPCODES 277 | DEF( push_minus1, 1, 0, 1, none_int) 278 | DEF( push_0, 1, 0, 1, none_int) 279 | DEF( push_1, 1, 0, 1, none_int) 280 | DEF( push_2, 1, 0, 1, none_int) 281 | DEF( push_3, 1, 0, 1, none_int) 282 | DEF( push_4, 1, 0, 1, none_int) 283 | DEF( push_5, 1, 0, 1, none_int) 284 | DEF( push_6, 1, 0, 1, none_int) 285 | DEF( push_7, 1, 0, 1, none_int) 286 | DEF( push_i8, 2, 0, 1, i8) 287 | DEF( push_i16, 3, 0, 1, i16) 288 | DEF( push_const8, 2, 0, 1, const8) 289 | DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */ 290 | DEF(push_empty_string, 1, 0, 1, none) 291 | 292 | DEF( get_loc8, 2, 0, 1, loc8) 293 | DEF( put_loc8, 2, 1, 0, loc8) 294 | DEF( set_loc8, 2, 1, 1, loc8) 295 | 296 | DEF( get_loc0, 1, 0, 1, none_loc) 297 | DEF( get_loc1, 1, 0, 1, none_loc) 298 | DEF( get_loc2, 1, 0, 1, none_loc) 299 | DEF( get_loc3, 1, 0, 1, none_loc) 300 | DEF( put_loc0, 1, 1, 0, none_loc) 301 | DEF( put_loc1, 1, 1, 0, none_loc) 302 | DEF( put_loc2, 1, 1, 0, none_loc) 303 | DEF( put_loc3, 1, 1, 0, none_loc) 304 | DEF( set_loc0, 1, 1, 1, none_loc) 305 | DEF( set_loc1, 1, 1, 1, none_loc) 306 | DEF( set_loc2, 1, 1, 1, none_loc) 307 | DEF( set_loc3, 1, 1, 1, none_loc) 308 | DEF( get_arg0, 1, 0, 1, none_arg) 309 | DEF( get_arg1, 1, 0, 1, none_arg) 310 | DEF( get_arg2, 1, 0, 1, none_arg) 311 | DEF( get_arg3, 1, 0, 1, none_arg) 312 | DEF( put_arg0, 1, 1, 0, none_arg) 313 | DEF( put_arg1, 1, 1, 0, none_arg) 314 | DEF( put_arg2, 1, 1, 0, none_arg) 315 | DEF( put_arg3, 1, 1, 0, none_arg) 316 | DEF( set_arg0, 1, 1, 1, none_arg) 317 | DEF( set_arg1, 1, 1, 1, none_arg) 318 | DEF( set_arg2, 1, 1, 1, none_arg) 319 | DEF( set_arg3, 1, 1, 1, none_arg) 320 | DEF( get_var_ref0, 1, 0, 1, none_var_ref) 321 | DEF( get_var_ref1, 1, 0, 1, none_var_ref) 322 | DEF( get_var_ref2, 1, 0, 1, none_var_ref) 323 | DEF( get_var_ref3, 1, 0, 1, none_var_ref) 324 | DEF( put_var_ref0, 1, 1, 0, none_var_ref) 325 | DEF( put_var_ref1, 1, 1, 0, none_var_ref) 326 | DEF( put_var_ref2, 1, 1, 0, none_var_ref) 327 | DEF( put_var_ref3, 1, 1, 0, none_var_ref) 328 | DEF( set_var_ref0, 1, 1, 1, none_var_ref) 329 | DEF( set_var_ref1, 1, 1, 1, none_var_ref) 330 | DEF( set_var_ref2, 1, 1, 1, none_var_ref) 331 | DEF( set_var_ref3, 1, 1, 1, none_var_ref) 332 | 333 | DEF( get_length, 1, 1, 1, none) 334 | 335 | DEF( if_false8, 2, 1, 0, label8) 336 | DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */ 337 | DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */ 338 | DEF( goto16, 3, 0, 0, label16) 339 | 340 | DEF( call0, 1, 1, 1, npopx) 341 | DEF( call1, 1, 1, 1, npopx) 342 | DEF( call2, 1, 1, 1, npopx) 343 | DEF( call3, 1, 1, 1, npopx) 344 | 345 | DEF( is_undefined, 1, 1, 1, none) 346 | DEF( is_null, 1, 1, 1, none) 347 | DEF( is_function, 1, 1, 1, none) 348 | #endif 349 | 350 | DEF( nop, 1, 0, 0, none) /* temporary use during code generation */ 351 | 352 | #undef DEF 353 | #undef def 354 | #endif /* DEF */ 355 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | The main documentation is in doc/quickjs.pdf or doc/quickjs.html. 2 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Release the QuickJS source code 3 | 4 | set -e 5 | 6 | version=`cat VERSION` 7 | 8 | if [ "$1" = "-h" ] ; then 9 | echo "release.sh [all]" 10 | echo "" 11 | echo "all: build all the archives. Otherwise only build the quickjs source archive." 12 | exit 1 13 | fi 14 | 15 | 16 | if [ "$1" = "all" ] ; then 17 | 18 | #################################################" 19 | # unicode data 20 | 21 | d="quickjs-${version}" 22 | name="quickjs-unicode-data-${version}" 23 | outdir="/tmp/${d}" 24 | 25 | rm -rf $outdir 26 | mkdir -p $outdir $outdir/unicode 27 | 28 | cp unicode/* $outdir/unicode 29 | 30 | ( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} ) 31 | 32 | #################################################" 33 | # all tests 34 | 35 | d="quickjs-${version}" 36 | name="quickjs-tests-${version}" 37 | outdir="/tmp/${d}" 38 | 39 | rm -rf $outdir 40 | mkdir -p $outdir $outdir/test262o $outdir/test262 $outdir/tests 41 | 42 | cp -a test262o/test $outdir/test262o 43 | 44 | cp -a test262/test test262/harness $outdir/test262 45 | 46 | cp -a tests/bench-v8 $outdir/tests 47 | 48 | ( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} ) 49 | 50 | fi # all 51 | 52 | #################################################" 53 | # quickjs 54 | 55 | make build_doc 56 | 57 | d="quickjs-${version}" 58 | outdir="/tmp/${d}" 59 | 60 | rm -rf $outdir 61 | mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples 62 | 63 | cp Makefile VERSION TODO readme.txt release.sh \ 64 | qjs.c qjsc.c qjscalc.js repl.js \ 65 | quickjs.c quickjs.h quickjs-atom.h \ 66 | quickjs-libc.c quickjs-libc.h quickjs-opcode.h \ 67 | cutils.c cutils.h list.h \ 68 | libregexp.c libregexp.h libregexp-opcode.h \ 69 | libunicode.c libunicode.h libunicode-table.h \ 70 | libbf.c libbf.h \ 71 | jscompress.c unicode_gen.c unicode_gen_def.h \ 72 | bjson.c \ 73 | run-test262.c test262o.conf test262.conf test262bn.conf \ 74 | test262o_errors.txt test262_errors.txt test262bn_errors.txt \ 75 | $outdir 76 | 77 | cp tests/*.js tests/*.patch $outdir/tests 78 | 79 | cp examples/*.js examples/*.c $outdir/examples 80 | 81 | cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \ 82 | doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \ 83 | $outdir/doc 84 | 85 | ( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} ) 86 | -------------------------------------------------------------------------------- /test262.conf: -------------------------------------------------------------------------------- 1 | [config] 2 | # general settings for test262 ES6 version 3 | 4 | # framework style: old, new 5 | style=new 6 | 7 | # handle tests tagged as [noStrict]: yes, no, skip 8 | nostrict=yes 9 | 10 | # handle tests tagged as [strictOnly]: yes, no, skip 11 | strict=yes 12 | 13 | # test mode: default, default-nostrict, default-strict, strict, nostrict, both, all 14 | mode=default 15 | 16 | # handle tests flagged as [async]: yes, no, skip 17 | # for these, load 'harness/doneprintHandle.js' prior to test 18 | # and expect `print('Test262:AsyncTestComplete')` to be called for 19 | # successful termination 20 | async=yes 21 | 22 | # handle tests flagged as [module]: yes, no, skip 23 | module=yes 24 | 25 | # output error messages: yes, no 26 | verbose=yes 27 | 28 | # load harness files from this directory 29 | harnessdir=test262/harness 30 | 31 | # names of harness include files to skip 32 | #harnessexclude= 33 | 34 | # name of the error file for known errors 35 | errorfile=test262_errors.txt 36 | 37 | # exclude tests enumerated in this file (see also [exclude] section) 38 | #excludefile=test262_exclude.txt 39 | 40 | # report test results to this file 41 | reportfile=test262_report.txt 42 | 43 | # enumerate tests from this directory 44 | testdir=test262/test 45 | 46 | [features] 47 | # Standard language features and proposed extensions 48 | # list the features that are included 49 | # skipped features are tagged as such to avoid warnings 50 | 51 | Array.prototype.flat 52 | Array.prototype.flatMap 53 | Array.prototype.flatten 54 | Array.prototype.values 55 | ArrayBuffer 56 | arrow-function 57 | async-functions 58 | async-iteration 59 | Atomics 60 | BigInt=skip 61 | caller 62 | class 63 | class-fields-private=skip 64 | class-fields-public=skip 65 | computed-property-names 66 | const 67 | cross-realm=skip 68 | DataView 69 | DataView.prototype.getFloat32 70 | DataView.prototype.getFloat64 71 | DataView.prototype.getInt16 72 | DataView.prototype.getInt32 73 | DataView.prototype.getInt8 74 | DataView.prototype.getUint16 75 | DataView.prototype.getUint32 76 | DataView.prototype.setUint8 77 | default-arg 78 | default-parameters 79 | destructuring-assignment 80 | destructuring-binding 81 | export-star-as-namespace-from-module=skip 82 | Float32Array 83 | Float64Array 84 | for-of 85 | generators 86 | global 87 | Int8Array 88 | IsHTMLDDA=skip 89 | json-superset 90 | let 91 | Map 92 | new.target 93 | numeric-separator-literal 94 | object-rest 95 | object-spread 96 | Object.is 97 | optional-catch-binding 98 | Promise.prototype.finally 99 | Proxy 100 | Reflect 101 | Reflect.construct 102 | Reflect.set 103 | Reflect.setPrototypeOf 104 | regexp-dotall 105 | regexp-lookbehind 106 | regexp-named-groups 107 | regexp-unicode-property-escapes 108 | Set 109 | SharedArrayBuffer 110 | string-trimming 111 | String.fromCodePoint 112 | String.prototype.endsWith 113 | String.prototype.includes 114 | String.prototype.matchAll=skip 115 | String.prototype.trimEnd 116 | String.prototype.trimStart 117 | super 118 | Symbol 119 | Symbol.asyncIterator 120 | Symbol.hasInstance 121 | Symbol.isConcatSpreadable 122 | Symbol.iterator 123 | Symbol.match 124 | Symbol.matchAll=skip 125 | Symbol.prototype.description 126 | Symbol.replace 127 | Symbol.search 128 | Symbol.species 129 | Symbol.split 130 | Symbol.toPrimitive 131 | Symbol.toStringTag 132 | Symbol.unscopables 133 | tail-call-optimization=skip 134 | template 135 | TypedArray 136 | u180e 137 | Uint16Array 138 | Uint8Array 139 | Uint8ClampedArray 140 | WeakMap 141 | WeakSet 142 | 143 | [exclude] 144 | # list excluded tests and directories here 145 | 146 | # intl not supported 147 | test262/test/intl402/ 148 | 149 | # these builtins are not supported: 150 | test262/test/built-ins/BigInt/ 151 | 152 | # mislabelled feature Symbol.match -> Symbol.matchAll 153 | test262/test/built-ins/Symbol/matchAll/prop-desc.js 154 | 155 | # incompatible with the "caller" feature 156 | test262/test/built-ins/Function/prototype/restricted-property-caller.js 157 | test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js 158 | 159 | # no debugger keyword support 160 | test262/test/language/statements/debugger/statement.js 161 | 162 | # bogus html close comment test with syntax error 163 | test262/test/annexB/built-ins/Function/createdynfn-html-close-comment-params.js 164 | 165 | # bogus test #14 compares 2 consecutive calls to Date(), may be different if unlucky 166 | #test262/test/built-ins/Date/S15.9.2.1_A2.js 167 | 168 | # slow tests 169 | #test262/test/built-ins/RegExp/CharacterClassEscapes/ 170 | #test262/test/built-ins/RegExp/property-escapes/ 171 | 172 | [tests] 173 | # list test files or use config.testdir 174 | -------------------------------------------------------------------------------- /test262_errors.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calbertts/qnode/27bd7e7fd124aba8fac2216e60fe735612b377bb/test262_errors.txt -------------------------------------------------------------------------------- /test262bn.conf: -------------------------------------------------------------------------------- 1 | [config] 2 | # general settings for test262 ES6 bignum version 3 | 4 | # framework style: old, new 5 | style=new 6 | 7 | # handle tests tagged as [noStrict]: yes, no, skip 8 | nostrict=yes 9 | 10 | # handle tests tagged as [strictOnly]: yes, no, skip 11 | strict=yes 12 | 13 | # test mode: default, default-nostrict, default-strict, strict, nostrict, both, all 14 | mode=default 15 | 16 | # handle tests flagged as [async]: yes, no, skip 17 | # for these, load 'harness/doneprintHandle.js' prior to test 18 | # and expect `print('Test262:AsyncTestComplete')` to be called for 19 | # successful termination 20 | async=yes 21 | 22 | # handle tests flagged as [module]: yes, no, skip 23 | module=yes 24 | 25 | # output error messages: yes, no 26 | verbose=yes 27 | 28 | # load harness files from this directory 29 | harnessdir=test262/harness 30 | 31 | # names of harness include files to skip 32 | # bignum version does not support Atomics 33 | harnessexclude=testAtomics.js 34 | 35 | # name of the error file for known errors 36 | errorfile=test262bn_errors.txt 37 | 38 | # exclude tests enumerated in this file (see also [exclude] section) 39 | #excludefile=test262bn_exclude.txt 40 | 41 | # report test results to this file 42 | reportfile=test262bn_report.txt 43 | 44 | # enumerate tests from this directory 45 | testdir=test262/test 46 | 47 | [features] 48 | # Standard language features and proposed extensions 49 | # list the features that are included 50 | # skipped features are tagged as such to avoid warnings 51 | 52 | Array.prototype.flat 53 | Array.prototype.flatMap 54 | Array.prototype.flatten 55 | Array.prototype.values 56 | ArrayBuffer 57 | arrow-function 58 | async-functions 59 | async-iteration 60 | Atomics=skip 61 | BigInt 62 | caller 63 | class 64 | class-fields-private=skip 65 | class-fields-public=skip 66 | computed-property-names 67 | const 68 | cross-realm=skip 69 | DataView 70 | DataView.prototype.getFloat32 71 | DataView.prototype.getFloat64 72 | DataView.prototype.getInt16 73 | DataView.prototype.getInt32 74 | DataView.prototype.getInt8 75 | DataView.prototype.getUint16 76 | DataView.prototype.getUint32 77 | DataView.prototype.setUint8 78 | default-arg 79 | default-parameters 80 | destructuring-assignment 81 | destructuring-binding 82 | export-star-as-namespace-from-module=skip 83 | Float32Array 84 | Float64Array 85 | for-of 86 | generators 87 | global 88 | Int8Array 89 | IsHTMLDDA=skip 90 | json-superset 91 | let 92 | Map 93 | new.target 94 | numeric-separator-literal 95 | object-rest 96 | object-spread 97 | Object.is 98 | optional-catch-binding 99 | Promise.prototype.finally 100 | Proxy 101 | Reflect 102 | Reflect.construct 103 | Reflect.set 104 | Reflect.setPrototypeOf 105 | regexp-dotall 106 | regexp-lookbehind 107 | regexp-named-groups 108 | regexp-unicode-property-escapes 109 | Set 110 | SharedArrayBuffer=skip 111 | string-trimming 112 | String.fromCodePoint 113 | String.prototype.endsWith 114 | String.prototype.includes 115 | String.prototype.matchAll=skip 116 | String.prototype.trimEnd 117 | String.prototype.trimStart 118 | super 119 | Symbol 120 | Symbol.asyncIterator 121 | Symbol.hasInstance 122 | Symbol.isConcatSpreadable 123 | Symbol.iterator 124 | Symbol.match 125 | Symbol.matchAll=skip 126 | Symbol.prototype.description 127 | Symbol.replace 128 | Symbol.search 129 | Symbol.species 130 | Symbol.split 131 | Symbol.toPrimitive 132 | Symbol.toStringTag 133 | Symbol.unscopables 134 | tail-call-optimization=skip 135 | template 136 | TypedArray 137 | u180e 138 | Uint16Array 139 | Uint8Array 140 | Uint8ClampedArray 141 | WeakMap 142 | WeakSet 143 | 144 | [exclude] 145 | # list excluded tests and directories here 146 | 147 | # intl not supported 148 | test262/test/intl402/ 149 | 150 | # these builtins are not supported: 151 | test262/test/built-ins/Atomics/ 152 | test262/test/built-ins/SharedArrayBuffer/ 153 | 154 | # mislabelled feature Symbol.match -> Symbol.matchAll 155 | test262/test/built-ins/Symbol/matchAll/prop-desc.js 156 | 157 | # incompatible with the "caller" feature 158 | test262/test/built-ins/Function/prototype/restricted-property-caller.js 159 | test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js 160 | 161 | # no debugger keyword support 162 | test262/test/language/statements/debugger/statement.js 163 | 164 | # bogus html close comment test with syntax error 165 | test262/test/annexB/built-ins/Function/createdynfn-html-close-comment-params.js 166 | 167 | # bogus test #14 compares 2 consecutive calls to Date(), may be different if unlucky 168 | #test262/test/built-ins/Date/S15.9.2.1_A2.js 169 | 170 | # slow tests 171 | #test262/test/built-ins/RegExp/CharacterClassEscapes/ 172 | #test262/test/built-ins/RegExp/property-escapes/ 173 | 174 | [tests] 175 | # list test files or use config.testdir 176 | -------------------------------------------------------------------------------- /test262bn_errors.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calbertts/qnode/27bd7e7fd124aba8fac2216e60fe735612b377bb/test262bn_errors.txt -------------------------------------------------------------------------------- /test262o_errors.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calbertts/qnode/27bd7e7fd124aba8fac2216e60fe735612b377bb/test262o_errors.txt -------------------------------------------------------------------------------- /tests/test_bignum.js: -------------------------------------------------------------------------------- 1 | "use math"; 2 | "use strict"; 3 | 4 | function assert(actual, expected, message) { 5 | if (arguments.length == 1) 6 | expected = true; 7 | 8 | if (actual === expected) 9 | return; 10 | 11 | if (actual !== null && expected !== null 12 | && typeof actual == 'object' && typeof expected == 'object' 13 | && actual.toString() === expected.toString()) 14 | return; 15 | 16 | throw Error("assertion failed: got |" + actual + "|" + 17 | ", expected |" + expected + "|" + 18 | (message ? " (" + message + ")" : "")); 19 | } 20 | 21 | // load more elaborate version of assert if available 22 | try { __loadScript("test_assert.js"); } catch(e) {} 23 | 24 | /*----------------*/ 25 | 26 | function pow(a, n) 27 | { 28 | var r, i; 29 | r = 1; 30 | for(i = 0; i < n; i++) 31 | r *= a; 32 | return r; 33 | } 34 | 35 | function test_integer() 36 | { 37 | var a, r; 38 | a = pow(3, 100); 39 | assert((a - 1) != a); 40 | assert(a == 515377520732011331036461129765621272702107522001); 41 | assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1); 42 | assert(Integer.isInteger(1) === true); 43 | assert(Integer.isInteger(1.0) === false); 44 | 45 | assert(Integer.floorLog2(0) === -1); 46 | assert(Integer.floorLog2(7) === 2); 47 | 48 | r = 1 << 31; 49 | assert(r, 2147483648, "1 << 31 === 2147483648"); 50 | 51 | r = 1 << 32; 52 | assert(r, 4294967296, "1 << 32 === 4294967296"); 53 | 54 | r = (1 << 31) < 0; 55 | assert(r, false, "(1 << 31) < 0 === false"); 56 | } 57 | 58 | function test_divrem(div1, a, b, q) 59 | { 60 | var div, divrem, t; 61 | div = Integer[div1]; 62 | divrem = Integer[div1 + "rem"]; 63 | assert(div(a, b) == q); 64 | t = divrem(a, b); 65 | assert(t[0] == q); 66 | assert(a == b * q + t[1]); 67 | } 68 | 69 | function test_idiv1(div, a, b, r) 70 | { 71 | test_divrem(div, a, b, r[0]); 72 | test_divrem(div, -a, b, r[1]); 73 | test_divrem(div, a, -b, r[2]); 74 | test_divrem(div, -a, -b, r[3]); 75 | } 76 | 77 | function test_idiv() 78 | { 79 | test_idiv1("tdiv", 3, 2, [1, -1, -1, 1]); 80 | test_idiv1("fdiv", 3, 2, [1, -2, -2, 1]); 81 | test_idiv1("cdiv", 3, 2, [2, -1, -1, 2]); 82 | test_idiv1("ediv", 3, 2, [1, -2, -1, 2]); 83 | } 84 | 85 | function test_float() 86 | { 87 | var e, a, b, sqrt2; 88 | 89 | assert(typeof 1 === "bigint"); 90 | assert(typeof 1.0 === "bigfloat"); 91 | assert(1 == 1.0); 92 | assert(1 !== 1.0); 93 | 94 | e = new BigFloatEnv(128); 95 | assert(e.prec == 128); 96 | a = BigFloat.sqrt(2, e); 97 | assert(a == BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e)); 98 | assert(e.inexact === true); 99 | assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcd); 100 | 101 | b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128); 102 | assert(a == b); 103 | } 104 | 105 | /* jscalc tests */ 106 | 107 | function test_modulo() 108 | { 109 | var i, p, a, b; 110 | 111 | /* Euclidian modulo operator */ 112 | assert((-3) % 2 == 1); 113 | assert(3 % (-2) == 1); 114 | 115 | p = 101; 116 | for(i = 1; i < p; i++) { 117 | a = Integer.invmod(i, p); 118 | assert(a >= 0 && a < p); 119 | assert((i * a) % p == 1); 120 | } 121 | 122 | assert(Integer.isPrime(2^107-1)); 123 | assert(!Integer.isPrime((2^107-1) * (2^89-1))); 124 | a = Integer.factor((2^89-1)*2^3*11*13^2*1009); 125 | assert(a == [ 2,2,2,11,13,13,1009,618970019642690137449562111 ]); 126 | } 127 | 128 | function test_mod() 129 | { 130 | var a, b, p; 131 | 132 | a = Mod(3, 101); 133 | b = Mod(-1, 101); 134 | assert((a + b) == Mod(2, 101)); 135 | assert(a ^ 100 == Mod(1, 101)); 136 | 137 | p = 2 ^ 607 - 1; /* mersenne prime */ 138 | a = Mod(3, p) ^ (p - 1); 139 | assert(a == Mod(1, p)); 140 | } 141 | 142 | function test_polynomial() 143 | { 144 | var a, b, q, r, t, i; 145 | a = (1 + X) ^ 4; 146 | assert(a == X^4+4*X^3+6*X^2+4*X+1); 147 | 148 | r = (1 + X); 149 | q = (1+X+X^2); 150 | b = (1 - X^2); 151 | a = q * b + r; 152 | t = Polynomial.divrem(a, b); 153 | assert(t[0] == q); 154 | assert(t[1] == r); 155 | 156 | a = 1 + 2*X + 3*X^2; 157 | assert(a.apply(0.1) == 1.23); 158 | 159 | a = 1-2*X^2+2*X^3; 160 | assert(deriv(a) == (6*X^2-4*X)); 161 | assert(deriv(integ(a)) == a); 162 | 163 | a = (X-1)*(X-2)*(X-3)*(X-4)*(X-0.1); 164 | r = polroots(a); 165 | for(i = 0; i < r.length; i++) { 166 | b = abs(a.apply(r[i])); 167 | assert(b <= 1e-13); 168 | } 169 | } 170 | 171 | function test_poly_mod() 172 | { 173 | var a, p; 174 | 175 | /* modulo using polynomials */ 176 | p = X^2 + X + 1; 177 | a = PolyMod(3+X, p) ^ 10; 178 | assert(a == PolyMod(-3725*X-18357, p)); 179 | 180 | a = PolyMod(1/X, 1+X^2); 181 | assert(a == PolyMod(-X, X^2+1)); 182 | } 183 | 184 | function test_rfunc() 185 | { 186 | var a; 187 | a = (X+1)/((X+1)*(X-1)); 188 | assert(a == 1/(X-1)); 189 | a = (X + 2) / (X - 2); 190 | assert(a.apply(1/3) == -7/5); 191 | 192 | assert(deriv((X^2-X+1)/(X-1)) == (X^2-2*X)/(X^2-2*X+1)); 193 | } 194 | 195 | function test_series() 196 | { 197 | var a, b; 198 | a = 1+X+O(X^5); 199 | b = a.inverse(); 200 | assert(b == 1-X+X^2-X^3+X^4+O(X^5)); 201 | assert(deriv(b) == -1+2*X-3*X^2+4*X^3+O(X^4)); 202 | assert(deriv(integ(b)) == b); 203 | 204 | a = Series(1/(1-X), 5); 205 | assert(a == 1+X+X^2+X^3+X^4+O(X^5)); 206 | b = a.apply(0.1); 207 | assert(b == 1.1111); 208 | 209 | 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)); 210 | assert(sin(X+O(X^6)) == X-1/6*X^3+1/120*X^5+O(X^6)); 211 | assert(cos(X+O(X^6)) == 1-1/2*X^2+1/24*X^4+O(X^6)); 212 | assert(tan(X+O(X^8)) == X+1/3*X^3+2/15*X^5+17/315*X^7+O(X^8)); 213 | 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)); 214 | } 215 | 216 | function test_matrix() 217 | { 218 | var a, b, r; 219 | a = [[1, 2],[3, 4]]; 220 | b = [3, 4]; 221 | r = a * b; 222 | assert(r == [11, 25]); 223 | r = (a^-1) * 2; 224 | assert(r == [[-4, 2],[3, -1]]); 225 | 226 | assert(norm2([1,2,3]) == 14); 227 | 228 | assert(diag([1,2,3]) == [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]); 229 | assert(trans(a) == [ [ 1, 3 ], [ 2, 4 ] ]); 230 | assert(trans([1,2,3]) == [[1,2,3]]); 231 | assert(trace(a) == 5); 232 | 233 | assert(charpoly(Matrix.hilbert(4)) == X^4-176/105*X^3+3341/12600*X^2-41/23625*X+1/6048000); 234 | assert(det(Matrix.hilbert(4)) == 1/6048000); 235 | 236 | a = [[1,2,1],[-2,-3,1],[3,5,0]]; 237 | assert(rank(a) == 2); 238 | assert(ker(a) == [ [ 5 ], [ -3 ], [ 1 ] ]); 239 | 240 | assert(dp([1, 2, 3], [3, -4, -7]) === -26); 241 | assert(cp([1, 2, 3], [3, -4, -7]) == [ -2, 16, -10 ]); 242 | } 243 | 244 | function assert_eq(a, ref) 245 | { 246 | assert(abs(a / ref - 1.0) <= 1e-15); 247 | } 248 | 249 | function test_trig() 250 | { 251 | assert_eq(sin(1/2), 0.479425538604203); 252 | assert_eq(sin(2+3*I), 9.154499146911428-4.168906959966565*I); 253 | assert_eq(cos(2+3*I), -4.189625690968807-9.109227893755337*I); 254 | assert_eq((2+0.5*I)^(1.1-0.5*I), 2.494363021357619-0.23076804554558092*I); 255 | assert_eq(sqrt(2*I), 1 + I); 256 | } 257 | 258 | test_integer(); 259 | test_idiv(); 260 | test_float(); 261 | 262 | test_modulo(); 263 | test_mod(); 264 | test_polynomial(); 265 | test_poly_mod(); 266 | test_rfunc(); 267 | test_series(); 268 | test_matrix(); 269 | test_trig(); 270 | -------------------------------------------------------------------------------- /tests/test_bjson.js: -------------------------------------------------------------------------------- 1 | import * as bjson from "../bjson.so"; 2 | 3 | function assert(b, str) 4 | { 5 | if (b) { 6 | return; 7 | } else { 8 | throw Error("assertion failed: " + str); 9 | } 10 | } 11 | 12 | function toHex(a) 13 | { 14 | var i, s = "", tab, v; 15 | tab = new Uint8Array(a); 16 | for(i = 0; i < tab.length; i++) { 17 | v = tab[i].toString(16); 18 | if (v.length < 2) 19 | v = "0" + v; 20 | if (i !== 0) 21 | s += " "; 22 | s += v; 23 | } 24 | return s; 25 | } 26 | 27 | function toStr(a) 28 | { 29 | var s, i, props, prop; 30 | 31 | switch(typeof(a)) { 32 | case "object": 33 | if (a === null) 34 | return "null"; 35 | if (Array.isArray(a)) { 36 | s = "["; 37 | for(i = 0; i < a.length; i++) { 38 | if (i != 0) 39 | s += ","; 40 | s += toStr(a[i]); 41 | } 42 | s += "]"; 43 | } else { 44 | props = Object.keys(a); 45 | s = "{"; 46 | for(i = 0; i < props.length; i++) { 47 | if (i != 0) 48 | s += ","; 49 | prop = props[i]; 50 | s += prop + ":" + toStr(a[prop]); 51 | } 52 | s += "}"; 53 | } 54 | return s; 55 | case "undefined": 56 | return "undefined"; 57 | case "string": 58 | return a.__quote(); 59 | case "number": 60 | case "bigfloat": 61 | if (a == 0 && 1 / a < 0) 62 | return "-0"; 63 | else 64 | return a.toString(); 65 | break; 66 | default: 67 | return a.toString(); 68 | } 69 | } 70 | 71 | function bjson_test(a) 72 | { 73 | var buf, r, a_str, r_str; 74 | a_str = toStr(a); 75 | buf = bjson.write(a); 76 | if (0) { 77 | print(a_str, "->", toHex(buf)); 78 | } 79 | r = bjson.read(buf, 0, buf.byteLength); 80 | r_str = toStr(r); 81 | if (a_str != r_str) { 82 | print(a_str); 83 | print(r_str); 84 | assert(false); 85 | } 86 | } 87 | 88 | function bjson_test_all() 89 | { 90 | var obj; 91 | 92 | bjson_test({x:1, y:2, if:3}); 93 | bjson_test([1, 2, 3]); 94 | bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]); 95 | if (typeof BigInt !== "undefined") { 96 | bjson_test([BigInt("1"), -BigInt("0x123456789"), 97 | BigInt("0x123456789abcdef123456789abcdef")]); 98 | } 99 | if (typeof BigFloat !== "undefined") { 100 | BigFloatEnv.setPrec(function () { 101 | bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"), 102 | BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"), 103 | 0.0 / BigFloat("0"), BigFloat.MAX_VALUE, 104 | BigFloat.MIN_VALUE]); 105 | }, 113, 15); 106 | } 107 | 108 | /* tested with a circular reference */ 109 | obj = {}; 110 | obj.x = obj; 111 | try { 112 | bjson.write(obj); 113 | assert(false); 114 | } catch(e) { 115 | assert(e instanceof TypeError); 116 | } 117 | } 118 | 119 | bjson_test_all(); 120 | -------------------------------------------------------------------------------- /tests/test_builtin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function assert(actual, expected, message) { 4 | if (arguments.length == 1) 5 | expected = true; 6 | 7 | if (actual === expected) 8 | return; 9 | 10 | if (actual !== null && expected !== null 11 | && typeof actual == 'object' && typeof expected == 'object' 12 | && actual.toString() === expected.toString()) 13 | return; 14 | 15 | throw Error("assertion failed: got |" + actual + "|" + 16 | ", expected |" + expected + "|" + 17 | (message ? " (" + message + ")" : "")); 18 | } 19 | 20 | // load more elaborate version of assert if available 21 | try { __loadScript("test_assert.js"); } catch(e) {} 22 | 23 | /*----------------*/ 24 | 25 | function my_func(a, b) 26 | { 27 | return a + b; 28 | } 29 | 30 | function test_function() 31 | { 32 | function f(a, b) { 33 | var i, tab = []; 34 | tab.push(this); 35 | for(i = 0; i < arguments.length; i++) 36 | tab.push(arguments[i]); 37 | return tab; 38 | } 39 | function constructor1(a) { 40 | this.x = a; 41 | } 42 | 43 | var r, g; 44 | 45 | r = my_func.call(null, 1, 2); 46 | assert(r, 3, "call"); 47 | 48 | r = my_func.apply(null, [1, 2]); 49 | assert(r, 3, "apply"); 50 | 51 | r = new Function("a", "b", "return a + b;"); 52 | assert(r(2,3), 5, "function"); 53 | 54 | g = f.bind(1, 2); 55 | assert(g.length, 1); 56 | assert(g.name, "bound f"); 57 | assert(g(3), [1,2,3]); 58 | 59 | g = constructor1.bind(null, 1); 60 | r = new g(); 61 | assert(r.x, 1); 62 | } 63 | 64 | function test() 65 | { 66 | var r, a, b, c, err; 67 | 68 | r = Error("hello"); 69 | assert(r.message, "hello", "Error"); 70 | 71 | a = new Object(); 72 | a.x = 1; 73 | assert(a.x, 1, "Object"); 74 | 75 | assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf"); 76 | Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true }); 77 | assert(a.y, 3, "defineProperty"); 78 | 79 | Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true }); 80 | assert(a.z, 4, "get"); 81 | a.z = 5; 82 | assert(a.z_val, 5, "set"); 83 | 84 | a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; 85 | assert(a.z, 4, "get"); 86 | a.z = 5; 87 | assert(a.z_val, 5, "set"); 88 | 89 | b = Object.create(a); 90 | assert(Object.getPrototypeOf(b), a, "create"); 91 | c = {u:2}; 92 | /* XXX: refcount bug in 'b' instead of 'a' */ 93 | Object.setPrototypeOf(a, c); 94 | assert(Object.getPrototypeOf(a), c, "setPrototypeOf"); 95 | 96 | a = {}; 97 | assert(a.toString(), "[object Object]", "toString"); 98 | 99 | a = {x:1}; 100 | assert(Object.isExtensible(a), true, "extensible"); 101 | Object.preventExtensions(a); 102 | 103 | err = false; 104 | try { 105 | a.y = 2; 106 | } catch(e) { 107 | err = true; 108 | } 109 | assert(Object.isExtensible(a), false, "extensible"); 110 | assert(typeof a.y, "undefined", "extensible"); 111 | assert(err, true, "extensible"); 112 | } 113 | 114 | function test_enum() 115 | { 116 | var a, tab; 117 | a = {x:1, 118 | "18014398509481984": 1, 119 | "9007199254740992": 1, 120 | "9007199254740991": 1, 121 | "4294967296": 1, 122 | "4294967295": 1, 123 | y:1, 124 | "4294967294": 1, 125 | "1": 2}; 126 | tab = Object.keys(a); 127 | // console.log("tab=" + tab.toString()); 128 | assert(tab, ["1","4294967294","4294967295","4294967296","9007199254740991","x","18014398509481984","9007199254740992","y"], "keys"); 129 | } 130 | 131 | function test_array() 132 | { 133 | var a, err; 134 | 135 | a = [1, 2, 3]; 136 | assert(a.length, 3, "array"); 137 | assert(a[2], 3, "array1"); 138 | 139 | a = new Array(10); 140 | assert(a.length, 10, "array2"); 141 | 142 | a = new Array(1, 2); 143 | assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3"); 144 | 145 | a = [1, 2, 3]; 146 | a.length = 2; 147 | assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4"); 148 | 149 | a = []; 150 | a[1] = 10; 151 | a[4] = 3; 152 | assert(a.length, 5); 153 | 154 | a = [1,2]; 155 | a.length = 5; 156 | a[4] = 1; 157 | a.length = 4; 158 | assert(a[4] !== 1, true, "array5"); 159 | 160 | a = [1,2]; 161 | a.push(3,4); 162 | assert(a.join(), "1,2,3,4", "join"); 163 | 164 | a = [1,2,3,4,5]; 165 | Object.defineProperty(a, "3", { configurable: false }); 166 | err = false; 167 | try { 168 | a.length = 2; 169 | } catch(e) { 170 | err = true; 171 | } 172 | assert(err && a.toString() === "1,2,3,4"); 173 | } 174 | 175 | function test_string() 176 | { 177 | var a; 178 | a = String("abc"); 179 | assert(a.length, 3, "string"); 180 | assert(a[1], "b", "string"); 181 | assert(a.charCodeAt(1), 0x62, "string"); 182 | assert(String.fromCharCode(65), "A", "string"); 183 | assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string"); 184 | assert(a.charAt(1), "b"); 185 | assert(a.charAt(-1), ""); 186 | assert(a.charAt(3), ""); 187 | 188 | a = "abcd"; 189 | assert(a.substring(1, 3), "bc", "substring"); 190 | a = String.fromCharCode(0x20ac); 191 | assert(a.charCodeAt(0), 0x20ac, "unicode"); 192 | assert(a, "€", "unicode"); 193 | assert(a, "\u20ac", "unicode"); 194 | assert(a, "\u{20ac}", "unicode"); 195 | assert("a", "\x61", "unicode"); 196 | 197 | a = "\u{10ffff}"; 198 | assert(a.length, 2, "unicode"); 199 | assert(a, "\u{dbff}\u{dfff}", "unicode"); 200 | assert(a.codePointAt(0), 0x10ffff); 201 | assert(String.fromCodePoint(0x10ffff), a); 202 | 203 | assert("a".concat("b", "c"), "abc"); 204 | 205 | assert("abcabc".indexOf("cab"), 2); 206 | assert("abcabc".indexOf("cab2"), -1); 207 | assert("abc".indexOf("c"), 2); 208 | 209 | assert("aaa".indexOf("a"), 0); 210 | assert("aaa".indexOf("a", NaN), 0); 211 | assert("aaa".indexOf("a", -Infinity), 0); 212 | assert("aaa".indexOf("a", -1), 0); 213 | assert("aaa".indexOf("a", -0), 0); 214 | assert("aaa".indexOf("a", 0), 0); 215 | assert("aaa".indexOf("a", 1), 1); 216 | assert("aaa".indexOf("a", 2), 2); 217 | assert("aaa".indexOf("a", 3), -1); 218 | assert("aaa".indexOf("a", 4), -1); 219 | assert("aaa".indexOf("a", Infinity), -1); 220 | 221 | assert("aaa".indexOf(""), 0); 222 | assert("aaa".indexOf("", NaN), 0); 223 | assert("aaa".indexOf("", -Infinity), 0); 224 | assert("aaa".indexOf("", -1), 0); 225 | assert("aaa".indexOf("", -0), 0); 226 | assert("aaa".indexOf("", 0), 0); 227 | assert("aaa".indexOf("", 1), 1); 228 | assert("aaa".indexOf("", 2), 2); 229 | assert("aaa".indexOf("", 3), 3); 230 | assert("aaa".indexOf("", 4), 3); 231 | assert("aaa".indexOf("", Infinity), 3); 232 | 233 | assert("aaa".lastIndexOf("a"), 2); 234 | assert("aaa".lastIndexOf("a", NaN), 2); 235 | assert("aaa".lastIndexOf("a", -Infinity), 0); 236 | assert("aaa".lastIndexOf("a", -1), 0); 237 | assert("aaa".lastIndexOf("a", -0), 0); 238 | assert("aaa".lastIndexOf("a", 0), 0); 239 | assert("aaa".lastIndexOf("a", 1), 1); 240 | assert("aaa".lastIndexOf("a", 2), 2); 241 | assert("aaa".lastIndexOf("a", 3), 2); 242 | assert("aaa".lastIndexOf("a", 4), 2); 243 | assert("aaa".lastIndexOf("a", Infinity), 2); 244 | 245 | assert("aaa".lastIndexOf(""), 3); 246 | assert("aaa".lastIndexOf("", NaN), 3); 247 | assert("aaa".lastIndexOf("", -Infinity), 0); 248 | assert("aaa".lastIndexOf("", -1), 0); 249 | assert("aaa".lastIndexOf("", -0), 0); 250 | assert("aaa".lastIndexOf("", 0), 0); 251 | assert("aaa".lastIndexOf("", 1), 1); 252 | assert("aaa".lastIndexOf("", 2), 2); 253 | assert("aaa".lastIndexOf("", 3), 3); 254 | assert("aaa".lastIndexOf("", 4), 3); 255 | assert("aaa".lastIndexOf("", Infinity), 3); 256 | 257 | assert("a,b,c".split(","), ["a","b","c"]); 258 | assert(",b,c".split(","), ["","b","c"]); 259 | assert("a,b,".split(","), ["a","b",""]); 260 | 261 | assert("aaaa".split(), [ "aaaa" ]); 262 | assert("aaaa".split(undefined, 0), [ ]); 263 | assert("aaaa".split(""), [ "a", "a", "a", "a" ]); 264 | assert("aaaa".split("", 0), [ ]); 265 | assert("aaaa".split("", 1), [ "a" ]); 266 | assert("aaaa".split("", 2), [ "a", "a" ]); 267 | assert("aaaa".split("a"), [ "", "", "", "", "" ]); 268 | assert("aaaa".split("a", 2), [ "", "" ]); 269 | assert("aaaa".split("aa"), [ "", "", "" ]); 270 | assert("aaaa".split("aa", 0), [ ]); 271 | assert("aaaa".split("aa", 1), [ "" ]); 272 | assert("aaaa".split("aa", 2), [ "", "" ]); 273 | assert("aaaa".split("aaa"), [ "", "a" ]); 274 | assert("aaaa".split("aaaa"), [ "", "" ]); 275 | assert("aaaa".split("aaaaa"), [ "aaaa" ]); 276 | assert("aaaa".split("aaaaa", 0), [ ]); 277 | assert("aaaa".split("aaaaa", 1), [ "aaaa" ]); 278 | 279 | assert(eval('"\0"'), "\0"); 280 | } 281 | 282 | function test_math() 283 | { 284 | var a; 285 | a = 1.4; 286 | assert(Math.floor(a), 1); 287 | assert(Math.ceil(a), 2); 288 | assert(Math.imul(0x12345678, 123), -1088058456); 289 | assert(Math.fround(0.1), 0.10000000149011612); 290 | } 291 | 292 | function test_number() 293 | { 294 | assert(parseInt("123"), 123); 295 | assert(parseInt(" 123r"), 123); 296 | assert(parseInt("0x123"), 0x123); 297 | assert(parseInt("0o123"), 0); 298 | assert(+" 123 ", 123); 299 | assert(+"0b111", 7); 300 | assert(+"0o123", 83); 301 | assert(parseFloat("0x1234"), 0); 302 | assert(parseFloat("Infinity"), Infinity); 303 | assert(parseFloat("-Infinity"), -Infinity); 304 | assert(parseFloat("123.2"), 123.2); 305 | assert(parseFloat("123.2e3"), 123200); 306 | 307 | assert((25).toExponential(0), "3e+1"); 308 | assert((-25).toExponential(0), "-3e+1"); 309 | assert((2.5).toPrecision(1), "3"); 310 | assert((-2.5).toPrecision(1), "-3"); 311 | assert((1.125).toFixed(2), "1.13"); 312 | assert((-1.125).toFixed(2), "-1.13"); 313 | } 314 | 315 | function test_eval() 316 | { 317 | function f(b) { 318 | var x = 1; 319 | return eval(b); 320 | } 321 | var r, a; 322 | 323 | r = eval("1+1;"); 324 | assert(r, 2, "eval"); 325 | 326 | r = eval("var my_var=2; my_var;"); 327 | assert(r, 2, "eval"); 328 | assert(typeof my_var, "undefined"); 329 | 330 | assert(eval("if (1) 2; else 3;"), 2); 331 | assert(eval("if (0) 2; else 3;"), 3); 332 | 333 | assert(f.call(1, "this"), 1); 334 | 335 | a = 2; 336 | assert(eval("a"), 2); 337 | 338 | eval("a = 3"); 339 | assert(a, 3); 340 | 341 | assert(f("arguments.length", 1), 2); 342 | assert(f("arguments[1]", 1), 1); 343 | 344 | a = 4; 345 | assert(f("a"), 4); 346 | f("a=3"); 347 | assert(a, 3); 348 | } 349 | 350 | function test_typed_array() 351 | { 352 | var buffer, a, i; 353 | 354 | a = new Uint8Array(4); 355 | assert(a.length, 4); 356 | for(i = 0; i < a.length; i++) 357 | a[i] = i; 358 | assert(a.join(","), "0,1,2,3"); 359 | a[0] = -1; 360 | assert(a[0], 255); 361 | 362 | a = new Int8Array(3); 363 | a[0] = 255; 364 | assert(a[0], -1); 365 | 366 | a = new Int32Array(3); 367 | a[0] = Math.pow(2, 32) - 1; 368 | assert(a[0], -1); 369 | assert(a.BYTES_PER_ELEMENT, 4); 370 | 371 | a = new Uint8ClampedArray(4); 372 | a[0] = -100; 373 | a[1] = 1.5; 374 | a[2] = 0.5; 375 | a[3] = 1233.5; 376 | assert(a.toString(), "0,2,0,255"); 377 | 378 | buffer = new ArrayBuffer(16); 379 | assert(buffer.byteLength, 16); 380 | a = new Uint32Array(buffer, 12, 1); 381 | assert(a.length, 1); 382 | a[0] = -1; 383 | 384 | a = new Uint16Array(buffer, 2); 385 | a[0] = -1; 386 | 387 | a = new Float32Array(buffer, 8, 1); 388 | a[0] = 1; 389 | 390 | a = new Uint8Array(buffer); 391 | 392 | assert(a.toString(), "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255"); 393 | 394 | assert(a.buffer, buffer); 395 | 396 | a = new Uint8Array([1, 2, 3, 4]); 397 | assert(a.toString(), "1,2,3,4"); 398 | a.set([10, 11], 2); 399 | assert(a.toString(), "1,2,10,11"); 400 | } 401 | 402 | function test_json() 403 | { 404 | var a, s; 405 | s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}'; 406 | a = JSON.parse(s); 407 | assert(a.x, 1); 408 | assert(a.y, true); 409 | assert(a.z, null); 410 | assert(JSON.stringify(a), s); 411 | } 412 | 413 | function test_date() 414 | { 415 | var d = new Date(1506098258091), a; 416 | assert(d.toISOString(), "2017-09-22T16:37:38.091Z"); 417 | d.setUTCHours(18, 10, 11); 418 | assert(d.toISOString(), "2017-09-22T18:10:11.091Z"); 419 | a = Date.parse(d.toISOString()); 420 | assert((new Date(a)).toISOString(), d.toISOString()); 421 | } 422 | 423 | function test_regexp() 424 | { 425 | var a, str; 426 | str = "abbbbbc"; 427 | a = /(b+)c/.exec(str); 428 | assert(a[0], "bbbbbc"); 429 | assert(a[1], "bbbbb"); 430 | assert(a.index, 1); 431 | assert(a.input, str); 432 | a = /(b+)c/.test(str); 433 | assert(a, true); 434 | assert(/\x61/.exec("a")[0], "a"); 435 | assert(/\u0061/.exec("a")[0], "a"); 436 | assert(/\ca/.exec("\x01")[0], "\x01"); 437 | assert(/\\a/.exec("\\a")[0], "\\a"); 438 | assert(/\c0/.exec("\\c0")[0], "\\c0"); 439 | 440 | a = /(\.(?=com|org)|\/)/.exec("ah.com"); 441 | assert(a.index === 2 && a[0] === "."); 442 | 443 | a = /(\.(?!com|org)|\/)/.exec("ah.com"); 444 | assert(a, null); 445 | 446 | a = /(?=(a+))/.exec("baaabac"); 447 | assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); 448 | 449 | a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); 450 | assert(a, ["zaacbbbcac","z","ac","a",,"c"]); 451 | 452 | a = eval("/\0a/"); 453 | assert(a.toString(), "/\0a/"); 454 | assert(a.exec("\0a")[0], "\0a"); 455 | } 456 | 457 | function test_symbol() 458 | { 459 | var a, b, obj, c; 460 | a = Symbol("abc"); 461 | obj = {}; 462 | obj[a] = 2; 463 | assert(obj[a], 2); 464 | assert(typeof obj["abc"], "undefined"); 465 | assert(String(a), "Symbol(abc)"); 466 | b = Symbol("abc"); 467 | assert(a == a); 468 | assert(a === a); 469 | assert(a != b); 470 | assert(a !== b); 471 | 472 | b = Symbol.for("abc"); 473 | c = Symbol.for("abc"); 474 | assert(b === c); 475 | assert(b !== a); 476 | 477 | assert(Symbol.keyFor(b), "abc"); 478 | assert(Symbol.keyFor(a), undefined); 479 | 480 | a = Symbol("aaa"); 481 | assert(a.valueOf(), a); 482 | assert(a.toString(), "Symbol(aaa)"); 483 | 484 | b = Object(a); 485 | assert(b.valueOf(), a); 486 | assert(b.toString(), "Symbol(aaa)"); 487 | } 488 | 489 | function test_map() 490 | { 491 | var a, i, n, tab, o, v; 492 | n = 1000; 493 | a = new Map(); 494 | tab = []; 495 | for(i = 0; i < n; i++) { 496 | v = { }; 497 | o = { id: i }; 498 | tab[i] = [o, v]; 499 | a.set(o, v); 500 | } 501 | 502 | assert(a.size, n); 503 | for(i = 0; i < n; i++) { 504 | assert(a.get(tab[i][0]), tab[i][1]); 505 | } 506 | 507 | i = 0; 508 | a.forEach(function (v, o) { 509 | assert(o, tab[i++][0]); 510 | assert(a.has(o)); 511 | assert(a.delete(o)); 512 | assert(!a.has(o)); 513 | }); 514 | 515 | assert(a.size, 0); 516 | } 517 | 518 | function test_weak_map() 519 | { 520 | var a, i, n, tab, o, v, n2; 521 | a = new WeakMap(); 522 | n = 10; 523 | tab = []; 524 | for(i = 0; i < n; i++) { 525 | v = { }; 526 | o = { id: i }; 527 | tab[i] = [o, v]; 528 | a.set(o, v); 529 | } 530 | o = null; 531 | 532 | n2 = n >> 1; 533 | for(i = 0; i < n2; i++) { 534 | a.delete(tab[i][0]); 535 | } 536 | for(i = n2; i < n; i++) { 537 | tab[i][0] = null; /* should remove the object from the WeakMap too */ 538 | } 539 | /* the WeakMap should be empty here */ 540 | } 541 | 542 | function test_generator() 543 | { 544 | function *f() { 545 | var ret; 546 | yield 1; 547 | ret = yield 2; 548 | assert(ret, "next_arg"); 549 | return 3; 550 | } 551 | function *f2() { 552 | yield 1; 553 | yield 2; 554 | return "ret_val"; 555 | } 556 | function *f1() { 557 | var ret = yield *f2(); 558 | assert(ret, "ret_val"); 559 | return 3; 560 | } 561 | var g, v; 562 | g = f(); 563 | v = g.next(); 564 | assert(v.value === 1 && v.done === false); 565 | v = g.next(); 566 | assert(v.value === 2 && v.done === false); 567 | v = g.next("next_arg"); 568 | assert(v.value === 3 && v.done === true); 569 | v = g.next(); 570 | assert(v.value === undefined && v.done === true); 571 | 572 | g = f1(); 573 | v = g.next(); 574 | assert(v.value === 1 && v.done === false); 575 | v = g.next(); 576 | assert(v.value === 2 && v.done === false); 577 | v = g.next(); 578 | assert(v.value === 3 && v.done === true); 579 | v = g.next(); 580 | assert(v.value === undefined && v.done === true); 581 | } 582 | 583 | test(); 584 | test_function(); 585 | test_enum(); 586 | test_array(); 587 | test_string(); 588 | test_math(); 589 | test_number(); 590 | test_eval(); 591 | test_typed_array(); 592 | test_json(); 593 | test_date(); 594 | test_regexp(); 595 | test_symbol(); 596 | test_map(); 597 | test_weak_map(); 598 | test_generator(); 599 | -------------------------------------------------------------------------------- /tests/test_closure.js: -------------------------------------------------------------------------------- 1 | function assert(actual, expected, message) { 2 | if (arguments.length == 1) 3 | expected = true; 4 | 5 | if (actual === expected) 6 | return; 7 | 8 | if (actual !== null && expected !== null 9 | && typeof actual == 'object' && typeof expected == 'object' 10 | && actual.toString() === expected.toString()) 11 | return; 12 | 13 | throw Error("assertion failed: got |" + actual + "|" + 14 | ", expected |" + expected + "|" + 15 | (message ? " (" + message + ")" : "")); 16 | } 17 | 18 | // load more elaborate version of assert if available 19 | try { __loadScript("test_assert.js"); } catch(e) {} 20 | 21 | /*----------------*/ 22 | 23 | var log_str = ""; 24 | 25 | function log(str) 26 | { 27 | log_str += str + ","; 28 | } 29 | 30 | function f(a, b, c) 31 | { 32 | var x = 10; 33 | log("a="+a); 34 | function g(d) { 35 | function h() { 36 | log("d=" + d); 37 | log("x=" + x); 38 | } 39 | log("b=" + b); 40 | log("c=" + c); 41 | h(); 42 | } 43 | g(4); 44 | return g; 45 | } 46 | 47 | var g1 = f(1, 2, 3); 48 | g1(5); 49 | 50 | assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1"); 51 | 52 | function test_closure1() 53 | { 54 | function f2() 55 | { 56 | var val = 1; 57 | 58 | function set(a) { 59 | val = a; 60 | } 61 | function get(a) { 62 | return val; 63 | } 64 | return { "set": set, "get": get }; 65 | } 66 | 67 | var obj = f2(); 68 | obj.set(10); 69 | var r; 70 | r = obj.get(); 71 | assert(r, 10, "closure2"); 72 | } 73 | 74 | function test_closure2() 75 | { 76 | var expr_func = function myfunc1(n) { 77 | function myfunc2(n) { 78 | return myfunc1(n - 1); 79 | } 80 | if (n == 0) 81 | return 0; 82 | else 83 | return myfunc2(n); 84 | }; 85 | var r; 86 | r = expr_func(1); 87 | assert(r, 0, "expr_func"); 88 | } 89 | 90 | function test_closure3() 91 | { 92 | function fib(n) 93 | { 94 | if (n <= 0) 95 | return 0; 96 | else if (n == 1) 97 | return 1; 98 | else 99 | return fib(n - 1) + fib(n - 2); 100 | } 101 | 102 | var fib_func = function fib1(n) 103 | { 104 | if (n <= 0) 105 | return 0; 106 | else if (n == 1) 107 | return 1; 108 | else 109 | return fib1(n - 1) + fib1(n - 2); 110 | }; 111 | 112 | assert(fib(6), 8, "fib"); 113 | assert(fib_func(6), 8, "fib_func"); 114 | } 115 | 116 | function test_arrow_function() 117 | { 118 | "use strict"; 119 | 120 | function f1() { 121 | return (() => arguments)(); 122 | } 123 | function f2() { 124 | return (() => this)(); 125 | } 126 | function f3() { 127 | return (() => eval("this"))(); 128 | } 129 | function f4() { 130 | return (() => eval("new.target"))(); 131 | } 132 | var a; 133 | 134 | a = f1(1, 2); 135 | assert(a.length, 2); 136 | assert(a[0] === 1 && a[1] === 2); 137 | 138 | assert(f2.call("this_val") === "this_val"); 139 | assert(f3.call("this_val") === "this_val"); 140 | assert(new f4() === f4); 141 | 142 | var o1 = { f() { return this; } }; 143 | var o2 = { f() { 144 | return (() => eval("super.f()"))(); 145 | } }; 146 | o2.__proto__ = o1; 147 | 148 | assert(o2.f() === o2); 149 | } 150 | 151 | function test_with() 152 | { 153 | var o1 = { x: "o1", y: "o1" }; 154 | var x = "local"; 155 | eval('var z="var_obj";'); 156 | assert(z === "var_obj"); 157 | with (o1) { 158 | assert(x === "o1"); 159 | assert(eval("x") === "o1"); 160 | var f = function () { 161 | o2 = { x: "o2" }; 162 | with (o2) { 163 | assert(x === "o2"); 164 | assert(y === "o1"); 165 | assert(z === "var_obj"); 166 | assert(eval("x") === "o2"); 167 | assert(eval("y") === "o1"); 168 | assert(eval("z") === "var_obj"); 169 | assert(eval('eval("x")') === "o2"); 170 | } 171 | }; 172 | f(); 173 | } 174 | } 175 | 176 | function test_eval_closure() 177 | { 178 | var tab; 179 | 180 | tab = []; 181 | for(let i = 0; i < 3; i++) { 182 | eval("tab.push(function g1() { return i; })"); 183 | } 184 | for(let i = 0; i < 3; i++) { 185 | assert(tab[i]() === i); 186 | } 187 | 188 | tab = []; 189 | for(let i = 0; i < 3; i++) { 190 | let f = function f() { 191 | eval("tab.push(function g2() { return i; })"); 192 | }; 193 | f(); 194 | } 195 | for(let i = 0; i < 3; i++) { 196 | assert(tab[i]() === i); 197 | } 198 | } 199 | 200 | function test_eval_const() 201 | { 202 | const a = 1; 203 | var success = false; 204 | var f = function () { 205 | eval("a = 1"); 206 | }; 207 | try { 208 | f(); 209 | } catch(e) { 210 | success = (e instanceof TypeError); 211 | } 212 | assert(success); 213 | } 214 | 215 | test_closure1(); 216 | test_closure2(); 217 | test_closure3(); 218 | test_arrow_function(); 219 | test_with(); 220 | test_eval_closure(); 221 | test_eval_const(); 222 | -------------------------------------------------------------------------------- /tests/test_loop.js: -------------------------------------------------------------------------------- 1 | function assert(actual, expected, message) { 2 | if (arguments.length == 1) 3 | expected = true; 4 | 5 | if (actual === expected) 6 | return; 7 | 8 | if (actual !== null && expected !== null 9 | && typeof actual == 'object' && typeof expected == 'object' 10 | && actual.toString() === expected.toString()) 11 | return; 12 | 13 | throw Error("assertion failed: got |" + actual + "|" + 14 | ", expected |" + expected + "|" + 15 | (message ? " (" + message + ")" : "")); 16 | } 17 | 18 | // load more elaborate version of assert if available 19 | try { __loadScript("test_assert.js"); } catch(e) {} 20 | 21 | /*----------------*/ 22 | 23 | function test_while() 24 | { 25 | var i, c; 26 | i = 0; 27 | c = 0; 28 | while (i < 3) { 29 | c++; 30 | i++; 31 | } 32 | assert(c === 3); 33 | } 34 | 35 | function test_while_break() 36 | { 37 | var i, c; 38 | i = 0; 39 | c = 0; 40 | while (i < 3) { 41 | c++; 42 | if (i == 1) 43 | break; 44 | i++; 45 | } 46 | assert(c === 2 && i === 1); 47 | } 48 | 49 | function test_do_while() 50 | { 51 | var i, c; 52 | i = 0; 53 | c = 0; 54 | do { 55 | c++; 56 | i++; 57 | } while (i < 3); 58 | assert(c === 3 && i === 3); 59 | } 60 | 61 | function test_for() 62 | { 63 | var i, c; 64 | c = 0; 65 | for(i = 0; i < 3; i++) { 66 | c++; 67 | } 68 | assert(c === 3 && i === 3); 69 | 70 | c = 0; 71 | for(var j = 0; j < 3; j++) { 72 | c++; 73 | } 74 | assert(c === 3 && j === 3); 75 | } 76 | 77 | function test_for_in() 78 | { 79 | var i, tab, a, b; 80 | 81 | tab = []; 82 | for(i in {x:1, y: 2}) { 83 | tab.push(i); 84 | } 85 | assert(tab.toString(), "x,y", "for_in"); 86 | 87 | /* prototype chain test */ 88 | a = {x:2, y: 2, "1": 3}; 89 | b = {"4" : 3 }; 90 | Object.setPrototypeOf(a, b); 91 | tab = []; 92 | for(i in a) { 93 | tab.push(i); 94 | } 95 | assert(tab.toString(), "1,x,y,4", "for_in"); 96 | 97 | /* non enumerable properties hide enumerables ones in the 98 | prototype chain */ 99 | a = {y: 2, "1": 3}; 100 | Object.defineProperty(a, "x", { value: 1 }); 101 | b = {"x" : 3 }; 102 | Object.setPrototypeOf(a, b); 103 | tab = []; 104 | for(i in a) { 105 | tab.push(i); 106 | } 107 | assert(tab.toString(), "1,y", "for_in"); 108 | 109 | /* array optimization */ 110 | a = []; 111 | for(i = 0; i < 10; i++) 112 | a.push(i); 113 | tab = []; 114 | for(i in a) { 115 | tab.push(i); 116 | } 117 | assert(tab.toString(), "0,1,2,3,4,5,6,7,8,9", "for_in"); 118 | 119 | /* iterate with a field */ 120 | a={x:0}; 121 | tab = []; 122 | for(a.x in {x:1, y: 2}) { 123 | tab.push(a.x); 124 | } 125 | assert(tab.toString(), "x,y", "for_in"); 126 | 127 | /* iterate with a variable field */ 128 | a=[0]; 129 | tab = []; 130 | for(a[0] in {x:1, y: 2}) { 131 | tab.push(a[0]); 132 | } 133 | assert(tab.toString(), "x,y", "for_in"); 134 | 135 | /* variable definition in the for in */ 136 | tab = []; 137 | for(var j in {x:1, y: 2}) { 138 | tab.push(j); 139 | } 140 | assert(tab.toString(), "x,y", "for_in"); 141 | 142 | /* variable assigment in the for in */ 143 | tab = []; 144 | for(var k = 2 in {x:1, y: 2}) { 145 | tab.push(k); 146 | } 147 | assert(tab.toString(), "x,y", "for_in"); 148 | } 149 | 150 | function test_for_in2() 151 | { 152 | var i; 153 | tab = []; 154 | for(i in {x:1, y: 2, z:3}) { 155 | if (i === "y") 156 | continue; 157 | tab.push(i); 158 | } 159 | assert(tab.toString() == "x,z"); 160 | 161 | tab = []; 162 | for(i in {x:1, y: 2, z:3}) { 163 | if (i === "z") 164 | break; 165 | tab.push(i); 166 | } 167 | assert(tab.toString() == "x,y"); 168 | } 169 | 170 | function test_for_break() 171 | { 172 | var i, c; 173 | c = 0; 174 | L1: for(i = 0; i < 3; i++) { 175 | c++; 176 | if (i == 0) 177 | continue; 178 | while (1) { 179 | break L1; 180 | } 181 | } 182 | assert(c === 2 && i === 1); 183 | } 184 | 185 | function test_switch1() 186 | { 187 | var i, a, s; 188 | s = ""; 189 | for(i = 0; i < 3; i++) { 190 | a = "?"; 191 | switch(i) { 192 | case 0: 193 | a = "a"; 194 | break; 195 | case 1: 196 | a = "b"; 197 | break; 198 | default: 199 | a = "c"; 200 | break; 201 | } 202 | s += a; 203 | } 204 | assert(s === "abc" && i === 3); 205 | } 206 | 207 | function test_switch2() 208 | { 209 | var i, a, s; 210 | s = ""; 211 | for(i = 0; i < 4; i++) { 212 | a = "?"; 213 | switch(i) { 214 | case 0: 215 | a = "a"; 216 | break; 217 | case 1: 218 | a = "b"; 219 | break; 220 | case 2: 221 | continue; 222 | default: 223 | a = "" + i; 224 | break; 225 | } 226 | s += a; 227 | } 228 | assert(s === "ab3" && i === 4); 229 | } 230 | 231 | function test_try_catch1() 232 | { 233 | try { 234 | throw "hello"; 235 | } catch (e) { 236 | assert(e, "hello", "catch"); 237 | return; 238 | } 239 | assert(false, "catch"); 240 | } 241 | 242 | function test_try_catch2() 243 | { 244 | var a; 245 | try { 246 | a = 1; 247 | } catch (e) { 248 | a = 2; 249 | } 250 | assert(a, 1, "catch"); 251 | } 252 | 253 | function test_try_catch3() 254 | { 255 | var s; 256 | s = ""; 257 | try { 258 | s += "t"; 259 | } catch (e) { 260 | s += "c"; 261 | } finally { 262 | s += "f"; 263 | } 264 | assert(s, "tf", "catch"); 265 | } 266 | 267 | function test_try_catch4() 268 | { 269 | var s; 270 | s = ""; 271 | try { 272 | s += "t"; 273 | throw "c"; 274 | } catch (e) { 275 | s += e; 276 | } finally { 277 | s += "f"; 278 | } 279 | assert(s, "tcf", "catch"); 280 | } 281 | 282 | function test_try_catch5() 283 | { 284 | var s; 285 | s = ""; 286 | for(;;) { 287 | try { 288 | s += "t"; 289 | break; 290 | s += "b"; 291 | } finally { 292 | s += "f"; 293 | } 294 | } 295 | assert(s, "tf", "catch"); 296 | } 297 | 298 | function test_try_catch6() 299 | { 300 | function f() { 301 | try { 302 | s += 't'; 303 | return 1; 304 | } finally { 305 | s += "f"; 306 | } 307 | } 308 | var s = ""; 309 | assert(f() === 1); 310 | assert(s, "tf", "catch6"); 311 | } 312 | 313 | function test_try_catch7() 314 | { 315 | var s; 316 | s = ""; 317 | 318 | try { 319 | try { 320 | s += "t"; 321 | throw "a"; 322 | } finally { 323 | s += "f"; 324 | } 325 | } catch(e) { 326 | s += e; 327 | } finally { 328 | s += "g"; 329 | } 330 | assert(s, "tfag", "catch"); 331 | } 332 | 333 | function test_try_catch8() 334 | { 335 | var i, s; 336 | 337 | s = ""; 338 | for(var i in {x:1, y:2}) { 339 | try { 340 | s += i; 341 | throw "a"; 342 | } catch (e) { 343 | s += e; 344 | } finally { 345 | s += "f"; 346 | } 347 | } 348 | assert(s === "xafyaf"); 349 | } 350 | 351 | test_while(); 352 | test_while_break(); 353 | test_do_while(); 354 | test_for(); 355 | test_for_break(); 356 | test_switch1(); 357 | test_switch2(); 358 | test_for_in(); 359 | test_for_in2(); 360 | 361 | test_try_catch1(); 362 | test_try_catch2(); 363 | test_try_catch3(); 364 | test_try_catch4(); 365 | test_try_catch5(); 366 | test_try_catch6(); 367 | test_try_catch7(); 368 | test_try_catch8(); 369 | -------------------------------------------------------------------------------- /tests/test_op.js: -------------------------------------------------------------------------------- 1 | function assert(actual, expected, message) { 2 | if (arguments.length == 1) 3 | expected = true; 4 | 5 | if (actual === expected) 6 | return; 7 | 8 | if (actual !== null && expected !== null 9 | && typeof actual == 'object' && typeof expected == 'object' 10 | && actual.toString() === expected.toString()) 11 | return; 12 | 13 | throw Error("assertion failed: got |" + actual + "|" + 14 | ", expected |" + expected + "|" + 15 | (message ? " (" + message + ")" : "")); 16 | } 17 | 18 | // load more elaborate version of assert if available 19 | try { __loadScript("test_assert.js"); } catch(e) {} 20 | 21 | /*----------------*/ 22 | 23 | function test_op1() 24 | { 25 | var r, a; 26 | r = 1 + 2; 27 | assert(r, 3, "1 + 2 === 3"); 28 | 29 | r = 1 - 2; 30 | assert(r, -1, "1 - 2 === -1"); 31 | 32 | r = -1; 33 | assert(r, -1, "-1 === -1"); 34 | 35 | r = +2; 36 | assert(r, 2, "+2 === 2"); 37 | 38 | r = 2 * 3; 39 | assert(r, 6, "2 * 3 === 6"); 40 | 41 | r = 4 / 2; 42 | assert(r, 2, "4 / 2 === 2"); 43 | 44 | r = 4 % 3; 45 | assert(r, 1, "4 % 3 === 3"); 46 | 47 | r = 4 << 2; 48 | assert(r, 16, "4 << 2 === 16"); 49 | 50 | r = 1 << 0; 51 | assert(r, 1, "1 << 0 === 1"); 52 | 53 | r = 1 << 31; 54 | assert(r, -2147483648, "1 << 31 === -2147483648"); 55 | 56 | r = 1 << 32; 57 | assert(r, 1, "1 << 32 === 1"); 58 | 59 | r = (1 << 31) < 0; 60 | assert(r, true, "(1 << 31) < 0 === true"); 61 | 62 | r = -4 >> 1; 63 | assert(r, -2, "-4 >> 1 === -2"); 64 | 65 | r = -4 >>> 1; 66 | assert(r, 0x7ffffffe, "-4 >>> 1 === 0x7ffffffe"); 67 | 68 | r = 1 & 1; 69 | assert(r, 1, "1 & 1 === 1"); 70 | 71 | r = 0 | 1; 72 | assert(r, 1, "0 | 1 === 1"); 73 | 74 | r = 1 ^ 1; 75 | assert(r, 0, "1 ^ 1 === 0"); 76 | 77 | r = ~1; 78 | assert(r, -2, "~1 === -2"); 79 | 80 | r = !1; 81 | assert(r, false, "!1 === false"); 82 | 83 | assert((1 < 2), true, "(1 < 2) === true"); 84 | 85 | assert((2 > 1), true, "(2 > 1) === true"); 86 | 87 | assert(('b' > 'a'), true, "('b' > 'a') === true"); 88 | 89 | assert(2 ** 8, 256, "2 ** 8 === 256"); 90 | } 91 | 92 | function test_cvt() 93 | { 94 | assert((NaN | 0) === 0); 95 | assert((Infinity | 0) === 0); 96 | assert(((-Infinity) | 0) === 0); 97 | assert(("12345" | 0) === 12345); 98 | assert(("0x12345" | 0) === 0x12345); 99 | assert(((4294967296 * 3 - 4) | 0) === -4); 100 | 101 | assert(("12345" >>> 0) === 12345); 102 | assert(("0x12345" >>> 0) === 0x12345); 103 | assert((NaN >>> 0) === 0); 104 | assert((Infinity >>> 0) === 0); 105 | assert(((-Infinity) >>> 0) === 0); 106 | assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4)); 107 | } 108 | 109 | function test_eq() 110 | { 111 | assert(null == undefined); 112 | assert(undefined == null); 113 | assert(true == 1); 114 | assert(0 == false); 115 | assert("" == 0); 116 | assert("123" == 123); 117 | assert("122" != 123); 118 | assert((new Number(1)) == 1); 119 | assert(2 == (new Number(2))); 120 | assert((new String("abc")) == "abc"); 121 | assert({} != "abc"); 122 | } 123 | 124 | function test_inc_dec() 125 | { 126 | var a, r; 127 | 128 | a = 1; 129 | r = a++; 130 | assert(r === 1 && a === 2, true, "++"); 131 | 132 | a = 1; 133 | r = ++a; 134 | assert(r === 2 && a === 2, true, "++"); 135 | 136 | a = 1; 137 | r = a--; 138 | assert(r === 1 && a === 0, true, "--"); 139 | 140 | a = 1; 141 | r = --a; 142 | assert(r === 0 && a === 0, true, "--"); 143 | 144 | a = {x:true}; 145 | a.x++; 146 | assert(a.x, 2, "++"); 147 | 148 | a = {x:true}; 149 | a.x--; 150 | assert(a.x, 0, "--"); 151 | 152 | a = [true]; 153 | a[0]++; 154 | assert(a[0], 2, "++"); 155 | 156 | a = {x:true}; 157 | r = a.x++; 158 | assert(r === 1 && a.x === 2, true, "++"); 159 | 160 | a = {x:true}; 161 | r = a.x--; 162 | assert(r === 1 && a.x === 0, true, "--"); 163 | 164 | a = [true]; 165 | r = a[0]++; 166 | assert(r === 1 && a[0] === 2, true, "++"); 167 | 168 | a = [true]; 169 | r = a[0]--; 170 | assert(r === 1 && a[0] === 0, true, "--"); 171 | } 172 | 173 | function F(x) 174 | { 175 | this.x = x; 176 | } 177 | 178 | function test_op2() 179 | { 180 | var a, b; 181 | a = new Object; 182 | a.x = 1; 183 | assert(a.x, 1, "new"); 184 | b = new F(2); 185 | assert(b.x, 2, "new"); 186 | 187 | a = {x : 2}; 188 | assert(("x" in a), true, "in"); 189 | assert(("y" in a), false, "in"); 190 | 191 | a = {}; 192 | assert((a instanceof Object), true, "instanceof"); 193 | assert((a instanceof String), false, "instanceof"); 194 | 195 | assert((typeof 1), "number", "typeof"); 196 | assert((typeof Object), "function", "typeof"); 197 | assert((typeof null), "object", "typeof"); 198 | assert((typeof unknown_var), "undefined", "typeof"); 199 | 200 | a = {x: 1, y: 1}; 201 | assert((delete a.x), true, "delete"); 202 | assert(("x" in a), false, "delete"); 203 | 204 | a = {x: 1, if: 2}; 205 | assert(a.if === 2); 206 | } 207 | 208 | function test_prototype() 209 | { 210 | function f() { } 211 | assert(f.prototype.constructor, f, "prototype"); 212 | } 213 | 214 | function test_arguments() 215 | { 216 | function f2() { 217 | assert(arguments.length, 2, "arguments"); 218 | assert(arguments[0], 1, "arguments"); 219 | assert(arguments[1], 3, "arguments"); 220 | } 221 | f2(1, 3); 222 | } 223 | 224 | function test_class() 225 | { 226 | var o; 227 | class C { 228 | constructor() { 229 | this.x = 10; 230 | } 231 | f() { 232 | return 1; 233 | } 234 | static F() { 235 | return -1; 236 | } 237 | get y() { 238 | return 12; 239 | } 240 | }; 241 | class D extends C { 242 | constructor() { 243 | super(); 244 | this.z = 20; 245 | } 246 | g() { 247 | return 2; 248 | } 249 | static G() { 250 | return -2; 251 | } 252 | h() { 253 | return super.f(); 254 | } 255 | static H() { 256 | return super["F"](); 257 | } 258 | } 259 | 260 | assert(C.F() === -1); 261 | assert(Object.getOwnPropertyDescriptor(C.prototype, "y").get.name === "get y"); 262 | 263 | o = new C(); 264 | assert(o.f() === 1); 265 | assert(o.x === 10); 266 | 267 | assert(D.F() === -1); 268 | assert(D.G() === -2); 269 | assert(D.H() === -1); 270 | 271 | o = new D(); 272 | assert(o.f() === 1); 273 | assert(o.g() === 2); 274 | assert(o.x === 10); 275 | assert(o.z === 20); 276 | assert(o.h() === 1); 277 | 278 | /* test class name scope */ 279 | var E1 = class E { static F() { return E; } }; 280 | assert(E1 === E1.F()); 281 | }; 282 | 283 | function test_template() 284 | { 285 | var a, b; 286 | b = 123; 287 | a = `abc${b}d`; 288 | assert(a === "abc123d"); 289 | 290 | a = String.raw `abc${b}d`; 291 | assert(a === "abc123d"); 292 | } 293 | 294 | test_op1(); 295 | test_cvt(); 296 | test_eq(); 297 | test_inc_dec(); 298 | test_op2(); 299 | test_prototype(); 300 | test_arguments(); 301 | test_class(); 302 | test_template(); 303 | -------------------------------------------------------------------------------- /tests/test_std.js: -------------------------------------------------------------------------------- 1 | import * as std from "std"; 2 | import * as os from "os"; 3 | 4 | function assert(actual, expected, message) { 5 | if (arguments.length == 1) 6 | expected = true; 7 | 8 | if (actual === expected) 9 | return; 10 | 11 | if (actual !== null && expected !== null 12 | && typeof actual == 'object' && typeof expected == 'object' 13 | && actual.toString() === expected.toString()) 14 | return; 15 | 16 | throw Error("assertion failed: got |" + actual + "|" + 17 | ", expected |" + expected + "|" + 18 | (message ? " (" + message + ")" : "")); 19 | } 20 | 21 | // load more elaborate version of assert if available 22 | try { std.loadScript("test_assert.js"); } catch(e) {} 23 | 24 | /*----------------*/ 25 | 26 | function test_printf() 27 | { 28 | assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc"); 29 | } 30 | 31 | function test_file1() 32 | { 33 | var f, len, str, size, buf, ret, i, str1; 34 | 35 | f = std.tmpfile(); 36 | str = "hello world\n"; 37 | f.puts(str); 38 | 39 | f.seek(0, std.SEEK_SET); 40 | str1 = f.readAsString(); 41 | assert(str1 === str); 42 | 43 | f.seek(0, std.SEEK_END); 44 | size = f.tell(); 45 | assert(size === str.length); 46 | 47 | f.seek(0, std.SEEK_SET); 48 | 49 | buf = new Uint8Array(size); 50 | ret = f.read(buf.buffer, 0, size); 51 | assert(ret === size); 52 | for(i = 0; i < size; i++) 53 | assert(buf[i] === str.charCodeAt(i)); 54 | 55 | f.close(); 56 | } 57 | 58 | function test_file2() 59 | { 60 | var f, str, i, size; 61 | f = std.tmpfile(); 62 | str = "hello world\n"; 63 | size = str.length; 64 | for(i = 0; i < size; i++) 65 | f.putByte(str.charCodeAt(i)); 66 | f.seek(0, std.SEEK_SET); 67 | for(i = 0; i < size; i++) { 68 | assert(str.charCodeAt(i) === f.getByte()); 69 | } 70 | assert(f.getByte() === -1); 71 | f.close(); 72 | } 73 | 74 | function test_getline() 75 | { 76 | var f, line, line_count, lines, i; 77 | 78 | lines = ["hello world", "line 1", "line 2" ]; 79 | f = std.tmpfile(); 80 | for(i = 0; i < lines.length; i++) { 81 | f.puts(lines[i], "\n"); 82 | } 83 | 84 | f.seek(0, std.SEEK_SET); 85 | assert(!f.eof()); 86 | line_count = 0; 87 | for(;;) { 88 | line = f.getline(); 89 | if (line === null) 90 | break; 91 | assert(line == lines[line_count]); 92 | line_count++; 93 | } 94 | assert(f.eof()); 95 | assert(line_count === lines.length); 96 | 97 | f.close(); 98 | } 99 | 100 | function test_os() 101 | { 102 | var fd, fname, buf, buf2, i; 103 | 104 | assert(os.isatty(0)); 105 | 106 | fname = "tmp_file.txt"; 107 | fd = os.open(fname, os.O_RDWR | os.O_CREAT | os.O_TRUNC); 108 | assert(fd >= 0); 109 | 110 | buf = new Uint8Array(10); 111 | for(i = 0; i < buf.length; i++) 112 | buf[i] = i; 113 | assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length); 114 | 115 | assert(os.seek(fd, 0, os.SEEK_SET) === 0); 116 | buf2 = new Uint8Array(buf.length); 117 | assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length); 118 | 119 | for(i = 0; i < buf.length; i++) 120 | assert(buf[i] == buf2[i]); 121 | 122 | assert(os.close(fd) === 0); 123 | 124 | assert(os.remove(fname) === 0); 125 | 126 | fd = os.open(fname, os.O_RDONLY); 127 | assert(fd < 0); 128 | } 129 | 130 | function test_timer() 131 | { 132 | var th, i; 133 | 134 | /* just test that a timer can be inserted and removed */ 135 | th = []; 136 | for(i = 0; i < 3; i++) 137 | th[i] = os.setTimeout(1000, function () { }); 138 | for(i = 0; i < 3; i++) 139 | os.clearTimeout(th[i]); 140 | } 141 | 142 | test_printf(); 143 | test_file1(); 144 | test_file2(); 145 | test_getline(); 146 | test_os(); 147 | test_timer(); 148 | -------------------------------------------------------------------------------- /unicode_gen_def.h: -------------------------------------------------------------------------------- 1 | #ifdef UNICODE_GENERAL_CATEGORY 2 | DEF(Cn, "Unassigned") /* must be zero */ 3 | DEF(Lu, "Uppercase_Letter") 4 | DEF(Ll, "Lowercase_Letter") 5 | DEF(Lt, "Titlecase_Letter") 6 | DEF(Lm, "Modifier_Letter") 7 | DEF(Lo, "Other_Letter") 8 | DEF(Mn, "Nonspacing_Mark") 9 | DEF(Mc, "Spacing_Mark") 10 | DEF(Me, "Enclosing_Mark") 11 | DEF(Nd, "Decimal_Number,digit") 12 | DEF(Nl, "Letter_Number") 13 | DEF(No, "Other_Number") 14 | DEF(Sm, "Math_Symbol") 15 | DEF(Sc, "Currency_Symbol") 16 | DEF(Sk, "Modifier_Symbol") 17 | DEF(So, "Other_Symbol") 18 | DEF(Pc, "Connector_Punctuation") 19 | DEF(Pd, "Dash_Punctuation") 20 | DEF(Ps, "Open_Punctuation") 21 | DEF(Pe, "Close_Punctuation") 22 | DEF(Pi, "Initial_Punctuation") 23 | DEF(Pf, "Final_Punctuation") 24 | DEF(Po, "Other_Punctuation") 25 | DEF(Zs, "Space_Separator") 26 | DEF(Zl, "Line_Separator") 27 | DEF(Zp, "Paragraph_Separator") 28 | DEF(Cc, "Control,cntrl") 29 | DEF(Cf, "Format") 30 | DEF(Cs, "Surrogate") 31 | DEF(Co, "Private_Use") 32 | /* synthetic properties */ 33 | DEF(LC, "Cased_Letter") 34 | DEF(L, "Letter") 35 | DEF(M, "Mark,Combining_Mark") 36 | DEF(N, "Number") 37 | DEF(S, "Symbol") 38 | DEF(P, "Punctuation,punct") 39 | DEF(Z, "Separator") 40 | DEF(C, "Other") 41 | #endif 42 | 43 | #ifdef UNICODE_SCRIPT 44 | DEF(Unknown, "Zzzz") 45 | DEF(Adlam, "Adlm") 46 | DEF(Ahom, "Ahom") 47 | DEF(Anatolian_Hieroglyphs, "Hluw") 48 | DEF(Arabic, "Arab") 49 | DEF(Armenian, "Armn") 50 | DEF(Avestan, "Avst") 51 | DEF(Balinese, "Bali") 52 | DEF(Bamum, "Bamu") 53 | DEF(Bassa_Vah, "Bass") 54 | DEF(Batak, "Batk") 55 | DEF(Bengali, "Beng") 56 | DEF(Bhaiksuki, "Bhks") 57 | DEF(Bopomofo, "Bopo") 58 | DEF(Brahmi, "Brah") 59 | DEF(Braille, "Brai") 60 | DEF(Buginese, "Bugi") 61 | DEF(Buhid, "Buhd") 62 | DEF(Canadian_Aboriginal, "Cans") 63 | DEF(Carian, "Cari") 64 | DEF(Caucasian_Albanian, "Aghb") 65 | DEF(Chakma, "Cakm") 66 | DEF(Cham, "Cham") 67 | DEF(Cherokee, "Cher") 68 | DEF(Common, "Zyyy") 69 | DEF(Coptic, "Copt,Qaac") 70 | DEF(Cuneiform, "Xsux") 71 | DEF(Cypriot, "Cprt") 72 | DEF(Cyrillic, "Cyrl") 73 | DEF(Deseret, "Dsrt") 74 | DEF(Devanagari, "Deva") 75 | DEF(Dogra, "Dogr") 76 | DEF(Duployan, "Dupl") 77 | DEF(Egyptian_Hieroglyphs, "Egyp") 78 | DEF(Elbasan, "Elba") 79 | DEF(Ethiopic, "Ethi") 80 | DEF(Georgian, "Geor") 81 | DEF(Glagolitic, "Glag") 82 | DEF(Gothic, "Goth") 83 | DEF(Grantha, "Gran") 84 | DEF(Greek, "Grek") 85 | DEF(Gujarati, "Gujr") 86 | DEF(Gunjala_Gondi, "Gong") 87 | DEF(Gurmukhi, "Guru") 88 | DEF(Han, "Hani") 89 | DEF(Hangul, "Hang") 90 | DEF(Hanifi_Rohingya, "Rohg") 91 | DEF(Hanunoo, "Hano") 92 | DEF(Hatran, "Hatr") 93 | DEF(Hebrew, "Hebr") 94 | DEF(Hiragana, "Hira") 95 | DEF(Imperial_Aramaic, "Armi") 96 | DEF(Inherited, "Zinh,Qaai") 97 | DEF(Inscriptional_Pahlavi, "Phli") 98 | DEF(Inscriptional_Parthian, "Prti") 99 | DEF(Javanese, "Java") 100 | DEF(Kaithi, "Kthi") 101 | DEF(Kannada, "Knda") 102 | DEF(Katakana, "Kana") 103 | DEF(Kayah_Li, "Kali") 104 | DEF(Kharoshthi, "Khar") 105 | DEF(Khmer, "Khmr") 106 | DEF(Khojki, "Khoj") 107 | DEF(Khudawadi, "Sind") 108 | DEF(Lao, "Laoo") 109 | DEF(Latin, "Latn") 110 | DEF(Lepcha, "Lepc") 111 | DEF(Limbu, "Limb") 112 | DEF(Linear_A, "Lina") 113 | DEF(Linear_B, "Linb") 114 | DEF(Lisu, "Lisu") 115 | DEF(Lycian, "Lyci") 116 | DEF(Lydian, "Lydi") 117 | DEF(Makasar, "Maka") 118 | DEF(Mahajani, "Mahj") 119 | DEF(Malayalam, "Mlym") 120 | DEF(Mandaic, "Mand") 121 | DEF(Manichaean, "Mani") 122 | DEF(Marchen, "Marc") 123 | DEF(Masaram_Gondi, "Gonm") 124 | DEF(Medefaidrin, "Medf") 125 | DEF(Meetei_Mayek, "Mtei") 126 | DEF(Mende_Kikakui, "Mend") 127 | DEF(Meroitic_Cursive, "Merc") 128 | DEF(Meroitic_Hieroglyphs, "Mero") 129 | DEF(Miao, "Plrd") 130 | DEF(Modi, "Modi") 131 | DEF(Mongolian, "Mong") 132 | DEF(Mro, "Mroo") 133 | DEF(Multani, "Mult") 134 | DEF(Myanmar, "Mymr") 135 | DEF(Nabataean, "Nbat") 136 | DEF(New_Tai_Lue, "Talu") 137 | DEF(Newa, "Newa") 138 | DEF(Nko, "Nkoo") 139 | DEF(Nushu, "Nshu") 140 | DEF(Ogham, "Ogam") 141 | DEF(Ol_Chiki, "Olck") 142 | DEF(Old_Hungarian, "Hung") 143 | DEF(Old_Italic, "Ital") 144 | DEF(Old_North_Arabian, "Narb") 145 | DEF(Old_Permic, "Perm") 146 | DEF(Old_Persian, "Xpeo") 147 | DEF(Old_Sogdian, "Sogo") 148 | DEF(Old_South_Arabian, "Sarb") 149 | DEF(Old_Turkic, "Orkh") 150 | DEF(Oriya, "Orya") 151 | DEF(Osage, "Osge") 152 | DEF(Osmanya, "Osma") 153 | DEF(Pahawh_Hmong, "Hmng") 154 | DEF(Palmyrene, "Palm") 155 | DEF(Pau_Cin_Hau, "Pauc") 156 | DEF(Phags_Pa, "Phag") 157 | DEF(Phoenician, "Phnx") 158 | DEF(Psalter_Pahlavi, "Phlp") 159 | DEF(Rejang, "Rjng") 160 | DEF(Runic, "Runr") 161 | DEF(Samaritan, "Samr") 162 | DEF(Saurashtra, "Saur") 163 | DEF(Sharada, "Shrd") 164 | DEF(Shavian, "Shaw") 165 | DEF(Siddham, "Sidd") 166 | DEF(SignWriting, "Sgnw") 167 | DEF(Sinhala, "Sinh") 168 | DEF(Sogdian, "Sogd") 169 | DEF(Sora_Sompeng, "Sora") 170 | DEF(Soyombo, "Soyo") 171 | DEF(Sundanese, "Sund") 172 | DEF(Syloti_Nagri, "Sylo") 173 | DEF(Syriac, "Syrc") 174 | DEF(Tagalog, "Tglg") 175 | DEF(Tagbanwa, "Tagb") 176 | DEF(Tai_Le, "Tale") 177 | DEF(Tai_Tham, "Lana") 178 | DEF(Tai_Viet, "Tavt") 179 | DEF(Takri, "Takr") 180 | DEF(Tamil, "Taml") 181 | DEF(Tangut, "Tang") 182 | DEF(Telugu, "Telu") 183 | DEF(Thaana, "Thaa") 184 | DEF(Thai, "Thai") 185 | DEF(Tibetan, "Tibt") 186 | DEF(Tifinagh, "Tfng") 187 | DEF(Tirhuta, "Tirh") 188 | DEF(Ugaritic, "Ugar") 189 | DEF(Vai, "Vaii") 190 | DEF(Warang_Citi, "Wara") 191 | DEF(Yi, "Yiii") 192 | DEF(Zanabazar_Square, "Zanb") 193 | #endif 194 | 195 | #ifdef UNICODE_PROP_LIST 196 | /* Prop list not exported to regexp */ 197 | DEF(Hyphen, "") 198 | DEF(Other_Math, "") 199 | DEF(Other_Alphabetic, "") 200 | DEF(Other_Lowercase, "") 201 | DEF(Other_Uppercase, "") 202 | DEF(Other_Grapheme_Extend, "") 203 | DEF(Other_Default_Ignorable_Code_Point, "") 204 | DEF(Other_ID_Start, "") 205 | DEF(Other_ID_Continue, "") 206 | DEF(Prepended_Concatenation_Mark, "") 207 | /* additional computed properties for smaller tables */ 208 | DEF(ID_Continue1, "") 209 | DEF(XID_Start1, "") 210 | DEF(XID_Continue1, "") 211 | DEF(Changes_When_Titlecased1, "") 212 | DEF(Changes_When_Casefolded1, "") 213 | DEF(Changes_When_NFKC_Casefolded1, "") 214 | 215 | /* Prop list exported to JS */ 216 | DEF(ASCII_Hex_Digit, "AHex") 217 | DEF(Bidi_Control, "Bidi_C") 218 | DEF(Dash, "") 219 | DEF(Deprecated, "Dep") 220 | DEF(Diacritic, "Dia") 221 | DEF(Extender, "Ext") 222 | DEF(Hex_Digit, "Hex") 223 | DEF(IDS_Binary_Operator, "IDSB") 224 | DEF(IDS_Trinary_Operator, "IDST") 225 | DEF(Ideographic, "Ideo") 226 | DEF(Join_Control, "Join_C") 227 | DEF(Logical_Order_Exception, "LOE") 228 | DEF(Noncharacter_Code_Point, "NChar") 229 | DEF(Pattern_Syntax, "Pat_Syn") 230 | DEF(Pattern_White_Space, "Pat_WS") 231 | DEF(Quotation_Mark, "QMark") 232 | DEF(Radical, "") 233 | DEF(Regional_Indicator, "RI") 234 | DEF(Sentence_Terminal, "STerm") 235 | DEF(Soft_Dotted, "SD") 236 | DEF(Terminal_Punctuation, "Term") 237 | DEF(Unified_Ideograph, "UIdeo") 238 | DEF(Variation_Selector, "VS") 239 | DEF(White_Space, "space") 240 | DEF(Bidi_Mirrored, "Bidi_M") 241 | DEF(Emoji, "") 242 | DEF(Emoji_Component, "") 243 | DEF(Emoji_Modifier, "") 244 | DEF(Emoji_Modifier_Base, "") 245 | DEF(Emoji_Presentation, "") 246 | DEF(Extended_Pictographic, "") 247 | DEF(Default_Ignorable_Code_Point, "DI") 248 | DEF(ID_Start, "IDS") 249 | DEF(Case_Ignorable, "CI") 250 | 251 | /* other binary properties */ 252 | DEF(ASCII,"") 253 | DEF(Alphabetic, "Alpha") 254 | DEF(Any, "") 255 | DEF(Assigned,"") 256 | DEF(Cased, "") 257 | DEF(Changes_When_Casefolded, "CWCF") 258 | DEF(Changes_When_Casemapped, "CWCM") 259 | DEF(Changes_When_Lowercased, "CWL") 260 | DEF(Changes_When_NFKC_Casefolded, "CWKCF") 261 | DEF(Changes_When_Titlecased, "CWT") 262 | DEF(Changes_When_Uppercased, "CWU") 263 | DEF(Grapheme_Base, "Gr_Base") 264 | DEF(Grapheme_Extend, "Gr_Ext") 265 | DEF(ID_Continue, "IDC") 266 | DEF(Lowercase, "Lower") 267 | DEF(Math, "") 268 | DEF(Uppercase, "Upper") 269 | DEF(XID_Continue, "XIDC") 270 | DEF(XID_Start, "XIDS") 271 | 272 | /* internal tables with index */ 273 | DEF(Cased1, "") 274 | 275 | #endif 276 | --------------------------------------------------------------------------------