rebase on nextgen
Some checks are pending
ci / Linux (Ubuntu) (push) Waiting to run
ci / linux-asan (push) Waiting to run
ci / linux-msan (push) Waiting to run
ci / linux-ubsan (push) Waiting to run
ci / macOS (push) Waiting to run
ci / macos-asan (push) Waiting to run
ci / macos-ubsan (push) Waiting to run
ci / freebsd (push) Waiting to run
ci / qemu-alpine (arm32v6) (push) Waiting to run
ci / qemu-alpine (arm32v7) (push) Waiting to run
ci / qemu-alpine (arm64v8) (push) Waiting to run
ci / qemu-alpine (i386) (push) Waiting to run
ci / qemu-alpine (s390x) (push) Waiting to run

This commit is contained in:
Arma-Damna-Dillo 2025-01-06 14:48:15 -06:00
parent c12360ba55
commit e18d08e951
136 changed files with 41686 additions and 26124 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

403
CMakeLists.txt Normal file
View file

@ -0,0 +1,403 @@
cmake_minimum_required(VERSION 3.10)
project(quickjs LANGUAGES C)
include(CheckCCompilerFlag)
include(GNUInstallDirs)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_C_STANDARD 11)
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
endif()
message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode")
message(STATUS "Building with ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION} on ${CMAKE_SYSTEM}")
macro(xcheck_add_c_compiler_flag FLAG)
string(REPLACE "-" "" FLAG_NO_HYPHEN ${FLAG})
check_c_compiler_flag(${FLAG} COMPILER_SUPPORTS_${FLAG_NO_HYPHEN})
if(COMPILER_SUPPORTS_${FLAG_NO_HYPHEN})
add_compile_options(${FLAG})
endif()
endmacro()
xcheck_add_c_compiler_flag(-Wall)
if(NOT MSVC AND NOT IOS)
xcheck_add_c_compiler_flag(-Werror)
xcheck_add_c_compiler_flag(-Wextra)
endif()
xcheck_add_c_compiler_flag(-Wno-implicit-fallthrough)
xcheck_add_c_compiler_flag(-Wno-sign-compare)
xcheck_add_c_compiler_flag(-Wno-missing-field-initializers)
xcheck_add_c_compiler_flag(-Wno-unused-parameter)
xcheck_add_c_compiler_flag(-Wno-unused-but-set-variable)
xcheck_add_c_compiler_flag(-Wno-array-bounds)
xcheck_add_c_compiler_flag(-Wno-format-truncation)
xcheck_add_c_compiler_flag(-funsigned-char)
# ClangCL is command line compatible with MSVC, so 'MSVC' is set.
if(MSVC)
xcheck_add_c_compiler_flag(-Wno-unsafe-buffer-usage)
xcheck_add_c_compiler_flag(-Wno-sign-conversion)
xcheck_add_c_compiler_flag(-Wno-nonportable-system-include-path)
xcheck_add_c_compiler_flag(-Wno-implicit-int-conversion)
xcheck_add_c_compiler_flag(-Wno-shorten-64-to-32)
xcheck_add_c_compiler_flag(-Wno-reserved-macro-identifier)
xcheck_add_c_compiler_flag(-Wno-reserved-identifier)
xcheck_add_c_compiler_flag(-Wdeprecated-declarations)
xcheck_add_c_compiler_flag(/experimental:c11atomics)
xcheck_add_c_compiler_flag(/wd4018) # -Wno-sign-conversion
xcheck_add_c_compiler_flag(/wd4061) # -Wno-implicit-fallthrough
xcheck_add_c_compiler_flag(/wd4100) # -Wno-unused-parameter
xcheck_add_c_compiler_flag(/wd4200) # -Wno-zero-length-array
xcheck_add_c_compiler_flag(/wd4242) # -Wno-shorten-64-to-32
xcheck_add_c_compiler_flag(/wd4244) # -Wno-shorten-64-to-32
xcheck_add_c_compiler_flag(/wd4245) # -Wno-sign-compare
xcheck_add_c_compiler_flag(/wd4267) # -Wno-shorten-64-to-32
xcheck_add_c_compiler_flag(/wd4388) # -Wno-sign-compare
xcheck_add_c_compiler_flag(/wd4389) # -Wno-sign-compare
xcheck_add_c_compiler_flag(/wd4710) # Function not inlined
xcheck_add_c_compiler_flag(/wd4711) # Function was inlined
xcheck_add_c_compiler_flag(/wd4820) # Padding added after construct
xcheck_add_c_compiler_flag(/wd4996) # -Wdeprecated-declarations
xcheck_add_c_compiler_flag(/wd5045) # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
endif()
# MacOS and GCC 11 or later need -Wno-maybe-uninitialized
# https://github.com/quickjs-ng/quickjs/issues/453
if(APPLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11)
xcheck_add_c_compiler_flag(-Wno-maybe-uninitialized)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "WASI")
add_compile_definitions(
_WASI_EMULATED_PROCESS_CLOCKS
_WASI_EMULATED_SIGNAL
)
add_link_options(
-lwasi-emulated-process-clocks
-lwasi-emulated-signal
)
endif()
if(CMAKE_BUILD_TYPE MATCHES "Debug")
add_compile_options(-O0)
xcheck_add_c_compiler_flag(-ggdb)
xcheck_add_c_compiler_flag(-fno-omit-frame-pointer)
endif()
macro(xoption OPTION_NAME OPTION_TEXT OPTION_DEFAULT)
option(${OPTION_NAME} ${OPTION_TEXT} ${OPTION_DEFAULT})
if(DEFINED ENV{${OPTION_NAME}})
# Allow setting the option through an environment variable.
set(${OPTION_NAME} $ENV{${OPTION_NAME}})
endif()
if(${OPTION_NAME})
add_definitions(-D${OPTION_NAME})
endif()
message(STATUS " ${OPTION_NAME}: ${${OPTION_NAME}}")
endmacro()
xoption(BUILD_SHARED_LIBS "Build a shared library" OFF)
if(BUILD_SHARED_LIBS)
message(STATUS "Building a shared library")
endif()
# note: CONFIG_TSAN is currently incompatible with the other sanitizers but we
# don't explicitly check for that because who knows what the future will bring?
# CONFIG_MSAN only works with clang at the time of writing; also not checked
# for the same reason
xoption(BUILD_EXAMPLES "Build examples" OFF)
xoption(BUILD_STATIC_QJS_EXE "Build a static qjs executable" OFF)
xoption(BUILD_CLI_WITH_MIMALLOC "Build the qjs executable with mimalloc" OFF)
xoption(BUILD_CLI_WITH_STATIC_MIMALLOC "Build the qjs executable with mimalloc (statically linked)" OFF)
xoption(CONFIG_ASAN "Enable AddressSanitizer (ASan)" OFF)
xoption(CONFIG_MSAN "Enable MemorySanitizer (MSan)" OFF)
xoption(CONFIG_TSAN "Enable ThreadSanitizer (TSan)" OFF)
xoption(CONFIG_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF)
if(CONFIG_ASAN)
message(STATUS "Building with ASan")
add_compile_options(
-fsanitize=address
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
add_link_options(
-fsanitize=address
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
endif()
if(CONFIG_MSAN)
message(STATUS "Building with MSan")
add_compile_options(
-fsanitize=memory
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
add_link_options(
-fsanitize=memory
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
endif()
if(CONFIG_TSAN)
message(STATUS "Building with TSan")
add_compile_options(
-fsanitize=thread
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
add_link_options(
-fsanitize=thread
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
endif()
if(CONFIG_UBSAN)
message(STATUS "Building with UBSan")
add_compile_options(
-fsanitize=undefined
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
add_link_options(
-fsanitize=undefined
-fno-sanitize-recover=all
-fno-omit-frame-pointer
)
endif()
# QuickJS library
#
xoption(BUILD_QJS_LIBC "Build standard library modules as part of the library" OFF)
macro(add_qjs_libc_if_needed target)
if(NOT BUILD_QJS_LIBC)
target_sources(${target} PRIVATE quickjs-libc.c)
endif()
endmacro()
set(qjs_sources
cutils.c
libbf.c
libregexp.c
libunicode.c
quickjs.c
)
if(BUILD_QJS_LIBC)
list(APPEND qjs_sources quickjs-libc.c)
endif()
list(APPEND qjs_defines _GNU_SOURCE)
if(WIN32)
list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602)
endif()
list(APPEND qjs_libs ${CMAKE_DL_LIBS})
find_package(Threads)
if(NOT CMAKE_SYSTEM_NAME STREQUAL "WASI")
list(APPEND qjs_libs ${CMAKE_THREAD_LIBS_INIT})
endif()
# try to find libm
find_library(M_LIBRARIES m)
if(M_LIBRARIES OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC")
list(APPEND qjs_libs m)
endif()
add_library(qjs ${qjs_sources})
target_compile_definitions(qjs PRIVATE ${qjs_defines})
target_include_directories(qjs PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(qjs PUBLIC ${qjs_libs})
if(EMSCRIPTEN)
add_executable(qjs_wasm ${qjs_sources})
target_link_options(qjs_wasm PRIVATE
# in emscripten 3.x, this will be set to 16k which is too small for quickjs. #write sth. to force github rebuild
-sSTACK_SIZE=2097152 # let it be 2m = 2 * 1024 * 1024 = 2097152, otherwise, stack overflow may be occured at bootstrap
-sNO_INVOKE_RUN
-sNO_EXIT_RUNTIME
-sMODULARIZE # do not mess the global
-sEXPORT_ES6 # export js file to morden es module
-sEXPORT_NAME=getQuickJs # give a name
-sTEXTDECODER=1 # it will be 2 if we use -Oz, and that will cause js -> c string convertion fail
-sNO_DEFAULT_TO_CXX # this project is pure c project, no need for c plus plus handle
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap
)
target_compile_definitions(qjs_wasm PRIVATE ${qjs_defines})
target_link_libraries(qjs_wasm m)
endif()
# QuickJS bytecode compiler
#
add_executable(qjsc
qjsc.c
)
add_qjs_libc_if_needed(qjsc)
target_compile_definitions(qjsc PRIVATE ${qjs_defines})
target_link_libraries(qjsc qjs)
# QuickJS CLI
#
add_executable(qjs_exe
gen/repl.c
gen/standalone.c
qjs.c
)
add_qjs_libc_if_needed(qjs_exe)
set_target_properties(qjs_exe PROPERTIES
OUTPUT_NAME "qjs"
)
target_compile_definitions(qjs_exe PRIVATE ${qjs_defines})
target_link_libraries(qjs_exe qjs)
if(BUILD_STATIC_QJS_EXE OR MINGW)
target_link_options(qjs_exe PRIVATE -static)
if(MINGW)
target_link_options(qjs_exe PRIVATE -static-libgcc)
endif()
endif()
if(NOT WIN32)
set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE)
endif()
if(BUILD_CLI_WITH_MIMALLOC OR BUILD_CLI_WITH_STATIC_MIMALLOC)
find_package(mimalloc REQUIRED)
# Upstream mimalloc doesn't provide a way to know if both libraries are supported.
if(BUILD_CLI_WITH_STATIC_MIMALLOC)
target_link_libraries(qjs_exe mimalloc-static)
else()
target_link_libraries(qjs_exe mimalloc)
endif()
endif()
# Test262 runner
#
if(NOT EMSCRIPTEN)
add_executable(run-test262
run-test262.c
)
add_qjs_libc_if_needed(run-test262)
target_compile_definitions(run-test262 PRIVATE ${qjs_defines})
target_link_libraries(run-test262 qjs)
endif()
# Unicode generator
#
add_executable(unicode_gen EXCLUDE_FROM_ALL
cutils.c
libunicode.c
unicode_gen.c
)
target_compile_definitions(unicode_gen PRIVATE ${qjs_defines})
add_executable(function_source
gen/function_source.c
)
add_qjs_libc_if_needed(function_source)
target_include_directories(function_source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(function_source PRIVATE ${qjs_defines})
target_link_libraries(function_source qjs)
# Examples
#
if(BUILD_EXAMPLES)
add_executable(hello
gen/hello.c
)
add_qjs_libc_if_needed(hello)
target_include_directories(hello PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(hello PRIVATE ${qjs_defines})
target_link_libraries(hello qjs)
add_executable(hello_module
gen/hello_module.c
)
add_qjs_libc_if_needed(hello_module)
target_include_directories(hello_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(hello_module PRIVATE ${qjs_defines})
target_link_libraries(hello_module qjs)
add_library(fib MODULE examples/fib.c)
set_target_properties(fib PROPERTIES
PREFIX ""
C_VISIBILITY_PRESET default
)
target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY)
if(WIN32)
target_link_libraries(fib qjs)
elseif(APPLE)
target_link_options(fib PRIVATE -undefined dynamic_lookup)
endif()
add_library(point MODULE examples/point.c)
set_target_properties(point PROPERTIES
PREFIX ""
C_VISIBILITY_PRESET default
)
target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY)
if(WIN32)
target_link_libraries(point qjs)
elseif(APPLE)
target_link_options(point PRIVATE -undefined dynamic_lookup)
endif()
add_executable(test_fib
examples/fib.c
gen/test_fib.c
)
add_qjs_libc_if_needed(test_fib)
target_include_directories(test_fib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(test_fib PRIVATE ${qjs_defines})
target_link_libraries(test_fib qjs)
endif()
add_executable(test_conv
tests/test_conv.c
)
# Install target
#
if(NOT IOS)
file(STRINGS quickjs.h quickjs_h REGEX QJS_VERSION)
string(REGEX MATCHALL "([0-9])" QJS_VERSION "${quickjs_h}")
list(GET QJS_VERSION 0 QJS_VERSION_MAJOR)
list(GET QJS_VERSION 1 QJS_VERSION_MINOR)
list(GET QJS_VERSION 2 QJS_VERSION_PATCH)
set_target_properties(qjs PROPERTIES
VERSION ${QJS_VERSION_MAJOR}.${QJS_VERSION_MINOR}.${QJS_VERSION_PATCH}
SOVERSION ${QJS_VERSION_MAJOR}
)
install(FILES quickjs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if(BUILD_QJS_LIBC)
install(FILES quickjs-libc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()
install(TARGETS qjs_exe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS qjsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS qjs EXPORT qjsConfig
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(EXPORT qjsConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/quickjs)
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
install(DIRECTORY examples DESTINATION ${CMAKE_INSTALL_DOCDIR})
endif()

175
Changelog
View file

@ -1,175 +0,0 @@
2024-01-13:
- top-level-await support in modules
- allow 'await' in the REPL
- added Array.prototype.{with,toReversed,toSpliced,toSorted} and
TypedArray.prototype.{with,toReversed,toSorted}
- added String.prototype.isWellFormed and String.prototype.toWellFormed
- added Object.groupBy and Map.groupBy
- added Promise.withResolvers
- class static block
- 'in' operator support for private fields
- optional chaining fixes
- added RegExp 'd' flag
- fixed RegExp zero length match logic
- fixed RegExp case insensitive flag
- added os.getpid() and os.now()
- added cosmopolitan build
- misc bug fixes
2023-12-09:
- added Object.hasOwn, {String|Array|TypedArray}.prototype.at,
{Array|TypedArray}.prototype.findLast{Index}
- BigInt support is enabled even if CONFIG_BIGNUM disabled
- updated to Unicode 15.0.0
- misc bug fixes
2021-03-27:
- faster Array.prototype.push and Array.prototype.unshift
- added JS_UpdateStackTop()
- fixed Windows console
- misc bug fixes
2020-11-08:
- improved function parameter initializers
- added std.setenv(), std.unsetenv() and std.getenviron()
- added JS_EvalThis()
- misc bug fixes
2020-09-06:
- added logical assignment operators
- added IsHTMLDDA support
- faster for-of loops
- os.Worker now takes a module filename as parameter
- qjsc: added -D option to compile dynamically loaded modules or workers
- misc bug fixes
2020-07-05:
- modified JS_GetPrototype() to return a live value
- REPL: support unicode characters larger than 16 bits
- added os.Worker
- improved object serialization
- added std.parseExtJSON
- misc bug fixes
2020-04-12:
- added cross realm support
- added AggregateError and Promise.any
- added env, uid and gid options in os.exec()
- misc bug fixes
2020-03-16:
- reworked error handling in std and os libraries: suppressed I/O
exceptions in std FILE functions and return a positive errno value
when it is explicit
- output exception messages to stderr
- added std.loadFile(), std.strerror(), std.FILE.prototype.tello()
- added JS_GetRuntimeOpaque(), JS_SetRuntimeOpaque(), JS_NewUint32()
- updated to Unicode 13.0.0
- misc bug fixes
2020-01-19:
- keep CONFIG_BIGNUM in the makefile
- added os.chdir()
- qjs: added -I option
- more memory checks in the bignum operations
- modified operator overloading semantics to be closer to the TC39
proposal
- suppressed "use bigint" mode. Simplified "use math" mode
- BigDecimal: changed suffix from 'd' to 'm'
- misc bug fixes
2020-01-05:
- always compile the bignum code. Added '--bignum' option to qjs.
- added BigDecimal
- added String.prototype.replaceAll
- misc bug fixes
2019-12-21:
- added nullish coalescing operator (ES2020)
- added optional chaining (ES2020)
- removed recursions in garbage collector
- test stack overflow in the parser
- improved backtrace logic
- added JS_SetHostPromiseRejectionTracker()
- allow exotic constructors
- improved c++ compatibility
- misc bug fixes
2019-10-27:
- added example of C class in a module (examples/test_point.js)
- added JS_GetTypedArrayBuffer()
- misc bug fixes
2019-09-18:
- added os.exec and other system calls
- exported JS_ValueToAtom()
- qjsc: added 'qjsc_' prefix to the generated C identifiers
- added cross-compilation support
- misc bug fixes
2019-09-01:
- added globalThis
- documented JS_EVAL_FLAG_COMPILE_ONLY
- added import.meta.url and import.meta.main
- added 'debugger' statement
- misc bug fixes
2019-08-18:
- added os.realpath, os.getcwd, os.mkdir, os.stat, os.lstat,
os.readlink, os.readdir, os.utimes, std.popen
- module autodetection
- added import.meta
- misc bug fixes
2019-08-10:
- added public class fields and private class fields, methods and
accessors (TC39 proposal)
- changed JS_ToCStringLen() prototype
- qjsc: handle '-' in module names and modules with the same filename
- added std.urlGet
- exported JS_GetOwnPropertyNames() and JS_GetOwnProperty()
- exported some bigint C functions
- added support for eshost in run-test262
- misc bug fixes
2019-07-28:
- added dynamic import
- added Promise.allSettled
- added String.prototype.matchAll
- added Object.fromEntries
- reduced number of ticks in await
- added BigInt support in Atomics
- exported JS_NewPromiseCapability()
- misc async function and async generator fixes
- enabled hashbang support by default
2019-07-21:
- updated test262 tests
- updated to Unicode version 12.1.0
- fixed missing Date object in qjsc
- fixed multi-context creation
- misc ES2020 related fixes
- simplified power and division operators in bignum extension
- fixed several crash conditions
2019-07-09:
- first public release

View file

@ -1,6 +1,8 @@
QuickJS Javascript Engine (DoneJS Edition)
Copyright (c) 2024 Sneed Group
Copyright (c) 2025 Sneed Group
Copyright (c) 2023 Ben Noordhuis
Copyright (c) 2023 Saúl Ibarra Corretgé
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon

511
Makefile
View file

@ -3,6 +3,8 @@
#
# Copyright (c) 2017-2021 Fabrice Bellard
# Copyright (c) 2017-2021 Charlie Gordon
# Copyright (c) 2023 Ben Noordhuis
# Copyright (c) 2023 Saúl Ibarra Corretgé
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@ -22,466 +24,103 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
ifeq ($(shell uname -s),Darwin)
CONFIG_DARWIN=y
BUILD_DIR=build
BUILD_TYPE?=Release
INSTALL_PREFIX?=/usr/local
QJS=$(BUILD_DIR)/qjs
QJSC=$(BUILD_DIR)/qjsc
RUN262=$(BUILD_DIR)/run-test262
JOBS?=$(shell getconf _NPROCESSORS_ONLN)
ifeq ($(JOBS),)
JOBS := $(shell sysctl -n hw.ncpu)
endif
# Windows cross compilation from Linux
#CONFIG_WIN32=y
# use link time optimization (smaller and faster executables but slower build)
CONFIG_LTO=y
# consider warnings as errors (for development)
#CONFIG_WERROR=y
# force 32 bit build for some utilities
#CONFIG_M32=y
# cosmopolitan build (see https://github.com/jart/cosmopolitan)
#CONFIG_COSMO=y
# installation directory
PREFIX?=/usr/local
# use the gprof profiler
#CONFIG_PROFILE=y
# use address sanitizer
#CONFIG_ASAN=y
# include the code for BigFloat/BigDecimal, math mode and faster large integers
CONFIG_BIGNUM=y
OBJDIR=.obj
ifdef CONFIG_DARWIN
# use clang instead of gcc
CONFIG_CLANG=y
CONFIG_DEFAULT_AR=y
ifeq ($(JOBS),)
JOBS := $(shell nproc)
endif
ifeq ($(JOBS),)
JOBS := 4
endif
ifdef CONFIG_WIN32
ifdef CONFIG_M32
CROSS_PREFIX?=i686-w64-mingw32-
else
CROSS_PREFIX?=x86_64-w64-mingw32-
endif
EXE=.exe
else
CROSS_PREFIX?=
EXE=
endif
all: $(QJS)
ifdef CONFIG_CLANG
HOST_CC=clang
CC=$(CROSS_PREFIX)clang
CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wextra
CFLAGS += -Wno-sign-compare
CFLAGS += -Wno-missing-field-initializers
CFLAGS += -Wundef -Wuninitialized
CFLAGS += -Wunused -Wno-unused-parameter
CFLAGS += -Wwrite-strings
CFLAGS += -Wchar-subscripts -funsigned-char
CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d
ifdef CONFIG_DEFAULT_AR
AR=$(CROSS_PREFIX)ar
else
ifdef CONFIG_LTO
AR=$(CROSS_PREFIX)llvm-ar
else
AR=$(CROSS_PREFIX)ar
endif
endif
else ifdef CONFIG_COSMO
CONFIG_LTO=
HOST_CC=gcc
CC=cosmocc
# cosmocc does not correct support -MF
CFLAGS=-g -Wall #-MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wno-array-bounds -Wno-format-truncation
AR=cosmoar
else
HOST_CC=gcc
CC=$(CROSS_PREFIX)gcc
CFLAGS+=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wno-array-bounds -Wno-format-truncation
ifdef CONFIG_LTO
AR=$(CROSS_PREFIX)gcc-ar
else
AR=$(CROSS_PREFIX)ar
endif
endif
STRIP=$(CROSS_PREFIX)strip
CFLAGS+=-fwrapv # ensure that signed overflows behave as expected
ifdef CONFIG_WERROR
CFLAGS+=-Werror
endif
DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
ifdef CONFIG_BIGNUM
DEFINES+=-DCONFIG_BIGNUM
endif
ifdef CONFIG_WIN32
DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior
endif
fuzz:
clang -g -O1 -fsanitize=address,undefined,fuzzer -o fuzz fuzz.c
./fuzz
CFLAGS+=$(DEFINES)
CFLAGS_DEBUG=$(CFLAGS) -O0
CFLAGS_SMALL=$(CFLAGS) -Os
CFLAGS_OPT=$(CFLAGS) -O2
CFLAGS_NOLTO:=$(CFLAGS_OPT)
ifdef CONFIG_COSMO
LDFLAGS+=-s # better to strip by default
else
LDFLAGS+=-g
endif
ifdef CONFIG_LTO
CFLAGS_SMALL+=-flto
CFLAGS_OPT+=-flto
LDFLAGS+=-flto
endif
ifdef CONFIG_PROFILE
CFLAGS+=-p
LDFLAGS+=-p
endif
ifdef CONFIG_ASAN
CFLAGS+=-fsanitize=address -fno-omit-frame-pointer
LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer
endif
ifdef CONFIG_WIN32
LDEXPORT=
else
LDEXPORT=-rdynamic
endif
$(BUILD_DIR):
cmake -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX)
ifndef CONFIG_COSMO
ifndef CONFIG_DARWIN
CONFIG_SHARED_LIBS=y # building shared libraries is supported
endif
endif
$(QJS): $(BUILD_DIR)
cmake --build $(BUILD_DIR) -j $(JOBS)
PROGS=qjs$(EXE) qjsc$(EXE) run-test262
ifneq ($(CROSS_PREFIX),)
QJSC_CC=gcc
QJSC=./host-qjsc
PROGS+=$(QJSC)
else
QJSC_CC=$(CC)
QJSC=./qjsc$(EXE)
endif
ifndef CONFIG_WIN32
PROGS+=qjscalc
endif
ifdef CONFIG_M32
PROGS+=qjs32 qjs32_s
endif
PROGS+=libquickjs.a
ifdef CONFIG_LTO
PROGS+=libquickjs.lto.a
endif
$(QJSC): $(BUILD_DIR)
cmake --build $(BUILD_DIR) --target qjsc -j $(JOBS)
# examples
ifeq ($(CROSS_PREFIX),)
PROGS+=examples/hello
ifndef CONFIG_ASAN
PROGS+=examples/hello_module
endif
ifdef CONFIG_SHARED_LIBS
PROGS+=examples/test_fib examples/fib.so examples/point.so
endif
endif
$(BUILD_DIR)/test_conv: $(BUILD_DIR) tests/test_conv.c
cmake --build $(BUILD_DIR) --target test_conv
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o $(OBJDIR)/libbf.o
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
ifdef CONFIG_BIGNUM
QJS_OBJS+=$(OBJDIR)/qjscalc.o
endif
HOST_LIBS=-lm -ldl -lpthread
LIBS=-lm
ifndef CONFIG_WIN32
LIBS+=-ldl -lpthread
endif
LIBS+=$(EXTRA_LIBS)
$(OBJDIR):
mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
qjs$(EXE): $(QJS_OBJS)
$(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS))
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
ifneq ($(CROSS_PREFIX),)
$(QJSC): $(OBJDIR)/qjsc.host.o \
$(patsubst %.o, %.host.o, $(QJS_LIB_OBJS))
$(HOST_CC) $(LDFLAGS) -o $@ $^ $(HOST_LIBS)
endif #CROSS_PREFIX
QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(PREFIX)\"
ifdef CONFIG_LTO
QJSC_DEFINES+=-DCONFIG_LTO
endif
QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(PREFIX)\"
$(OBJDIR)/qjsc.o: CFLAGS+=$(QJSC_DEFINES)
$(OBJDIR)/qjsc.host.o: CFLAGS+=$(QJSC_HOST_DEFINES)
qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS))
$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS))
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
@size $@
qjscalc: qjs
ln -sf $< $@
ifdef CONFIG_LTO
LTOEXT=.lto
else
LTOEXT=
endif
libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS)
$(AR) rcs $@ $^
ifdef CONFIG_LTO
libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
$(AR) rcs $@ $^
endif # CONFIG_LTO
repl.c: $(QJSC) repl.js
$(QJSC) -c -o $@ -m repl.js
qjscalc.c: $(QJSC) qjscalc.js
$(QJSC) -fbignum -c -o $@ qjscalc.js
ifneq ($(wildcard unicode/UnicodeData.txt),)
$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
$(OBJDIR)/libunicode.nolto.o: libunicode-table.h
libunicode-table.h: unicode_gen
./unicode_gen unicode $@
endif
run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
# object suffix order: nolto, [m32|m32s]
$(OBJDIR)/%.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.host.o: %.c | $(OBJDIR)
$(HOST_CC) $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.pic.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $<
$(OBJDIR)/%.nolto.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_NOLTO) -c -o $@ $<
$(OBJDIR)/%.m32.o: %.c | $(OBJDIR)
$(CC) -m32 $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.m32s.o: %.c | $(OBJDIR)
$(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $<
$(OBJDIR)/%.debug.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_DEBUG) -c -o $@ $<
$(OBJDIR)/%.check.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $<
regexp_test: libregexp.c libunicode.c cutils.c
$(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS)
unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
install: $(QJS) $(QJSC)
cmake --build $(BUILD_DIR) --target install
clean:
rm -f repl.c qjscalc.c out.c
rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS)
rm -f hello.c test_fib.c
rm -f examples/*.so tests/*.so
rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
rm -rf run-test262-debug run-test262-32
cmake --build $(BUILD_DIR) --target clean
install: all
mkdir -p "$(DESTDIR)$(PREFIX)/bin"
$(STRIP) qjs qjsc
install -m755 qjs qjsc "$(DESTDIR)$(PREFIX)/bin"
ln -sf qjs "$(DESTDIR)$(PREFIX)/bin/qjscalc"
mkdir -p "$(DESTDIR)$(PREFIX)/lib/quickjs"
install -m644 libquickjs.a "$(DESTDIR)$(PREFIX)/lib/quickjs"
ifdef CONFIG_LTO
install -m644 libquickjs.lto.a "$(DESTDIR)$(PREFIX)/lib/quickjs"
endif
mkdir -p "$(DESTDIR)$(PREFIX)/include/quickjs"
install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(PREFIX)/include/quickjs"
codegen: $(QJSC)
$(QJSC) -ss -o gen/repl.c -m repl.js
$(QJSC) -ss -o gen/standalone.c -m standalone.js
$(QJSC) -e -o gen/function_source.c tests/function_source.js
$(QJSC) -e -o gen/hello.c examples/hello.js
$(QJSC) -e -o gen/hello_module.c -m examples/hello_module.js
$(QJSC) -e -o gen/test_fib.c -M examples/fib.so,fib -m examples/test_fib.js
###############################################################################
# examples
debug:
BUILD_TYPE=Debug $(MAKE)
# example of static JS compilation
HELLO_SRCS=examples/hello.js
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
-fno-date -fno-module-loader -fno-bigint
distclean:
@rm -rf $(BUILD_DIR)
hello.c: $(QJSC) $(HELLO_SRCS)
$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
stats: $(QJS)
$(QJS) -qd
ifdef CONFIG_M32
examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
else
examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
endif
# effectively .PHONY because it doesn't generate output
ctest: CFLAGS=-std=c11 -fsyntax-only -Wall -Wextra -Werror -pedantic
ctest: ctest.c quickjs.h
$(CC) $(CFLAGS) -DJS_NAN_BOXING=0 $<
$(CC) $(CFLAGS) -DJS_NAN_BOXING=1 $<
# example of static JS compilation with modules
HELLO_MODULE_SRCS=examples/hello_module.js
HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
-fno-date -m
examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS)
$(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS)
# effectively .PHONY because it doesn't generate output
cxxtest: CXXFLAGS=-std=c++11 -fsyntax-only -Wall -Wextra -Werror -pedantic
cxxtest: cxxtest.cc quickjs.h
$(CXX) $(CXXFLAGS) -DJS_NAN_BOXING=0 $<
$(CXX) $(CXXFLAGS) -DJS_NAN_BOXING=1 $<
# use of an external C module (static compilation)
test: $(QJS)
$(RUN262) -c tests.conf
test_fib.c: $(QJSC) examples/test_fib.js
$(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/test_fib.js
testconv: $(BUILD_DIR)/test_conv
$(BUILD_DIR)/test_conv
examples/test_fib: $(OBJDIR)/test_fib.o $(OBJDIR)/examples/fib.o libquickjs$(LTOEXT).a
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
test262: $(QJS)
$(RUN262) -m -c test262.conf -a
examples/fib.so: $(OBJDIR)/examples/fib.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^
test262-fast: $(QJS)
$(RUN262) -m -c test262.conf -c test262-fast.conf -a
examples/point.so: $(OBJDIR)/examples/point.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^
test262-update: $(QJS)
$(RUN262) -u -c test262.conf -a -t 1
###############################################################################
# documentation
test262-check: $(QJS)
$(RUN262) -m -c test262.conf -E -a
DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html
microbench: $(QJS)
$(QJS) tests/microbench.js
build_doc: $(DOCS)
unicode_gen: $(BUILD_DIR)
cmake --build $(BUILD_DIR) --target unicode_gen
clean_doc:
rm -f $(DOCS)
libunicode-table.h: unicode_gen
$(BUILD_DIR)/unicode_gen unicode $@
doc/%.pdf: doc/%.texi
texi2pdf --clean -o $@ -q $<
doc/%.html.pre: doc/%.texi
makeinfo --html --no-headers --no-split --number-sections -o $@ $<
doc/%.html: doc/%.html.pre
sed -e 's|</style>|</style>\n<meta name="viewport" content="width=device-width, initial-scale=1.0">|' < $< > $@
###############################################################################
# tests
ifdef CONFIG_SHARED_LIBS
test: tests/bjson.so examples/point.so
endif
ifdef CONFIG_M32
test: qjs32
endif
test: qjs
./qjs tests/test_closure.js
./qjs tests/test_language.js
./qjs tests/test_builtin.js
./qjs tests/test_loop.js
./qjs tests/test_std.js
./qjs tests/test_worker.js
ifdef CONFIG_SHARED_LIBS
ifdef CONFIG_BIGNUM
./qjs --bignum tests/test_bjson.js
else
./qjs tests/test_bjson.js
endif
./qjs examples/test_point.js
endif
ifdef CONFIG_BIGNUM
./qjs --bignum tests/test_op_overloading.js
./qjs --bignum tests/test_bignum.js
./qjs --qjscalc tests/test_qjscalc.js
endif
ifdef CONFIG_M32
./qjs32 tests/test_closure.js
./qjs32 tests/test_language.js
./qjs32 tests/test_builtin.js
./qjs32 tests/test_loop.js
./qjs32 tests/test_std.js
./qjs32 tests/test_worker.js
ifdef CONFIG_BIGNUM
./qjs32 --bignum tests/test_op_overloading.js
./qjs32 --bignum tests/test_bignum.js
./qjs32 --qjscalc tests/test_qjscalc.js
endif
endif
stats: qjs qjs32
./qjs -qd
./qjs32 -qd
microbench: qjs
./qjs tests/microbench.js
microbench-32: qjs32
./qjs32 tests/microbench.js
# ES5 tests (obsolete)
test2o: run-test262
time ./run-test262 -m -c test262o.conf
test2o-32: run-test262-32
time ./run-test262-32 -m -c test262o.conf
test2o-update: run-test262
./run-test262 -u -c test262o.conf
# Test262 tests
test2-default: run-test262
time ./run-test262 -m -c test262.conf
test2: run-test262
time ./run-test262 -m -c test262.conf -a
test2-32: run-test262-32
time ./run-test262-32 -m -c test262.conf -a
test2-update: run-test262
./run-test262 -u -c test262.conf -a
test2-check: run-test262
time ./run-test262 -m -c test262.conf -E -a
testall: all test microbench test2o test2
testall-32: all test-32 microbench-32 test2o-32 test2-32
testall-complete: testall testall-32
bench-v8: qjs
make -C tests/bench-v8
./qjs -d tests/bench-v8/combined.js
tests/bjson.so: $(OBJDIR)/tests/bjson.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS)
-include $(wildcard $(OBJDIR)/*.d)
.PHONY: all ctest cxxtest debug fuzz install clean codegen distclean stats test test262 test262-update test262-check microbench unicode_gen $(QJS) $(QJSC)

View file

@ -1,14 +1,24 @@
# QuickJS (DoneJS edition)
# ⚡️ QuickJS - A mighty JavaScript engine
An *unofficial* fork of QuickJS that contains polyfills and modifications to the source code to make it more like something such as NodeJS or De*no*.
## Overview
# FAQ
QuickJS is a small and embeddable JavaScript engine. It aims to support the latest
[ECMAScript] specification.
## Documentation Location
This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development.
The main documentation is in "doc/quickjs.pdf" for the PDF version or "doc/quickjs.html" for the HTML one.
## Getting started
Head over to the [project website] for instructions on how to get started and more
documentation.
## Location of Polyfills
## Authors
The polyfills are located in the "qjs.c" file.
[@bnoordhuis], [@saghul], and many more [contributors].
[ECMAScript]: https://tc39.es/ecma262/
[original QuickJS project]: https://bellard.org/quickjs
[@bnoordhuis]: https://github.com/bnoordhuis
[@saghul]: https://github.com/saghul
[contributors]: https://github.com/quickjs-ng/quickjs/graphs/contributors
[project website]: https://quickjs-ng.github.io/quickjs/

67
TODO
View file

@ -1,67 +0,0 @@
Misc ideas:
- use custom printf to avoid compatibility issues with floating point numbers
- consistent naming for preprocessor defines
- unify coding style and naming conventions
- use names from the ECMA spec in library implementation
- use byte code emitters with typed arguments (for clarity)
- use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing
and use the same wrappers in all phases
- use more generic method for line numbers in resolve_variables and resolve_labels
- use custom timezone support to avoid C library compatibility issues
Memory:
- use memory pools for objects, etc?
- test border cases for max number of atoms, object properties, string length
- add emergency malloc mode for out of memory exceptions.
- test all DynBuf memory errors
- test all js_realloc memory errors
- improve JS_ComputeMemoryUsage() with more info
Built-in standard library:
- BSD sockets
- modules: use realpath in module name normalizer and put it in quickjs-libc
- modules: if no ".", use a well known module loading path ?
- get rid of __loadScript, use more common name
REPL:
- debugger
- readline: support MS Windows terminal
- readline: handle dynamic terminal resizing
- readline: handle double width unicode characters
- multiline editing
- runtime object and function inspectors
- interactive object browser
- use more generic approach to display evaluation results
- improve directive handling: dispatch, colorize, completion...
- save history
- close all predefined methods in repl.js and jscalc.js
Optimization ideas:
- 64-bit atoms in 64-bit mode ?
- 64-bit small bigint in 64-bit mode ?
- reuse stack slots for disjoint scopes, if strip
- add heuristic to avoid some cycles in closures
- small String (0-2 charcodes) with immediate storage
- perform static string concatenation at compile time
- optimize string concatenation with ropes or miniropes?
- add implicit numeric strings for Uint32 numbers?
- optimize `s += a + b`, `s += a.b` and similar simple expressions
- ensure string canonical representation and optimise comparisons and hashes?
- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references
- property access optimization on the global object, functions,
prototypes and special non extensible objects.
- create object literals with the correct length by backpatching length argument
- remove redundant set_loc_uninitialized/check_uninitialized opcodes
- peephole optim: push_atom_value, to_propkey -> push_atom_value
- peephole optim: put_loc x, get_loc_check x -> set_loc x
- convert slow array to fast array when all properties != length are numeric
- optimize destructuring assignments for global and local variables
- implement some form of tail-call-optimization
- optimize OP_apply
- optimize f(...b)
Test262o: 0/11262 errors, 463 excluded
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
Result: 10/76947 errors, 1497 excluded, 8117 skipped
Test262 commit: 6cbb6da9473c56d95358d8e679c5a6d2b4574efb

View file

@ -1 +0,0 @@
2024-01-13

View file

@ -1,6 +0,0 @@
#include <unistd.h>
int main(void) {
closefrom(3);
return 0;
}

17
ctest.c Normal file
View file

@ -0,0 +1,17 @@
// note: file is not actually compiled, only checked for C syntax errors
#include "quickjs.h"
int main(void)
{
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
JS_FreeValue(ctx, JS_NAN);
JS_FreeValue(ctx, JS_UNDEFINED);
JS_FreeValue(ctx, JS_NewFloat64(ctx, 42));
// not a legal way of using JS_MKPTR but this is here
// to have the compiler syntax-check its definition
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_UNINITIALIZED, 0));
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}

1004
cutils.c

File diff suppressed because it is too large Load diff

394
cutils.h
View file

@ -26,31 +26,95 @@
#define CUTILS_H
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
/* set if CPU is big endian */
#undef WORDS_BIGENDIAN
#ifdef __cplusplus
extern "C" {
#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
#define __maybe_unused __attribute__((unused))
#if defined(_MSC_VER)
#include <winsock2.h>
#include <malloc.h>
#define alloca _alloca
#define ssize_t ptrdiff_t
#endif
#if defined(__APPLE__)
#include <malloc/malloc.h>
#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__)
#include <malloc.h>
#elif defined(__FreeBSD__)
#include <malloc_np.h>
#elif defined(_WIN32)
#include <windows.h>
#endif
#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__)
#include <errno.h>
#include <pthread.h>
#endif
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#if defined(_MSC_VER) && !defined(__clang__)
# define likely(x) (x)
# define unlikely(x) (x)
# define force_inline __forceinline
# define no_inline __declspec(noinline)
# define __maybe_unused
# define __attribute__(x)
# define __attribute(x)
# include <intrin.h>
static void *__builtin_frame_address(unsigned int level) {
return (void *)((char*)_AddressOfReturnAddress() - sizeof(int *) - level * sizeof(int *));
}
#else
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
# define force_inline inline __attribute__((always_inline))
# define no_inline __attribute__((noinline))
# define __maybe_unused __attribute__((unused))
#endif
// https://stackoverflow.com/a/6849629
#undef FORMAT_STRING
#if _MSC_VER >= 1400
# include <sal.h>
# if _MSC_VER > 1400
# define FORMAT_STRING(p) _Printf_format_string_ p
# else
# define FORMAT_STRING(p) __format_string p
# endif /* FORMAT_STRING */
#else
# define FORMAT_STRING(p) p
#endif /* _MSC_VER */
#if defined(_MSC_VER) && !defined(__clang__)
#include <math.h>
#define INF INFINITY
#define NEG_INF -INFINITY
#else
#define INF (1.0/0.0)
#define NEG_INF (-1.0/0.0)
#endif
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#ifndef endof
#define endof(x) ((x) + countof(x))
#endif
#endif
#ifndef container_of
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
#endif
#if defined(_MSC_VER)
#define minimum_length(n) n
#else
#define minimum_length(n) static n
#endif
typedef int BOOL;
@ -61,10 +125,18 @@ enum {
};
#endif
void pstrcpy(char *buf, int buf_size, const char *str);
char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int has_suffix(const char *str, const char *suffix);
void js__pstrcpy(char *buf, int buf_size, const char *str);
char *js__pstrcat(char *buf, int buf_size, const char *s);
int js__strstart(const char *str, const char *val, const char **ptr);
int js__has_suffix(const char *str, const char *suffix);
static inline uint8_t is_be(void) {
union {
uint16_t a;
uint8_t b;
} u = { 0x100 };
return u.b;
}
static inline int max_int(int a, int b)
{
@ -117,82 +189,113 @@ static inline int64_t min_int64(int64_t a, int64_t b)
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanReverse(&index, a);
return 31 - index;
#else
return __builtin_clz(a);
#endif
}
/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
#if defined(_MSC_VER) && !defined(__clang__)
#if INTPTR_MAX == INT64_MAX
unsigned long index;
_BitScanReverse64(&index, a);
return 63 - index;
#else
if (a >> 32)
return clz32((unsigned)(a >> 32));
else
return clz32((unsigned)a) + 32;
#endif
#else
return __builtin_clzll(a);
#endif
}
/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanForward(&index, a);
return index;
#else
return __builtin_ctz(a);
#endif
}
/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanForward64(&index, a);
return index;
#else
return __builtin_ctzll(a);
#endif
}
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
struct __attribute__((packed)) packed_u32 {
uint32_t v;
};
struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
static inline uint64_t get_u64(const uint8_t *tab)
{
return ((const struct packed_u64 *)tab)->v;
uint64_t v;
memcpy(&v, tab, sizeof(v));
return v;
}
static inline int64_t get_i64(const uint8_t *tab)
{
return (int64_t)((const struct packed_u64 *)tab)->v;
int64_t v;
memcpy(&v, tab, sizeof(v));
return v;
}
static inline void put_u64(uint8_t *tab, uint64_t val)
{
((struct packed_u64 *)tab)->v = val;
memcpy(tab, &val, sizeof(val));
}
static inline uint32_t get_u32(const uint8_t *tab)
{
return ((const struct packed_u32 *)tab)->v;
uint32_t v;
memcpy(&v, tab, sizeof(v));
return v;
}
static inline int32_t get_i32(const uint8_t *tab)
{
return (int32_t)((const struct packed_u32 *)tab)->v;
int32_t v;
memcpy(&v, tab, sizeof(v));
return v;
}
static inline void put_u32(uint8_t *tab, uint32_t val)
{
((struct packed_u32 *)tab)->v = val;
memcpy(tab, &val, sizeof(val));
}
static inline uint32_t get_u16(const uint8_t *tab)
{
return ((const struct packed_u16 *)tab)->v;
uint16_t v;
memcpy(&v, tab, sizeof(v));
return v;
}
static inline int32_t get_i16(const uint8_t *tab)
{
return (int16_t)((const struct packed_u16 *)tab)->v;
int16_t v;
memcpy(&v, tab, sizeof(v));
return v;
}
static inline void put_u16(uint8_t *tab, uint16_t val)
{
((struct packed_u16 *)tab)->v = val;
memcpy(tab, &val, sizeof(val));
}
static inline uint32_t get_u8(const uint8_t *tab)
@ -210,17 +313,22 @@ static inline void put_u8(uint8_t *tab, uint8_t val)
*tab = val;
}
#ifndef bswap16
static inline uint16_t bswap16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
#endif
#ifndef bswap32
static inline uint32_t bswap32(uint32_t v)
{
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
}
#endif
#ifndef bswap64
static inline uint64_t bswap64(uint64_t v)
{
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
@ -232,6 +340,90 @@ static inline uint64_t bswap64(uint64_t v)
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
#endif
static inline void inplace_bswap16(uint8_t *tab) {
put_u16(tab, bswap16(get_u16(tab)));
}
static inline void inplace_bswap32(uint8_t *tab) {
put_u32(tab, bswap32(get_u32(tab)));
}
static inline double fromfp16(uint16_t v) {
double d, s;
int e;
if ((v & 0x7C00) == 0x7C00) {
d = (v & 0x3FF) ? NAN : INFINITY;
} else {
d = (v & 0x3FF) / 1024.;
e = (v & 0x7C00) >> 10;
if (e == 0) {
e = -14;
} else {
d += 1;
e -= 15;
}
d = scalbn(d, e);
}
s = (v & 0x8000) ? -1.0 : 1.0;
return d * s;
}
static inline uint16_t tofp16(double d) {
uint16_t f, s;
double t;
int e;
s = 0;
if (copysign(1, d) < 0) { // preserve sign when |d| is negative zero
d = -d;
s = 0x8000;
}
if (isinf(d))
return s | 0x7C00;
if (isnan(d))
return s | 0x7C01;
if (d == 0)
return s | 0;
d = 2 * frexp(d, &e);
e--;
if (e > 15)
return s | 0x7C00; // out of range, return +/-infinity
if (e < -25) {
d = 0;
e = 0;
} else if (e < -14) {
d = scalbn(d, e + 14);
e = 0;
} else {
d -= 1;
e += 15;
}
d *= 1024.;
f = (uint16_t)d;
t = d - f;
if (t < 0.5)
goto done;
if (t == 0.5)
if ((f & 1) == 0)
goto done;
// adjust for rounding
if (++f == 1024) {
f = 0;
if (++e == 31)
return s | 0x7C00; // out of range, return +/-infinity
}
done:
return s | (e << 10) | f;
}
static inline int isfp16nan(uint16_t v) {
return (v & 0x7FFF) > 0x7C00;
}
static inline int isfp16zero(uint16_t v) {
return (v & 0x7FFF) == 0;
}
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
@ -248,8 +440,8 @@ typedef struct DynBuf {
void dbuf_init(DynBuf *s);
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
int dbuf_realloc(DynBuf *s, size_t new_size);
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len);
int dbuf_put(DynBuf *s, const void *data, size_t len);
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
int dbuf_putc(DynBuf *s, uint8_t c);
int dbuf_putstr(DynBuf *s, const char *str);
@ -266,7 +458,7 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
return dbuf_put(s, (uint8_t *)&val, 8);
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...);
FORMAT_STRING(const char *fmt), ...);
void dbuf_free(DynBuf *s);
static inline BOOL dbuf_error(DynBuf *s) {
return s->error;
@ -276,10 +468,56 @@ static inline void dbuf_set_error(DynBuf *s)
s->error = TRUE;
}
#define UTF8_CHAR_LEN_MAX 6
/*---- UTF-8 and UTF-16 handling ----*/
int unicode_to_utf8(uint8_t *buf, unsigned int c);
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
#define UTF8_CHAR_LEN_MAX 4
enum {
UTF8_PLAIN_ASCII = 0, // 7-bit ASCII plain text
UTF8_NON_ASCII = 1, // has non ASCII code points (8-bit or more)
UTF8_HAS_16BIT = 2, // has 16-bit code points
UTF8_HAS_NON_BMP1 = 4, // has non-BMP1 code points, needs UTF-16 surrogate pairs
UTF8_HAS_ERRORS = 8, // has encoding errors
};
int utf8_scan(const char *buf, size_t len, size_t *plen);
size_t utf8_encode_len(uint32_t c);
size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c);
uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp);
uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp);
size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len);
size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len);
size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len);
size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len);
static inline BOOL is_surrogate(uint32_t c)
{
return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
}
static inline BOOL is_hi_surrogate(uint32_t c)
{
return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
}
static inline BOOL is_lo_surrogate(uint32_t c)
{
return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
}
static inline uint32_t get_hi_surrogate(uint32_t c)
{
return (c >> 10) - (0x10000 >> 10) + 0xD800;
}
static inline uint32_t get_lo_surrogate(uint32_t c)
{
return (c & 0x3FF) | 0xDC00;
}
static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
{
return 65536 + 1024 * (hi & 1023) + (lo & 1023);
}
static inline int from_hex(int c)
{
@ -293,8 +531,78 @@ static inline int from_hex(int c)
return -1;
}
static inline uint8_t is_upper_ascii(uint8_t c) {
return c >= 'A' && c <= 'Z';
}
static inline uint8_t to_upper_ascii(uint8_t c) {
return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
}
extern char const digits36[36];
size_t u32toa(char buf[minimum_length(11)], uint32_t n);
size_t i32toa(char buf[minimum_length(12)], int32_t n);
size_t u64toa(char buf[minimum_length(21)], uint64_t n);
size_t i64toa(char buf[minimum_length(22)], int64_t n);
size_t u32toa_radix(char buf[minimum_length(33)], uint32_t n, unsigned int base);
size_t i32toa_radix(char buf[minimum_length(34)], int32_t n, unsigned base);
size_t u64toa_radix(char buf[minimum_length(65)], uint64_t n, unsigned int base);
size_t i64toa_radix(char buf[minimum_length(66)], int64_t n, unsigned int base);
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg);
int64_t js__gettimeofday_us(void);
uint64_t js__hrtime_ns(void);
static inline size_t js__malloc_usable_size(const void *ptr)
{
#if defined(__APPLE__)
return malloc_size(ptr);
#elif defined(_WIN32)
return _msize((void *)ptr);
#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__FreeBSD__)
return malloc_usable_size((void *)ptr);
#else
return 0;
#endif
}
/* Cross-platform threading APIs. */
#if !defined(EMSCRIPTEN) && !defined(__wasi__)
#if defined(_WIN32)
#define JS_ONCE_INIT INIT_ONCE_STATIC_INIT
typedef INIT_ONCE js_once_t;
typedef CRITICAL_SECTION js_mutex_t;
typedef CONDITION_VARIABLE js_cond_t;
#else
#define JS_ONCE_INIT PTHREAD_ONCE_INIT
typedef pthread_once_t js_once_t;
typedef pthread_mutex_t js_mutex_t;
typedef pthread_cond_t js_cond_t;
#endif
void js_once(js_once_t *guard, void (*callback)(void));
void js_mutex_init(js_mutex_t *mutex);
void js_mutex_destroy(js_mutex_t *mutex);
void js_mutex_lock(js_mutex_t *mutex);
void js_mutex_unlock(js_mutex_t *mutex);
void js_cond_init(js_cond_t *cond);
void js_cond_destroy(js_cond_t *cond);
void js_cond_signal(js_cond_t *cond);
void js_cond_broadcast(js_cond_t *cond);
void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex);
int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout);
#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* CUTILS_H */

2
cxxtest.cc Normal file
View file

@ -0,0 +1,2 @@
// note: file is not actually compiled, only checked for C++ syntax errors
#include "ctest.c"

1166
dirent_compat.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,734 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
<head>
<title>Javascript Bignum Extensions</title>
<meta name="description" content="Javascript Bignum Extensions">
<meta name="keywords" content="Javascript Bignum Extensions">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="#SEC_Contents" rel="contents" title="Table of Contents">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
blockquote.indentedblock {margin-right: 0em}
blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
blockquote.smallquotation {font-size: smaller}
div.display {margin-left: 3.2em}
div.example {margin-left: 3.2em}
div.lisp {margin-left: 3.2em}
div.smalldisplay {margin-left: 3.2em}
div.smallexample {margin-left: 3.2em}
div.smalllisp {margin-left: 3.2em}
kbd {font-style: oblique}
pre.display {font-family: inherit}
pre.format {font-family: inherit}
pre.menu-comment {font-family: serif}
pre.menu-preformatted {font-family: serif}
pre.smalldisplay {font-family: inherit; font-size: smaller}
pre.smallexample {font-size: smaller}
pre.smallformat {font-family: inherit; font-size: smaller}
pre.smalllisp {font-size: smaller}
span.nolinebreak {white-space: nowrap}
span.roman {font-family: initial; font-weight: normal}
span.sansserif {font-family: sans-serif; font-weight: normal}
ul.no-bullet {list-style: none}
-->
</style>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body lang="en">
<h1 class="settitle" align="center">Javascript Bignum Extensions</h1>
<a name="SEC_Contents"></a>
<h2 class="contents-heading">Table of Contents</h2>
<div class="contents">
<ul class="no-bullet">
<li><a name="toc-Introduction" href="#Introduction">1 Introduction</a></li>
<li><a name="toc-Operator-overloading" href="#Operator-overloading">2 Operator overloading</a></li>
<li><a name="toc-BigInt-extensions" href="#BigInt-extensions">3 BigInt extensions</a></li>
<li><a name="toc-BigFloat" href="#BigFloat">4 BigFloat</a>
<ul class="no-bullet">
<li><a name="toc-Introduction-1" href="#Introduction-1">4.1 Introduction</a></li>
<li><a name="toc-Floating-point-rounding" href="#Floating-point-rounding">4.2 Floating point rounding</a></li>
<li><a name="toc-Operators" href="#Operators">4.3 Operators</a></li>
<li><a name="toc-BigFloat-literals" href="#BigFloat-literals">4.4 BigFloat literals</a></li>
<li><a name="toc-Builtin-Object-changes" href="#Builtin-Object-changes">4.5 Builtin Object changes</a>
<ul class="no-bullet">
<li><a name="toc-BigFloat-function" href="#BigFloat-function">4.5.1 <code>BigFloat</code> function</a></li>
<li><a name="toc-BigFloat_002eprototype" href="#BigFloat_002eprototype">4.5.2 <code>BigFloat.prototype</code></a></li>
<li><a name="toc-BigFloatEnv-constructor" href="#BigFloatEnv-constructor">4.5.3 <code>BigFloatEnv</code> constructor</a></li>
</ul></li>
</ul></li>
<li><a name="toc-BigDecimal" href="#BigDecimal">5 BigDecimal</a>
<ul class="no-bullet">
<li><a name="toc-Operators-1" href="#Operators-1">5.1 Operators</a></li>
<li><a name="toc-BigDecimal-literals" href="#BigDecimal-literals">5.2 BigDecimal literals</a></li>
<li><a name="toc-Builtin-Object-changes-1" href="#Builtin-Object-changes-1">5.3 Builtin Object changes</a>
<ul class="no-bullet">
<li><a name="toc-The-BigDecimal-function_002e" href="#The-BigDecimal-function_002e">5.3.1 The <code>BigDecimal</code> function.</a></li>
<li><a name="toc-Properties-of-the-BigDecimal-object" href="#Properties-of-the-BigDecimal-object">5.3.2 Properties of the <code>BigDecimal</code> object</a></li>
<li><a name="toc-Properties-of-the-BigDecimal_002eprototype-object" href="#Properties-of-the-BigDecimal_002eprototype-object">5.3.3 Properties of the <code>BigDecimal.prototype</code> object</a></li>
</ul></li>
</ul></li>
<li><a name="toc-Math-mode" href="#Math-mode">6 Math mode</a></li>
</ul>
</div>
<a name="Introduction"></a>
<h2 class="chapter">1 Introduction</h2>
<p>The Bignum extensions add the following features to the Javascript
language while being 100% backward compatible:
</p>
<ul>
<li> Operator overloading with a dispatch logic inspired from the proposal available at <a href="https://github.com/tc39/proposal-operator-overloading/">https://github.com/tc39/proposal-operator-overloading/</a>.
</li><li> Arbitrarily large floating point numbers (<code>BigFloat</code>) in base 2 using the IEEE 754 semantics.
</li><li> Arbitrarily large floating point numbers (<code>BigDecimal</code>) in base 10 based on the proposal available at
<a href="https://github.com/littledan/proposal-bigdecimal">https://github.com/littledan/proposal-bigdecimal</a>.
</li><li> <code>math</code> mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (<code>%</code>) is defined as the Euclidian
remainder. <code>^</code> is an alias to the power operator
(<code>**</code>). <code>^^</code> is used as the exclusive or operator.
</li></ul>
<p>The extensions are independent from each other except the <code>math</code>
mode which relies on BigFloat and operator overloading.
</p>
<a name="Operator-overloading"></a>
<h2 class="chapter">2 Operator overloading</h2>
<p>Operator overloading is inspired from the proposal available at
<a href="https://github.com/tc39/proposal-operator-overloading/">https://github.com/tc39/proposal-operator-overloading/</a>. It
implements the same dispatch logic but finds the operator sets by
looking at the <code>Symbol.operatorSet</code> property in the objects. The
changes were done in order to simplify the implementation.
</p>
<p>More precisely, the following modifications were made:
</p>
<ul>
<li> <code>with operators from</code> is not supported. Operator overloading is always enabled.
</li><li> The dispatch is not based on a static <code>[[OperatorSet]]</code> field in all instances. Instead, a dynamic lookup of the <code>Symbol.operatorSet</code> property is done. This property is typically added in the prototype of each object.
</li><li> <code>Operators.create(...dictionaries)</code> is used to create a new OperatorSet object. The <code>Operators</code> function is supported as an helper to be closer to the TC39 proposal.
</li><li> <code>[]</code> cannot be overloaded.
</li><li> In math mode, the BigInt division and power operators can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li></ul>
<a name="BigInt-extensions"></a>
<h2 class="chapter">3 BigInt extensions</h2>
<p>A few properties are added to the BigInt object:
</p>
<dl compact="compact">
<dt><code>tdiv(a, b)</code></dt>
<dd><p>Return <em>trunc(a/b)</em>. <code>b = 0</code> raises a RangeError
exception.
</p>
</dd>
<dt><code>fdiv(a, b)</code></dt>
<dd><p>Return <em>\lfloor a/b \rfloor</em>. <code>b = 0</code> raises a RangeError
exception.
</p>
</dd>
<dt><code>cdiv(a, b)</code></dt>
<dd><p>Return <em>\lceil a/b \rceil</em>. <code>b = 0</code> raises a RangeError
exception.
</p>
</dd>
<dt><code>ediv(a, b)</code></dt>
<dd><p>Return <em>sgn(b) \lfloor a/{|b|} \rfloor</em> (Euclidian
division). <code>b = 0</code> raises a RangeError exception.
</p>
</dd>
<dt><code>tdivrem(a, b)</code></dt>
<dt><code>fdivrem(a, b)</code></dt>
<dt><code>cdivrem(a, b)</code></dt>
<dt><code>edivrem(a, b)</code></dt>
<dd><p>Return an array of two elements. The first element is the quotient,
the second is the remainder. The same rounding is done as the
corresponding division operation.
</p>
</dd>
<dt><code>sqrt(a)</code></dt>
<dd><p>Return <em>\lfloor \sqrt(a) \rfloor</em>. A RangeError exception is
raised if <em>a &lt; 0</em>.
</p>
</dd>
<dt><code>sqrtrem(a)</code></dt>
<dd><p>Return an array of two elements. The first element is <em>\lfloor
\sqrt{a} \rfloor</em>. The second element is <em>a-\lfloor \sqrt{a}
\rfloor^2</em>. A RangeError exception is raised if <em>a &lt; 0</em>.
</p>
</dd>
<dt><code>floorLog2(a)</code></dt>
<dd><p>Return -1 if <em>a \leq 0</em> otherwise return <em>\lfloor \log2(a) \rfloor</em>.
</p>
</dd>
<dt><code>ctz(a)</code></dt>
<dd><p>Return the number of trailing zeros in the two&rsquo;s complement binary representation of a. Return -1 if <em>a=0</em>.
</p>
</dd>
</dl>
<a name="BigFloat"></a>
<h2 class="chapter">4 BigFloat</h2>
<a name="Introduction-1"></a>
<h3 class="section">4.1 Introduction</h3>
<p>This extension adds the <code>BigFloat</code> primitive type. The
<code>BigFloat</code> type represents floating point numbers in base 2
with the IEEE 754 semantics. A floating
point number is represented as a sign, mantissa and exponent. The
special values <code>NaN</code>, <code>+/-Infinity</code>, <code>+0</code> and <code>-0</code>
are supported. The mantissa and exponent can have any bit length with
an implementation specific minimum and maximum.
</p>
<a name="Floating-point-rounding"></a>
<h3 class="section">4.2 Floating point rounding</h3>
<p>Each floating point operation operates with infinite precision and
then rounds the result according to the specified floating point
environment (<code>BigFloatEnv</code> object). The status flags of the
environment are also set according to the result of the operation.
</p>
<p>If no floating point environment is provided, the global floating
point environment is used.
</p>
<p>The rounding mode of the global floating point environment is always
<code>RNDN</code> (&ldquo;round to nearest with ties to even&rdquo;)<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>. The status flags of the global environment cannot be
read<a name="DOCF2" href="#FOOT2"><sup>2</sup></a>. The precision of the global environment is
<code>BigFloatEnv.prec</code>. The number of exponent bits of the global
environment is <code>BigFloatEnv.expBits</code>. The global environment
subnormal flag is set to <code>true</code>.
</p>
<p>For example, <code>prec = 53</code> and <code> expBits = 11</code> exactly give
the same precision as the IEEE 754 64 bit floating point format. The
default precision is <code>prec = 113</code> and <code> expBits = 15</code> (IEEE
754 128 bit floating point format).
</p>
<p>The global floating point environment can only be modified temporarily
when calling a function (see <code>BigFloatEnv.setPrec</code>). Hence a
function can change the global floating point environment for its
callees but not for its caller.
</p>
<a name="Operators"></a>
<h3 class="section">4.3 Operators</h3>
<p>The builtin operators are extended so that a BigFloat is returned if
at least one operand is a BigFloat. The computations are always done
with infinite precision and rounded according to the global floating
point environment.
</p>
<p><code>typeof</code> applied on a <code>BigFloat</code> returns <code>bigfloat</code>.
</p>
<p>BigFloat can be compared with all the other numeric types and the
result follows the expected mathematical relations.
</p>
<p>However, since BigFloat and Number are different types they are never
equal when using the strict comparison operators (e.g. <code>0.0 ===
0.0l</code> is false).
</p>
<a name="BigFloat-literals"></a>
<h3 class="section">4.4 BigFloat literals</h3>
<p>BigFloat literals are floating point numbers with a trailing <code>l</code>
suffix. BigFloat literals have an infinite precision. They are rounded
according to the global floating point environment when they are
evaluated.<a name="DOCF3" href="#FOOT3"><sup>3</sup></a>
</p>
<a name="Builtin-Object-changes"></a>
<h3 class="section">4.5 Builtin Object changes</h3>
<a name="BigFloat-function"></a>
<h4 class="subsection">4.5.1 <code>BigFloat</code> function</h4>
<p>The <code>BigFloat</code> function cannot be invoked as a constructor. When
invoked as a function: the parameter is converted to a primitive
type. If the result is a numeric type, it is converted to BigFloat
without rounding. If the result is a string, it is converted to
BigFloat using the precision of the global floating point environment.
</p>
<p><code>BigFloat</code> properties:
</p>
<dl compact="compact">
<dt><code>LN2</code></dt>
<dt><code>PI</code></dt>
<dd><p>Getter. Return the value of the corresponding mathematical constant
rounded to nearest, ties to even with the current global
precision. The constant values are cached for small precisions.
</p>
</dd>
<dt><code>MIN_VALUE</code></dt>
<dt><code>MAX_VALUE</code></dt>
<dt><code>EPSILON</code></dt>
<dd><p>Getter. Return the minimum, maximum and epsilon <code>BigFloat</code> values
(same definition as the corresponding <code>Number</code> constants).
</p>
</dd>
<dt><code>fpRound(a[, e])</code></dt>
<dd><p>Round the floating point number <code>a</code> according to the floating
point environment <code>e</code> or the global environment if <code>e</code> is
undefined.
</p>
</dd>
<dt><code>parseFloat(a[, radix[, e]])</code></dt>
<dd><p>Parse the string <code>a</code> as a floating point number in radix
<code>radix</code>. The radix is 0 (default) or from 2 to 36. The radix 0
means radix 10 unless there is a hexadecimal or binary prefix. The
result is rounded according to the floating point environment <code>e</code>
or the global environment if <code>e</code> is undefined.
</p>
</dd>
<dt><code>isFinite(a)</code></dt>
<dd><p>Return true if <code>a</code> is a finite bigfloat.
</p>
</dd>
<dt><code>isNaN(a)</code></dt>
<dd><p>Return true if <code>a</code> is a NaN bigfloat.
</p>
</dd>
<dt><code>add(a, b[, e])</code></dt>
<dt><code>sub(a, b[, e])</code></dt>
<dt><code>mul(a, b[, e])</code></dt>
<dt><code>div(a, b[, e])</code></dt>
<dd><p>Perform the specified floating point operation and round the floating
point number <code>a</code> according to the floating point environment
<code>e</code> or the global environment if <code>e</code> is undefined. If
<code>e</code> is specified, the floating point status flags are updated.
</p>
</dd>
<dt><code>floor(x)</code></dt>
<dt><code>ceil(x)</code></dt>
<dt><code>round(x)</code></dt>
<dt><code>trunc(x)</code></dt>
<dd><p>Round to an integer. No additional rounding is performed.
</p>
</dd>
<dt><code>abs(x)</code></dt>
<dd><p>Return the absolute value of x. No additional rounding is performed.
</p>
</dd>
<dt><code>fmod(x, y[, e])</code></dt>
<dt><code>remainder(x, y[, e])</code></dt>
<dd><p>Floating point remainder. The quotient is truncated to zero (fmod) or
to the nearest integer with ties to even (remainder). <code>e</code> is an
optional floating point environment.
</p>
</dd>
<dt><code>sqrt(x[, e])</code></dt>
<dd><p>Square root. Return a rounded floating point number. <code>e</code> is an
optional floating point environment.
</p>
</dd>
<dt><code>sin(x[, e])</code></dt>
<dt><code>cos(x[, e])</code></dt>
<dt><code>tan(x[, e])</code></dt>
<dt><code>asin(x[, e])</code></dt>
<dt><code>acos(x[, e])</code></dt>
<dt><code>atan(x[, e])</code></dt>
<dt><code>atan2(x, y[, e])</code></dt>
<dt><code>exp(x[, e])</code></dt>
<dt><code>log(x[, e])</code></dt>
<dt><code>pow(x, y[, e])</code></dt>
<dd><p>Transcendental operations. Return a rounded floating point
number. <code>e</code> is an optional floating point environment.
</p>
</dd>
</dl>
<a name="BigFloat_002eprototype"></a>
<h4 class="subsection">4.5.2 <code>BigFloat.prototype</code></h4>
<p>The following properties are modified:
</p>
<dl compact="compact">
<dt><code>valueOf()</code></dt>
<dd><p>Return the bigfloat primitive value corresponding to <code>this</code>.
</p>
</dd>
<dt><code>toString(radix)</code></dt>
<dd>
<p>For floating point numbers:
</p>
<ul>
<li> If the radix is a power of two, the conversion is done with infinite
precision.
</li><li> Otherwise, the number is rounded to nearest with ties to even using
the global precision. It is then converted to string using the minimum
number of digits so that its conversion back to a floating point using
the global precision and round to nearest gives the same number.
</li></ul>
<p>The exponent letter is <code>e</code> for base 10, <code>p</code> for bases 2, 8,
16 with a binary exponent and <code>@</code> for the other bases.
</p>
</dd>
<dt><code>toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
<dt><code>toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
<dt><code>toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
<dd><p>Same semantics as the corresponding <code>Number</code> functions with
BigFloats. There is no limit on the accepted precision <code>p</code>. The
rounding mode and radix can be optionally specified. The radix must be
between 2 and 36.
</p>
</dd>
</dl>
<a name="BigFloatEnv-constructor"></a>
<h4 class="subsection">4.5.3 <code>BigFloatEnv</code> constructor</h4>
<p>The <code>BigFloatEnv([p, [,rndMode]]</code> constructor cannot be invoked as a
function. The floating point environment contains:
</p>
<ul>
<li> the mantissa precision in bits
</li><li> the exponent size in bits assuming an IEEE 754 representation;
</li><li> the subnormal flag (if true, subnormal floating point numbers can
be generated by the floating point operations).
</li><li> the rounding mode
</li><li> the floating point status. The status flags can only be set by the floating point operations. They can be reset with <code>BigFloatEnv.prototype.clearStatus()</code> or with the various status flag setters.
</li></ul>
<p><code>new BigFloatEnv([p, [,rndMode]]</code> creates a new floating point
environment. The status flags are reset. If no parameter is given the
precision, exponent bits and subnormal flags are copied from the
global floating point environment. Otherwise, the precision is set to
<code>p</code>, the number of exponent bits is set to <code>expBitsMax</code> and the
subnormal flags is set to <code>false</code>. If <code>rndMode</code> is
<code>undefined</code>, the rounding mode is set to <code>RNDN</code>.
</p>
<p><code>BigFloatEnv</code> properties:
</p>
<dl compact="compact">
<dt><code>prec</code></dt>
<dd><p>Getter. Return the precision in bits of the global floating point
environment. The initial value is <code>113</code>.
</p>
</dd>
<dt><code>expBits</code></dt>
<dd><p>Getter. Return the exponent size in bits of the global floating point
environment assuming an IEEE 754 representation. The initial value is
<code>15</code>.
</p>
</dd>
<dt><code>setPrec(f, p[, e])</code></dt>
<dd><p>Set the precision of the global floating point environment to <code>p</code>
and the exponent size to <code>e</code> then call the function
<code>f</code>. Then the Float precision and exponent size are reset to
their precious value and the return value of <code>f</code> is returned (or
an exception is raised if <code>f</code> raised an exception). If <code>e</code>
is <code>undefined</code> it is set to <code>BigFloatEnv.expBitsMax</code>.
</p>
</dd>
<dt><code>precMin</code></dt>
<dd><p>Read-only integer. Return the minimum allowed precision. Must be at least 2.
</p>
</dd>
<dt><code>precMax</code></dt>
<dd><p>Read-only integer. Return the maximum allowed precision. Must be at least 113.
</p>
</dd>
<dt><code>expBitsMin</code></dt>
<dd><p>Read-only integer. Return the minimum allowed exponent size in
bits. Must be at least 3.
</p>
</dd>
<dt><code>expBitsMax</code></dt>
<dd><p>Read-only integer. Return the maximum allowed exponent size in
bits. Must be at least 15.
</p>
</dd>
<dt><code>RNDN</code></dt>
<dd><p>Read-only integer. Round to nearest, with ties to even rounding mode.
</p>
</dd>
<dt><code>RNDZ</code></dt>
<dd><p>Read-only integer. Round to zero rounding mode.
</p>
</dd>
<dt><code>RNDD</code></dt>
<dd><p>Read-only integer. Round to -Infinity rounding mode.
</p>
</dd>
<dt><code>RNDU</code></dt>
<dd><p>Read-only integer. Round to +Infinity rounding mode.
</p>
</dd>
<dt><code>RNDNA</code></dt>
<dd><p>Read-only integer. Round to nearest, with ties away from zero rounding mode.
</p>
</dd>
<dt><code>RNDA</code></dt>
<dd><p>Read-only integer. Round away from zero rounding mode.
</p>
</dd>
<dt><code>RNDF<a name="DOCF4" href="#FOOT4"><sup>4</sup></a></code></dt>
<dd><p>Read-only integer. Faithful rounding mode. The result is
non-deterministically rounded to -Infinity or +Infinity. This rounding
mode usually gives a faster and deterministic running time for the
floating point operations.
</p>
</dd>
</dl>
<p><code>BigFloatEnv.prototype</code> properties:
</p>
<dl compact="compact">
<dt><code>prec</code></dt>
<dd><p>Getter and setter (Integer). Return or set the precision in bits.
</p>
</dd>
<dt><code>expBits</code></dt>
<dd><p>Getter and setter (Integer). Return or set the exponent size in bits
assuming an IEEE 754 representation.
</p>
</dd>
<dt><code>rndMode</code></dt>
<dd><p>Getter and setter (Integer). Return or set the rounding mode.
</p>
</dd>
<dt><code>subnormal</code></dt>
<dd><p>Getter and setter (Boolean). subnormal flag. It is false when
<code>expBits = expBitsMax</code>.
</p>
</dd>
<dt><code>clearStatus()</code></dt>
<dd><p>Clear the status flags.
</p>
</dd>
<dt><code>invalidOperation</code></dt>
<dt><code>divideByZero</code></dt>
<dt><code>overflow</code></dt>
<dt><code>underflow</code></dt>
<dt><code>inexact</code></dt>
<dd><p>Getter and setter (Boolean). Status flags.
</p>
</dd>
</dl>
<a name="BigDecimal"></a>
<h2 class="chapter">5 BigDecimal</h2>
<p>This extension adds the <code>BigDecimal</code> primitive type. The
<code>BigDecimal</code> type represents floating point numbers in base
10. It is inspired from the proposal available at
<a href="https://github.com/littledan/proposal-bigdecimal">https://github.com/littledan/proposal-bigdecimal</a>.
</p>
<p>The <code>BigDecimal</code> floating point numbers are always normalized and
finite. There is no concept of <code>-0</code>, <code>Infinity</code> or
<code>NaN</code>. By default, all the computations are done with infinite
precision.
</p>
<a name="Operators-1"></a>
<h3 class="section">5.1 Operators</h3>
<p>The following builtin operators support BigDecimal:
</p>
<dl compact="compact">
<dt><code>+</code></dt>
<dt><code>-</code></dt>
<dt><code>*</code></dt>
<dd><p>Both operands must be BigDecimal. The result is computed with infinite
precision.
</p></dd>
<dt><code>%</code></dt>
<dd><p>Both operands must be BigDecimal. The result is computed with infinite
precision. A range error is throws in case of division by zero.
</p>
</dd>
<dt><code>/</code></dt>
<dd><p>Both operands must be BigDecimal. A range error is throws in case of
division by zero or if the result cannot be represented with infinite
precision (use <code>BigDecimal.div</code> to specify the rounding).
</p>
</dd>
<dt><code>**</code></dt>
<dd><p>Both operands must be BigDecimal. The exponent must be a positive
integer. The result is computed with infinite precision.
</p>
</dd>
<dt><code>===</code></dt>
<dd><p>When one of the operand is a BigDecimal, return true if both operands
are a BigDecimal and if they are equal.
</p>
</dd>
<dt><code>==</code></dt>
<dt><code>!=</code></dt>
<dt><code>&lt;=</code></dt>
<dt><code>&gt;=</code></dt>
<dt><code>&lt;</code></dt>
<dt><code>&gt;</code></dt>
<dd>
<p>Numerical comparison. When one of the operand is not a BigDecimal, it is
converted to BigDecimal by using ToString(). Hence comparisons between
Number and BigDecimal do not use the exact mathematical value of the
Number value.
</p>
</dd>
</dl>
<a name="BigDecimal-literals"></a>
<h3 class="section">5.2 BigDecimal literals</h3>
<p>BigDecimal literals are decimal floating point numbers with a trailing
<code>m</code> suffix.
</p>
<a name="Builtin-Object-changes-1"></a>
<h3 class="section">5.3 Builtin Object changes</h3>
<a name="The-BigDecimal-function_002e"></a>
<h4 class="subsection">5.3.1 The <code>BigDecimal</code> function.</h4>
<p>It returns <code>0m</code> if no parameter is provided. Otherwise the first
parameter is converted to a bigdecimal by using ToString(). Hence
Number values are not converted to their exact numerical value as
BigDecimal.
</p>
<a name="Properties-of-the-BigDecimal-object"></a>
<h4 class="subsection">5.3.2 Properties of the <code>BigDecimal</code> object</h4>
<dl compact="compact">
<dt><code>add(a, b[, e])</code></dt>
<dt><code>sub(a, b[, e])</code></dt>
<dt><code>mul(a, b[, e])</code></dt>
<dt><code>div(a, b[, e])</code></dt>
<dt><code>mod(a, b[, e])</code></dt>
<dt><code>sqrt(a, e)</code></dt>
<dt><code>round(a, e)</code></dt>
<dd><p>Perform the specified floating point operation and round the floating
point result according to the rounding object <code>e</code>. If the
rounding object is not present, the operation is executed with
infinite precision.
</p>
<p>For <code>div</code>, a <code>RangeError</code> exception is thrown in case of
division by zero or if the result cannot be represented with infinite
precision if no rounding object is present.
</p>
<p>For <code>sqrt</code>, a range error is thrown if <code>a</code> is less than
zero.
</p>
<p>The rounding object must contain the following properties:
<code>roundingMode</code> is a string specifying the rounding mode
(<code>&quot;floor&quot;</code>, <code>&quot;ceiling&quot;</code>, <code>&quot;down&quot;</code>, <code>&quot;up&quot;</code>,
<code>&quot;half-even&quot;</code>, <code>&quot;half-up&quot;</code>). Either
<code>maximumSignificantDigits</code> or <code>maximumFractionDigits</code> must
be present to specify respectively the number of significant digits
(must be &gt;= 1) or the number of digits after the decimal point (must
be &gt;= 0).
</p>
</dd>
</dl>
<a name="Properties-of-the-BigDecimal_002eprototype-object"></a>
<h4 class="subsection">5.3.3 Properties of the <code>BigDecimal.prototype</code> object</h4>
<dl compact="compact">
<dt><code>valueOf()</code></dt>
<dd><p>Return the bigdecimal primitive value corresponding to <code>this</code>.
</p>
</dd>
<dt><code>toString()</code></dt>
<dd><p>Convert <code>this</code> to a string with infinite precision in base 10.
</p>
</dd>
<dt><code>toPrecision(p, rnd_mode = &quot;half-up&quot;)</code></dt>
<dt><code>toFixed(p, rnd_mode = &quot;half-up&quot;)</code></dt>
<dt><code>toExponential(p, rnd_mode = &quot;half-up&quot;)</code></dt>
<dd><p>Convert the BigDecimal <code>this</code> to string with the specified
precision <code>p</code>. There is no limit on the accepted precision
<code>p</code>. The rounding mode can be optionally
specified. <code>toPrecision</code> outputs either in decimal fixed notation
or in decimal exponential notation with a <code>p</code> digits of
precision. <code>toExponential</code> outputs in decimal exponential
notation with <code>p</code> digits after the decimal point. <code>toFixed</code>
outputs in decimal notation with <code>p</code> digits after the decimal
point.
</p>
</dd>
</dl>
<a name="Math-mode"></a>
<h2 class="chapter">6 Math mode</h2>
<p>A new <em>math mode</em> is enabled with the <code>&quot;use math&quot;</code>
directive. It propagates the same way as the <em>strict mode</em>. It is
designed so that arbitrarily large integers and floating point numbers
are available by default. In order to minimize the number of changes
in the Javascript semantics, integers are represented either as Number
or BigInt depending on their magnitude. Floating point numbers are
always represented as BigFloat.
</p>
<p>The following changes are made to the Javascript semantics:
</p>
<ul>
<li> Floating point literals (i.e. number with a decimal point or an exponent) are <code>BigFloat</code> by default (i.e. a <code>l</code> suffix is implied). Hence <code>typeof 1.0 === &quot;bigfloat&quot;</code>.
</li><li> Integer literals (i.e. numbers without a decimal point or an exponent) with or without the <code>n</code> suffix are <code>BigInt</code> if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to <code>2**53-1</code>. Hence <code>typeof 1 === &quot;number &quot;</code>, <code>typeof 1n === &quot;number&quot;</code> but <code>typeof 9007199254740992 === &quot;bigint&quot; </code>.
</li><li> All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt.
</li><li> The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result.
</li><li> The <code>^</code> operator is an alias to the power operator (<code>**</code>).
</li><li> The power operator (both <code>^</code> and <code>**</code>) grammar is modified so that <code>-2^2</code> is allowed and yields <code>-4</code>.
</li><li> The logical xor operator is still available with the <code>^^</code> operator.
</li><li> The modulo operator (<code>%</code>) returns the Euclidian remainder (always positive) instead of the truncated remainder.
</li><li> The integer division operator can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li><li> The integer power operator with a non zero negative exponent can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li></ul>
<div class="footnote">
<hr>
<h4 class="footnotes-heading">Footnotes</h4>
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
<p>The
rationale is that the rounding mode changes must always be
explicit.</p>
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
<p>The rationale is to avoid side effects for the built-in
operators.</p>
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
<p>Base 10 floating point literals cannot usually be
exactly represented as base 2 floating point number. In order to
ensure that the literal is represented accurately with the current
precision, it must be evaluated at runtime.</p>
<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
<p>Could be removed in case a deterministic behavior for floating point operations is required.</p>
</div>
<hr>
</body>
</html>

Binary file not shown.

View file

@ -1,589 +0,0 @@
\input texinfo
@iftex
@afourpaper
@headings double
@end iftex
@titlepage
@afourpaper
@sp 7
@center @titlefont{Javascript Bignum Extensions}
@sp 3
@center Version 2020-01-11
@sp 3
@center Author: Fabrice Bellard
@end titlepage
@setfilename jsbignum.info
@settitle Javascript Bignum Extensions
@contents
@chapter Introduction
The Bignum extensions add the following features to the Javascript
language while being 100% backward compatible:
@itemize
@item Operator overloading with a dispatch logic inspired from the proposal available at @url{https://github.com/tc39/proposal-operator-overloading/}.
@item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics.
@item Arbitrarily large floating point numbers (@code{BigDecimal}) in base 10 based on the proposal available at
@url{https://github.com/littledan/proposal-bigdecimal}.
@item @code{math} mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (@code{%}) is defined as the Euclidian
remainder. @code{^} is an alias to the power operator
(@code{**}). @code{^^} is used as the exclusive or operator.
@end itemize
The extensions are independent from each other except the @code{math}
mode which relies on BigFloat and operator overloading.
@chapter Operator overloading
Operator overloading is inspired from the proposal available at
@url{https://github.com/tc39/proposal-operator-overloading/}. It
implements the same dispatch logic but finds the operator sets by
looking at the @code{Symbol.operatorSet} property in the objects. The
changes were done in order to simplify the implementation.
More precisely, the following modifications were made:
@itemize
@item @code{with operators from} is not supported. Operator overloading is always enabled.
@item The dispatch is not based on a static @code{[[OperatorSet]]} field in all instances. Instead, a dynamic lookup of the @code{Symbol.operatorSet} property is done. This property is typically added in the prototype of each object.
@item @code{Operators.create(...dictionaries)} is used to create a new OperatorSet object. The @code{Operators} function is supported as an helper to be closer to the TC39 proposal.
@item @code{[]} cannot be overloaded.
@item In math mode, the BigInt division and power operators can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@end itemize
@chapter BigInt extensions
A few properties are added to the BigInt object:
@table @code
@item tdiv(a, b)
Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError
exception.
@item fdiv(a, b)
Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError
exception.
@item cdiv(a, b)
Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError
exception.
@item ediv(a, b)
Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian
division). @code{b = 0} raises a RangeError exception.
@item tdivrem(a, b)
@item fdivrem(a, b)
@item cdivrem(a, b)
@item edivrem(a, b)
Return an array of two elements. The first element is the quotient,
the second is the remainder. The same rounding is done as the
corresponding division operation.
@item sqrt(a)
Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is
raised if @math{a < 0}.
@item sqrtrem(a)
Return an array of two elements. The first element is @math{\lfloor
\sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a}
\rfloor^2}. A RangeError exception is raised if @math{a < 0}.
@item floorLog2(a)
Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}.
@item ctz(a)
Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}.
@end table
@chapter BigFloat
@section Introduction
This extension adds the @code{BigFloat} primitive type. The
@code{BigFloat} type represents floating point numbers in base 2
with the IEEE 754 semantics. A floating
point number is represented as a sign, mantissa and exponent. The
special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0}
are supported. The mantissa and exponent can have any bit length with
an implementation specific minimum and maximum.
@section Floating point rounding
Each floating point operation operates with infinite precision and
then rounds the result according to the specified floating point
environment (@code{BigFloatEnv} object). The status flags of the
environment are also set according to the result of the operation.
If no floating point environment is provided, the global floating
point environment is used.
The rounding mode of the global floating point environment is always
@code{RNDN} (``round to nearest with ties to even'')@footnote{The
rationale is that the rounding mode changes must always be
explicit.}. The status flags of the global environment cannot be
read@footnote{The rationale is to avoid side effects for the built-in
operators.}. The precision of the global environment is
@code{BigFloatEnv.prec}. The number of exponent bits of the global
environment is @code{BigFloatEnv.expBits}. The global environment
subnormal flag is set to @code{true}.
For example, @code{prec = 53} and @code{ expBits = 11} exactly give
the same precision as the IEEE 754 64 bit floating point format. The
default precision is @code{prec = 113} and @code{ expBits = 15} (IEEE
754 128 bit floating point format).
The global floating point environment can only be modified temporarily
when calling a function (see @code{BigFloatEnv.setPrec}). Hence a
function can change the global floating point environment for its
callees but not for its caller.
@section Operators
The builtin operators are extended so that a BigFloat is returned if
at least one operand is a BigFloat. The computations are always done
with infinite precision and rounded according to the global floating
point environment.
@code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}.
BigFloat can be compared with all the other numeric types and the
result follows the expected mathematical relations.
However, since BigFloat and Number are different types they are never
equal when using the strict comparison operators (e.g. @code{0.0 ===
0.0l} is false).
@section BigFloat literals
BigFloat literals are floating point numbers with a trailing @code{l}
suffix. BigFloat literals have an infinite precision. They are rounded
according to the global floating point environment when they are
evaluated.@footnote{Base 10 floating point literals cannot usually be
exactly represented as base 2 floating point number. In order to
ensure that the literal is represented accurately with the current
precision, it must be evaluated at runtime.}
@section Builtin Object changes
@subsection @code{BigFloat} function
The @code{BigFloat} function cannot be invoked as a constructor. When
invoked as a function: the parameter is converted to a primitive
type. If the result is a numeric type, it is converted to BigFloat
without rounding. If the result is a string, it is converted to
BigFloat using the precision of the global floating point environment.
@code{BigFloat} properties:
@table @code
@item LN2
@item PI
Getter. Return the value of the corresponding mathematical constant
rounded to nearest, ties to even with the current global
precision. The constant values are cached for small precisions.
@item MIN_VALUE
@item MAX_VALUE
@item EPSILON
Getter. Return the minimum, maximum and epsilon @code{BigFloat} values
(same definition as the corresponding @code{Number} constants).
@item fpRound(a[, e])
Round the floating point number @code{a} according to the floating
point environment @code{e} or the global environment if @code{e} is
undefined.
@item parseFloat(a[, radix[, e]])
Parse the string @code{a} as a floating point number in radix
@code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0
means radix 10 unless there is a hexadecimal or binary prefix. The
result is rounded according to the floating point environment @code{e}
or the global environment if @code{e} is undefined.
@item isFinite(a)
Return true if @code{a} is a finite bigfloat.
@item isNaN(a)
Return true if @code{a} is a NaN bigfloat.
@item add(a, b[, e])
@item sub(a, b[, e])
@item mul(a, b[, e])
@item div(a, b[, e])
Perform the specified floating point operation and round the floating
point number @code{a} according to the floating point environment
@code{e} or the global environment if @code{e} is undefined. If
@code{e} is specified, the floating point status flags are updated.
@item floor(x)
@item ceil(x)
@item round(x)
@item trunc(x)
Round to an integer. No additional rounding is performed.
@item abs(x)
Return the absolute value of x. No additional rounding is performed.
@item fmod(x, y[, e])
@item remainder(x, y[, e])
Floating point remainder. The quotient is truncated to zero (fmod) or
to the nearest integer with ties to even (remainder). @code{e} is an
optional floating point environment.
@item sqrt(x[, e])
Square root. Return a rounded floating point number. @code{e} is an
optional floating point environment.
@item sin(x[, e])
@item cos(x[, e])
@item tan(x[, e])
@item asin(x[, e])
@item acos(x[, e])
@item atan(x[, e])
@item atan2(x, y[, e])
@item exp(x[, e])
@item log(x[, e])
@item pow(x, y[, e])
Transcendental operations. Return a rounded floating point
number. @code{e} is an optional floating point environment.
@end table
@subsection @code{BigFloat.prototype}
The following properties are modified:
@table @code
@item valueOf()
Return the bigfloat primitive value corresponding to @code{this}.
@item toString(radix)
For floating point numbers:
@itemize
@item
If the radix is a power of two, the conversion is done with infinite
precision.
@item
Otherwise, the number is rounded to nearest with ties to even using
the global precision. It is then converted to string using the minimum
number of digits so that its conversion back to a floating point using
the global precision and round to nearest gives the same number.
@end itemize
The exponent letter is @code{e} for base 10, @code{p} for bases 2, 8,
16 with a binary exponent and @code{@@} for the other bases.
@item toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
@item toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
@item toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
Same semantics as the corresponding @code{Number} functions with
BigFloats. There is no limit on the accepted precision @code{p}. The
rounding mode and radix can be optionally specified. The radix must be
between 2 and 36.
@end table
@subsection @code{BigFloatEnv} constructor
The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a
function. The floating point environment contains:
@itemize
@item the mantissa precision in bits
@item the exponent size in bits assuming an IEEE 754 representation;
@item the subnormal flag (if true, subnormal floating point numbers can
be generated by the floating point operations).
@item the rounding mode
@item the floating point status. The status flags can only be set by the floating point operations. They can be reset with @code{BigFloatEnv.prototype.clearStatus()} or with the various status flag setters.
@end itemize
@code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point
environment. The status flags are reset. If no parameter is given the
precision, exponent bits and subnormal flags are copied from the
global floating point environment. Otherwise, the precision is set to
@code{p}, the number of exponent bits is set to @code{expBitsMax} and the
subnormal flags is set to @code{false}. If @code{rndMode} is
@code{undefined}, the rounding mode is set to @code{RNDN}.
@code{BigFloatEnv} properties:
@table @code
@item prec
Getter. Return the precision in bits of the global floating point
environment. The initial value is @code{113}.
@item expBits
Getter. Return the exponent size in bits of the global floating point
environment assuming an IEEE 754 representation. The initial value is
@code{15}.
@item setPrec(f, p[, e])
Set the precision of the global floating point environment to @code{p}
and the exponent size to @code{e} then call the function
@code{f}. Then the Float precision and exponent size are reset to
their precious value and the return value of @code{f} is returned (or
an exception is raised if @code{f} raised an exception). If @code{e}
is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}.
@item precMin
Read-only integer. Return the minimum allowed precision. Must be at least 2.
@item precMax
Read-only integer. Return the maximum allowed precision. Must be at least 113.
@item expBitsMin
Read-only integer. Return the minimum allowed exponent size in
bits. Must be at least 3.
@item expBitsMax
Read-only integer. Return the maximum allowed exponent size in
bits. Must be at least 15.
@item RNDN
Read-only integer. Round to nearest, with ties to even rounding mode.
@item RNDZ
Read-only integer. Round to zero rounding mode.
@item RNDD
Read-only integer. Round to -Infinity rounding mode.
@item RNDU
Read-only integer. Round to +Infinity rounding mode.
@item RNDNA
Read-only integer. Round to nearest, with ties away from zero rounding mode.
@item RNDA
Read-only integer. Round away from zero rounding mode.
@item RNDF@footnote{Could be removed in case a deterministic behavior for floating point operations is required.}
Read-only integer. Faithful rounding mode. The result is
non-deterministically rounded to -Infinity or +Infinity. This rounding
mode usually gives a faster and deterministic running time for the
floating point operations.
@end table
@code{BigFloatEnv.prototype} properties:
@table @code
@item prec
Getter and setter (Integer). Return or set the precision in bits.
@item expBits
Getter and setter (Integer). Return or set the exponent size in bits
assuming an IEEE 754 representation.
@item rndMode
Getter and setter (Integer). Return or set the rounding mode.
@item subnormal
Getter and setter (Boolean). subnormal flag. It is false when
@code{expBits = expBitsMax}.
@item clearStatus()
Clear the status flags.
@item invalidOperation
@item divideByZero
@item overflow
@item underflow
@item inexact
Getter and setter (Boolean). Status flags.
@end table
@chapter BigDecimal
This extension adds the @code{BigDecimal} primitive type. The
@code{BigDecimal} type represents floating point numbers in base
10. It is inspired from the proposal available at
@url{https://github.com/littledan/proposal-bigdecimal}.
The @code{BigDecimal} floating point numbers are always normalized and
finite. There is no concept of @code{-0}, @code{Infinity} or
@code{NaN}. By default, all the computations are done with infinite
precision.
@section Operators
The following builtin operators support BigDecimal:
@table @code
@item +
@item -
@item *
Both operands must be BigDecimal. The result is computed with infinite
precision.
@item %
Both operands must be BigDecimal. The result is computed with infinite
precision. A range error is throws in case of division by zero.
@item /
Both operands must be BigDecimal. A range error is throws in case of
division by zero or if the result cannot be represented with infinite
precision (use @code{BigDecimal.div} to specify the rounding).
@item **
Both operands must be BigDecimal. The exponent must be a positive
integer. The result is computed with infinite precision.
@item ===
When one of the operand is a BigDecimal, return true if both operands
are a BigDecimal and if they are equal.
@item ==
@item !=
@item <=
@item >=
@item <
@item >
Numerical comparison. When one of the operand is not a BigDecimal, it is
converted to BigDecimal by using ToString(). Hence comparisons between
Number and BigDecimal do not use the exact mathematical value of the
Number value.
@end table
@section BigDecimal literals
BigDecimal literals are decimal floating point numbers with a trailing
@code{m} suffix.
@section Builtin Object changes
@subsection The @code{BigDecimal} function.
It returns @code{0m} if no parameter is provided. Otherwise the first
parameter is converted to a bigdecimal by using ToString(). Hence
Number values are not converted to their exact numerical value as
BigDecimal.
@subsection Properties of the @code{BigDecimal} object
@table @code
@item add(a, b[, e])
@item sub(a, b[, e])
@item mul(a, b[, e])
@item div(a, b[, e])
@item mod(a, b[, e])
@item sqrt(a, e)
@item round(a, e)
Perform the specified floating point operation and round the floating
point result according to the rounding object @code{e}. If the
rounding object is not present, the operation is executed with
infinite precision.
For @code{div}, a @code{RangeError} exception is thrown in case of
division by zero or if the result cannot be represented with infinite
precision if no rounding object is present.
For @code{sqrt}, a range error is thrown if @code{a} is less than
zero.
The rounding object must contain the following properties:
@code{roundingMode} is a string specifying the rounding mode
(@code{"floor"}, @code{"ceiling"}, @code{"down"}, @code{"up"},
@code{"half-even"}, @code{"half-up"}). Either
@code{maximumSignificantDigits} or @code{maximumFractionDigits} must
be present to specify respectively the number of significant digits
(must be >= 1) or the number of digits after the decimal point (must
be >= 0).
@end table
@subsection Properties of the @code{BigDecimal.prototype} object
@table @code
@item valueOf()
Return the bigdecimal primitive value corresponding to @code{this}.
@item toString()
Convert @code{this} to a string with infinite precision in base 10.
@item toPrecision(p, rnd_mode = "half-up")
@item toFixed(p, rnd_mode = "half-up")
@item toExponential(p, rnd_mode = "half-up")
Convert the BigDecimal @code{this} to string with the specified
precision @code{p}. There is no limit on the accepted precision
@code{p}. The rounding mode can be optionally
specified. @code{toPrecision} outputs either in decimal fixed notation
or in decimal exponential notation with a @code{p} digits of
precision. @code{toExponential} outputs in decimal exponential
notation with @code{p} digits after the decimal point. @code{toFixed}
outputs in decimal notation with @code{p} digits after the decimal
point.
@end table
@chapter Math mode
A new @emph{math mode} is enabled with the @code{"use math"}
directive. It propagates the same way as the @emph{strict mode}. It is
designed so that arbitrarily large integers and floating point numbers
are available by default. In order to minimize the number of changes
in the Javascript semantics, integers are represented either as Number
or BigInt depending on their magnitude. Floating point numbers are
always represented as BigFloat.
The following changes are made to the Javascript semantics:
@itemize
@item Floating point literals (i.e. number with a decimal point or an exponent) are @code{BigFloat} by default (i.e. a @code{l} suffix is implied). Hence @code{typeof 1.0 === "bigfloat"}.
@item Integer literals (i.e. numbers without a decimal point or an exponent) with or without the @code{n} suffix are @code{BigInt} if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to @code{2**53-1}. Hence @code{typeof 1 === "number "}, @code{typeof 1n === "number"} but @code{typeof 9007199254740992 === "bigint" }.
@item All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt.
@item The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result.
@item The @code{^} operator is an alias to the power operator (@code{**}).
@item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}.
@item The logical xor operator is still available with the @code{^^} operator.
@item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
@item The integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@end itemize
@bye

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

20
docs/.gitignore vendored Normal file
View file

@ -0,0 +1,20 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

1
docs/.nvmrc Normal file
View file

@ -0,0 +1 @@
18

3
docs/babel.config.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};

53
docs/docs/building.md Normal file
View file

@ -0,0 +1,53 @@
---
sidebar_position: 2
---
# Building
QuickJS uses [CMake] as its main build system, with an additional helper [Makefile].
:::note
Windows users will need to run the CMake commands manually.
:::
## Getting the source
```bash
git clone https://github.com/quickjs-ng/quickjs.git
cd quickjs
```
## Compiling everything
```bash
make
```
This will build the `qjs` and `qjsc` executables and other test tools. Head over [here](./cli) for
instructions on how to use them.
## Debug builds
```bash
make debug
```
This will produce a debug build without optimizations, suitable for developers.
## Running test262
```bash
make test262
```
This will run the test262 suite.
```bash
make test262-update
```
This will run the test262 suite and update the error / pass report, useful after
implementing a new feature that would alter the result of the test suite.
[CMake]: https://cmake.org
[Makefile]: https://www.gnu.org/software/make/

130
docs/docs/cli.md Normal file
View file

@ -0,0 +1,130 @@
---
sidebar_position: 4
---
# The qjs and qjsc CLI tools
## `qjs` - The QuickJS JavaScript interpreter
The `qjs` executable runs the JavaScript interpreter. It includes a simple standard
library and REPL.
```
$ qjs
usage: qjs [options] [file [args]]
-h --help list options
-e --eval EXPR evaluate EXPR
-i --interactive go to interactive mode
-m --module load as ES6 module (default=autodetect)
--script load as ES6 script (default=autodetect)
-I --include file include an additional file
--std make 'std', 'os' and 'bjson' available to script
-T --trace trace memory allocation
-d --dump dump the memory usage stats
-D --dump-flags flags for dumping debug data (see DUMP_* defines)
-c --compile FILE compile the given JS file as a standalone executable
-o --out FILE output file for standalone executables
--exe select the executable to use as the base, defaults to the current one
--memory-limit n limit the memory usage to 'n' Kbytes
--stack-size n limit the stack size to 'n' Kbytes
--unhandled-rejection dump unhandled promise rejections
-q --quit just instantiate the interpreter and quit
```
The following dump flags are supported:
```
DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */
DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */
DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */
DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */
DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */
DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */
DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */
DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */
DUMP_FREE 0x200 /* dump every object free */
DUMP_GC 0x400 /* dump the occurrence of the automatic GC */
DUMP_GC_FREE 0x800 /* dump objects freed by the GC */
DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */
DUMP_PROMISE 0x2000 /* dump promise steps */
DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */
DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */
DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */
DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */
DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */
DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */
```
### Creating standalone executables
With the `qjs` CLI it's possible to create standalone executables that will bundle the given JavaScript file
alongside the binary.
```
$ qjs -c app.js -o app --exe qjs
```
The resulting `app` binary will have the same runtime dependencies as the `qjs` binary. This is acomplished
by compiling the target JavaScript file to bytecode and adding it a copy of the executable, with a little
trailer to help locate it. `--exe` expects the absolute path to `qjs`, e.g., `~/bin/qjs` or `$HOME/bin/qjs`.
Rather than using the current executable, it's possible to use the `--exe` switch to create standalone
executables for other platforms.
No JavaScript bundling is performed, the specified JS file cannot depend on other files. A bundler such
as `esbuild` can be used to generate an app bundle which can then be turned into the executable.
```
npx esbuild my-app/index.js \
--bundle \
--outfile=app.js \
--external:qjs:* \
--minify \
--target=es2023 \
--platform=neutral \
--format=esm \
--main-fields=main,module
```
## `qjsc` - The QuickJS JavaScript compiler
The `qjsc` executable runs the JavaScript compiler, it can generate bytecode from
source files which can then be embedded in an executable, or it can generate the necessary
scaffolding to build a C application which embeds QuickJS.
```
$ qjsc
usage: qjsc [options] [files]
options are:
-b output raw bytecode instead of C code
-e output main() and bytecode in a C file
-o output set the output filename
-n script_name set the script name (as used in stack traces)
-N cname set the C name of the generated data
-m compile as JavaScript module (default=autodetect)
-D module_name compile a dynamically loaded module or worker
-M module_name[,cname] add initialization code for an external C module
-p prefix set the prefix of the generated C names
-s strip the source code, specify twice to also strip debug info
-S n set the maximum stack size to 'n' bytes (default=262144)
```
Here is an example on how to create a standalone executable that embeds QuickJS
and the `examples/hello.js` JavaScript file:
```bash
# Make sure you are in the QuickJS source directory.
$ cc hello.c cutils.c libbf.c libregexp.c libunicode.c quickjs.c quickjs-libc.c -I. -o hello
```
The resulting binary `hello` will be in the current directory.
```bash
$ ./hello
Hello World
```
:::note
See the ["Creating standalone executables"](#creating-standalone-executables) section for a simpler way.
:::

View file

@ -0,0 +1,7 @@
{
"label": "Developer Guide",
"position": 6,
"link": {
"type": "generated-index"
}
}

View file

@ -0,0 +1,3 @@
# API Reference
WIP.

View file

@ -0,0 +1,117 @@
# Internals
## Bytecode
The compiler generates bytecode directly with no intermediate
representation such as a parse tree, hence it is very fast. Several
optimizations passes are done over the generated bytecode.
A stack-based bytecode was chosen because it is simple and generates
compact code.
For each function, the maximum stack size is computed at compile time so that
no runtime stack overflow tests are needed.
A separate compressed line number table is maintained for the debug
information.
Access to closure variables is optimized and is almost as fast as local
variables.
Direct `eval` in strict mode is optimized.
## Runtime
### Strings
Strings are stored either as an 8 bit or a 16 bit array of
characters. Hence random access to characters is always fast.
The C API provides functions to convert JavaScript Strings to C UTF-8 encoded
strings. The most common case where the JavaScript string contains
only ASCII characters involves no copying.
### Objects
The object shapes (object prototype, property names and flags) are shared
between objects to save memory.
Arrays with no holes (except at the end of the array) are optimized.
TypedArray accesses are optimized.
### Atoms
Object property names and some strings are stored as Atoms (unique
strings) to save memory and allow fast comparison. Atoms are
represented as a 32 bit integer. Half of the atom range is reserved for
immediate integer literals from 0 to 2^31-1.
### Numbers
Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754
floating point values. Most operations have fast paths for the 32-bit
integer case.
### Garbage collection
Reference counting is used to free objects automatically and
deterministically. A separate cycle removal pass is done when the allocated
memory becomes too large. The cycle removal algorithm only uses the
reference counts and the object content, so no explicit garbage
collection roots need to be manipulated in the C code.
### JSValue
It is a JavaScript value which can be a primitive type (such as
Number, String, ...) or an Object. NaN boxing is used in the 32-bit version
to store 64-bit floating point numbers. The representation is
optimized so that 32-bit integers and reference counted values can be
efficiently tested.
In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The
rationale is that in 64-bit code memory usage is less critical.
In both cases (32 or 64 bits), JSValue exactly fits two CPU registers,
so it can be efficiently returned by C functions.
### Function call
The engine is optimized so that function calls are fast. The system
stack holds the JavaScript parameters and local variables.
### RegExp
A specific regular expression engine was developed. It is both small
and efficient and supports all the ES2020+ features including the
Unicode properties. As the JavaScript compiler, it directly generates
bytecode without a parse tree.
Backtracking with an explicit stack is used so that there is no
recursion on the system stack. Simple quantifiers are specifically
optimized to avoid recursions.
Infinite recursions coming from quantifiers with empty terms are
avoided.
The full regexp library weighs about 15 KiB (x86 code), excluding the
Unicode library.
### Unicode
A specific Unicode library was developed so that there is no
dependency on an external large Unicode library such as ICU. All the
Unicode tables are compressed while keeping a reasonable access
speed.
The library supports case conversion, Unicode normalization, Unicode
script queries, Unicode general category queries and all Unicode
binary properties.
The full Unicode library weighs about 45 KiB (x86 code).
### BigInt
BigInt is implemented with the [libbf](https://bellard.org/libbf) library.
It weights about 90 KiB (x86 code) and provides arbitrary precision IEEE 754 floating
point operations and transcendental functions with exact rounding.

View file

@ -0,0 +1,113 @@
---
sidebar_position: 1
---
# The QuickJS C API
The C API was designed to be simple and efficient. The C API is
defined in the header `quickjs.h`.
## Runtime and contexts
`JSRuntime` represents a JavaScript runtime corresponding to an
object heap. Several runtimes can exist at the same time but they
cannot exchange objects. Inside a given runtime, no multi-threading is
supported.
`JSContext` represents a JavaScript context (or Realm). Each
JSContext has its own global objects and system objects. There can be
several JSContexts per JSRuntime and they can share objects, similar
to frames of the same origin sharing JavaScript objects in a
web browser.
## JSValue
`JSValue` represents a JavaScript value which can be a primitive
type or an object. Reference counting is used, so it is important to
explicitly duplicate (`JS_DupValue()`, increment the reference
count) or free (`JS_FreeValue()`, decrement the reference count)
JSValues.
## C functions
C functions can be created with
`JS_NewCFunction()`. `JS_SetPropertyFunctionList()` is a
shortcut to easily add functions, setters and getters properties to a
given object.
Unlike other embedded JavaScript engines, there is no implicit stack,
so C functions get their parameters as normal C parameters. As a
general rule, C functions take constant `JSValue`s as parameters
(so they don't need to free them) and return a newly allocated (=live)
`JSValue`.
## Exceptions
Most C functions can return a JavaScript exception. It
must be explicitly tested and handled by the C code. The specific
`JSValue` `JS_EXCEPTION` indicates that an exception
occurred. The actual exception object is stored in the
`JSContext` and can be retrieved with `JS_GetException()`.
## Script evaluation
Use `JS_Eval()` to evaluate a script or module source.
If the script or module was compiled to bytecode with `qjsc`, it
can be evaluated by calling `js_std_eval_binary()`. The advantage
is that no compilation is needed so it is faster and smaller because
the compiler can be removed from the executable if no `eval` is
required.
Note: the bytecode format is linked to a given QuickJS
version. Moreover, no security check is done before its
execution. Hence the bytecode should not be loaded from untrusted
sources.
## JS Classes
C opaque data can be attached to a JavaScript object. The type of the
C opaque data is determined with the class ID (`JSClassID`) of
the object. Hence the first step is to register a new class ID and JS
class (`JS_NewClassID()`, `JS_NewClass()`). Then you can
create objects of this class with `JS_NewObjectClass()` and get or
set the C opaque point with `JS_GetOpaque()` / `JS_SetOpaque()`.
When defining a new JS class, it is possible to declare a finalizer
which is called when the object is destroyed. The finalizer should be
used to release C resources. It is invalid to execute JS code from
it. A `gc_mark` method can be provided so that the cycle removal
algorithm can find the other objects referenced by this object. Other
methods are available to define exotic object behaviors.
The Class ID are allocated per-runtime. The
`JSClass` are allocated per `JSRuntime`. `JS_SetClassProto()`
is used to define a prototype for a given class in a given
`JSContext`. `JS_NewObjectClass()` sets this prototype in the
created object.
Examples are available in `quickjs-libc.c`.
## C Modules
Native ES6 modules are supported and can be dynamically or statically
linked. The standard library `quickjs-libc.c` is a good example
of a native module.
## Memory handling
Use `JS_SetMemoryLimit()` to set a global memory allocation limit
to a given `JSRuntime`.
Custom memory allocation functions can be provided with `JS_NewRuntime2()`.
The maximum system stack size can be set with `JS_SetMaxStackSize()`.
## Execution timeout and interrupts
Use `JS_SetInterruptHandler()` to set a callback which is
regularly called by the engine when it is executing code. This
callback can be used to implement an execution timeout.
It is used by the command line interpreter to implement a
`Ctrl-C` handler.

68
docs/docs/diff.md Normal file
View file

@ -0,0 +1,68 @@
# Differences with bellard/quickjs
This project aims to be a drop-in replacement for those already using QuickJS.
Minimal API changes might be necessary.
## Community development
NG is developed in the open, interacting with the wider community and through
these interactions many improvements have already been made, including the incorporation
of patches previously maintained in other forks.
Each PR is reviewed, iterated on, and merged in GitHub.
To date, NG has had over 40 distinct contributors and over 400 PRs.
## Consistent release cadence
As the project moves forward, a steady cadence of releases has been maintained, with an
average of a new release every 2 months.
## Testing
Since its inception testing has been a focus. Each PR is tested in over 50 configurations,
involving different operating systems, build types and sanitizers.
The `test262` suite is also ran for every change.
## Cross-platform support
In order to better support other platforms such as Windows the build system was
changed to use [CMake].
In addition, Windows is treated as a first class citizen, with the addition of support
for the MSVC compiler.
[CMake]: https://cmake.org/
## Performance
While being an interpreter limits the performance in comparison with other engines which
use a JIT, several significant performance improvements have been made:
- Opcode fusion
- Polymorphic inline caching
- Memory allocation improvements
- Improved parse speeds
## New ECMAScript APIs
The main focus of NG is to deliver state-of-the-art JavaScript features. Typically once they
are stable (stage 4) but sometimes even at earlier stages. Here is a non-exhaustive list
of ES features present in NG:
- Resizable ArrayBuffer
- Float16Array
- WeakRef
- FinalizationRegistry
- Iterator Helpers
- Promise.try
- Error.isError
- Set operations
Some non-standard but widely used APIs have also been added:
- V8's [stack trace API](https://v8.dev/docs/stack-trace-api)
- `Error.captureStackTrace`
- `Error.prepareStackTrace`
- `Error.stackTraceLimit`

11
docs/docs/es_features.md Normal file
View file

@ -0,0 +1,11 @@
---
sidebar_position: 7
---
# ECMAScript Features
QuickJS aims to support the latest available ECMAScript features once they hit the spec.
Progress on _test262_ compliance can be checked [here](https://test262.fyi/#|qjs_ng).
Due to size constraints it is unlikely QuickJS will ever support the [Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) APIs.

34
docs/docs/installation.md Normal file
View file

@ -0,0 +1,34 @@
---
sidebar_position: 3
---
# Installation
Installing QuickJS is simple, and we provide several ways to do so.
## Build from source
If you built it from source as outlined in [building](./building) you can just run:
```bash
make install
```
and it will be installed in your system. The default installation path is `/usr/local`.
## Using a prebuilt binary
Each [release on GitHub] includes binaries for several systems and architectures.
## Using jsvu
As of version 2.2.0 of `jsvu`, QuickJS-ng will be installed when the `quickjs` engine is requested.
```bash
npm install jsvu -g
```
[release on GitHub]: https://github.com/quickjs-ng/quickjs/releases

33
docs/docs/intro.md Normal file
View file

@ -0,0 +1,33 @@
---
slug: /
sidebar_position: 1
sidebar_label: Welcome
---
# Welcome to QuickJS-NG
QuickJS is a small and embeddable JavaScript engine. It aims to support the latest
[ECMAScript] specification.
This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development.
This project is focused on (but not limited to):
- Community development
- Testing
- Cross-platform support
- ES features
You can check the differences with the original project [here.](./diff)
:::note
This site is under construction, the entire API is not yet documented.
:::
## Getting Started
Head over to [building](./building) if you want to build QuickJS from source or [installation](./installation)
for installing it from prebuilt binaries.
[ECMAScript]: https://tc39.es/ecma262/
[original QuickJS project]: https://bellard.org/quickjs

28
docs/docs/projects.md Normal file
View file

@ -0,0 +1,28 @@
# Projects using NG
Here is a list of projects currently using, supporting or migrating to QuickJS-NG.
If you want yours to be listed here, please open a PR!
## [txiki.js](https://github.com/saghul/txiki.js)
A tiny JavaScript runtime.
## [radare2](https://github.com/radareorg/radare2)
Reverse engineering framework.
## [rquickjs](https://github.com/DelSkayn/rquickjs)
High level Rust bindings.
## [llrt](https://github.com/awslabs/llrt)
Lightweight JS runtime for serverless applications.
## [nx.js](https://github.com/TooTallNate/nx.js)
JavaScript runtime for Nintendo Switch homebrew applications.
## [quickjs-rusty](https://github.com/Icemic/quickjs-rusty)
Rust wrapper focus on embedding-ready and no-pain type conversion and interoperability.

553
docs/docs/stdlib.md Normal file
View file

@ -0,0 +1,553 @@
---
sidebar_position: 5
---
# Standard library
The standard libary is provided as part of the `qjs` executable and the `quickjs-libc.c` source file
and it's not part of the core engine.
## Globals
### `argv0`
Provides the executable path.
### `scriptArgs`
Provides the command line arguments. The first argument is the script name.
### `print(...args)`
Print the arguments separated by spaces and a trailing newline.
### `console.log(...args)`
Same as `print()`.
### `navigator.userAgent`
Returns `quickjs-ng/<version>`.
### `gc()`
Shorthand for `std.gc()`.
## `qjs:bjson` module
### `bjson.write(obj, [flags])`
Serializes the given object into the QuickJS internal serialization format.
Returns an ArrayBuffer with the serialized data.
Supported flags:
- `WRITE_OBJ_BYTECODE`: allow serializing functions and modules
- `WRITE_OBJ_REFERENCE`: allow serializing object references
- `WRITE_OBJ_SAB`: allow serializing SharedArrayBuffer instances
- `WRITE_OBJ_STRIP_DEBUG`: strip debugging information when serializing
- `WRITE_OBJ_STRIP_SOURCE`: strip the source information when serializing
### `bjson.read(buf, [pos], [len], [flags])`
De-serialize the given ArrayBuffer (in QuickJS internal serialization format) back into a JavaScript value.
Supported flags:
- `READ_OBJ_BYTECODE`: allow de-serializing functions and modules
- `READ_OBJ_REFERENCE`: allow de-serializing object references
- `READ_OBJ_SAB`: allow de-serializing SharedArrayBuffer instances
## `qjs:os` module
The `os` module provides Operating System specific functions:
- low level file access
- signals
- timers
- basic asynchronous I/O
- workers (threads)
The OS functions usually return 0 if OK or an OS specific negative
error code.
### `open(filename, flags, mode = 0o666)`
Open a file. Return a handle or < 0 if error.
Supported flags:
- `O_RDONLY`
- `O_WRONLY`
- `O_RDWR`
- `O_APPEND`
- `O_CREAT`
- `O_EXCL`
- `O_TRUNC`
POSIX open flags.
- `O_TEXT`
(Windows specific). Open the file in text mode. The default is binary mode.
### `close(fd)`
Close the file handle `fd`.
### `seek(fd, offset, whence)`
Seek in the file. Use `std.SEEK_*` for
`whence`. `offset` is either a number or a BigInt. If
`offset` is a BigInt, a BigInt is returned too.
### `read(fd, buffer, offset, length)`
Read `length` bytes from the file handle `fd` to the
ArrayBuffer `buffer` at byte position `offset`.
Return the number of read bytes or < 0 if error.
### `write(fd, buffer, offset, length)`
Write `length` bytes to the file handle `fd` from the
ArrayBuffer `buffer` at byte position `offset`.
Return the number of written bytes or < 0 if error.
### `isatty(fd)`
Return `true` is `fd` is a TTY (terminal) handle.
### `ttyGetWinSize(fd)`
Return the TTY size as `[width, height]` or `null` if not available.
### `ttySetRaw(fd)`
Set the TTY in raw mode.
### `remove(filename)`
Remove a file. Return 0 if OK or `-errno`.
### `rename(oldname, newname)`
Rename a file. Return 0 if OK or `-errno`.
### `realpath(path)`
Return `[str, err]` where `str` is the canonicalized absolute
pathname of `path` and `err` the error code.
### `getcwd()`
Return `[str, err]` where `str` is the current working directory
and `err` the error code.
### `chdir(path)`
Change the current directory. Return 0 if OK or `-errno`.
### `mkdir(path, mode = 0o777)`
Create a directory at `path`. Return 0 if OK or `-errno`.
### `stat(path)` / `lstat(path)`
Return `[obj, err]` where `obj` is an object containing the
file status of `path`. `err` is the error code. The
following fields are defined in `obj`: `dev`, `ino`, `mode`, `nlink`,
`uid`, `gid`, `rdev`, `size`, `blocks`, `atime`, `mtime`, `ctime`. The times are
specified in milliseconds since 1970. `lstat()` is the same as
`stat()` excepts that it returns information about the link
itself.
- `S_IFMT`
- `S_IFIFO`
- `S_IFCHR`
- `S_IFDIR`
- `S_IFBLK`
- `S_IFREG`
- `S_IFSOCK`
- `S_IFLNK`
- `S_ISGID`
- `S_ISUID`
Constants to interpret the `mode` property returned by
`stat()`. They have the same value as in the C system header
`sys/stat.h`.
### `utimes(path, atime, mtime)`
Change the access and modification times of the file `path`. The
times are specified in milliseconds since 1970. Return 0 if OK or `-errno`.
### `symlink(target, linkpath)`
Create a link at `linkpath` containing the string `target`. Return 0 if OK or `-errno`.
### `readlink(path)`
Return `[str, err]` where `str` is the link target and `err`
the error code.
### `readdir(path)`
Return `[array, err]` where `array` is an array of strings
containing the filenames of the directory `path`. `err` is
the error code.
### `setReadHandler(fd, func)`
Add a read handler to the file handle `fd`. `func` is called
each time there is data pending for `fd`. A single read handler
per file handle is supported. Use `func = null` to remove the
handler.
### `setWriteHandler(fd, func)`
Add a write handler to the file handle `fd`. `func` is
called each time data can be written to `fd`. A single write
handler per file handle is supported. Use `func = null` to remove
the handler.
### `signal(signal, func)`
Call the function `func` when the signal `signal`
happens. Only a single handler per signal number is supported. Use
`null` to set the default handler or `undefined` to ignore
the signal. Signal handlers can only be defined in the main thread.
- `SIGINT`
- `SIGABRT`
- `SIGFPE`
- `SIGILL`
- `SIGSEGV`
- `SIGTERM`
POSIX signal numbers.
### `kill(pid, sig)`
Send the signal `sig` to the process `pid`.
### `exec(args[, options])`
Execute a process with the arguments `args`. `options` is an
object containing optional parameters:
- `block` - Boolean (default = true). If true, wait until the process is
terminated. In this case, `exec` return the exit code if positive
or the negated signal number if the process was interrupted by a
signal. If false, do not block and return the process id of the child.
- `usePath` - Boolean (default = true). If true, the file is searched in the
`PATH` environment variable.
- `file` - String (default = `args[0]`). Set the file to be executed.
- `cwd` - String. If present, set the working directory of the new process.
- `stdin`, `stdout`, `stderr` - If present, set the handle in the child for stdin, stdout or stderr.
- `env` - Object. If present, set the process environment from the object
key-value pairs. Otherwise use the same environment as the current
process.
- `uid` - Integer. If present, the process uid with `setuid`.
- `gid` - Integer. If present, the process gid with `setgid`.
### `waitpid(pid, options)`
`waitpid` Unix system call. Return the array `[ret, status]`.
`ret` contains `-errno` in case of error.
- `WNOHANG`
Constant for the `options` argument of `waitpid`.
### `dup(fd)`
`dup` Unix system call.
### `dup2(oldfd, newfd)`
`dup2` Unix system call.
### `pipe()`
`pipe` Unix system call. Return two handles as `[read_fd, write_fd]` or null in case of error.
### `sleep(delay_ms)`
Sleep during `delay_ms` milliseconds.
### `sleepAsync(delay_ms)`
Asynchronouse sleep during `delay_ms` milliseconds. Returns a promise. Example:
```js
await os.sleepAsync(500);
```
### `setTimeout(func, delay)`
Call the function `func` after `delay` ms. Return a timer ID.
### `clearTimeout(id)`
Cancel a timer.
### `platform`
Return a string representing the platform: `"linux"`, `"darwin"`, `"win32"` or `"js"`.
### `Worker(module_filename)`
Constructor to create a new thread (worker) with an API close to that of
`WebWorkers`. `module_filename` is a string specifying the
module filename which is executed in the newly created thread. As for
dynamically imported module, it is relative to the current script or
module path. Threads normally don't share any data and communicate
between each other with messages. Nested workers are not supported. An
example is available in `tests/test_worker.js`.
The worker class has the following static properties:
- `parent` - In the created worker, `Worker.parent` represents the parent
worker and is used to send or receive messages.
The worker instances have the following properties:
- `postMessage(msg)` - Send a message to the corresponding worker. `msg` is cloned in
the destination worker using an algorithm similar to the `HTML`
structured clone algorithm. `SharedArrayBuffer` are shared
between workers.
- `onmessage` - Getter and setter. Set a function which is called each time a
message is received. The function is called with a single
argument. It is an object with a `data` property containing the
received message. The thread is not terminated if there is at least
one non `null` `onmessage` handler.
## `qjs:std` module
The `std` module provides wrappers to libc (`stdlib.h` and `stdio.h`) and a few other utilities.
### `exit(n)`
Exit the process.
### `evalScript(str, options = undefined)`
Evaluate the string `str` as a script (global
eval). `options` is an optional object containing the following
optional properties:
- `backtrace_barrier` - Boolean (default = false). If true, error backtraces do not list the
stack frames below the evalScript.
- `async` - Boolean (default = false). If true, `await` is accepted in the
script and a promise is returned. The promise is resolved with an
object whose `value` property holds the value returned by the
script.
### `loadScript(filename)`
Evaluate the file `filename` as a script (global eval).
### `loadFile(filename, [options])`
Load the file `filename` and return it as a string assuming UTF-8
encoding. Return `null` in case of I/O error.
If `options.binary` is set to `true` a `Uint8Array` is returned instead.
### `open(filename, flags, errorObj = undefined)`
Open a file (wrapper to the libc `fopen()`). Return the FILE
object or `null` in case of I/O error. If `errorObj` is not
undefined, set its `errno` property to the error code or to 0 if
no error occurred.
### `popen(command, flags, errorObj = undefined)`
Open a process by creating a pipe (wrapper to the libc
`popen()`). Return the FILE
object or `null` in case of I/O error. If `errorObj` is not
undefined, set its `errno` property to the error code or to 0 if
no error occurred.
### `fdopen(fd, flags, errorObj = undefined)`
Open a file from a file handle (wrapper to the libc
`fdopen()`). Return the FILE
object or null` in case of I/O error. If `errorObj` is not
undefined, set its `errno` property to the error code or to 0 if
no error occurred.
### `tmpfile(errorObj = undefined)`
Open a temporary file. Return the FILE
object or `null` in case of I/O error. If `errorObj` is not
undefined, set its `errno` property to the error code or to 0 if
no error occurred.
### `puts(str)`
Equivalent to `std.out.puts(str)`.
### `printf(fmt, ...args)`
Equivalent to `std.out.printf(fmt, ...args)`.
### `sprintf(fmt, ...args)`
Equivalent to the libc sprintf().
### `in`, `out`, `err`
Wrappers to the libc file `stdin`, `stdout`, `stderr`.
### `Error`
Enumeration object containing the integer value of common errors
(additional error codes may be defined):
- `EINVAL`
- `EIO`
- `EACCES`
- `EEXIST`
- `ENOSPC`
- `ENOSYS`
- `EBUSY`
- `ENOENT`
- `EPERM`
- `EPIPE`
### `strerror(errno)`
Return a string that describes the error `errno`.
### `gc()`
Manually invoke the cycle removal algorithm. The cycle removal
algorithm is automatically started when needed, so this function is
useful in case of specific memory constraints or for testing.
### `getenv(name)`
Return the value of the environment variable `name` or
`undefined` if it is not defined.
### `setenv(name, value)`
Set the value of the environment variable `name` to the string
`value`.
### `unsetenv(name)`
Delete the environment variable `name`.
### `getenviron()`
Return an object containing the environment variables as key-value pairs.
### `urlGet(url, options = undefined)`
Download `url` using the `curl` command line
utility. `options` is an optional object containing the following
optional properties:
- `binary` - Boolean (default = false). If true, the response is an ArrayBuffer
instead of a string. When a string is returned, the data is assumed
to be UTF-8 encoded.
- `full` - Boolean (default = false). If true, return the an object contains
the properties `response` (response content),
`responseHeaders` (headers separated by CRLF), `status`
(status code). `response` is `null` is case of protocol or
network error. If `full` is false, only the response is
returned if the status is between 200 and 299. Otherwise `null`
is returned.
### `FILE`
File object.
#### `close()`
Close the file. Return 0 if OK or `-errno` in case of I/O error.
#### `puts(str)`
Outputs the string with the UTF-8 encoding.
#### `printf(fmt, ...args)`
Formatted printf.
The same formats as the standard C library `printf` are
supported. Integer format types (e.g. `%d`) truncate the Numbers
or BigInts to 32 bits. Use the `l` modifier (e.g. `%ld`) to
truncate to 64 bits.
#### `flush()`
Flush the buffered file.
#### `seek(offset, whence)`
Seek to a give file position (whence is
`std.SEEK_*`). `offset` can be a number or a BigInt. Return
0 if OK or `-errno` in case of I/O error.
- `SEEK_SET`
- `SEEK_CUR`
- `SEEK_END`
Constants for seek().
#### `tell()`
Return the current file position.
#### `tello()`
Return the current file position as a BigInt.
#### `eof()`
Return true if end of file.
#### `fileno()`
Return the associated OS handle.
#### `error()`
Return true if there was an error.
#### `clearerr()`
Clear the error indication.
#### `read(buffer, position, length)`
Read `length` bytes from the file to the ArrayBuffer `buffer` at byte
position `position` (wrapper to the libc `fread`).
#### `write(buffer, position, length)`
Write `length` bytes to the file from the ArrayBuffer `buffer` at byte
position `position` (wrapper to the libc `fwrite`).
#### `getline()`
Return the next line from the file, assuming UTF-8 encoding, excluding
the trailing line feed.
#### `readAsString(max_size = undefined)`
Read `max_size` bytes from the file and return them as a string
assuming UTF-8 encoding. If `max_size` is not present, the file
is read up its end.
#### `getByte()`
Return the next byte from the file. Return -1 if the end of file is reached.
#### `putByte(c)`
Write one byte to the file.

View file

@ -0,0 +1,18 @@
---
sidebar_position: 8
---
# Supported Platforms
| System | Supported versions | Notes |
|---|---|---|
| GNU/Linux | * | glibc and musl are supported |
| macOS | macOS >= 11 | Currently supported macOS releases |
| Windows | >= Windows 8 | VS >= 2022 and Clang are supported |
| FreeBSD | * | Limited testing |
| OpenBSD | * | Limited testing |
| NetBSD | * | Limited testing |
| Android | NDK >= 26.0.10792818 | Limited testing |
| iOS | * | Limited testing |
| MinGW | MinGW-w64 | |
| Other | N/A | Missing? Open a PR! |

114
docs/docusaurus.config.js Normal file
View file

@ -0,0 +1,114 @@
// @ts-check
// `@type` JSDoc annotations allow editor autocompletion and type checking
// (when paired with `@ts-check`).
// There are various equivalent ways to declare your Docusaurus config.
// See: https://docusaurus.io/docs/api/docusaurus-config
/** @type {import('@docusaurus/types').Config} */
const config = {
title: 'QuickJS-NG',
tagline: 'QuickJS, the Next Generation: a mighty JavaScript engine',
favicon: 'img/favicon.ico',
// Set the production url of your site here
url: 'https://quickjs-ng.github.io',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/quickjs/',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'quickjs-ng', // Usually your GitHub org/user name.
projectName: 'quickjs', // Usually your repo name.
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'throw',
// Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you
// may want to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
routeBasePath: '/',
sidebarPath: './sidebars.js',
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl: 'https://github.com/quickjs-ng/quickjs/tree/master/docs/',
},
blog: false,
theme: {
customCss: './src/css/custom.css',
},
}),
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
navbar: {
title: 'QuickJS-NG',
items: [
{
type: 'docSidebar',
sidebarId: 'docsSidebar',
position: 'left',
label: 'Documentation',
},
{
href: 'https://github.com/quickjs-ng/quickjs',
label: 'GitHub',
position: 'right',
},
],
},
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [
],
},
{
title: 'Community',
items: [
{
label: 'GitHub Discussions',
href: 'https://github.com/quickjs-ng/quickjs/discussions',
},
{
label: 'Matrix',
href: 'https://matrix.to/#/%23quickjs-ng%3Amatrix.org?via=matrix.org',
},
],
},
{
title: 'More',
items: [
{
label: 'GitHub',
href: 'https://github.com/quickjs-ng/quickjs',
},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} QuickJS-NG project contributors.`,
},
prism: {
},
}),
};
export default config;

14656
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

42
docs/package.json Normal file
View file

@ -0,0 +1,42 @@
{
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "3.5.2",
"@docusaurus/preset-classic": "3.5.2",
"@mdx-js/react": "3.0.1",
"clsx": "2.1.1",
"prism-react-renderer": "2.4.0",
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.5.2",
"@docusaurus/types": "3.5.2"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
}
}

20
docs/sidebars.js Normal file
View file

@ -0,0 +1,20 @@
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
docsSidebar: [{type: 'autogenerated', dirName: '.'}],
};
export default sidebars;

30
docs/src/css/custom.css Normal file
View file

@ -0,0 +1,30 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #2e8555;
--ifm-color-primary-dark: #29784c;
--ifm-color-primary-darker: #277148;
--ifm-color-primary-darkest: #205d3b;
--ifm-color-primary-light: #33925d;
--ifm-color-primary-lighter: #359962;
--ifm-color-primary-lightest: #3cad6e;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #25c2a0;
--ifm-color-primary-dark: #21af90;
--ifm-color-primary-darker: #1fa588;
--ifm-color-primary-darkest: #1a8870;
--ifm-color-primary-light: #29d5b0;
--ifm-color-primary-lighter: #32d8b4;
--ifm-color-primary-lightest: #4fddbf;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}

BIN
docs/static/img/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -35,8 +35,8 @@ static int fib(int n)
return fib(n - 1) + fib(n - 2);
}
static JSValue js_fib(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
static JSValue js_fib(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
int n, res;
if (JS_ToInt32(ctx, &n, argv[0]))
@ -61,7 +61,15 @@ static int js_fib_init(JSContext *ctx, JSModuleDef *m)
#define JS_INIT_MODULE js_init_module_fib
#endif
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
#ifndef JS_EXTERN
#ifdef _WIN32
#define JS_EXTERN __declspec(dllexport)
#else
#define JS_EXTERN
#endif
#endif
JS_EXTERN JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_fib_init);

View file

@ -1,9 +0,0 @@
function fib(n)
{
if (n <= 0)
return 0;
else if (n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}

View file

@ -1,6 +0,0 @@
/* example of JS module */
const fibModule = require("./fib_require.js");
console.log("Hello World");
console.log("fib(10)=", fib(10));

View file

@ -1,68 +0,0 @@
/*
* PI computation in Javascript using the QuickJS bigdecimal type
* (decimal floating point)
*/
"use strict";
/* compute PI with a precision of 'prec' digits */
function calc_pi(prec) {
const CHUD_A = 13591409m;
const CHUD_B = 545140134m;
const CHUD_C = 640320m;
const CHUD_C3 = 10939058860032000m; /* C^3/24 */
const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(C/12)*3 */
/* return [P, Q, G] */
function chud_bs(a, b, need_G) {
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2, b1;
if (a == (b - 1n)) {
b1 = BigDecimal(b);
G = (2m * b1 - 1m) * (6m * b1 - 1m) * (6m * b1 - 5m);
P = G * (CHUD_B * b1 + CHUD_A);
if (b & 1n)
P = -P;
G = G;
Q = b1 * b1 * b1 * CHUD_C3;
} else {
c = (a + b) >> 1n;
[P1, Q1, G1] = chud_bs(a, c, true);
[P2, Q2, G2] = chud_bs(c, b, need_G);
P = P1 * Q2 + P2 * G1;
Q = Q1 * Q2;
if (need_G)
G = G1 * G2;
else
G = 0m;
}
return [P, Q, G];
}
var n, P, Q, G;
/* number of serie terms */
n = BigInt(Math.ceil(prec / CHUD_DIGITS_PER_TERM)) + 10n;
[P, Q, G] = chud_bs(0n, n, false);
Q = BigDecimal.div(Q, (P + Q * CHUD_A),
{ roundingMode: "half-even",
maximumSignificantDigits: prec });
G = (CHUD_C / 12m) * BigDecimal.sqrt(CHUD_C,
{ roundingMode: "half-even",
maximumSignificantDigits: prec });
return Q * G;
}
(function() {
var r, n_digits, n_bits;
if (typeof scriptArgs != "undefined") {
if (scriptArgs.length < 2) {
print("usage: pi n_digits");
return;
}
n_digits = scriptArgs[1] | 0;
} else {
n_digits = 1000;
}
/* we add more digits to reduce the probability of bad rounding for
the last digits */
r = calc_pi(n_digits + 20);
print(r.toFixed(n_digits, "down"));
})();

View file

@ -1,66 +0,0 @@
/*
* PI computation in Javascript using the QuickJS bigfloat type
* (binary floating point)
*/
"use strict";
/* compute PI with a precision of 'prec' bits */
function calc_pi() {
const CHUD_A = 13591409n;
const CHUD_B = 545140134n;
const CHUD_C = 640320n;
const CHUD_C3 = 10939058860032000n; /* C^3/24 */
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */
/* return [P, Q, G] */
function chud_bs(a, b, need_G) {
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2;
if (a == (b - 1n)) {
G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n);
P = BigFloat(G * (CHUD_B * b + CHUD_A));
if (b & 1n)
P = -P;
G = BigFloat(G);
Q = BigFloat(b * b * b * CHUD_C3);
} else {
c = (a + b) >> 1n;
[P1, Q1, G1] = chud_bs(a, c, true);
[P2, Q2, G2] = chud_bs(c, b, need_G);
P = P1 * Q2 + P2 * G1;
Q = Q1 * Q2;
if (need_G)
G = G1 * G2;
else
G = 0l;
}
return [P, Q, G];
}
var n, P, Q, G;
/* number of serie terms */
n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n;
[P, Q, G] = chud_bs(0n, n, false);
Q = Q / (P + Q * BigFloat(CHUD_A));
G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C));
return Q * G;
}
(function() {
var r, n_digits, n_bits;
if (typeof scriptArgs != "undefined") {
if (scriptArgs.length < 2) {
print("usage: pi n_digits");
return;
}
n_digits = scriptArgs[1];
} else {
n_digits = 1000;
}
n_bits = Math.ceil(n_digits * Math.log2(10));
/* we add more bits to reduce the probability of bad rounding for
the last digits */
BigFloatEnv.setPrec( () => {
r = calc_pi();
print(r.toFixed(n_digits, BigFloatEnv.RNDZ));
}, n_bits + 32);
})();

View file

@ -43,8 +43,8 @@ static void js_point_finalizer(JSRuntime *rt, JSValue val)
}
static JSValue js_point_ctor(JSContext *ctx,
JSValueConst new_target,
int argc, JSValueConst *argv)
JSValue new_target,
int argc, JSValue *argv)
{
JSPointData *s;
JSValue obj = JS_UNDEFINED;
@ -74,7 +74,7 @@ static JSValue js_point_ctor(JSContext *ctx,
return JS_EXCEPTION;
}
static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic)
static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
if (!s)
@ -85,7 +85,7 @@ static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic)
return JS_NewInt32(ctx, s->y);
}
static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic)
static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, int magic)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
int v;
@ -100,8 +100,8 @@ static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue va
return JS_UNDEFINED;
}
static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
static JSValue js_point_norm(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
if (!s)
@ -123,10 +123,11 @@ static const JSCFunctionListEntry js_point_proto_funcs[] = {
static int js_point_init(JSContext *ctx, JSModuleDef *m)
{
JSValue point_proto, point_class;
JSRuntime *rt = JS_GetRuntime(ctx);
/* create the Point class */
JS_NewClassID(&js_point_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class);
JS_NewClassID(rt, &js_point_class_id);
JS_NewClass(rt, js_point_class_id, &js_point_class);
point_proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs));
@ -140,7 +141,15 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m)
return 0;
}
JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
#ifndef JS_EXTERN
#ifdef _WIN32
#define JS_EXTERN __declspec(dllexport)
#else
#define JS_EXTERN
#endif
#endif
JS_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_point_init);

View file

@ -1,6 +1,8 @@
/* example of JS module importing a C module */
import * as os from "qjs:os";
import { fib } from "./fib.so";
const isWin = os.platform === 'win32';
const { fib } = await import(`./fib.${isWin ? 'dll' : 'so'}`);
console.log("Hello World");
console.log("fib(10)=", fib(10));

View file

@ -1,5 +1,8 @@
/* example of JS module importing a C module */
import { Point } from "./point.so";
import * as os from "qjs:os";
const isWin = os.platform === 'win32';
const { Point } = await import(`./point.${isWin ? 'dll' : 'so'}`);
function assert(b, str)
{

23
fuzz.c Normal file
View file

@ -0,0 +1,23 @@
// clang -g -O1 -fsanitize=fuzzer -o fuzz fuzz.c
#include "quickjs.h"
#include "quickjs.c"
#include "cutils.c"
#include "libbf.c"
#include "libregexp.c"
#include "libunicode.c"
#include <stdlib.h>
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
{
JSRuntime *rt = JS_NewRuntime();
if (!rt)
exit(1);
JSContext *ctx = JS_NewContext(rt);
if (!ctx)
exit(1);
JSValueConst val = JS_ReadObject(ctx, buf, len, /*flags*/0);
JS_FreeValue(ctx, val);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}

View file

@ -1,27 +0,0 @@
libFuzzer support for QuickJS
=============================
Build QuickJS with libFuzzer support as follows:
CONFIG_CLANG=y make libfuzzer
This can be extended with sanitizer support to improve efficacy:
CONFIG_CLANG=y CONFIG_ASAN=y make libfuzzer
Currently, there are three fuzzing targets defined: fuzz_eval, fuzz_compile and fuzz_regexp.
The above build command will produce an executable binary for each of them, which can be
simply executed as:
./fuzz_eval
or with an initial corpus:
./fuzz_compile corpus_dir/
or with a predefined dictionary to improve its efficacy:
./fuzz_eval -dict fuzz/fuzz.dict
or with arbitrary CLI arguments provided by libFuzzer (https://llvm.org/docs/LibFuzzer.html).

View file

@ -1,257 +0,0 @@
"__loadScript"
"abs"
"acos"
"acosh"
"add"
"AggregateError"
"and"
"apply"
"Array"
"ArrayBuffer"
"asin"
"asinh"
"atan"
"atan2"
"atanh"
"Atomics"
"BigDecimal"
"BigFloat"
"BigFloatEnv"
"BigInt"
"BigInt64Array"
"BigUint64Array"
"Boolean"
"cbrt"
"ceil"
"chdir"
"clearTimeout"
"close"
"clz32"
"compareExchange"
"console"
"construct"
"cos"
"cosh"
"DataView"
"Date"
"decodeURI"
"decodeURIComponent"
"defineProperty"
"deleteProperty"
"dup"
"dup2"
"E"
"encodeURI"
"encodeURIComponent"
"err"
"Error"
"escape"
"eval"
"EvalError"
"evalScript"
"exchange"
"exec"
"exit"
"exp"
"expm1"
"fdopen"
"Float32Array"
"Float64Array"
"floor"
"fround"
"Function"
"gc"
"get"
"getcwd"
"getenv"
"getenviron"
"getOwnPropertyDescriptor"
"getpid"
"getPrototypeOf"
"globalThis"
"has"
"hypot"
"imul"
"in"
"Infinity"
"Int16Array"
"Int32Array"
"Int8Array"
"InternalError"
"isatty"
"isExtensible"
"isFinite"
"isLockFree"
"isNaN"
"iterateBuiltIns"
"JSON"
"kill"
"length"
"LN10"
"LN2"
"load"
"loadFile"
"loadScript"
"log"
"log10"
"LOG10E"
"log1p"
"log2"
"LOG2E"
"lstat"
"Map"
"Math"
"max"
"min"
"mkdir"
"NaN"
"notify"
"now"
"Number"
"O_APPEND"
"O_CREAT"
"O_EXCL"
"O_RDONLY"
"O_RDWR"
"O_TRUNC"
"O_WRONLY"
"Object"
"open"
"Operators"
"or"
"os"
"out"
"ownKeys"
"parse"
"parseExtJSON"
"parseFloat"
"parseInt"
"PI"
"pipe"
"platform"
"popen"
"pow"
"preventExtensions"
"print"
"printf"
"Promise"
"Proxy"
"puts"
"random"
"RangeError"
"read"
"readdir"
"readlink"
"realpath"
"ReferenceError"
"Reflect"
"RegExp"
"remove"
"rename"
"round"
"S_IFBLK"
"S_IFCHR"
"S_IFDIR"
"S_IFIFO"
"S_IFLNK"
"S_IFMT"
"S_IFREG"
"S_IFSOCK"
"S_ISGID"
"S_ISUID"
"scriptArgs"
"seek"
"SEEK_CUR"
"SEEK_END"
"SEEK_SET"
"set"
"Set"
"setenv"
"setPrototypeOf"
"setReadHandler"
"setTimeout"
"setWriteHandler"
"SharedArrayBuffer"
"SIGABRT"
"SIGALRM"
"SIGCHLD"
"SIGCONT"
"SIGFPE"
"SIGILL"
"SIGINT"
"sign"
"signal"
"SIGPIPE"
"SIGQUIT"
"SIGSEGV"
"SIGSTOP"
"SIGTERM"
"SIGTSTP"
"SIGTTIN"
"SIGTTOU"
"SIGUSR1"
"SIGUSR2"
"sin"
"sinh"
"sleep"
"sleepAsync"
"sprintf"
"sqrt"
"SQRT1_2"
"SQRT2"
"stat"
"std"
"store"
"strerror"
"String"
"stringify"
"sub"
"Symbol"
"symlink"
"SyntaxError"
"tan"
"tanh"
"tmpfile"
"trunc"
"ttyGetWinSize"
"ttySetRaw"
"TypeError"
"Uint16Array"
"Uint32Array"
"Uint8Array"
"Uint8ClampedArray"
"undefined"
"unescape"
"unsetenv"
"URIError"
"urlGet"
"utimes"
"wait"
"waitpid"
"WeakMap"
"WeakSet"
"WNOHANG"
"Worker"
"write"
"xor"
"v0"
"v1"
"v2"
"v3"
"v4"
"v5"
"v6"
"v7"
"v8"
"v9"
"v10"
"v11"
"v12"
"v13"
"v14"
"v15"
"v16"
"v17"
"v18"
"v19"
"v20"

View file

@ -1,62 +0,0 @@
/* Copyright 2020 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <string.h>
#include "fuzz/fuzz_common.h"
// handle timeouts from infinite loops
static int interrupt_handler(JSRuntime *rt, void *opaque)
{
nbinterrupts++;
return (nbinterrupts > 100);
}
void reset_nbinterrupts() {
nbinterrupts = 0;
}
void test_one_input_init(JSRuntime *rt, JSContext *ctx) {
// 64 Mo
JS_SetMemoryLimit(rt, 0x4000000);
// 64 Kb
JS_SetMaxStackSize(rt, 0x10000);
JS_AddIntrinsicBigFloat(ctx);
JS_AddIntrinsicBigDecimal(ctx);
JS_AddIntrinsicOperators(ctx);
JS_EnableBignumExt(ctx, 1);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);
js_std_add_helpers(ctx, 0, NULL);
// Load os and std
js_std_init_handlers(rt);
js_init_module_std(ctx, "std");
js_init_module_os(ctx, "os");
const char *str = "import * as std from 'std';\n"
"import * as os from 'os';\n"
"globalThis.std = std;\n"
"globalThis.os = os;\n";
JSValue std_val = JS_Eval(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
if (!JS_IsException(std_val)) {
js_module_set_import_meta(ctx, std_val, 1, 1);
std_val = JS_EvalFunction(ctx, std_val);
} else {
js_std_dump_error(ctx);
}
std_val = js_std_await(ctx, std_val);
JS_FreeValue(ctx, std_val);
}

View file

@ -1,22 +0,0 @@
/* Copyright 2020 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "quickjs.h"
#include "quickjs-libc.h"
static int nbinterrupts = 0;
void reset_nbinterrupts();
void test_one_input_init(JSRuntime *rt, JSContext *ctx);

View file

@ -1,93 +0,0 @@
/* Copyright 2020 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "quickjs.h"
#include "quickjs-libc.h"
#include "cutils.h"
#include "fuzz/fuzz_common.h"
#include <stdint.h>
#include <stdio.h>
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size == 0)
return 0;
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
test_one_input_init(rt, ctx);
uint8_t *null_terminated_data = malloc(size + 1);
memcpy(null_terminated_data, data, size);
null_terminated_data[size] = 0;
JSValue obj = JS_Eval(ctx, (const char *)null_terminated_data, size, "<none>", JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_MODULE);
free(null_terminated_data);
//TODO target with JS_ParseJSON
if (JS_IsException(obj)) {
js_std_free_handlers(rt);
JS_FreeValue(ctx, obj);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
obj = js_std_await(ctx, obj);
size_t bytecode_size;
uint8_t* bytecode = JS_WriteObject(ctx, &bytecode_size, obj, JS_WRITE_OBJ_BYTECODE);
JS_FreeValue(ctx, obj);
if (!bytecode) {
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
obj = JS_ReadObject(ctx, bytecode, bytecode_size, JS_READ_OBJ_BYTECODE);
js_free(ctx, bytecode);
if (JS_IsException(obj)) {
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
reset_nbinterrupts();
/* this is based on
* js_std_eval_binary(ctx, bytecode, bytecode_size, 0);
* modified so as not to exit on JS exception
*/
JSValue val;
if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {
if (JS_ResolveModule(ctx, obj) < 0) {
JS_FreeValue(ctx, obj);
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
js_module_set_import_meta(ctx, obj, FALSE, TRUE);
}
val = JS_EvalFunction(ctx, obj);
if (JS_IsException(val)) {
js_std_dump_error(ctx);
} else {
js_std_loop(ctx);
}
JS_FreeValue(ctx, val);
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}

View file

@ -1,49 +0,0 @@
/* Copyright 2020 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "quickjs.h"
#include "quickjs-libc.h"
#include "fuzz/fuzz_common.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size == 0)
return 0;
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
test_one_input_init(rt, ctx);
uint8_t *null_terminated_data = malloc(size + 1);
memcpy(null_terminated_data, data, size);
null_terminated_data[size] = 0;
reset_nbinterrupts();
//the final 0 does not count (as in strlen)
JSValue val = JS_Eval(ctx, (const char *)null_terminated_data, size, "<none>", JS_EVAL_TYPE_GLOBAL);
free(null_terminated_data);
//TODO targets with JS_ParseJSON, JS_ReadObject
if (!JS_IsException(val)) {
js_std_loop(ctx);
JS_FreeValue(ctx, val);
}
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}

View file

@ -1,59 +0,0 @@
/* Copyright 2020 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "libregexp.h"
#include "quickjs-libc.h"
int lre_check_stack_overflow(void *opaque, size_t alloca_size) { return 0; }
void *lre_realloc(void *opaque, void *ptr, size_t size)
{
return realloc(ptr, size);
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
int len, ret, i;
uint8_t *bc;
char error_msg[64];
const uint8_t *input;
uint8_t *capture[255 * 2];
size_t size1 = size;
//Splits buffer into 2 sub buffers delimited by null character
for (i = 0; i < size; i++) {
if (data[i] == 0) {
size1 = i;
break;
}
}
if (size1 == size) {
//missing delimiter
return 0;
}
bc = lre_compile(&len, error_msg, sizeof(error_msg), (const char *) data,
size1, 0, NULL);
if (!bc) {
return 0;
}
input = data + size1 + 1;
ret = lre_exec(capture, bc, input, 0, size - (size1 + 1), 0, NULL);
if (ret == 1) {
lre_get_capture_count(bc);
}
free(bc);
return 0;
}

View file

@ -1,24 +0,0 @@
// Function to recursively iterate through built-in names.
function collectBuiltinNames(obj, visited = new Set(), result = new Set()) {
// Check if the object has already been visited to avoid infinite recursion.
if (visited.has(obj))
return;
// Add the current object to the set of visited objects
visited.add(obj);
// Get the property names of the current object
const properties = Object.getOwnPropertyNames(obj);
// Iterate through each property
for (var i=0; i < properties.length; i++) {
var property = properties[i];
if (property != "collectBuiltinNames" && typeof property != "number")
result.add(property);
// Check if the property is an object and if so, recursively iterate through its properties.
if (typeof obj[property] === 'object' && obj[property] !== null)
collectBuiltinNames(obj[property], visited, result);
}
return result;
}
// Start the recursive iteration with the global object.
console.log(Array.from(collectBuiltinNames(this)).join('\n'));

82
gen/function_source.c Normal file
View file

@ -0,0 +1,82 @@
/* File generated automatically by the QuickJS-ng compiler. */
#include "quickjs-libc.h"
const uint32_t qjsc_function_source_size = 320;
const uint8_t qjsc_function_source[320] = {
0x13, 0x05, 0x01, 0x30, 0x74, 0x65, 0x73, 0x74,
0x73, 0x2f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x2e, 0x6a, 0x73, 0x01, 0x0c, 0x61, 0x63,
0x74, 0x75, 0x61, 0x6c, 0x01, 0x02, 0x66, 0x01,
0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x01,
0x34, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34,
0x32, 0x20, 0x7d, 0x0d, 0xc0, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x20, 0xfa, 0x01, 0xa2,
0x01, 0x00, 0x05, 0x00, 0x03, 0x02, 0x01, 0x74,
0x05, 0xc2, 0x03, 0x02, 0x00, 0x30, 0xc4, 0x03,
0x04, 0x00, 0x70, 0xc2, 0x03, 0x04, 0x02, 0x70,
0x10, 0x00, 0x01, 0x00, 0xe4, 0x01, 0x00, 0x01,
0x00, 0xc6, 0x03, 0x00, 0x0d, 0xc4, 0x03, 0x01,
0x01, 0x0c, 0x43, 0xfa, 0x01, 0xc4, 0x03, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0xbd,
0x2a, 0x28, 0xc0, 0x03, 0x03, 0x01, 0x00, 0x1a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34, 0x32,
0x20, 0x7d, 0x0c, 0x03, 0xc3, 0x04, 0x08, 0xcd,
0x08, 0xeb, 0x05, 0xc0, 0x00, 0xe3, 0x29, 0x04,
0xe4, 0x00, 0x00, 0x00, 0xe2, 0x62, 0x00, 0x00,
0xdf, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00,
0x00, 0xca, 0x63, 0x00, 0x00, 0x66, 0x00, 0x00,
0xb0, 0xeb, 0x0b, 0x39, 0x95, 0x00, 0x00, 0x00,
0x63, 0x00, 0x00, 0xf0, 0x30, 0x62, 0x02, 0x00,
0x62, 0x01, 0x00, 0x39, 0x3b, 0x00, 0x00, 0x00,
0x66, 0x00, 0x00, 0x04, 0xe2, 0x00, 0x00, 0x00,
0x9e, 0x32, 0x01, 0x00, 0x03, 0x00, 0xcb, 0x63,
0x01, 0x00, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24,
0x00, 0x00, 0xcc, 0x63, 0x02, 0x00, 0x66, 0x00,
0x00, 0xb0, 0xeb, 0x0b, 0x39, 0x95, 0x00, 0x00,
0x00, 0x63, 0x02, 0x00, 0xf0, 0x30, 0x69, 0x02,
0x00, 0x69, 0x01, 0x00, 0x06, 0x2f, 0xc0, 0x03,
0x01, 0x01, 0x14, 0x00, 0x1c, 0x0a, 0x2a, 0x26,
0x03, 0x39, 0x28, 0x00, 0x10, 0x08, 0x27, 0x11,
0x12, 0x67, 0x0d, 0x26, 0x03, 0x39, 0x28, 0x00,
};
static JSContext *JS_NewCustomContext(JSRuntime *rt)
{
JSContext *ctx = JS_NewContext(rt);
if (!ctx)
return NULL;
return ctx;
}
int main(int argc, char **argv)
{
int r;
JSValue ret;
JSRuntime *rt;
JSContext *ctx;
r = 0;
rt = JS_NewRuntime();
js_std_set_worker_new_context_func(JS_NewCustomContext);
js_std_init_handlers(rt);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
ctx = JS_NewCustomContext(rt);
js_std_add_helpers(ctx, argc, argv);
js_std_eval_binary(ctx, qjsc_function_source, qjsc_function_source_size, 0);
ret = js_std_loop(ctx);
if (JS_IsException(ret)) {
js_std_dump_error1(ctx, ret);
r = 1;
}
JS_FreeValue(ctx, ret);
JS_FreeContext(ctx);
js_std_free_handlers(rt);
JS_FreeRuntime(rt);
return r;
}

109
gen/hello_module.c Normal file
View file

@ -0,0 +1,109 @@
/* File generated automatically by the QuickJS-ng compiler. */
#include "quickjs-libc.h"
const uint32_t qjsc_fib_module_size = 290;
const uint8_t qjsc_fib_module[290] = {
0x13, 0x03, 0x01, 0x2c, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62,
0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e,
0x6a, 0x73, 0x01, 0x06, 0x66, 0x69, 0x62, 0x01,
0x02, 0x6e, 0x0d, 0xc0, 0x03, 0x00, 0x01, 0x00,
0x00, 0xc2, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x20,
0xfa, 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x01,
0x01, 0x01, 0x09, 0x00, 0xc2, 0x03, 0x00, 0x01,
0x0c, 0x43, 0xfa, 0x01, 0xc2, 0x03, 0x01, 0x00,
0x01, 0x04, 0x01, 0x00, 0x1a, 0x01, 0xc4, 0x03,
0x00, 0x01, 0x00, 0xc2, 0x03, 0x00, 0x00, 0xd2,
0xb5, 0xa8, 0xeb, 0x03, 0xb5, 0x28, 0xd2, 0xb6,
0xad, 0xeb, 0x03, 0xb6, 0x28, 0xde, 0xd2, 0xb6,
0x9f, 0xf0, 0xde, 0xd2, 0xb7, 0x9f, 0xf0, 0x9e,
0x28, 0xc0, 0x03, 0x02, 0x08, 0x0e, 0x09, 0x0c,
0x27, 0x0a, 0x28, 0x02, 0x07, 0x08, 0x11, 0x0a,
0x07, 0x08, 0x07, 0x08, 0x8d, 0x01, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66,
0x69, 0x62, 0x28, 0x6e, 0x29, 0x0a, 0x7b, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
0x6e, 0x20, 0x3c, 0x3d, 0x20, 0x30, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30,
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c,
0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e,
0x20, 0x3d, 0x3d, 0x20, 0x31, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x3b,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73,
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x66, 0x69, 0x62, 0x28, 0x6e, 0x20, 0x2d,
0x20, 0x31, 0x29, 0x20, 0x2b, 0x20, 0x66, 0x69,
0x62, 0x28, 0x6e, 0x20, 0x2d, 0x20, 0x32, 0x29,
0x3b, 0x0a, 0x7d, 0x08, 0xeb, 0x05, 0xc0, 0x00,
0xe2, 0x29, 0x06, 0x2f, 0xc0, 0x03, 0x01, 0x01,
0x00, 0x00,
};
const uint32_t qjsc_hello_module_size = 187;
const uint8_t qjsc_hello_module[187] = {
0x13, 0x07, 0x01, 0x30, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c,
0x6c, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
0x65, 0x2e, 0x6a, 0x73, 0x01, 0x1e, 0x2e, 0x2f,
0x66, 0x69, 0x62, 0x5f, 0x6d, 0x6f, 0x64, 0x75,
0x6c, 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x06, 0x66,
0x69, 0x62, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73,
0x6f, 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67,
0x01, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
0x57, 0x6f, 0x72, 0x6c, 0x64, 0x01, 0x10, 0x66,
0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d,
0xc0, 0x03, 0x01, 0xc2, 0x03, 0x00, 0x00, 0x01,
0x00, 0xc4, 0x03, 0x00, 0x00, 0x0c, 0x20, 0xfa,
0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01,
0x00, 0x32, 0x00, 0xc4, 0x03, 0x00, 0x0c, 0x08,
0xeb, 0x02, 0x29, 0x39, 0xe3, 0x00, 0x00, 0x00,
0x43, 0xe4, 0x00, 0x00, 0x00, 0x04, 0xe5, 0x00,
0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, 0xe3,
0x00, 0x00, 0x00, 0x43, 0xe4, 0x00, 0x00, 0x00,
0x04, 0xe6, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,
0xbd, 0x0a, 0xf0, 0x24, 0x02, 0x00, 0x0e, 0x06,
0x2f, 0xc0, 0x03, 0x01, 0x01, 0x0c, 0x00, 0x04,
0x08, 0x00, 0x34, 0x10, 0x30, 0x0f, 0x34, 0x10,
0x2a, 0x20, 0x00,
};
static JSContext *JS_NewCustomContext(JSRuntime *rt)
{
JSContext *ctx = JS_NewContext(rt);
if (!ctx)
return NULL;
js_std_eval_binary(ctx, qjsc_fib_module, qjsc_fib_module_size, 1);
return ctx;
}
int main(int argc, char **argv)
{
int r;
JSValue ret;
JSRuntime *rt;
JSContext *ctx;
r = 0;
rt = JS_NewRuntime();
js_std_set_worker_new_context_func(JS_NewCustomContext);
js_std_init_handlers(rt);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
ctx = JS_NewCustomContext(rt);
js_std_add_helpers(ctx, argc, argv);
js_std_eval_binary(ctx, qjsc_hello_module, qjsc_hello_module_size, 0);
ret = js_std_loop(ctx);
if (JS_IsException(ret)) {
js_std_dump_error1(ctx, ret);
r = 1;
}
JS_FreeValue(ctx, ret);
JS_FreeContext(ctx);
js_std_free_handlers(rt);
JS_FreeRuntime(rt);
return r;
}

318
gen/standalone.c Normal file
View file

@ -0,0 +1,318 @@
/* File generated automatically by the QuickJS-ng compiler. */
#include <inttypes.h>
const uint32_t qjsc_standalone_size = 2466;
const uint8_t qjsc_standalone[2466] = {
0x13, 0x4d, 0x01, 0x1a, 0x73, 0x74, 0x61, 0x6e,
0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x6a,
0x73, 0x01, 0x0e, 0x71, 0x6a, 0x73, 0x3a, 0x73,
0x74, 0x64, 0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a,
0x6f, 0x73, 0x01, 0x12, 0x71, 0x6a, 0x73, 0x3a,
0x62, 0x6a, 0x73, 0x6f, 0x6e, 0x01, 0x22, 0x63,
0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x53, 0x74,
0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65,
0x01, 0x1a, 0x72, 0x75, 0x6e, 0x53, 0x74, 0x61,
0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x01,
0x06, 0x73, 0x74, 0x64, 0x01, 0x04, 0x6f, 0x73,
0x01, 0x0a, 0x62, 0x6a, 0x73, 0x6f, 0x6e, 0x01,
0x28, 0x4a, 0x53, 0x5f, 0x52, 0x45, 0x41, 0x44,
0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x42, 0x59, 0x54,
0x45, 0x43, 0x4f, 0x44, 0x45, 0x01, 0x2a, 0x4a,
0x53, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f,
0x42, 0x4a, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52,
0x45, 0x4e, 0x43, 0x45, 0x01, 0x2a, 0x4a, 0x53,
0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f,
0x42, 0x4a, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x43,
0x4f, 0x44, 0x45, 0x01, 0x2c, 0x4a, 0x53, 0x5f,
0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, 0x42,
0x4a, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45,
0x4e, 0x43, 0x45, 0x01, 0x32, 0x4a, 0x53, 0x5f,
0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, 0x42,
0x4a, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x5f,
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x01, 0x0e,
0x54, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x01,
0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x41,
0x73, 0x63, 0x69, 0x69, 0x01, 0x16, 0x64, 0x65,
0x63, 0x6f, 0x64, 0x65, 0x41, 0x73, 0x63, 0x69,
0x69, 0x01, 0x06, 0x74, 0x78, 0x74, 0x01, 0x02,
0x63, 0x01, 0x14, 0x63, 0x68, 0x61, 0x72, 0x43,
0x6f, 0x64, 0x65, 0x41, 0x74, 0x01, 0x06, 0x6d,
0x61, 0x70, 0x01, 0x06, 0x62, 0x75, 0x66, 0x01,
0x18, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61,
0x72, 0x43, 0x6f, 0x64, 0x65, 0x01, 0x0c, 0x69,
0x6e, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x0e, 0x6f,
0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x12,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x45, 0x78,
0x65, 0x01, 0x04, 0x6a, 0x73, 0x01, 0x08, 0x63,
0x6f, 0x64, 0x65, 0x01, 0x10, 0x62, 0x79, 0x74,
0x65, 0x63, 0x6f, 0x64, 0x65, 0x01, 0x16, 0x65,
0x78, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61,
0x6d, 0x65, 0x01, 0x06, 0x65, 0x78, 0x65, 0x01,
0x0e, 0x65, 0x78, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x01, 0x12, 0x6e, 0x65, 0x77, 0x42, 0x75, 0x66,
0x66, 0x65, 0x72, 0x01, 0x0c, 0x6e, 0x65, 0x77,
0x45, 0x78, 0x65, 0x01, 0x04, 0x64, 0x77, 0x01,
0x0a, 0x6e, 0x65, 0x77, 0x46, 0x64, 0x01, 0x10,
0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65,
0x01, 0x1e, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
0x20, 0x74, 0x6f, 0x20, 0x6f, 0x70, 0x65, 0x6e,
0x20, 0x01, 0x14, 0x65, 0x76, 0x61, 0x6c, 0x53,
0x63, 0x72, 0x69, 0x70, 0x74, 0x01, 0x18, 0x63,
0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x6f,
0x6e, 0x6c, 0x79, 0x01, 0x1c, 0x63, 0x6f, 0x6d,
0x70, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64,
0x75, 0x6c, 0x65, 0x01, 0x0a, 0x77, 0x72, 0x69,
0x74, 0x65, 0x01, 0x0a, 0x61, 0x72, 0x67, 0x76,
0x30, 0x01, 0x0c, 0x62, 0x69, 0x6e, 0x61, 0x72,
0x79, 0x01, 0x36, 0x66, 0x61, 0x69, 0x6c, 0x65,
0x64, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x70, 0x65,
0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74,
0x61, 0x62, 0x6c, 0x65, 0x3a, 0x20, 0x01, 0x0c,
0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x01, 0x10,
0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72,
0x01, 0x08, 0x53, 0x69, 0x7a, 0x65, 0x01, 0x0a,
0x4d, 0x61, 0x67, 0x69, 0x63, 0x01, 0x12, 0x4d,
0x61, 0x67, 0x69, 0x63, 0x53, 0x69, 0x7a, 0x65,
0x01, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53, 0x69,
0x7a, 0x65, 0x01, 0x12, 0x73, 0x65, 0x74, 0x55,
0x69, 0x6e, 0x74, 0x33, 0x32, 0x01, 0x08, 0x6f,
0x70, 0x65, 0x6e, 0x01, 0x10, 0x4f, 0x5f, 0x57,
0x52, 0x4f, 0x4e, 0x4c, 0x59, 0x01, 0x0e, 0x4f,
0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x01, 0x0e,
0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x01,
0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74,
0x65, 0x20, 0x01, 0x14, 0x62, 0x79, 0x74, 0x65,
0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x01, 0x0a,
0x63, 0x6c, 0x6f, 0x73, 0x65, 0x01, 0x3c, 0x66,
0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f,
0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74,
0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
0x20, 0x66, 0x69, 0x6c, 0x65, 0x01, 0x08, 0x66,
0x69, 0x6c, 0x65, 0x01, 0x02, 0x72, 0x01, 0x0e,
0x74, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x01,
0x0a, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x01, 0x0c,
0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x01, 0x04,
0x72, 0x62, 0x01, 0x08, 0x73, 0x65, 0x65, 0x6b,
0x01, 0x10, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x45,
0x4e, 0x44, 0x01, 0x18, 0x73, 0x65, 0x65, 0x6b,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20,
0x01, 0x08, 0x72, 0x65, 0x61, 0x64, 0x01, 0x40,
0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x65,
0x64, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79,
0x2c, 0x20, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x20,
0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x01, 0x12, 0x67, 0x65, 0x74, 0x55, 0x69, 0x6e,
0x74, 0x33, 0x32, 0x01, 0x10, 0x53, 0x45, 0x45,
0x4b, 0x5f, 0x53, 0x45, 0x54, 0x01, 0x0a, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x01, 0x14, 0x72, 0x65,
0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x01, 0x16, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x6d,
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x01, 0x10, 0x71,
0x75, 0x69, 0x63, 0x6b, 0x6a, 0x73, 0x32, 0x0d,
0xc0, 0x03, 0x03, 0xc2, 0x03, 0xc4, 0x03, 0xc6,
0x03, 0x02, 0x00, 0x0b, 0xc8, 0x03, 0x00, 0x0c,
0xca, 0x03, 0x00, 0x03, 0x00, 0xfc, 0x01, 0x00,
0x01, 0xfc, 0x01, 0x01, 0x02, 0xfc, 0x01, 0x02,
0x00, 0x0c, 0x20, 0x02, 0x01, 0xa2, 0x01, 0x00,
0x00, 0x00, 0x02, 0x0d, 0x04, 0x58, 0x00, 0xcc,
0x03, 0x00, 0x0d, 0xce, 0x03, 0x01, 0x0d, 0xd0,
0x03, 0x02, 0x0d, 0xd2, 0x03, 0x00, 0x0d, 0xd4,
0x03, 0x01, 0x0d, 0xd6, 0x03, 0x02, 0x0d, 0xd8,
0x03, 0x03, 0x0d, 0xda, 0x03, 0x04, 0x0d, 0xdc,
0x03, 0x05, 0x0d, 0xde, 0x03, 0x06, 0x01, 0xe0,
0x03, 0x07, 0x01, 0xc8, 0x03, 0x08, 0x01, 0xca,
0x03, 0x09, 0x01, 0x0c, 0x43, 0x02, 0x01, 0xde,
0x03, 0x01, 0x00, 0x01, 0x05, 0x00, 0x01, 0x1e,
0x01, 0xe2, 0x03, 0x00, 0x01, 0x00, 0x0c, 0x42,
0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00,
0x00, 0x0a, 0x01, 0xe4, 0x03, 0x00, 0x01, 0x00,
0xd2, 0x43, 0xf3, 0x00, 0x00, 0x00, 0xb5, 0x25,
0x01, 0x00, 0x39, 0xa6, 0x00, 0x00, 0x00, 0x11,
0xd2, 0x43, 0x5e, 0x00, 0x00, 0x00, 0xc1, 0x24,
0x01, 0x00, 0x43, 0xf4, 0x00, 0x00, 0x00, 0xc0,
0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x28,
0x0c, 0x43, 0x02, 0x01, 0xe0, 0x03, 0x01, 0x00,
0x01, 0x03, 0x00, 0x01, 0x21, 0x01, 0xea, 0x03,
0x00, 0x01, 0x00, 0x0c, 0x42, 0x02, 0x01, 0x00,
0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x0e, 0x01,
0xe4, 0x03, 0x00, 0x01, 0x00, 0x39, 0x97, 0x00,
0x00, 0x00, 0x43, 0xf6, 0x00, 0x00, 0x00, 0xd2,
0x25, 0x01, 0x00, 0x39, 0x94, 0x00, 0x00, 0x00,
0x43, 0x7b, 0x00, 0x00, 0x00, 0xd2, 0x24, 0x01,
0x00, 0x43, 0xf4, 0x00, 0x00, 0x00, 0xc0, 0x00,
0x24, 0x01, 0x00, 0x43, 0x5c, 0x00, 0x00, 0x00,
0xc1, 0x25, 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01,
0xc8, 0x03, 0x03, 0x0a, 0x03, 0x07, 0x08, 0x00,
0x86, 0x04, 0x0d, 0xee, 0x03, 0x00, 0x01, 0x00,
0xf0, 0x03, 0x00, 0x01, 0x00, 0xf2, 0x03, 0x00,
0x01, 0x00, 0xf4, 0x03, 0x01, 0x00, 0x30, 0xf6,
0x03, 0x01, 0x01, 0x30, 0xf8, 0x03, 0x01, 0x02,
0x30, 0xfa, 0x03, 0x01, 0x03, 0x30, 0xfc, 0x03,
0x01, 0x04, 0x30, 0xfe, 0x03, 0x01, 0x05, 0x30,
0x80, 0x04, 0x01, 0x06, 0x30, 0x82, 0x04, 0x01,
0x07, 0x30, 0x84, 0x04, 0x01, 0x08, 0x30, 0x86,
0x04, 0x01, 0x09, 0x30, 0xcc, 0x03, 0x00, 0x0c,
0xd0, 0x03, 0x02, 0x0c, 0xd6, 0x03, 0x05, 0x0c,
0xd8, 0x03, 0x06, 0x0c, 0xda, 0x03, 0x07, 0x0c,
0xdc, 0x03, 0x08, 0x0c, 0xde, 0x03, 0x09, 0x00,
0xce, 0x03, 0x01, 0x0c, 0x62, 0x09, 0x00, 0x62,
0x08, 0x00, 0x62, 0x07, 0x00, 0x62, 0x06, 0x00,
0x62, 0x05, 0x00, 0x62, 0x04, 0x00, 0x62, 0x03,
0x00, 0x62, 0x02, 0x00, 0x62, 0x01, 0x00, 0x62,
0x00, 0x00, 0x66, 0x00, 0x00, 0x43, 0x04, 0x01,
0x00, 0x00, 0xd2, 0x24, 0x01, 0x00, 0xca, 0x63,
0x00, 0x00, 0x97, 0xeb, 0x19, 0x39, 0x95, 0x00,
0x00, 0x00, 0x11, 0x04, 0x05, 0x01, 0x00, 0x00,
0x43, 0x5d, 0x00, 0x00, 0x00, 0xd2, 0x24, 0x01,
0x00, 0x21, 0x01, 0x00, 0x30, 0x66, 0x00, 0x00,
0x43, 0x06, 0x01, 0x00, 0x00, 0x63, 0x00, 0x00,
0x0b, 0x0a, 0x4d, 0x07, 0x01, 0x00, 0x00, 0x0a,
0x4d, 0x08, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00,
0xcb, 0x39, 0xa6, 0x00, 0x00, 0x00, 0x11, 0x66,
0x01, 0x00, 0x43, 0x09, 0x01, 0x00, 0x00, 0x63,
0x01, 0x00, 0x66, 0x02, 0x00, 0x66, 0x03, 0x00,
0xa5, 0x66, 0x04, 0x00, 0xa5, 0x24, 0x02, 0x00,
0x21, 0x01, 0x00, 0xcc, 0xd4, 0x11, 0xb1, 0xeb,
0x0c, 0x0e, 0x39, 0x8c, 0x00, 0x00, 0x00, 0x42,
0x0a, 0x01, 0x00, 0x00, 0xcd, 0x66, 0x00, 0x00,
0x43, 0x04, 0x01, 0x00, 0x00, 0x63, 0x03, 0x00,
0x0b, 0x0a, 0x4d, 0x0b, 0x01, 0x00, 0x00, 0x24,
0x02, 0x00, 0xc3, 0x04, 0x63, 0x04, 0x00, 0x97,
0xeb, 0x1b, 0x39, 0x95, 0x00, 0x00, 0x00, 0x11,
0x04, 0x0c, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00,
0x00, 0x00, 0x63, 0x03, 0x00, 0x24, 0x01, 0x00,
0x21, 0x01, 0x00, 0x30, 0x63, 0x04, 0x00, 0xea,
0xc3, 0x05, 0x63, 0x04, 0x00, 0x42, 0x0d, 0x01,
0x00, 0x00, 0x43, 0x0e, 0x01, 0x00, 0x00, 0x63,
0x05, 0x00, 0x63, 0x02, 0x00, 0xea, 0x9e, 0x66,
0x05, 0x00, 0x42, 0x0f, 0x01, 0x00, 0x00, 0x9e,
0x24, 0x01, 0x00, 0xc3, 0x06, 0x39, 0xa6, 0x00,
0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x21, 0x01,
0x00, 0xc3, 0x07, 0x63, 0x07, 0x00, 0x43, 0x43,
0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x63, 0x05,
0x00, 0x24, 0x02, 0x00, 0x0e, 0x63, 0x07, 0x00,
0x43, 0x43, 0x00, 0x00, 0x00, 0x5f, 0x06, 0x00,
0x66, 0x05, 0x00, 0x42, 0x10, 0x01, 0x00, 0x00,
0xf0, 0x63, 0x05, 0x00, 0x63, 0x02, 0x00, 0xea,
0x9e, 0x24, 0x02, 0x00, 0x0e, 0x39, 0xb0, 0x00,
0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x63, 0x05,
0x00, 0x63, 0x02, 0x00, 0xea, 0x9e, 0x66, 0x05,
0x00, 0x42, 0x11, 0x01, 0x00, 0x00, 0x9e, 0x66,
0x05, 0x00, 0x42, 0x12, 0x01, 0x00, 0x00, 0x21,
0x03, 0x00, 0xc3, 0x08, 0x63, 0x08, 0x00, 0x43,
0x13, 0x01, 0x00, 0x00, 0xb5, 0x63, 0x05, 0x00,
0x0a, 0x24, 0x03, 0x00, 0x0e, 0x66, 0x07, 0x00,
0x43, 0x14, 0x01, 0x00, 0x00, 0xd3, 0x66, 0x07,
0x00, 0x42, 0x15, 0x01, 0x00, 0x00, 0x66, 0x07,
0x00, 0x42, 0x16, 0x01, 0x00, 0x00, 0xa5, 0x66,
0x07, 0x00, 0x42, 0x17, 0x01, 0x00, 0x00, 0xa5,
0xbe, 0xed, 0x01, 0x24, 0x03, 0x00, 0xc3, 0x09,
0x63, 0x09, 0x00, 0xb5, 0xa7, 0xeb, 0x19, 0x39,
0x95, 0x00, 0x00, 0x00, 0x11, 0x04, 0x18, 0x01,
0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xd3,
0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x66,
0x07, 0x00, 0x43, 0x09, 0x01, 0x00, 0x00, 0x63,
0x09, 0x00, 0x63, 0x06, 0x00, 0xb5, 0x63, 0x06,
0x00, 0x42, 0x19, 0x01, 0x00, 0x00, 0x24, 0x04,
0x00, 0xb5, 0xa7, 0xeb, 0x1f, 0x66, 0x07, 0x00,
0x43, 0x1a, 0x01, 0x00, 0x00, 0x63, 0x09, 0x00,
0x24, 0x01, 0x00, 0x0e, 0x39, 0x95, 0x00, 0x00,
0x00, 0x11, 0x04, 0x1b, 0x01, 0x00, 0x00, 0x21,
0x01, 0x00, 0x30, 0x66, 0x07, 0x00, 0x43, 0x1a,
0x01, 0x00, 0x00, 0x63, 0x09, 0x00, 0x24, 0x01,
0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xca, 0x03,
0x00, 0x09, 0x00, 0x07, 0x06, 0x00, 0xa4, 0x04,
0x09, 0xb8, 0x04, 0x01, 0x00, 0x30, 0xfc, 0x03,
0x01, 0x01, 0x30, 0xba, 0x04, 0x01, 0x02, 0x20,
0xbc, 0x04, 0x01, 0x03, 0x30, 0xbe, 0x04, 0x01,
0x04, 0x30, 0x84, 0x04, 0x01, 0x05, 0x30, 0xc0,
0x04, 0x01, 0x06, 0x30, 0xf8, 0x03, 0x01, 0x07,
0x30, 0xf6, 0x03, 0x01, 0x08, 0x30, 0xcc, 0x03,
0x00, 0x0c, 0xdc, 0x03, 0x08, 0x0c, 0xe0, 0x03,
0x0a, 0x00, 0xd0, 0x03, 0x02, 0x0c, 0xd2, 0x03,
0x03, 0x0c, 0xd4, 0x03, 0x04, 0x0c, 0x62, 0x08,
0x00, 0x62, 0x07, 0x00, 0x62, 0x06, 0x00, 0x62,
0x05, 0x00, 0x62, 0x04, 0x00, 0x62, 0x03, 0x00,
0x62, 0x02, 0x00, 0x62, 0x01, 0x00, 0x62, 0x00,
0x00, 0x39, 0x8c, 0x00, 0x00, 0x00, 0x42, 0x0a,
0x01, 0x00, 0x00, 0xca, 0x66, 0x00, 0x00, 0x43,
0x14, 0x01, 0x00, 0x00, 0x63, 0x00, 0x00, 0x04,
0x21, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xcb,
0x63, 0x01, 0x00, 0x97, 0xeb, 0x1b, 0x39, 0x95,
0x00, 0x00, 0x00, 0x11, 0x04, 0x0c, 0x01, 0x00,
0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0x63, 0x00,
0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30,
0x63, 0x01, 0x00, 0x43, 0x22, 0x01, 0x00, 0x00,
0x66, 0x01, 0x00, 0x42, 0x0f, 0x01, 0x00, 0x00,
0x8d, 0x66, 0x00, 0x00, 0x42, 0x23, 0x01, 0x00,
0x00, 0x24, 0x02, 0x00, 0xcc, 0x63, 0x02, 0x00,
0xb5, 0xa7, 0xeb, 0x1c, 0x39, 0x95, 0x00, 0x00,
0x00, 0x11, 0x04, 0x24, 0x01, 0x00, 0x00, 0x43,
0x5d, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x8d,
0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x39,
0xa6, 0x00, 0x00, 0x00, 0x11, 0x66, 0x01, 0x00,
0x42, 0x0f, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00,
0xcd, 0x63, 0x01, 0x00, 0x43, 0x25, 0x01, 0x00,
0x00, 0x63, 0x03, 0x00, 0x42, 0x0d, 0x01, 0x00,
0x00, 0xb5, 0x66, 0x01, 0x00, 0x42, 0x0f, 0x01,
0x00, 0x00, 0x24, 0x03, 0x00, 0x0e, 0x39, 0xa6,
0x00, 0x00, 0x00, 0x11, 0x63, 0x03, 0x00, 0x42,
0x0d, 0x01, 0x00, 0x00, 0xb5, 0x66, 0x01, 0x00,
0x42, 0x11, 0x01, 0x00, 0x00, 0x21, 0x03, 0x00,
0xc3, 0x04, 0xe0, 0x63, 0x04, 0x00, 0xf0, 0x66,
0x01, 0x00, 0x42, 0x10, 0x01, 0x00, 0x00, 0xb0,
0xeb, 0x1c, 0x63, 0x01, 0x00, 0x43, 0x1a, 0x01,
0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, 0x39, 0x95,
0x00, 0x00, 0x00, 0x11, 0x04, 0x26, 0x01, 0x00,
0x00, 0x21, 0x01, 0x00, 0x30, 0x39, 0xb0, 0x00,
0x00, 0x00, 0x11, 0x63, 0x03, 0x00, 0x42, 0x0d,
0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x42, 0x11,
0x01, 0x00, 0x00, 0x66, 0x01, 0x00, 0x42, 0x12,
0x01, 0x00, 0x00, 0x21, 0x03, 0x00, 0xc3, 0x05,
0x63, 0x05, 0x00, 0x43, 0x27, 0x01, 0x00, 0x00,
0xb5, 0x0a, 0x24, 0x02, 0x00, 0xc3, 0x06, 0x39,
0xa6, 0x00, 0x00, 0x00, 0x11, 0x63, 0x06, 0x00,
0x66, 0x01, 0x00, 0x42, 0x0f, 0x01, 0x00, 0x00,
0x9f, 0x21, 0x01, 0x00, 0xc3, 0x07, 0x63, 0x01,
0x00, 0x43, 0x22, 0x01, 0x00, 0x00, 0x63, 0x06,
0x00, 0x66, 0x00, 0x00, 0x42, 0x28, 0x01, 0x00,
0x00, 0x24, 0x02, 0x00, 0x11, 0x64, 0x02, 0x00,
0x0e, 0x63, 0x02, 0x00, 0xb5, 0xa7, 0xeb, 0x28,
0x63, 0x01, 0x00, 0x43, 0x1a, 0x01, 0x00, 0x00,
0x24, 0x00, 0x00, 0x0e, 0x39, 0x95, 0x00, 0x00,
0x00, 0x11, 0x04, 0x24, 0x01, 0x00, 0x00, 0x43,
0x5d, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x8d,
0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x63,
0x01, 0x00, 0x43, 0x25, 0x01, 0x00, 0x00, 0x63,
0x07, 0x00, 0x42, 0x0d, 0x01, 0x00, 0x00, 0xb5,
0x63, 0x07, 0x00, 0xea, 0x24, 0x03, 0x00, 0x0e,
0x63, 0x01, 0x00, 0x43, 0x29, 0x01, 0x00, 0x00,
0x24, 0x00, 0x00, 0xeb, 0x1c, 0x63, 0x01, 0x00,
0x43, 0x1a, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00,
0x0e, 0x39, 0x95, 0x00, 0x00, 0x00, 0x11, 0x04,
0x2a, 0x01, 0x00, 0x00, 0x21, 0x01, 0x00, 0x30,
0x63, 0x01, 0x00, 0x43, 0x1a, 0x01, 0x00, 0x00,
0x24, 0x00, 0x00, 0x0e, 0x66, 0x03, 0x00, 0x43,
0x25, 0x01, 0x00, 0x00, 0x63, 0x07, 0x00, 0x42,
0x0d, 0x01, 0x00, 0x00, 0xb5, 0x63, 0x07, 0x00,
0xea, 0x66, 0x04, 0x00, 0x66, 0x05, 0x00, 0xa5,
0x24, 0x04, 0x00, 0xc3, 0x08, 0x66, 0x00, 0x00,
0x43, 0x06, 0x01, 0x00, 0x00, 0x63, 0x08, 0x00,
0x0b, 0x0a, 0x4d, 0x2b, 0x01, 0x00, 0x00, 0x25,
0x02, 0x00, 0x08, 0xeb, 0x16, 0xc0, 0x00, 0x60,
0x09, 0x00, 0xc0, 0x01, 0x60, 0x0a, 0x00, 0xc0,
0x02, 0x60, 0x0b, 0x00, 0xc0, 0x03, 0x60, 0x0c,
0x00, 0x29, 0xb6, 0xb5, 0xa0, 0xe5, 0xb6, 0xb8,
0xa0, 0x60, 0x04, 0x00, 0xb6, 0xb5, 0xa0, 0x60,
0x05, 0x00, 0xb6, 0xb8, 0xa0, 0x60, 0x06, 0x00,
0xb6, 0xb9, 0xa0, 0x60, 0x07, 0x00, 0x0b, 0x04,
0x2c, 0x01, 0x00, 0x00, 0x4d, 0x10, 0x01, 0x00,
0x00, 0xbd, 0x08, 0x4d, 0x11, 0x01, 0x00, 0x00,
0xb9, 0x4d, 0x12, 0x01, 0x00, 0x00, 0xbd, 0x0c,
0x4d, 0x0f, 0x01, 0x00, 0x00, 0x60, 0x08, 0x00,
0x06, 0x2f,
};

83
gen/test_fib.c Normal file
View file

@ -0,0 +1,83 @@
/* File generated automatically by the QuickJS-ng compiler. */
#include "quickjs-libc.h"
const uint32_t qjsc_test_fib_size = 294;
const uint8_t qjsc_test_fib[294] = {
0x13, 0x0e, 0x01, 0x28, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73,
0x74, 0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73,
0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a, 0x6f, 0x73,
0x01, 0x04, 0x6f, 0x73, 0x01, 0x0a, 0x69, 0x73,
0x57, 0x69, 0x6e, 0x01, 0x06, 0x66, 0x69, 0x62,
0x01, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x01, 0x0a, 0x77, 0x69, 0x6e, 0x33,
0x32, 0x01, 0x0c, 0x2e, 0x2f, 0x66, 0x69, 0x62,
0x2e, 0x01, 0x06, 0x64, 0x6c, 0x6c, 0x01, 0x04,
0x73, 0x6f, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73,
0x6f, 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67,
0x01, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
0x57, 0x6f, 0x72, 0x6c, 0x64, 0x01, 0x10, 0x66,
0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d,
0xc0, 0x03, 0x01, 0xc2, 0x03, 0x00, 0x00, 0x01,
0x00, 0xfc, 0x01, 0x00, 0x01, 0x0c, 0x20, 0xfa,
0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03,
0x00, 0x73, 0x00, 0xc4, 0x03, 0x00, 0x0d, 0xc6,
0x03, 0x00, 0x0d, 0xc8, 0x03, 0x01, 0x0d, 0x08,
0xeb, 0x02, 0x29, 0x66, 0x00, 0x00, 0x42, 0xe5,
0x00, 0x00, 0x00, 0x04, 0xe6, 0x00, 0x00, 0x00,
0xaf, 0xe3, 0x06, 0x11, 0xf3, 0xec, 0x0b, 0x71,
0x43, 0xe4, 0x00, 0x00, 0x00, 0xe4, 0x0e, 0xed,
0x24, 0x0e, 0x04, 0xe7, 0x00, 0x00, 0x00, 0x43,
0x5d, 0x00, 0x00, 0x00, 0x66, 0x01, 0x00, 0xeb,
0x08, 0x04, 0xe8, 0x00, 0x00, 0x00, 0xed, 0x06,
0x04, 0xe9, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00,
0x36, 0x8c, 0xed, 0xd4, 0x39, 0xea, 0x00, 0x00,
0x00, 0x43, 0xeb, 0x00, 0x00, 0x00, 0x04, 0xec,
0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39,
0xea, 0x00, 0x00, 0x00, 0x43, 0xeb, 0x00, 0x00,
0x00, 0x04, 0xed, 0x00, 0x00, 0x00, 0x66, 0x02,
0x00, 0xbd, 0x0a, 0xf0, 0x24, 0x02, 0x00, 0x0e,
0x06, 0x2f, 0xc0, 0x03, 0x01, 0x01, 0x0e, 0x41,
0x3c, 0x00, 0x39, 0x06, 0x3b, 0x34, 0x10, 0x30,
0x0f, 0x34, 0x10, 0x2a, 0x20, 0x00,
};
static JSContext *JS_NewCustomContext(JSRuntime *rt)
{
JSContext *ctx = JS_NewContext(rt);
if (!ctx)
return NULL;
{
extern JSModuleDef *js_init_module_os(JSContext *ctx, const char *name);
js_init_module_os(ctx, "qjs:os");
}
return ctx;
}
int main(int argc, char **argv)
{
int r;
JSValue ret;
JSRuntime *rt;
JSContext *ctx;
r = 0;
rt = JS_NewRuntime();
js_std_set_worker_new_context_func(JS_NewCustomContext);
js_std_init_handlers(rt);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
ctx = JS_NewCustomContext(rt);
js_std_add_helpers(ctx, argc, argv);
js_std_eval_binary(ctx, qjsc_test_fib, qjsc_test_fib_size, 0);
ret = js_std_loop(ctx);
if (JS_IsException(ret)) {
js_std_dump_error1(ctx, ret);
r = 1;
}
JS_FreeValue(ctx, ret);
JS_FreeContext(ctx);
js_std_free_handlers(rt);
JS_FreeRuntime(rt);
return r;
}

653
getopt_compat.h Normal file
View file

@ -0,0 +1,653 @@
#ifndef __GETOPT_H__
/**
* DISCLAIMER
* This file is part of the mingw-w64 runtime package.
*
* The mingw-w64 runtime package and its code is distributed in the hope that it
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma warning(disable:4996)
#define __GETOPT_H__
/* All the headers include this file. */
#include <crtdefs.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
#ifdef REPLACE_GETOPT
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
#undef optreset /* see getopt.h */
#define optreset __mingw_optreset
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#endif
//extern int optind; /* index of first non-option in argv */
//extern int optopt; /* single option character, as parsed */
//extern int opterr; /* flag to enable built-in diagnostics... */
// /* (user may set to zero, to suppress) */
//
//extern char *optarg; /* pointer to argument of current option */
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#ifndef __CYGWIN__
#define __progname __argv[0]
#else
extern char __declspec(dllimport) *__progname;
#endif
#ifdef __CYGWIN__
static char EMSG[] = "";
#else
#define EMSG ""
#endif
struct option /* specification for a long form option... */
{
const char *name; /* option name, without leading hyphens */
int has_arg; /* does it take an argument? */
int *flag; /* where to save its status, or NULL */
int val; /* its associated status value */
};
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
static void
_vwarnx(const char *fmt,va_list ap)
{
(void)fprintf(stderr,"%s: ",__progname);
if (fmt != NULL)
(void)vfprintf(stderr,fmt,ap);
(void)fprintf(stderr,"\n");
}
static void
warnx(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
_vwarnx(fmt,ap);
va_end(ap);
}
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
}
#ifdef REPLACE_GETOPT
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#endif /* REPLACE_GETOPT */
//extern int getopt(int nargc, char * const *nargv, const char *options);
#ifdef _BSD_SOURCE
/*
* BSD adds the non-standard `optreset' feature, for reinitialisation
* of `getopt' parsing. We support this feature, for applications which
* proclaim their BSD heritage, before including this header; however,
* to maintain portability, developers are advised to avoid it.
*/
# define optreset __mingw_optreset
extern int optreset;
#endif
#ifdef __cplusplus
}
#endif
/*
* POSIX requires the `getopt' API to be specified in `unistd.h';
* thus, `unistd.h' includes this header. However, we do not want
* to expose the `getopt_long' or `getopt_long_only' APIs, when
* included in this manner. Thus, close the standard __GETOPT_H__
* declarations block, and open an additional __GETOPT_LONG_H__
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
* to declare the extended API.
*/
#endif /* !defined(__GETOPT_H__) */
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
#define __GETOPT_LONG_H__
#ifdef __cplusplus
extern "C" {
#endif
enum /* permitted values for its `has_arg' field... */
{
no_argument = 0, /* option never takes an argument */
required_argument, /* option always requires an argument */
optional_argument /* option may take an argument */
};
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
current_argv = place;
match = -1;
ambiguous = 0;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
#undef IDENTICAL_INTERPRETATION
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
* optreset != 0 for GNU compatibility.
*/
if (posixly_correct == -1 || optreset != 0)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = (char*)strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
}
//extern int getopt_long(int nargc, char * const *nargv, const char *options,
// const struct option *long_options, int *idx);
//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
// const struct option *long_options, int *idx);
/*
* Previous MinGW implementation had...
*/
#ifndef HAVE_DECL_GETOPT
/*
* ...for the long form API only; keep this for compatibility.
*/
# define HAVE_DECL_GETOPT 1
#endif
#ifdef __cplusplus
}
#endif
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */

97
libbf.c
View file

@ -37,12 +37,10 @@
/* enable it to check the multiplication result */
//#define USE_MUL_CHECK
#ifdef CONFIG_BIGNUM
/* enable it to use FFT/NTT multiplication */
#define USE_FFT_MUL
/* enable decimal floating point support */
#define USE_BF_DEC
#endif
//#define inline __attribute__((always_inline))
@ -309,7 +307,8 @@ int bf_set(bf_t *r, const bf_t *a)
}
r->sign = a->sign;
r->expn = a->expn;
memcpy(r->tab, a->tab, a->len * sizeof(limb_t));
if (a->len > 0)
memcpy(r->tab, a->tab, a->len * sizeof(limb_t));
return 0;
}
@ -1602,9 +1601,7 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
r = &tmp;
}
if (bf_resize(r, a_len + b_len)) {
#ifdef USE_FFT_MUL
fail:
#endif
bf_set_nan(r);
ret = BF_ST_MEM_ERROR;
goto done;
@ -1713,6 +1710,13 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
slimb_t d;
na = n + nb;
#if LIMB_LOG2_BITS == 6
if (na >= (SIZE_MAX / sizeof(limb_t)) - 1) {
return BF_ST_MEM_ERROR; /* Return memory error status */
}
#endif
taba = bf_malloc(s, (na + 1) * sizeof(limb_t));
if (!taba)
goto fail;
@ -2301,14 +2305,11 @@ static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b,
bf_t a;
int ret;
#ifdef USE_BF_DEC
if (a1 == 10 && b <= LIMB_DIGITS) {
/* use precomputed powers. We do not round at this point
because we expect the caller to do it */
ret = bf_set_ui(r, mp_pow_dec[b]);
} else
#endif
{
} else {
bf_init(r->ctx, &a);
ret = bf_set_ui(&a, a1);
ret |= bf_pow_ui(r, &a, b, prec, flags);
@ -2839,7 +2840,7 @@ int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
return ret;
}
static inline int to_digit(int c)
static inline int bf_to_digit(int c)
{
if (c >= '0' && c <= '9')
return c - '0';
@ -2946,7 +2947,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
goto no_prefix;
}
/* there must be a digit after the prefix */
if (to_digit((uint8_t)*p) >= radix) {
if (bf_to_digit((uint8_t)*p) >= radix) {
bf_set_nan(r);
ret = 0;
goto done;
@ -2994,14 +2995,14 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
int_len = digit_count = 0;
for(;;) {
limb_t c;
if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) {
if (*p == '.' && (p > p_start || bf_to_digit(p[1]) < radix)) {
if (has_decpt)
break;
has_decpt = TRUE;
int_len = digit_count;
p++;
}
c = to_digit(*p);
c = bf_to_digit(*p);
if (c >= radix)
break;
digit_count++;
@ -3082,7 +3083,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
}
for(;;) {
int c;
c = to_digit(*p);
c = bf_to_digit(*p);
if (c >= 10)
break;
if (unlikely(expn > ((BF_RAW_EXP_MAX - 2 - 9) / 10))) {
@ -4820,11 +4821,6 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags)
bf_t *y1;
if (y_emin < 0 && check_exact_power2n(r, T, -y_emin)) {
/* the problem is reduced to a power to an integer */
#if 0
printf("\nn=%" PRId64 "\n", -(int64_t)y_emin);
bf_print_str("T", T);
bf_print_str("r", r);
#endif
bf_set(T, r);
y1 = &ytmp_s;
y1->tab = y->tab;
@ -5376,19 +5372,20 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
#if LIMB_BITS == 64
/* Note: we assume __int128 is available */
/* uint128_t defined in libbf.h */
#define muldq(r1, r0, a, b) \
do { \
unsigned __int128 __t; \
__t = (unsigned __int128)(a) * (unsigned __int128)(b); \
uint128_t __t; \
__t = (uint128_t)(a) * (uint128_t)(b); \
r0 = __t; \
r1 = __t >> 64; \
} while (0)
#define divdq(q, r, a1, a0, b) \
do { \
unsigned __int128 __t; \
uint128_t __t; \
limb_t __b = (b); \
__t = ((unsigned __int128)(a1) << 64) | (a0); \
__t = ((uint128_t)(a1) << 64) | (a0); \
q = __t / __b; \
r = __t % __b; \
} while (0)
@ -6333,34 +6330,6 @@ static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos)
return fast_shr_dec(tab[i], shift) % 10;
}
#if 0
static limb_t get_digits(const limb_t *tab, limb_t len, slimb_t pos)
{
limb_t a0, a1;
int shift;
slimb_t i;
i = floor_div(pos, LIMB_DIGITS);
shift = pos - i * LIMB_DIGITS;
if (i >= 0 && i < len)
a0 = tab[i];
else
a0 = 0;
if (shift == 0) {
return a0;
} else {
i++;
if (i >= 0 && i < len)
a1 = tab[i];
else
a1 = 0;
return fast_shr_dec(a0, shift) +
fast_urem(a1, &mp_pow_div[LIMB_DIGITS - shift]) *
mp_pow_dec[shift];
}
}
#endif
/* return the addend for rounding. Note that prec can be <= 0 for bf_rint() */
static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l,
slimb_t prec, int rnd_mode)
@ -7987,12 +7956,6 @@ static no_inline void limb_to_ntt(BFNTTState *s,
int j, shift;
limb_t base_mask1, a0, a1, a2, r, m, m_inv;
#if 0
for(i = 0; i < a_len; i++) {
printf("%" PRId64 ": " FMT_LIMB "\n",
(int64_t)i, taba[i]);
}
#endif
memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods);
shift = dpl & (LIMB_BITS - 1);
if (shift == 0)
@ -8119,14 +8082,6 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
}
u[l] = r + carry[l];
#if 0
printf("%" PRId64 ": ", i);
for(j = nb_mods - 1; j >= 0; j--) {
printf(" %019" PRIu64, u[j]);
}
printf("\n");
#endif
/* write the digits */
pos = i * dpl;
for(j = 0; j < n_limb1; j++) {
@ -8220,14 +8175,6 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
}
u[l] = r + carry[l];
#if 0
printf("%" PRId64 ": ", (int64_t)i);
for(j = nb_mods - 1; j >= 0; j--) {
printf(" " FMT_LIMB, u[j]);
}
printf("\n");
#endif
/* write the digits */
pos = i * dpl;
for(j = 0; j < n_limb1; j++) {
@ -8471,3 +8418,7 @@ int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len)
}
#endif /* !USE_FFT_MUL */
#undef malloc
#undef free
#undef realloc

16
libbf.h
View file

@ -27,7 +27,11 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
#ifdef __cplusplus
extern "C" {
#endif
#if INTPTR_MAX >= INT64_MAX && !defined(_WIN32) && !defined(__TINYC__)
#define LIMB_LOG2_BITS 6
#else
#define LIMB_LOG2_BITS 5
@ -36,8 +40,10 @@
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
#if LIMB_BITS == 64
typedef __int128 int128_t;
typedef unsigned __int128 uint128_t;
#ifndef INT128_MAX
__extension__ typedef __int128 int128_t;
__extension__ typedef unsigned __int128 uint128_t;
#endif
typedef int64_t slimb_t;
typedef uint64_t limb_t;
typedef uint128_t dlimb_t;
@ -532,4 +538,8 @@ static inline int bfdec_resize(bfdec_t *r, limb_t len)
}
int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* LIBBF_H */

View file

@ -25,7 +25,8 @@
#ifdef DEF
DEF(invalid, 1) /* never used */
DEF(char, 3)
DEF(char8, 2) /* 7 bits in fact */
DEF(char16, 3)
DEF(char32, 5)
DEF(dot, 1)
DEF(any, 1) /* same as dot but match any character including line terminator */

File diff suppressed because it is too large Load diff

View file

@ -28,17 +28,21 @@
#include "libunicode.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LRE_BOOL int /* for documentation purposes */
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
#define LRE_FLAG_MULTILINE (1 << 2)
#define LRE_FLAG_DOTALL (1 << 3)
#define LRE_FLAG_UTF16 (1 << 4)
#define LRE_FLAG_UNICODE (1 << 4)
#define LRE_FLAG_STICKY (1 << 5)
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
#define LRE_FLAG_UNICODE_SETS (1 << 8)
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
const char *buf, size_t buf_len, int re_flags,
@ -53,6 +57,8 @@ int lre_exec(uint8_t **capture,
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
LRE_BOOL lre_is_space(int c);
void lre_byte_swap(uint8_t *buf, size_t len, LRE_BOOL is_byte_swapped);
/* must be provided by the user */
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
@ -66,11 +72,7 @@ static inline int lre_js_is_ident_first(int c)
if ((uint32_t)c < 128) {
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_start(c);
#else
return !lre_is_space(c);
#endif
}
}
@ -80,14 +82,14 @@ static inline int lre_js_is_ident_next(int c)
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
/* ZWNJ and ZWJ are accepted in identifiers */
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
#else
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
#endif
}
}
#undef LRE_BOOL
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* LIBREGEXP_H */

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,7 @@
#include "libunicode.h"
#include "libunicode-table.h"
// note: stored as 4 bit tag, not much room left
enum {
RUN_TYPE_U,
RUN_TYPE_L,
@ -262,11 +263,7 @@ int lre_canonicalize(uint32_t c, BOOL is_unicode)
static uint32_t get_le24(const uint8_t *ptr)
{
#if defined(__x86__) || defined(__x86_64__)
return *(uint16_t *)ptr | (ptr[2] << 16);
#else
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
#endif
}
#define UNICODE_INDEX_BLOCK_LEN 32
@ -533,8 +530,6 @@ int cr_invert(CharRange *cr)
return 0;
}
#ifdef CONFIG_ALL_UNICODE
BOOL lre_is_id_start(uint32_t c)
{
return lre_is_in_table(c, unicode_prop_ID_Start_table,
@ -550,6 +545,13 @@ BOOL lre_is_id_continue(uint32_t c)
sizeof(unicode_prop_ID_Continue1_index) / 3);
}
BOOL lre_is_white_space(uint32_t c)
{
return lre_is_in_table(c, unicode_prop_White_Space_table,
unicode_prop_White_Space_index,
sizeof(unicode_prop_White_Space_index) / 3);
}
#define UNICODE_DECOMP_LEN_MAX 18
typedef enum {
@ -897,13 +899,6 @@ static void sort_cc(int *buf, int len)
buf[k + 1] = ch1;
j++;
}
#if 0
printf("cc:");
for(k = start; k < j; k++) {
printf(" %3d", unicode_get_cc(buf[k]));
}
printf("\n");
#endif
i = j;
}
}
@ -1063,8 +1058,8 @@ int unicode_script(CharRange *cr,
int script_idx;
const uint8_t *p, *p_end;
uint32_t c, c1, b, n, v, v_len, i, type;
CharRange cr1_s, *cr1;
CharRange cr2_s, *cr2 = &cr2_s;
CharRange cr1_s = { 0 }, *cr1 = NULL;
CharRange cr2_s = { 0 }, *cr2 = &cr2_s;
BOOL is_common;
script_idx = unicode_find_name(unicode_script_name_table, script_name);
@ -1731,42 +1726,6 @@ int unicode_prop(CharRange *cr, const char *prop_name)
POP_XOR,
POP_END);
break;
#if 0
case UNICODE_PROP_ID_Start:
ret = unicode_prop_ops(cr,
POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl),
POP_PROP, UNICODE_PROP_Other_ID_Start,
POP_UNION,
POP_PROP, UNICODE_PROP_Pattern_Syntax,
POP_PROP, UNICODE_PROP_Pattern_White_Space,
POP_UNION,
POP_INVERT,
POP_INTER,
POP_END);
break;
case UNICODE_PROP_ID_Continue:
ret = unicode_prop_ops(cr,
POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl) |
M(Mn) | M(Mc) | M(Nd) | M(Pc),
POP_PROP, UNICODE_PROP_Other_ID_Start,
POP_UNION,
POP_PROP, UNICODE_PROP_Other_ID_Continue,
POP_UNION,
POP_PROP, UNICODE_PROP_Pattern_Syntax,
POP_PROP, UNICODE_PROP_Pattern_White_Space,
POP_UNION,
POP_INVERT,
POP_INTER,
POP_END);
break;
case UNICODE_PROP_Case_Ignorable:
ret = unicode_prop_ops(cr,
POP_GC, M(Mn) | M(Cf) | M(Lm) | M(Sk),
POP_PROP, UNICODE_PROP_Case_Ignorable1,
POP_XOR,
POP_END);
break;
#else
/* we use the existing tables */
case UNICODE_PROP_ID_Continue:
ret = unicode_prop_ops(cr,
@ -1775,7 +1734,6 @@ int unicode_prop(CharRange *cr, const char *prop_name)
POP_XOR,
POP_END);
break;
#endif
default:
if (prop_idx >= countof(unicode_prop_table))
return -2;
@ -1784,5 +1742,3 @@ int unicode_prop(CharRange *cr, const char *prop_name)
}
return ret;
}
#endif /* CONFIG_ALL_UNICODE */

View file

@ -24,12 +24,14 @@
#ifndef LIBUNICODE_H
#define LIBUNICODE_H
#include <stddef.h>
#include <inttypes.h>
#define LRE_BOOL int /* for documentation purposes */
#ifdef __cplusplus
extern "C" {
#endif
/* define it to include all the unicode tables (40KB larger) */
#define CONFIG_ALL_UNICODE
#define LRE_BOOL int /* for documentation purposes */
#define LRE_CC_RES_LEN_MAX 3
@ -101,13 +103,11 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
const uint32_t *b_pt, int b_len, int op);
int cr_invert(CharRange *cr);
int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode);
#ifdef CONFIG_ALL_UNICODE
LRE_BOOL lre_is_id_start(uint32_t c);
LRE_BOOL lre_is_id_continue(uint32_t c);
LRE_BOOL lre_is_white_space(uint32_t c);
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
@ -120,8 +120,10 @@ int unicode_script(CharRange *cr,
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
#endif /* CONFIG_ALL_UNICODE */
#undef LRE_BOOL
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* LIBUNICODE_H */

8
list.h
View file

@ -28,6 +28,10 @@
#include <stddef.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct list_head {
struct list_head *prev;
struct list_head *next;
@ -96,4 +100,8 @@ static inline int list_empty(struct list_head *el)
for(el = (head)->prev, el1 = el->prev; el != (head); \
el = el1, el1 = el->prev)
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* LIST_H */

553
qjs.c
View file

@ -1,7 +1,6 @@
/*
* QuickJS stand alone interpreter
*
* Copyright (c) 2024 Sneed Group
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
@ -29,26 +28,81 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#if !defined(_MSC_VER)
#include <unistd.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#if defined(__APPLE__)
#include <malloc/malloc.h>
#elif defined(__linux__)
#include <malloc.h>
#endif
#include "cutils.h"
#include "quickjs.h"
#include "quickjs-libc.h"
#ifdef QJS_USE_MIMALLOC
#include <mimalloc.h>
#endif
extern const uint8_t qjsc_repl[];
extern const uint32_t qjsc_repl_size;
#ifdef CONFIG_BIGNUM
extern const uint8_t qjsc_qjscalc[];
extern const uint32_t qjsc_qjscalc_size;
static int bignum_ext;
#endif
extern const uint8_t qjsc_standalone[];
extern const uint32_t qjsc_standalone_size;
// Must match standalone.js
#define TRAILER_SIZE 12
static const char trailer_magic[] = "quickjs2";
static const int trailer_magic_size = sizeof(trailer_magic) - 1;
static const int trailer_size = TRAILER_SIZE;
static int qjs__argc;
static char **qjs__argv;
static BOOL is_standalone(const char *exe)
{
FILE *exe_f = fopen(exe, "rb");
if (!exe_f)
return FALSE;
if (fseek(exe_f, -trailer_size, SEEK_END) < 0)
goto fail;
uint8_t buf[TRAILER_SIZE];
if (fread(buf, 1, trailer_size, exe_f) != trailer_size)
goto fail;
fclose(exe_f);
return !memcmp(buf, trailer_magic, trailer_magic_size);
fail:
fclose(exe_f);
return FALSE;
}
static JSValue load_standalone_module(JSContext *ctx)
{
JSModuleDef *m;
JSValue obj, val;
obj = JS_ReadObject(ctx, qjsc_standalone, qjsc_standalone_size, JS_READ_OBJ_BYTECODE);
if (JS_IsException(obj))
goto exception;
assert(JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE);
if (JS_ResolveModule(ctx, obj) < 0) {
JS_FreeValue(ctx, obj);
goto exception;
}
js_module_set_import_meta(ctx, obj, FALSE, TRUE);
val = JS_EvalFunction(ctx, JS_DupValue(ctx, obj));
val = js_std_await(ctx, val);
if (JS_IsException(val)) {
JS_FreeValue(ctx, obj);
exception:
js_std_dump_error(ctx);
exit(1);
}
JS_FreeValue(ctx, val);
m = JS_VALUE_GET_PTR(obj);
JS_FreeValue(ctx, obj);
return JS_GetModuleNamespace(ctx, m);
}
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
const char *filename, int eval_flags)
@ -65,6 +119,7 @@ static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
js_module_set_import_meta(ctx, val, TRUE, TRUE);
val = JS_EvalFunction(ctx, val);
}
val = js_std_await(ctx, val);
} else {
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
}
@ -91,7 +146,7 @@ static int eval_file(JSContext *ctx, const char *filename, int module)
}
if (module < 0) {
module = (has_suffix(filename, ".mjs") ||
module = (js__has_suffix(filename, ".mjs") ||
JS_DetectModule((const char *)buf, buf_len));
}
if (module)
@ -99,7 +154,8 @@ static int eval_file(JSContext *ctx, const char *filename, int module)
else
eval_flags = JS_EVAL_TYPE_GLOBAL;
//POLYFILLS FOR QJS FILES BEGIN
//POLYFILLS FOR QJS FILES BEGIN
const char *pf = "globalThis.global = globalThis;\n"
"global.console.error = console.log\n"
"global.console.warn = console.log\n"
@ -118,19 +174,70 @@ static int eval_file(JSContext *ctx, const char *filename, int module)
" globalThis.loadFile = std.loadFile;\n"
" globalThis.printf = console.log;\n"
" globalThis.evalFile = std.loadScript;\n"
" globalThis.require = std.loadScript;\n"
//" globalThis.require = std.loadScript;\n"
" globalThis.getURL = std.urlGet;\n"
"} else {\n"
" console.error('std is not defined.');\n"
"}\n";
eval_buf(ctx, pf, strlen(pf), "<input>", JS_EVAL_TYPE_MODULE);
ret = eval_buf(ctx, buf, buf_len, filename, eval_flags);
js_free(ctx, buf);
return ret;
}
static int64_t parse_limit(const char *arg) {
char *p;
unsigned long unit = 1024; /* default to traditional KB */
double d = strtod(arg, &p);
if (p == arg) {
fprintf(stderr, "Invalid limit: %s\n", arg);
return -1;
}
if (*p) {
switch (*p++) {
case 'b': case 'B': unit = 1UL << 0; break;
case 'k': case 'K': unit = 1UL << 10; break; /* IEC kibibytes */
case 'm': case 'M': unit = 1UL << 20; break; /* IEC mebibytes */
case 'g': case 'G': unit = 1UL << 30; break; /* IEC gigibytes */
default:
fprintf(stderr, "Invalid limit: %s, unrecognized suffix, only k,m,g are allowed\n", arg);
return -1;
}
if (*p) {
fprintf(stderr, "Invalid limit: %s, only one suffix allowed\n", arg);
return -1;
}
}
return (int64_t)(d * unit);
}
static JSValue js_gc(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
JS_RunGC(JS_GetRuntime(ctx));
return JS_UNDEFINED;
}
static JSValue js_navigator_get_userAgent(JSContext *ctx, JSValue this_val)
{
char version[32];
snprintf(version, sizeof(version), "quickjs-ng/%s", JS_GetVersion());
return JS_NewString(ctx, version);
}
static const JSCFunctionListEntry navigator_proto_funcs[] = {
JS_CGETSET_DEF2("userAgent", js_navigator_get_userAgent, NULL, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Navigator", JS_PROP_CONFIGURABLE),
};
static const JSCFunctionListEntry global_obj[] = {
JS_CFUNC_DEF("gc", 0, js_gc),
};
/* also used to initialize the worker context */
static JSContext *JS_NewCustomContext(JSRuntime *rt)
{
@ -138,26 +245,30 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt)
ctx = JS_NewContext(rt);
if (!ctx)
return NULL;
#ifdef CONFIG_BIGNUM
if (bignum_ext) {
JS_AddIntrinsicBigFloat(ctx);
JS_AddIntrinsicBigDecimal(ctx);
JS_AddIntrinsicOperators(ctx);
JS_EnableBignumExt(ctx, TRUE);
}
#endif
/* system modules */
js_init_module_std(ctx, "std");
js_init_module_os(ctx, "os");
js_init_module_std(ctx, "qjs:std");
js_init_module_os(ctx, "qjs:os");
js_init_module_bjson(ctx, "qjs:bjson");
JSValue global = JS_GetGlobalObject(ctx);
JS_SetPropertyFunctionList(ctx, global, global_obj, countof(global_obj));
JSValue args = JS_NewArray(ctx);
int i;
for(i = 0; i < qjs__argc; i++) {
JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, qjs__argv[i]));
}
JS_SetPropertyStr(ctx, global, "execArgv", args);
JS_SetPropertyStr(ctx, global, "argv0", JS_NewString(ctx, qjs__argv[0]));
JSValue navigator_proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, navigator_proto, navigator_proto_funcs, countof(navigator_proto_funcs));
JSValue navigator = JS_NewObjectProto(ctx, navigator_proto);
JS_DefinePropertyValueStr(ctx, global, "navigator", navigator, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE);
JS_FreeValue(ctx, global);
JS_FreeValue(ctx, navigator_proto);
return ctx;
}
#if defined(__APPLE__)
#define MALLOC_OVERHEAD 0
#else
#define MALLOC_OVERHEAD 8
#endif
struct trace_malloc_data {
uint8_t *base;
};
@ -168,31 +279,14 @@ static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
return ptr - dp->base;
}
/* default memory allocation functions with memory limitation */
static size_t js_trace_malloc_usable_size(const void *ptr)
{
#if defined(__APPLE__)
return malloc_size(ptr);
#elif defined(_WIN32)
return _msize((void *)ptr);
#elif defined(EMSCRIPTEN)
return 0;
#elif defined(__linux__)
return malloc_usable_size((void *)ptr);
#else
/* change this to `return 0;` if compilation fails */
return malloc_usable_size((void *)ptr);
#endif
}
static void
#ifdef _WIN32
#if defined(_WIN32) && !defined(__clang__)
/* mingw printf is used */
__attribute__((format(gnu_printf, 2, 3)))
#else
__attribute__((format(printf, 2, 3)))
#endif
js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...)
js_trace_malloc_printf(void *opaque, const char *fmt, ...)
{
va_list ap;
int c;
@ -207,8 +301,8 @@ __attribute__((format(printf, 2, 3)))
printf("NULL");
} else {
printf("H%+06lld.%zd",
js_trace_malloc_ptr_offset(ptr, s->opaque),
js_trace_malloc_usable_size(ptr));
js_trace_malloc_ptr_offset(ptr, opaque),
js__malloc_usable_size(ptr));
}
fmt++;
continue;
@ -230,77 +324,83 @@ static void js_trace_malloc_init(struct trace_malloc_data *s)
free(s->base = malloc(8));
}
static void *js_trace_malloc(JSMallocState *s, size_t size)
static void *js_trace_calloc(void *opaque, size_t count, size_t size)
{
void *ptr;
/* Do not allocate zero bytes: behavior is platform dependent */
assert(size != 0);
if (unlikely(s->malloc_size + size > s->malloc_limit))
return NULL;
ptr = malloc(size);
js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr);
if (ptr) {
s->malloc_count++;
s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
}
ptr = calloc(count, size);
js_trace_malloc_printf(opaque, "C %zd %zd -> %p\n", count, size, ptr);
return ptr;
}
static void js_trace_free(JSMallocState *s, void *ptr)
static void *js_trace_malloc(void *opaque, size_t size)
{
void *ptr;
ptr = malloc(size);
js_trace_malloc_printf(opaque, "A %zd -> %p\n", size, ptr);
return ptr;
}
static void js_trace_free(void *opaque, void *ptr)
{
if (!ptr)
return;
js_trace_malloc_printf(s, "F %p\n", ptr);
s->malloc_count--;
s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
js_trace_malloc_printf(opaque, "F %p\n", ptr);
free(ptr);
}
static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size)
static void *js_trace_realloc(void *opaque, void *ptr, size_t size)
{
size_t old_size;
if (!ptr) {
if (size == 0)
return NULL;
return js_trace_malloc(s, size);
}
old_size = js_trace_malloc_usable_size(ptr);
if (size == 0) {
js_trace_malloc_printf(s, "R %zd %p\n", size, ptr);
s->malloc_count--;
s->malloc_size -= old_size + MALLOC_OVERHEAD;
free(ptr);
return NULL;
}
if (s->malloc_size + size - old_size > s->malloc_limit)
return NULL;
js_trace_malloc_printf(s, "R %zd %p", size, ptr);
js_trace_malloc_printf(opaque, "R %zd %p", size, ptr);
ptr = realloc(ptr, size);
js_trace_malloc_printf(s, " -> %p\n", ptr);
if (ptr) {
s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size;
}
js_trace_malloc_printf(opaque, " -> %p\n", ptr);
return ptr;
}
static const JSMallocFunctions trace_mf = {
js_trace_calloc,
js_trace_malloc,
js_trace_free,
js_trace_realloc,
js_trace_malloc_usable_size,
js__malloc_usable_size
};
#ifdef QJS_USE_MIMALLOC
static void *js_mi_calloc(void *opaque, size_t count, size_t size)
{
return mi_calloc(count, size);
}
static void *js_mi_malloc(void *opaque, size_t size)
{
return mi_malloc(size);
}
static void js_mi_free(void *opaque, void *ptr)
{
if (!ptr)
return;
mi_free(ptr);
}
static void *js_mi_realloc(void *opaque, void *ptr, size_t size)
{
return mi_realloc(ptr, size);
}
static const JSMallocFunctions mi_mf = {
js_mi_calloc,
js_mi_malloc,
js_mi_free,
js_mi_realloc,
mi_malloc_usable_size
};
#endif
#define PROG_NAME "qjs"
void help(void)
{
printf("QuickJS version " CONFIG_VERSION "\n"
printf("QuickJS-ng DoneJS Edition version %s\n"
"usage: " PROG_NAME " [options] [file [args]]\n"
"-h --help list options\n"
"-e --eval EXPR evaluate EXPR\n"
@ -308,17 +408,17 @@ void help(void)
"-m --module load as ES6 module (default=autodetect)\n"
" --script load as ES6 script (default=autodetect)\n"
"-I --include file include an additional file\n"
" --std make 'std' and 'os' available to the loaded script\n"
#ifdef CONFIG_BIGNUM
" --bignum enable the bignum extensions (BigFloat, BigDecimal)\n"
" --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n"
#endif
" --std make 'std', 'os' and 'bjson' available to script\n"
"-T --trace trace memory allocation\n"
"-d --dump dump the memory usage stats\n"
" --memory-limit n limit the memory usage to 'n' bytes\n"
" --stack-size n limit the stack size to 'n' bytes\n"
"-D --dump-flags flags for dumping debug data (see DUMP_* defines)\n"
"-c --compile FILE compile the given JS file as a standalone executable\n"
"-o --out FILE output file for standalone executables\n"
" --exe select the executable to use as the base, defaults to the current one\n"
" --memory-limit n limit the memory usage to 'n' Kbytes\n"
" --stack-size n limit the stack size to 'n' Kbytes\n"
" --unhandled-rejection dump unhandled promise rejections\n"
"-q --quit just instantiate the interpreter and quit\n");
"-q --quit just instantiate the interpreter and quit\n", JS_GetVersion());
exit(1);
}
@ -326,48 +426,55 @@ int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *ctx;
JSValue ret = JS_UNDEFINED;
struct trace_malloc_data trace_data = { NULL };
int optind;
int optind = 1;
char *compile_file = NULL;
char *exe = NULL;
char *expr = NULL;
char *dump_flags_str = NULL;
char *out = NULL;
int standalone = 0;
int interactive = 0;
int dump_memory = 0;
int dump_flags = 0;
int trace_memory = 0;
int empty_run = 0;
int module = -1;
//int load_std = 0; //we don't need this anymore, we ignore this and always load std libs
int load_std = 0;
int dump_unhandled_promise_rejection = 0;
size_t memory_limit = 0;
char *include_list[32];
int i, include_count = 0;
#ifdef CONFIG_BIGNUM
int load_jscalc;
#endif
size_t stack_size = 0;
int64_t memory_limit = -1;
int64_t stack_size = -1;
#ifdef CONFIG_BIGNUM
/* load jscalc runtime if invoked as 'qjscalc' */
{
const char *p, *exename;
exename = argv[0];
p = strrchr(exename, '/');
if (p)
exename = p + 1;
load_jscalc = !strcmp(exename, "qjscalc");
/* save for later */
qjs__argc = argc;
qjs__argv = argv;
if (is_standalone(argv[0])) {
standalone = 1;
goto start;
}
#endif
dump_flags_str = getenv("QJS_DUMP_FLAGS");
dump_flags = dump_flags_str ? strtol(dump_flags_str, NULL, 16) : 0;
/* cannot use getopt because we want to pass the command line to
the script */
optind = 1;
while (optind < argc && *argv[optind] == '-') {
char *arg = argv[optind] + 1;
const char *longopt = "";
char *opt_arg = NULL;
/* a single - is not an option, it also stops argument scanning */
if (!*arg)
break;
optind++;
if (*arg == '-') {
longopt = arg + 1;
opt_arg = strchr(longopt, '=');
if (opt_arg)
*opt_arg++ = '\0';
arg += strlen(arg);
/* -- stops argument scanning */
if (!*longopt)
@ -375,23 +482,25 @@ int main(int argc, char **argv)
}
for (; *arg || *longopt; longopt = "") {
char opt = *arg;
if (opt)
if (opt) {
arg++;
if (!opt_arg && *arg)
opt_arg = arg;
}
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
help();
continue;
}
if (opt == 'e' || !strcmp(longopt, "eval")) {
if (*arg) {
expr = arg;
break;
if (!opt_arg) {
if (optind >= argc) {
fprintf(stderr, "qjs: missing expression for -e\n");
exit(1);
}
opt_arg = argv[optind++];
}
if (optind < argc) {
expr = argv[optind++];
break;
}
fprintf(stderr, "qjs: missing expression for -e\n");
exit(2);
expr = opt_arg;
break;
}
if (opt == 'I' || !strcmp(longopt, "include")) {
if (optind >= argc) {
@ -421,47 +530,80 @@ int main(int argc, char **argv)
dump_memory++;
continue;
}
if (opt == 'D' || !strcmp(longopt, "dump-flags")) {
dump_flags = opt_arg ? strtol(opt_arg, NULL, 16) : 0;
break;
}
if (opt == 'T' || !strcmp(longopt, "trace")) {
trace_memory++;
continue;
}
//if (!strcmp(longopt, "std")) {
//load_std = 1;
//continue;
//}
if (!strcmp(longopt, "std")) {
load_std = 1;
continue;
}
if (!strcmp(longopt, "unhandled-rejection")) {
dump_unhandled_promise_rejection = 1;
continue;
}
#ifdef CONFIG_BIGNUM
if (!strcmp(longopt, "bignum")) {
bignum_ext = 1;
continue;
}
if (!strcmp(longopt, "qjscalc")) {
load_jscalc = 1;
continue;
}
#endif
if (opt == 'q' || !strcmp(longopt, "quit")) {
empty_run++;
continue;
}
if (!strcmp(longopt, "memory-limit")) {
if (optind >= argc) {
fprintf(stderr, "expecting memory limit");
exit(1);
if (!opt_arg) {
if (optind >= argc) {
fprintf(stderr, "expecting memory limit");
exit(1);
}
opt_arg = argv[optind++];
}
memory_limit = (size_t)strtod(argv[optind++], NULL);
continue;
memory_limit = parse_limit(opt_arg);
break;
}
if (!strcmp(longopt, "stack-size")) {
if (optind >= argc) {
fprintf(stderr, "expecting stack size");
exit(1);
if (!opt_arg) {
if (optind >= argc) {
fprintf(stderr, "expecting stack size");
exit(1);
}
opt_arg = argv[optind++];
}
stack_size = (size_t)strtod(argv[optind++], NULL);
continue;
stack_size = parse_limit(opt_arg);
break;
}
if (opt == 'c' || !strcmp(longopt, "compile")) {
if (!opt_arg) {
if (optind >= argc) {
fprintf(stderr, "qjs: missing file for -c\n");
exit(1);
}
opt_arg = argv[optind++];
}
compile_file = opt_arg;
break;
}
if (opt == 'o' || !strcmp(longopt, "out")) {
if (!opt_arg) {
if (optind >= argc) {
fprintf(stderr, "qjs: missing file for -o\n");
exit(1);
}
opt_arg = argv[optind++];
}
out = opt_arg;
break;
}
if (!strcmp(longopt, "exe")) {
if (!opt_arg) {
if (optind >= argc) {
fprintf(stderr, "qjs: missing file for --exe\n");
exit(1);
}
opt_arg = argv[optind++];
}
exe = opt_arg;
break;
}
if (opt) {
fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
@ -472,25 +614,31 @@ int main(int argc, char **argv)
}
}
#ifdef CONFIG_BIGNUM
if (load_jscalc)
bignum_ext = 1;
#endif
if (compile_file && !out)
help();
start:
if (trace_memory) {
js_trace_malloc_init(&trace_data);
rt = JS_NewRuntime2(&trace_mf, &trace_data);
} else {
#ifdef QJS_USE_MIMALLOC
rt = JS_NewRuntime2(&mi_mf, NULL);
#else
rt = JS_NewRuntime();
#endif
}
if (!rt) {
fprintf(stderr, "qjs: cannot allocate JS runtime\n");
exit(2);
}
if (memory_limit != 0)
JS_SetMemoryLimit(rt, memory_limit);
if (stack_size != 0)
JS_SetMaxStackSize(rt, stack_size);
if (memory_limit >= 0)
JS_SetMemoryLimit(rt, (size_t)memory_limit);
if (stack_size >= 0)
JS_SetMaxStackSize(rt, (size_t)stack_size);
if (dump_flags != 0)
JS_SetDumpFlags(rt, dump_flags);
js_std_set_worker_new_context_func(JS_NewCustomContext);
js_std_init_handlers(rt);
ctx = JS_NewCustomContext(rt);
@ -508,33 +656,56 @@ int main(int argc, char **argv)
}
if (!empty_run) {
#ifdef CONFIG_BIGNUM
if (load_jscalc) {
js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0);
}
#endif
js_std_add_helpers(ctx, argc - optind, argv + optind);
/* make 'std' and 'os' visible to all code */
//if (load_std) {
const char *str = "import * as std from 'std';\n"
"import * as os from 'os';\n"
/* make 'std' and 'os' visible to non module code */
if (load_std) {
const char *str =
"import * as bjson from 'qjs:bjson';\n"
"import * as std from 'qjs:std';\n"
"import * as os from 'qjs:os';\n"
"globalThis.bjson = bjson;\n"
"globalThis.std = std;\n"
"globalThis.os = os;\n";
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
//}
}
for(i = 0; i < include_count; i++) {
if (eval_file(ctx, include_list[i], module))
if (eval_file(ctx, include_list[i], 0))
goto fail;
}
if (expr) {
if (standalone) {
JSValue ns = load_standalone_module(ctx);
if (JS_IsException(ns))
goto fail;
JSValue func = JS_GetPropertyStr(ctx, ns, "runStandalone");
JS_FreeValue(ctx, ns);
if (JS_IsException(func))
goto fail;
ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL);
JS_FreeValue(ctx, func);
} else if (compile_file) {
JSValue ns = load_standalone_module(ctx);
if (JS_IsException(ns))
goto fail;
JSValue func = JS_GetPropertyStr(ctx, ns, "compileStandalone");
JS_FreeValue(ctx, ns);
if (JS_IsException(func))
goto fail;
JSValue args[3];
args[0] = JS_NewString(ctx, compile_file);
args[1] = JS_NewString(ctx, out);
args[2] = JS_NewString(ctx, exe != NULL ? exe : argv[0]);
ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
JS_FreeValue(ctx, func);
JS_FreeValue(ctx, args[0]);
JS_FreeValue(ctx, args[1]);
JS_FreeValue(ctx, args[2]);
} else if (expr) {
if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", 0))
goto fail;
} else
if (optind >= argc) {
} else if (optind >= argc) {
/* interactive mode */
interactive = 1;
} else {
@ -546,7 +717,6 @@ int main(int argc, char **argv)
if (interactive) {
js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0);
}
//POLYFILLS FOR QJS REPL BEGIN
const char *pf = "globalThis.global = globalThis;\n"
"global.console.error = console.log\n"
@ -566,7 +736,7 @@ int main(int argc, char **argv)
" globalThis.loadFile = std.loadFile;\n"
" globalThis.printf = console.log;\n"
" globalThis.evalFile = std.loadScript;\n"
" globalThis.require = std.loadScript;\n"
// " globalThis.require = std.loadScript;\n"
" globalThis.getURL = std.urlGet;\n"
"} else {\n"
" console.error('std is not defined.');\n"
@ -574,8 +744,21 @@ int main(int argc, char **argv)
eval_buf(ctx, pf, strlen(pf), "<input>", JS_EVAL_TYPE_MODULE);
js_std_loop(ctx);
if (standalone || compile_file) {
if (JS_IsException(ret)) {
ret = JS_GetException(ctx);
} else {
JS_FreeValue(ctx, ret);
ret = js_std_loop(ctx);
}
} else {
ret = js_std_loop(ctx);
}
if (!JS_IsUndefined(ret)) {
js_std_dump_error1(ctx, ret);
JS_FreeValue(ctx, ret);
goto fail;
}
}
if (dump_memory) {
@ -589,7 +772,7 @@ int main(int argc, char **argv)
if (empty_run && dump_memory) {
clock_t t[5];
double best[5];
double best[5] = {0};
int i, j;
for (i = 0; i < 100; i++) {
t[0] = clock();

388
qjsc.c
View file

@ -2,6 +2,8 @@
* QuickJS command line compiler
*
* Copyright (c) 2018-2021 Fabrice Bellard
* Copyright (c) 2023 Ben Noordhuis
* Copyright (c) 2023 Saúl Ibarra Corretgé
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -27,15 +29,22 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#if defined(_MSC_VER)
#include "getopt_compat.h"
#else
#include <unistd.h>
#include <errno.h>
#if !defined(_WIN32)
#include <sys/wait.h>
#endif
#include <errno.h>
#include "cutils.h"
#include "quickjs-libc.h"
typedef enum {
OUTPUT_C,
OUTPUT_C_MAIN,
OUTPUT_RAW,
} OutputTypeEnum;
typedef struct {
char *name;
char *short_name;
@ -48,36 +57,13 @@ typedef struct namelist_t {
int size;
} namelist_t;
typedef struct {
const char *option_name;
const char *init_name;
} FeatureEntry;
static namelist_t cname_list;
static namelist_t cmodule_list;
static namelist_t init_module_list;
static uint64_t feature_bitmap;
static OutputTypeEnum output_type;
static FILE *outfile;
static BOOL byte_swap;
static BOOL dynamic_export;
static const char *c_ident_prefix = "qjsc_";
#define FE_ALL (-1)
static const FeatureEntry feature_list[] = {
{ "date", "Date" },
{ "eval", "Eval" },
{ "string-normalize", "StringNormalize" },
{ "regexp", "RegExp" },
{ "json", "JSON" },
{ "proxy", "Proxy" },
{ "map", "MapSet" },
{ "typedarray", "TypedArrays" },
{ "promise", "Promise" },
#define FE_MODULE_LOADER 9
{ "module-loader", NULL },
{ "bigint", "BigInt" },
};
static int strip;
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
int flags)
@ -140,7 +126,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
len = strlen(p);
else
len = r - p;
pstrcpy(buf, buf_size, c_ident_prefix);
js__pstrcpy(buf, buf_size, c_ident_prefix);
q = buf + strlen(buf);
for(i = 0; i < len; i++) {
c = p[i];
@ -171,15 +157,19 @@ static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
}
static void output_object_code(JSContext *ctx,
FILE *fo, JSValueConst obj, const char *c_name,
FILE *fo, JSValue obj, const char *c_name,
BOOL load_only)
{
uint8_t *out_buf;
size_t out_buf_len;
int flags;
flags = JS_WRITE_OBJ_BYTECODE;
if (byte_swap)
flags |= JS_WRITE_OBJ_BSWAP;
int flags = JS_WRITE_OBJ_BYTECODE;
if (strip) {
flags |= JS_WRITE_OBJ_STRIP_SOURCE;
if (strip > 1)
flags |= JS_WRITE_OBJ_STRIP_DEBUG;
}
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
if (!out_buf) {
js_std_dump_error(ctx);
@ -188,12 +178,16 @@ static void output_object_code(JSContext *ctx,
namelist_add(&cname_list, c_name, NULL, load_only);
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
c_name, (unsigned int)out_buf_len);
fprintf(fo, "const uint8_t %s[%u] = {\n",
c_name, (unsigned int)out_buf_len);
dump_hex(fo, out_buf, out_buf_len);
fprintf(fo, "};\n\n");
if (output_type == OUTPUT_RAW) {
fwrite(out_buf, 1, out_buf_len, fo);
} else {
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
c_name, (unsigned int)out_buf_len);
fprintf(fo, "const uint8_t %s[%u] = {\n",
c_name, (unsigned int)out_buf_len);
dump_hex(fo, out_buf, out_buf_len);
fprintf(fo, "};\n\n");
}
js_free(ctx, out_buf);
}
@ -202,6 +196,7 @@ static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
{
/* should never be called when compiling JS code */
abort();
return -1; // pacify compiler
}
static void find_unique_cname(char *cname, size_t cname_size)
@ -223,7 +218,7 @@ static void find_unique_cname(char *cname, size_t cname_size)
break;
suffix_num++;
}
pstrcpy(cname, cname_size, cname1);
js__pstrcpy(cname, cname_size, cname1);
}
JSModuleDef *jsc_module_loader(JSContext *ctx,
@ -239,13 +234,10 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
namelist_add(&init_module_list, e->name, e->short_name, 0);
/* create a dummy module */
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
} else if (has_suffix(module_name, ".so")) {
fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name);
/* create a dummy module */
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
/* the resulting executable will export its symbols for the
dynamic library */
dynamic_export = TRUE;
} else if (js__has_suffix(module_name, ".so")) {
JS_ThrowReferenceError(ctx, "%s: dynamically linking to shared libraries not supported",
module_name);
return NULL;
} else {
size_t buf_len;
uint8_t *buf;
@ -280,6 +272,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
static void compile_file(JSContext *ctx, FILE *fo,
const char *filename,
const char *script_name,
const char *c_name1,
int module)
{
@ -296,21 +289,21 @@ static void compile_file(JSContext *ctx, FILE *fo,
}
eval_flags = JS_EVAL_FLAG_COMPILE_ONLY;
if (module < 0) {
module = (has_suffix(filename, ".mjs") ||
module = (js__has_suffix(filename, ".mjs") ||
JS_DetectModule((const char *)buf, buf_len));
}
if (module)
eval_flags |= JS_EVAL_TYPE_MODULE;
else
eval_flags |= JS_EVAL_TYPE_GLOBAL;
obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags);
obj = JS_Eval(ctx, (const char *)buf, buf_len, script_name ? script_name : filename, eval_flags);
if (JS_IsException(obj)) {
js_std_dump_error(ctx);
exit(1);
}
js_free(ctx, buf);
if (c_name1) {
pstrcpy(c_name, sizeof(c_name), c_name1);
js__pstrcpy(c_name, sizeof(c_name), c_name1);
} else {
get_c_name(c_name, sizeof(c_name), filename);
}
@ -321,245 +314,106 @@ static void compile_file(JSContext *ctx, FILE *fo,
static const char main_c_template1[] =
"int main(int argc, char **argv)\n"
"{\n"
" int r;\n"
" JSValue ret;\n"
" JSRuntime *rt;\n"
" JSContext *ctx;\n"
" r = 0;\n"
" rt = JS_NewRuntime();\n"
" js_std_set_worker_new_context_func(JS_NewCustomContext);\n"
" js_std_init_handlers(rt);\n"
;
static const char main_c_template2[] =
" js_std_loop(ctx);\n"
" js_std_free_handlers(rt);\n"
" ret = js_std_loop(ctx);\n"
" if (JS_IsException(ret)) {\n"
" js_std_dump_error1(ctx, ret);\n"
" r = 1;\n"
" }\n"
" JS_FreeValue(ctx, ret);\n"
" JS_FreeContext(ctx);\n"
" js_std_free_handlers(rt);\n"
" JS_FreeRuntime(rt);\n"
" return 0;\n"
" return r;\n"
"}\n";
#define PROG_NAME "qjsc"
void help(void)
{
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
printf("QuickJS-ng Compiler DoneJS Edition version %s\n"
"usage: " PROG_NAME " [options] [files]\n"
"\n"
"options are:\n"
"-c only output bytecode to a C file\n"
"-e output main() and bytecode to a C file (default = executable output)\n"
"-b output raw bytecode instead of C code\n"
"-e output main() and bytecode in a C file\n"
"-o output set the output filename\n"
"-n script_name set the script name (as used in stack traces)\n"
"-N cname set the C name of the generated data\n"
"-m compile as Javascript module (default=autodetect)\n"
"-D module_name compile a dynamically loaded module or worker\n"
"-M module_name[,cname] add initialization code for an external C module\n"
"-x byte swapped output\n"
"-p prefix set the prefix of the generated C names\n"
"-s strip the source code, specify twice to also strip debug info\n"
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
JS_GetVersion(),
JS_DEFAULT_STACK_SIZE);
#ifdef CONFIG_LTO
{
int i;
printf("-flto use link time optimization\n");
printf("-fbignum enable bignum extensions\n");
printf("-fno-[");
for(i = 0; i < countof(feature_list); i++) {
if (i != 0)
printf("|");
printf("%s", feature_list[i].option_name);
}
printf("]\n"
" disable selected language features (smaller code size)\n");
}
#endif
exit(1);
}
#if defined(CONFIG_CC) && !defined(_WIN32)
int exec_cmd(char **argv)
{
int pid, status, ret;
pid = fork();
if (pid == 0) {
execvp(argv[0], argv);
exit(1);
}
for(;;) {
ret = waitpid(pid, &status, 0);
if (ret == pid && WIFEXITED(status))
break;
}
return WEXITSTATUS(status);
}
static int output_executable(const char *out_filename, const char *cfilename,
BOOL use_lto, BOOL verbose, const char *exename)
{
const char *argv[64];
const char **arg, *bn_suffix, *lto_suffix;
char libjsname[1024];
char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
int ret;
/* get the directory of the executable */
pstrcpy(exe_dir, sizeof(exe_dir), exename);
p = strrchr(exe_dir, '/');
if (p) {
*p = '\0';
} else {
pstrcpy(exe_dir, sizeof(exe_dir), ".");
}
/* if 'quickjs.h' is present at the same path as the executable, we
use it as include and lib directory */
snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir);
if (access(buf, R_OK) == 0) {
pstrcpy(inc_dir, sizeof(inc_dir), exe_dir);
pstrcpy(lib_dir, sizeof(lib_dir), exe_dir);
} else {
snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
}
lto_suffix = "";
bn_suffix = "";
arg = argv;
*arg++ = CONFIG_CC;
*arg++ = "-O2";
#ifdef CONFIG_LTO
if (use_lto) {
*arg++ = "-flto";
lto_suffix = ".lto";
}
#endif
/* XXX: use the executable path to find the includes files and
libraries */
*arg++ = "-D";
*arg++ = "_GNU_SOURCE";
*arg++ = "-I";
*arg++ = inc_dir;
*arg++ = "-o";
*arg++ = out_filename;
if (dynamic_export)
*arg++ = "-rdynamic";
*arg++ = cfilename;
snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a",
lib_dir, bn_suffix, lto_suffix);
*arg++ = libjsname;
*arg++ = "-lm";
*arg++ = "-ldl";
*arg++ = "-lpthread";
*arg = NULL;
if (verbose) {
for(arg = argv; *arg != NULL; arg++)
printf("%s ", *arg);
printf("\n");
}
ret = exec_cmd((char **)argv);
unlink(cfilename);
return ret;
}
#else
static int output_executable(const char *out_filename, const char *cfilename,
BOOL use_lto, BOOL verbose, const char *exename)
{
fprintf(stderr, "Executable output is not supported for this target\n");
exit(1);
return 0;
}
#endif
typedef enum {
OUTPUT_C,
OUTPUT_C_MAIN,
OUTPUT_EXECUTABLE,
} OutputTypeEnum;
int main(int argc, char **argv)
{
int c, i, verbose;
const char *out_filename, *cname;
const char *out_filename, *cname, *script_name;
char cfilename[1024];
FILE *fo;
JSRuntime *rt;
JSContext *ctx;
BOOL use_lto;
int module;
OutputTypeEnum output_type;
size_t stack_size;
#ifdef CONFIG_BIGNUM
BOOL bignum_ext = FALSE;
#endif
namelist_t dynamic_module_list;
out_filename = NULL;
output_type = OUTPUT_EXECUTABLE;
script_name = NULL;
output_type = OUTPUT_C;
cname = NULL;
feature_bitmap = FE_ALL;
module = -1;
byte_swap = FALSE;
verbose = 0;
use_lto = FALSE;
strip = 0;
stack_size = 0;
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
/* add system modules */
namelist_add(&cmodule_list, "qjs:std", "std", 0);
namelist_add(&cmodule_list, "qjs:os", "os", 0);
namelist_add(&cmodule_list, "qjs:bjson", "bjson", 0);
namelist_add(&cmodule_list, "std", "std", 0);
namelist_add(&cmodule_list, "os", "os", 0);
namelist_add(&cmodule_list, "bjson", "bjson", 0);
for(;;) {
c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
c = getopt(argc, argv, "ho:N:mn:bxesvM:p:S:D:");
if (c == -1)
break;
switch(c) {
case 'h':
help();
case 'b':
output_type = OUTPUT_RAW;
break;
case 'o':
out_filename = optarg;
break;
case 'c':
output_type = OUTPUT_C;
break;
case 'e':
output_type = OUTPUT_C_MAIN;
break;
case 'n':
script_name = optarg;
break;
case 'N':
cname = optarg;
break;
case 'f':
{
const char *p;
p = optarg;
if (!strcmp(optarg, "lto")) {
use_lto = TRUE;
} else if (strstart(p, "no-", &p)) {
use_lto = TRUE;
for(i = 0; i < countof(feature_list); i++) {
if (!strcmp(p, feature_list[i].option_name)) {
feature_bitmap &= ~((uint64_t)1 << i);
break;
}
}
if (i == countof(feature_list))
goto bad_feature;
} else
#ifdef CONFIG_BIGNUM
if (!strcmp(optarg, "bignum")) {
bignum_ext = TRUE;
} else
#endif
{
bad_feature:
fprintf(stderr, "unsupported feature: %s\n", optarg);
exit(1);
}
}
break;
case 'm':
module = 1;
break;
@ -568,11 +422,11 @@ int main(int argc, char **argv)
char *p;
char path[1024];
char cname[1024];
pstrcpy(path, sizeof(path), optarg);
js__pstrcpy(path, sizeof(path), optarg);
p = strchr(path, ',');
if (p) {
*p = '\0';
pstrcpy(cname, sizeof(cname), p + 1);
js__pstrcpy(cname, sizeof(cname), p + 1);
} else {
get_c_name(cname, sizeof(cname), path);
}
@ -582,8 +436,8 @@ int main(int argc, char **argv)
case 'D':
namelist_add(&dynamic_module_list, optarg, NULL, 0);
break;
case 'x':
byte_swap = TRUE;
case 's':
strip++;
break;
case 'v':
verbose++;
@ -602,26 +456,16 @@ int main(int argc, char **argv)
if (optind >= argc)
help();
if (!out_filename) {
if (output_type == OUTPUT_EXECUTABLE) {
out_filename = "a.out";
} else {
out_filename = "out.c";
}
}
if (!out_filename)
out_filename = "out.c";
if (output_type == OUTPUT_EXECUTABLE) {
#if defined(_WIN32) || defined(__ANDROID__)
/* XXX: find a /tmp directory ? */
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
#else
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
#endif
} else {
pstrcpy(cfilename, sizeof(cfilename), out_filename);
}
js__pstrcpy(cfilename, sizeof(cfilename), out_filename);
if (output_type == OUTPUT_RAW)
fo = fopen(cfilename, "wb");
else
fo = fopen(cfilename, "w");
fo = fopen(cfilename, "w");
if (!fo) {
perror(cfilename);
exit(1);
@ -630,27 +474,21 @@ int main(int argc, char **argv)
rt = JS_NewRuntime();
ctx = JS_NewContext(rt);
#ifdef CONFIG_BIGNUM
if (bignum_ext) {
JS_AddIntrinsicBigFloat(ctx);
JS_AddIntrinsicBigDecimal(ctx);
JS_AddIntrinsicOperators(ctx);
JS_EnableBignumExt(ctx, TRUE);
}
#endif
/* loader for ES6 modules */
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
"\n"
);
if (output_type != OUTPUT_RAW) {
fprintf(fo, "/* File generated automatically by the QuickJS-ng compiler. */\n"
"\n"
);
}
if (output_type != OUTPUT_C) {
if (output_type == OUTPUT_C_MAIN) {
fprintf(fo, "#include \"quickjs-libc.h\"\n"
"\n"
);
} else {
} else if (output_type == OUTPUT_C) {
fprintf(fo, "#include <inttypes.h>\n"
"\n"
);
@ -658,7 +496,7 @@ int main(int argc, char **argv)
for(i = optind; i < argc; i++) {
const char *filename = argv[i];
compile_file(ctx, fo, filename, cname, module);
compile_file(ctx, fo, filename, script_name, cname, module);
cname = NULL;
}
@ -670,31 +508,13 @@ int main(int argc, char **argv)
}
}
if (output_type != OUTPUT_C) {
if (output_type == OUTPUT_C_MAIN) {
fprintf(fo,
"static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
"{\n"
" JSContext *ctx = JS_NewContextRaw(rt);\n"
" JSContext *ctx = JS_NewContext(rt);\n"
" if (!ctx)\n"
" return NULL;\n");
/* add the basic objects */
fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
for(i = 0; i < countof(feature_list); i++) {
if ((feature_bitmap & ((uint64_t)1 << i)) &&
feature_list[i].init_name) {
fprintf(fo, " JS_AddIntrinsic%s(ctx);\n",
feature_list[i].init_name);
}
}
#ifdef CONFIG_BIGNUM
if (bignum_ext) {
fprintf(fo,
" JS_AddIntrinsicBigFloat(ctx);\n"
" JS_AddIntrinsicBigDecimal(ctx);\n"
" JS_AddIntrinsicOperators(ctx);\n"
" JS_EnableBignumExt(ctx, 1);\n");
}
#endif
/* add the precompiled modules (XXX: could modify the module
loader instead) */
for(i = 0; i < init_module_list.count; i++) {
@ -726,10 +546,8 @@ int main(int argc, char **argv)
(unsigned int)stack_size);
}
/* add the module loader if necessary */
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
}
/* add the module loader */
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
fprintf(fo,
" ctx = JS_NewCustomContext(rt);\n"
@ -750,10 +568,6 @@ int main(int argc, char **argv)
fclose(fo);
if (output_type == OUTPUT_EXECUTABLE) {
return output_executable(out_filename, cfilename, use_lto, verbose,
argv[0]);
}
namelist_free(&cname_list);
namelist_free(&cmodule_list);
namelist_free(&init_module_list);

2657
qjscalc.js

File diff suppressed because it is too large Load diff

View file

@ -78,9 +78,9 @@ DEF(await, "await")
/* empty string */
DEF(empty_string, "")
/* identifiers */
DEF(keys, "keys")
DEF(size, "size")
DEF(length, "length")
DEF(fileName, "fileName")
DEF(lineNumber, "lineNumber")
DEF(message, "message")
DEF(cause, "cause")
DEF(errors, "errors")
@ -172,19 +172,11 @@ DEF(status, "status")
DEF(reason, "reason")
DEF(globalThis, "globalThis")
DEF(bigint, "bigint")
#ifdef CONFIG_BIGNUM
DEF(bigfloat, "bigfloat")
DEF(bigdecimal, "bigdecimal")
DEF(roundingMode, "roundingMode")
DEF(maximumSignificantDigits, "maximumSignificantDigits")
DEF(maximumFractionDigits, "maximumFractionDigits")
#endif
/* the following 3 atoms are only used with CONFIG_ATOMICS */
DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out")
DEF(ok, "ok")
/* */
DEF(toJSON, "toJSON")
DEF(maxByteLength, "maxByteLength")
/* class names */
DEF(Object, "Object")
DEF(Array, "Array")
@ -213,21 +205,20 @@ DEF(Int32Array, "Int32Array")
DEF(Uint32Array, "Uint32Array")
DEF(BigInt64Array, "BigInt64Array")
DEF(BigUint64Array, "BigUint64Array")
DEF(Float16Array, "Float16Array")
DEF(Float32Array, "Float32Array")
DEF(Float64Array, "Float64Array")
DEF(DataView, "DataView")
DEF(BigInt, "BigInt")
#ifdef CONFIG_BIGNUM
DEF(BigFloat, "BigFloat")
DEF(BigFloatEnv, "BigFloatEnv")
DEF(BigDecimal, "BigDecimal")
DEF(OperatorSet, "OperatorSet")
DEF(Operators, "Operators")
#endif
DEF(WeakRef, "WeakRef")
DEF(FinalizationRegistry, "FinalizationRegistry")
DEF(Map, "Map")
DEF(Set, "Set") /* Map + 1 */
DEF(WeakMap, "WeakMap") /* Map + 2 */
DEF(WeakSet, "WeakSet") /* Map + 3 */
DEF(Iterator, "Iterator")
DEF(IteratorHelper, "Iterator Helper")
DEF(IteratorWrap, "Iterator Wrap")
DEF(Map_Iterator, "Map Iterator")
DEF(Set_Iterator, "Set Iterator")
DEF(Array_Iterator, "Array Iterator")
@ -250,6 +241,7 @@ DEF(SyntaxError, "SyntaxError")
DEF(TypeError, "TypeError")
DEF(URIError, "URIError")
DEF(InternalError, "InternalError")
DEF(CallSite, "CallSite")
/* private symbols */
DEF(Private_brand, "<brand>")
/* symbols */
@ -266,8 +258,5 @@ DEF(Symbol_hasInstance, "Symbol.hasInstance")
DEF(Symbol_species, "Symbol.species")
DEF(Symbol_unscopables, "Symbol.unscopables")
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
#ifdef CONFIG_BIGNUM
DEF(Symbol_operatorSet, "Symbol.operatorSet")
#endif
#endif /* DEF */

54
quickjs-c-atomics.h Normal file
View file

@ -0,0 +1,54 @@
/*
* QuickJS C atomics definitions
*
* Copyright (c) 2023 Marcin Kolny
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
// Use GCC builtins for version < 4.9
# if((__GNUC__ << 16) + __GNUC_MINOR__ < ((4) << 16) + 9)
# define GCC_BUILTIN_ATOMICS
# endif
#endif
#ifdef GCC_BUILTIN_ATOMICS
#define atomic_fetch_add(obj, arg) \
__atomic_fetch_add(obj, arg, __ATOMIC_SEQ_CST)
#define atomic_compare_exchange_strong(obj, expected, desired) \
__atomic_compare_exchange_n(obj, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
#define atomic_exchange(obj, desired) \
__atomic_exchange_n (obj, desired, __ATOMIC_SEQ_CST)
#define atomic_load(obj) \
__atomic_load_n(obj, __ATOMIC_SEQ_CST)
#define atomic_store(obj, desired) \
__atomic_store_n(obj, desired, __ATOMIC_SEQ_CST)
#define atomic_fetch_or(obj, arg) \
__atomic_fetch_or(obj, arg, __ATOMIC_SEQ_CST)
#define atomic_fetch_xor(obj, arg) \
__atomic_fetch_xor(obj, arg, __ATOMIC_SEQ_CST)
#define atomic_fetch_and(obj, arg) \
__atomic_fetch_and(obj, arg, __ATOMIC_SEQ_CST)
#define atomic_fetch_sub(obj, arg) \
__atomic_fetch_sub(obj, arg, __ATOMIC_SEQ_CST)
#define _Atomic
#else
#include <stdatomic.h>
#endif

File diff suppressed because it is too large Load diff

View file

@ -35,20 +35,23 @@ extern "C" {
JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
JSModuleDef *js_init_module_bjson(JSContext *ctx, const char *module_name);
void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
void js_std_loop(JSContext *ctx);
JSValue js_std_loop(JSContext *ctx);
JSValue js_std_await(JSContext *ctx, JSValue obj);
void js_std_init_handlers(JSRuntime *rt);
void js_std_free_handlers(JSRuntime *rt);
void js_std_dump_error(JSContext *ctx);
void js_std_dump_error1(JSContext *ctx, JSValue exception_val);
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
int js_module_set_import_meta(JSContext *ctx, JSValue func_val,
JS_BOOL use_realpath, JS_BOOL is_main);
JSModuleDef *js_module_loader(JSContext *ctx,
const char *module_name, void *opaque);
void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
int flags);
void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
JSValueConst reason,
void js_std_promise_rejection_tracker(JSContext *ctx, JSValue promise,
JSValue reason,
JS_BOOL is_handled, void *opaque);
void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));

View file

@ -44,6 +44,7 @@ FMT(loc)
FMT(arg)
FMT(var_ref)
FMT(u32)
FMT(u32x2)
FMT(i32)
FMT(const)
FMT(label)
@ -110,6 +111,7 @@ DEF( return, 1, 1, 0, none)
DEF( return_undef, 1, 0, 0, none)
DEF(check_ctor_return, 1, 1, 2, none)
DEF( check_ctor, 1, 0, 0, none)
DEF( init_ctor, 1, 0, 1, none)
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
DEF( return_async, 1, 1, 0, none)
@ -135,9 +137,12 @@ DEF( put_ref_value, 1, 3, 0, none)
DEF( define_var, 6, 0, 0, atom_u8)
DEF(check_define_var, 6, 0, 0, atom_u8)
DEF( define_func, 6, 1, 0, atom_u8)
// order matters, see IC counterparts
DEF( get_field, 5, 1, 1, atom)
DEF( get_field2, 5, 1, 2, atom)
DEF( put_field, 5, 2, 0, atom)
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
@ -172,7 +177,6 @@ DEF(set_loc_uninitialized, 3, 0, 0, loc)
DEF( get_loc_check, 3, 0, 1, loc)
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
DEF( put_loc_check_init, 3, 1, 0, loc)
DEF(get_loc_checkthis, 3, 0, 1, loc)
DEF(get_var_ref_check, 3, 0, 1, var_ref)
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
@ -234,15 +238,20 @@ DEF( typeof, 1, 1, 1, none)
DEF( delete, 1, 2, 1, none)
DEF( delete_var, 5, 0, 1, atom)
/* warning: order matters (see js_parse_assign_expr) */
DEF( mul, 1, 2, 1, none)
DEF( div, 1, 2, 1, none)
DEF( mod, 1, 2, 1, none)
DEF( add, 1, 2, 1, none)
DEF( sub, 1, 2, 1, none)
DEF( pow, 1, 2, 1, none)
DEF( shl, 1, 2, 1, none)
DEF( sar, 1, 2, 1, none)
DEF( shr, 1, 2, 1, none)
DEF( and, 1, 2, 1, none)
DEF( xor, 1, 2, 1, none)
DEF( or, 1, 2, 1, none)
DEF( pow, 1, 2, 1, none)
DEF( lt, 1, 2, 1, none)
DEF( lte, 1, 2, 1, none)
DEF( gt, 1, 2, 1, none)
@ -253,15 +262,8 @@ DEF( eq, 1, 2, 1, none)
DEF( neq, 1, 2, 1, none)
DEF( strict_eq, 1, 2, 1, none)
DEF( strict_neq, 1, 2, 1, none)
DEF( and, 1, 2, 1, none)
DEF( xor, 1, 2, 1, none)
DEF( or, 1, 2, 1, none)
DEF(is_undefined_or_null, 1, 1, 1, none)
DEF( private_in, 1, 2, 1, none)
#ifdef CONFIG_BIGNUM
DEF( mul_pow10, 1, 2, 1, none)
DEF( math_mod, 1, 2, 1, none)
#endif
/* must be the last non short and non temporary opcode */
DEF( nop, 1, 0, 0, none)
@ -272,8 +274,6 @@ def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
/* the following opcodes must be in the same order as the 'with_x' and
get_var_undef, get_var and put_var opcodes */
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
@ -281,7 +281,6 @@ def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
@ -290,9 +289,8 @@ def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */
#if SHORT_OPCODES
DEF( push_minus1, 1, 0, 1, none_int)
DEF( push_0, 1, 0, 1, none_int)
DEF( push_1, 1, 0, 1, none_int)
@ -312,6 +310,7 @@ DEF( get_loc8, 2, 0, 1, loc8)
DEF( put_loc8, 2, 1, 0, loc8)
DEF( set_loc8, 2, 1, 1, loc8)
DEF( get_loc0_loc1, 1, 0, 2, none_loc)
DEF( get_loc0, 1, 0, 1, none_loc)
DEF( get_loc1, 1, 0, 1, none_loc)
DEF( get_loc2, 1, 0, 1, none_loc)
@ -365,7 +364,11 @@ DEF( is_undefined, 1, 1, 1, none)
DEF( is_null, 1, 1, 1, none)
DEF(typeof_is_undefined, 1, 1, 1, none)
DEF( typeof_is_function, 1, 1, 1, none)
#endif
// order matters, see non-IC counterparts
DEF( get_field_ic, 5, 1, 1, none)
DEF( get_field2_ic, 5, 1, 2, none)
DEF( put_field_ic, 5, 2, 0, none)
#undef DEF
#undef def

22238
quickjs.c

File diff suppressed because it is too large Load diff

934
quickjs.h

File diff suppressed because it is too large Load diff

View file

@ -1,180 +0,0 @@
#!/bin/sh
# Release the QuickJS source code
set -e
version=`cat VERSION`
if [ "$1" = "-h" ] ; then
echo "release.sh [release_list]"
echo ""
echo "release_list: extras binary win_binary cosmo_binary quickjs"
exit 1
fi
release_list="extras binary win_binary cosmo_binary quickjs"
if [ "$1" != "" ] ; then
release_list="$1"
fi
#################################################"
# extras
if echo $release_list | grep -w -q extras ; then
d="quickjs-${version}"
name="quickjs-extras-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir $outdir/unicode $outdir/tests
cp unicode/* $outdir/unicode
cp -a tests/bench-v8 $outdir/tests
( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} )
fi
#################################################"
# Windows binary release
if echo $release_list | grep -w -q win_binary ; then
# win64
dlldir=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
cross_prefix="x86_64-w64-mingw32-"
d="quickjs-win-x86_64-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
make CONFIG_WIN32=y qjs.exe
cp qjs.exe $outdir
${cross_prefix}strip $outdir/qjs.exe
cp $dlldir/libwinpthread-1.dll $outdir
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
make CONFIG_WIN32=y clean
# win32
dlldir=/usr/i686-w64-mingw32/sys-root/mingw/bin
cross_prefix="i686-w64-mingw32-"
d="quickjs-win-i686-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
make clean
make CONFIG_WIN32=y clean
make CONFIG_WIN32=y CONFIG_M32=y qjs.exe
cp qjs.exe $outdir
${cross_prefix}strip $outdir/qjs.exe
cp $dlldir/libwinpthread-1.dll $outdir
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
fi
#################################################"
# Cosmopolitan binary release
if echo $release_list | grep -w -q cosmo_binary ; then
export PATH=$PATH:$HOME/cosmocc/bin
d="quickjs-cosmo-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
make clean
make CONFIG_COSMO=y -j4 qjs run-test262
cp qjs run-test262 $outdir
cp readme-cosmo.txt $outdir/readme.txt
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
fi
#################################################"
# Linux binary release
if echo $release_list | grep -w -q binary ; then
make clean
make CONFIG_WIN32=y clean
make -j4 qjs run-test262
make -j4 CONFIG_M32=y qjs32 run-test262-32
strip qjs run-test262 qjs32 run-test262-32
d="quickjs-linux-x86_64-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
cp qjs run-test262 $outdir
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
d="quickjs-linux-i686-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
cp qjs32 $outdir/qjs
cp run-test262-32 $outdir/run-test262
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
fi
#################################################"
# quickjs
if echo $release_list | grep -w -q quickjs ; then
make build_doc
d="quickjs-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples
cp Makefile VERSION TODO Changelog readme.txt LICENSE \
release.sh unicode_download.sh \
qjs.c qjsc.c qjscalc.js repl.js \
quickjs.c quickjs.h quickjs-atom.h \
quickjs-libc.c quickjs-libc.h quickjs-opcode.h \
cutils.c cutils.h list.h \
libregexp.c libregexp.h libregexp-opcode.h \
libunicode.c libunicode.h libunicode-table.h \
libbf.c libbf.h \
unicode_gen.c unicode_gen_def.h \
run-test262.c test262o.conf test262.conf \
test262o_errors.txt test262_errors.txt \
$outdir
cp tests/*.js tests/*.patch tests/bjson.c $outdir/tests
cp examples/*.js examples/*.c $outdir/examples
cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \
doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \
$outdir/doc
( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} )
fi

1122
repl.js

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

129
standalone.js Normal file
View file

@ -0,0 +1,129 @@
import * as std from "qjs:std";
import * as os from "qjs:os";
import * as bjson from "qjs:bjson";
// See quickjs.h
const JS_READ_OBJ_BYTECODE = 1 << 0;
const JS_READ_OBJ_REFERENCE = 1 << 3;
const JS_WRITE_OBJ_BYTECODE = 1 << 0;
const JS_WRITE_OBJ_REFERENCE = 1 << 3;
const JS_WRITE_OBJ_STRIP_SOURCE = 1 << 4;
/**
* Trailer for standalone binaries. When some code gets bundled with the qjs
* executable we add a 12 byte trailer. The first 8 bytes are the magic
* string that helps us understand this is a standalone binary, and the
* remaining 4 are the offset (from the beginning of the binary) where the
* bundled data is located.
*
* The offset is stored as a 32bit little-endian number.
*/
const Trailer = {
Magic: 'quickjs2',
MagicSize: 8,
DataSize: 4,
Size: 12
};
function encodeAscii(txt) {
return new Uint8Array(txt.split('').map(c => c.charCodeAt(0)));
}
function decodeAscii(buf) {
return Array.from(buf).map(c => String.fromCharCode(c)).join('')
}
export function compileStandalone(inFile, outFile, targetExe) {
// Step 1: compile the source file to bytecode
const js = std.loadFile(inFile);
if (!js) {
throw new Error(`failed to open ${inFile}`);
}
const code = std.evalScript(js, {
compile_only: true,
compile_module: true
});
const bytecode = new Uint8Array(bjson.write(code, JS_WRITE_OBJ_BYTECODE | JS_WRITE_OBJ_REFERENCE | JS_WRITE_OBJ_STRIP_SOURCE));
// Step 2: copy the bytecode to the end of the executable and add a marker.
const exeFileName = targetExe ?? globalThis.argv0;
const exe = std.loadFile(exeFileName, { binary: true });
if (!exe) {
throw new Error(`failed to open executable: ${exeFileName}`);
}
const exeSize = exe.length;
const newBuffer = exe.buffer.transfer(exeSize + bytecode.length + Trailer.Size);
const newExe = new Uint8Array(newBuffer);
newExe.set(bytecode, exeSize);
newExe.set(encodeAscii(Trailer.Magic), exeSize + bytecode.length);
const dw = new DataView(newBuffer, exeSize + bytecode.length + Trailer.MagicSize, Trailer.DataSize);
dw.setUint32(0, exeSize, true /* little-endian */);
// We use os.open() so we can set the permissions mask.
const newFd = os.open(outFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o755);
if (newFd < 0) {
throw new Error(`failed to create ${outFile}`);
}
if (os.write(newFd, newBuffer, 0, newBuffer.byteLength) < 0) {
os.close(newFd);
throw new Error(`failed to write to output file`);
}
os.close(newFd);
}
export function runStandalone() {
const file = globalThis.argv0;
const exe = std.open(file, 'rb');
if (!exe) {
throw new Error(`failed to open executable: ${file}`);
}
let r = exe.seek(-Trailer.Size, std.SEEK_END);
if (r < 0) {
throw new Error(`seek error: ${-r}`);
}
const trailer = new Uint8Array(Trailer.Size);
exe.read(trailer.buffer, 0, Trailer.Size);
const magic = new Uint8Array(trailer.buffer, 0, Trailer.MagicSize);
// Shouldn't happen since qjs.c checks for it.
if (decodeAscii(magic) !== Trailer.Magic) {
exe.close();
throw new Error('corrupted binary, magic mismatch');
}
const dw = new DataView(trailer.buffer, Trailer.MagicSize, Trailer.DataSize);
const offset = dw.getUint32(0, true /* little-endian */);
const bytecode = new Uint8Array(offset - Trailer.Size);
r = exe.seek(offset, std.SEEK_SET);
if (r < 0) {
exe.close();
throw new Error(`seek error: ${-r}`);
}
exe.read(bytecode.buffer, 0, bytecode.length);
if (exe.error()) {
exe.close();
throw new Error('read error');
}
exe.close();
const code = bjson.read(bytecode.buffer, 0, bytecode.length, JS_READ_OBJ_BYTECODE | JS_READ_OBJ_REFERENCE);
return std.evalScript(code, {
eval_module: true
});
}

View file

@ -1,5 +0,0 @@
function test() {
breakFunction();
console.warn("lol it works!");
}
test()

132
test262-fast.conf Normal file
View file

@ -0,0 +1,132 @@
[exclude]
# list excluded tests and directories here for faster operation
# lengthy constructed regexp (>500 ms)
test262/test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js
test262/test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js
# slow notifications (> 600 ms)
test262/test/built-ins/Atomics/notify/notify-in-order-one-time.js
test262/test/built-ins/Atomics/notify/notify-in-order.js
test262/test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js
test262/test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js
# lengthy constructed regexp (>200 ms)
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js
test262/test/built-ins/RegExp/character-class-escape-non-whitespace.js
# 417 lengty tests with huge constructed regexp (>200 ms)
test262/test/built-ins/RegExp/property-escapes/generated/
# lengthy constructed URLS (>200 ms)
test262/test/built-ins/decodeURI/S15.1.3.1_A1.2_T1.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.2_T2.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.10_T1.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.11_T1.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.11_T2.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T1.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T2.js
test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T3.js
test262/test/built-ins/decodeURI/S15.1.3.1_A2.5_T1.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.2_T1.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.2_T2.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.10_T1.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.11_T1.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.11_T2.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T1.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T2.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T3.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
# lengthy comment tests
test262/test/language/comments/S7.4_A5.js
test262/test/language/comments/S7.4_A6.js
# lengthy unicode level tests
test262/test/language/identifiers/start-unicode-5.2.0-class-escaped.js
test262/test/language/identifiers/start-unicode-5.2.0-class.js
test262/test/language/identifiers/start-unicode-8.0.0-class-escaped.js
test262/test/language/identifiers/start-unicode-8.0.0-class.js
test262/test/language/identifiers/start-unicode-9.0.0-class-escaped.js
test262/test/language/identifiers/start-unicode-9.0.0-class.js
test262/test/language/identifiers/start-unicode-10.0.0-class-escaped.js
test262/test/language/identifiers/start-unicode-10.0.0-class.js
test262/test/language/identifiers/start-unicode-13.0.0-class-escaped.js
test262/test/language/identifiers/start-unicode-13.0.0-class.js
test262/test/language/identifiers/start-unicode-15.0.0-class-escaped.js
test262/test/language/identifiers/start-unicode-15.0.0-class.js
# Atomics tests with 2 second delays
test262/test/built-ins/Atomics/notify/bigint/notify-all-on-loc.js
test262/test/built-ins/Atomics/notify/negative-count.js
test262/test/built-ins/Atomics/notify/notify-all-on-loc.js
test262/test/built-ins/Atomics/notify/notify-all.js
test262/test/built-ins/Atomics/notify/notify-nan.js
test262/test/built-ins/Atomics/notify/notify-one.js
test262/test/built-ins/Atomics/notify/notify-two.js
test262/test/built-ins/Atomics/notify/notify-zero.js
# Atomics tests with 400 millisecond delays
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-no-operation.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-add.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-and.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-compareExchange.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-exchange.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-or.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-store.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-sub.js
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-xor.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-add.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-and.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-compareExchange.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-exchange.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-or.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-store.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-sub.js
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-xor.js
# Atomics tests with 200 millisecond delays
test262/test/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js
test262/test/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js
test262/test/built-ins/Atomics/notify/notify-renotify-noop.js
test262/test/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js
test262/test/built-ins/Atomics/wait/bigint/false-for-timeout-agent.js
test262/test/built-ins/Atomics/wait/bigint/nan-for-timeout.js
test262/test/built-ins/Atomics/wait/bigint/negative-timeout-agent.js
test262/test/built-ins/Atomics/wait/bigint/value-not-equal.js
test262/test/built-ins/Atomics/wait/bigint/was-woken-before-timeout.js
test262/test/built-ins/Atomics/wait/false-for-timeout-agent.js
test262/test/built-ins/Atomics/wait/nan-for-timeout.js
test262/test/built-ins/Atomics/wait/negative-timeout-agent.js
test262/test/built-ins/Atomics/wait/null-for-timeout-agent.js
test262/test/built-ins/Atomics/wait/object-for-timeout-agent.js
test262/test/built-ins/Atomics/wait/poisoned-object-for-timeout-throws-agent.js
test262/test/built-ins/Atomics/wait/symbol-for-index-throws-agent.js
test262/test/built-ins/Atomics/wait/symbol-for-timeout-throws-agent.js
test262/test/built-ins/Atomics/wait/symbol-for-value-throws-agent.js
test262/test/built-ins/Atomics/wait/true-for-timeout-agent.js
test262/test/built-ins/Atomics/wait/undefined-for-timeout.js
test262/test/built-ins/Atomics/wait/undefined-index-defaults-to-zero.js
test262/test/built-ins/Atomics/wait/value-not-equal.js
test262/test/built-ins/Atomics/wait/wait-index-value-not-equal.js
test262/test/built-ins/Atomics/wait/was-woken-before-timeout.js
# lengthy regexp literal construction (>500 ms)
test262/test/language/literals/regexp/S7.8.5_A1.1_T2.js
test262/test/language/literals/regexp/S7.8.5_A1.4_T2.js
test262/test/language/literals/regexp/S7.8.5_A2.1_T2.js
test262/test/language/literals/regexp/S7.8.5_A2.4_T2.js
# lengthy built-ins tests (100-200 ms)
test262/test/built-ins/Function/prototype/toString/built-in-function-object.js
test262/test/built-ins/decodeURI/S15.1.3.1_A2.4_T1.js
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A2.4_T1.js
test262/test/built-ins/encodeURI/S15.1.3.3_A2.3_T1.js
test262/test/built-ins/encodeURIComponent/S15.1.3.4_A2.3_T1.js
test262/test/language/expressions/dynamic-import/await-import-evaluation.js

View file

@ -1,9 +1,6 @@
[config]
# general settings for test262 ES6 version
# framework style: old, new
style=new
# handle tests tagged as [noStrict]: yes, no, skip
nostrict=yes
@ -37,9 +34,6 @@ errorfile=test262_errors.txt
# exclude tests enumerated in this file (see also [exclude] section)
#excludefile=test262_exclude.txt
# report test results to this file
reportfile=test262_report.txt
# enumerate tests from this directory
testdir=test262/test
@ -61,15 +55,16 @@ Array.fromAsync=skip
Array.prototype.at
Array.prototype.flat
Array.prototype.flatMap
Array.prototype.flatten
Array.prototype.includes
Array.prototype.values
ArrayBuffer
arraybuffer-transfer=skip
arraybuffer-transfer
arrow-function
async-functions
async-iteration
Atomics
# atomics are broken in recent versions of tcc
Atomics=!tcc
Atomics.pause=!tcc
Atomics.waitAsync=skip
BigInt
caller
@ -83,7 +78,6 @@ class-static-block
class-static-fields-private
class-static-fields-public
class-static-methods-private
cleanupSome=skip
coalesce-expression
computed-property-names
const
@ -103,11 +97,13 @@ destructuring-assignment
destructuring-binding
dynamic-import
error-cause
Error.isError
explicit-resource-management=skip
exponentiation
export-star-as-namespace-from-module
FinalizationGroup=skip
FinalizationRegistry
FinalizationRegistry.prototype.cleanupSome=skip
FinalizationRegistry=skip
Float16Array
Float32Array
Float64Array
for-in-order
@ -122,8 +118,25 @@ import.meta
Int16Array
Int32Array
Int8Array
Intl-enumeration=skip
intl-normative-optional=skip
Intl.DateTimeFormat-datetimestyle=skip
Intl.DateTimeFormat-dayPeriod=skip
Intl.DateTimeFormat-extend-timezonename=skip
Intl.DateTimeFormat-formatRange=skip
Intl.DateTimeFormat-fractionalSecondDigits=skip
Intl.DisplayNames-v2=skip
Intl.DisplayNames=skip
Intl.DurationFormat=skip
Intl.ListFormat=skip
Intl.Locale-info=skip
Intl.Locale=skip
Intl.NumberFormat-unified=skip
Intl.NumberFormat-v3=skip
Intl.RelativeTimeFormat=skip
Intl.Segmenter=skip
IsHTMLDDA
iterator-helpers=skip
iterator-helpers
json-modules=skip
json-parse-with-source=skip
json-superset
@ -131,6 +144,7 @@ legacy-regexp=skip
let
logical-assignment-operators
Map
Math.sumPrecise
new.target
numeric-separator-literal
object-rest
@ -141,6 +155,7 @@ Object.is
optional-catch-binding
optional-chaining
Promise
promise-try
promise-with-resolvers
Promise.allSettled
Promise.any
@ -155,15 +170,19 @@ regexp-dotall
regexp-duplicate-named-groups=skip
regexp-lookbehind
regexp-match-indices
regexp-modifiers=skip
regexp-named-groups
regexp-unicode-property-escapes
regexp-v-flag=skip
resizable-arraybuffer=skip
regexp-v-flag
RegExp.escape
resizable-arraybuffer
rest-parameters
Set
set-methods=skip
set-methods
ShadowRealm=skip
SharedArrayBuffer
source-phase-imports-module-source=skip
source-phase-imports=skip
string-trimming
String.fromCodePoint
String.prototype.at
@ -191,7 +210,7 @@ Symbol.split
Symbol.toPrimitive
Symbol.toStringTag
Symbol.unscopables
symbols-as-weakmap-keys=skip
symbols-as-weakmap-keys
tail-call-optimization=skip
template
Temporal=skip
@ -202,9 +221,10 @@ u180e
Uint16Array
Uint32Array
Uint8Array
uint8array-base64=skip
Uint8ClampedArray
WeakMap
WeakRef=skip
WeakRef
WeakSet
well-formed-json-stringify
@ -223,5 +243,147 @@ test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
#test262/test/built-ins/RegExp/CharacterClassEscapes/
#test262/test/built-ins/RegExp/property-escapes/
# in progress regexp-v-flag support, see https://github.com/quickjs-ng/quickjs/issues/228
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-13.1.js
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-14.0.js
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-15.0.js
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-15.1.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-string-literal.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-class-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-class.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-property-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-property-of-strings-escape.js
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-string-literal.js
[tests]
# list test files or use config.testdir

View file

@ -1,8 +1,84 @@
test262/test/annexB/language/eval-code/direct/script-decl-lex-collision-in-sloppy-mode.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/assignment/target-member-computed-reference-null.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: Test262Error: Expected a DummyError but got a TypeError
test262/test/language/expressions/assignment/target-member-computed-reference-undefined.js:32: strict mode: Test262Error: Expected a DummyError but got a TypeError
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-get-return-undefined.js:64: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-get-return-undefined.js:64: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-poisoned-return.js:68: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-poisoned-return.js:68: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-not-object.js:72: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-not-object.js:72: strict mode: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-object.js:66: TypeError: $DONE() not called
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-object.js:66: strict mode: TypeError: $DONE() not called
test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true
test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: strict mode: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true
test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: strict mode: TypeError: cannot read property 'call' of undefined
test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/built-ins/Object/defineProperty/coerced-P-grow.js:45: TypeError: out-of-bound index in typed array
test262/test/built-ins/Object/defineProperty/coerced-P-grow.js:45: strict mode: TypeError: out-of-bound index in typed array
test262/test/built-ins/Object/defineProperty/coerced-P-shrink.js:16: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/built-ins/Object/defineProperty/coerced-P-shrink.js:16: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/built-ins/Object/defineProperty/typedarray-backed-by-resizable-buffer.js:18: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/built-ins/Object/defineProperty/typedarray-backed-by-resizable-buffer.js:18: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag
test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: strict mode: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6)
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: strict mode: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6)
test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag
test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: strict mode: Test262Error: Actual argument shouldn't be nullish. Unicode property escapes with v flag
test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents.
test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: strict mode: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents.
test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true
test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
test262/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:73: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, get source, binding::defaultValue, binding::varTarget] and expected [binding::source, binding::sourceKey, sourceKey, binding::varTarget, get source, binding::defaultValue] should have the same contents.
test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents.
test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: strict mode: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents.
test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:37: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, targetKey, get source, binding::defaultValue, set target] and expected [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, get source, binding::defaultValue, targetKey, set target] should have the same contents.
test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents.
test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: strict mode: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents.
test262/test/language/expressions/assignment/target-member-computed-reference.js:22: Test262Error: Expected a DummyError but got a Test262Error
test262/test/language/expressions/assignment/target-member-computed-reference.js:22: strict mode: Test262Error: Expected a DummyError but got a Test262Error
test262/test/language/expressions/assignment/target-super-computed-reference.js:20: Test262Error: Expected a DummyError but got a Test262Error
test262/test/language/expressions/assignment/target-super-computed-reference.js:20: strict mode: Test262Error: Expected a DummyError but got a Test262Error
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated.
test262/test/language/global-code/script-decl-lex-var-declared-via-eval-sloppy.js:13: Test262Error: variable Expected a SyntaxError to be thrown but no exception was thrown at all
test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true
test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: strict mode: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true
test262/test/language/module-code/top-level-await/async-module-does-not-block-sibling-modules.js:13: SyntaxError: Could not find export 'check' in module 'test262/test/language/module-code/top-level-await/async-module-sync_FIXTURE.js'
test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: SyntaxError: invalid property name
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: SyntaxError: invalid property name
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name
test262/test/language/statements/with/get-binding-value-call-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents.
test262/test/language/statements/with/get-binding-value-idref-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents.
test262/test/language/statements/with/get-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js:21: Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all
test262/test/language/statements/with/set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain.js:20: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true
test262/test/language/statements/with/set-mutable-binding-idref-compound-assign-with-proxy-env.js:58: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), get:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, get:p, has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents.
test262/test/language/statements/with/set-mutable-binding-idref-with-proxy-env.js:50: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents.

View file

@ -1,410 +0,0 @@
[config]
# general settings for test262 ES5 version
# framework style: old, new
style=old
# handle tests tagged as @noStrict: yes, no, skip
nostrict=yes
# handle tests tagged as @strictOnly: yes, no, skip
strict=yes
# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all
mode=default
# output error messages: yes, no
verbose=yes
# load harness files this directory
harnessdir=test262o/test/harness
# name of the error file for known errors
errorfile=test262o_errors.txt
# exclude tests enumerated in this file
#excludefile=test262o_excluded.txt
# report test results to this file
reportfile=test262o_report.txt
# enumerate tests from this directory
testdir=test262o/test/suite
[exclude]
# list excluded tests and directories here
# intl not supported
test262o/test/suite/intl402/
# ES6 != ES5: block scoped function definitions allowed in strict mode
test262o/test/suite/bestPractice/Sbp_A1_T1.js
test262o/test/suite/bestPractice/Sbp_A2_T1.js
test262o/test/suite/bestPractice/Sbp_A2_T2.js
test262o/test/suite/bestPractice/Sbp_A3_T1.js
test262o/test/suite/bestPractice/Sbp_A3_T2.js
test262o/test/suite/bestPractice/Sbp_A4_T1.js
test262o/test/suite/bestPractice/Sbp_A4_T2.js
test262o/test/suite/bestPractice/Sbp_A5_T2.js
# ES6 != ES5: `y={x};` is shorthand for `y={x:x}`
test262o/test/suite/ch12/12.1/S12.1_A4_T2.js
test262o/test/suite/ch12/12.6/12.6.4/S12.6.4_A15.js
# ES6 != ES5: function length property is configurable
test262o/test/suite/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js
test262o/test/suite/ch13/13.2/13.2-15-1.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.1/S15.1.2.1_A4.2.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A9.2.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A7.2.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.4/S15.1.2.4_A2.2.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.5/S15.1.2.5_A2.2.js
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A5.2.js
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A5.2.js
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A5.2.js
test262o/test/suite/ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A5.2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-186.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-187.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-191.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-194.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-201.js
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.2/S15.2.4.2_A9.js
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.3/S15.2.4.3_A9.js
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.4/S15.2.4.4_A9.js
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.5/S15.2.4.5_A9.js
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.6/S15.2.4.6_A9.js
test262o/test/suite/ch15/15.2/15.2.4/15.2.4.7/S15.2.4.7_A9.js
test262o/test/suite/ch15/15.3/15.3.3/15.3.3.2/15.3.3.2-1.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.2/S15.3.4.2_A9.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.3/S15.3.4.3_A9.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.4/S15.3.4.4_A9.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-15-2.js
test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T1.js
test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T2.js
test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T3.js
test262o/test/suite/ch15/15.4/15.4.3/S15.4.3_A2.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.2/S15.4.4.2_A4.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.3/S15.4.4.3_A4.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.4/S15.4.4.4_A4.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A6.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A5.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A6.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A5.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A5.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A5.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A7.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A5.2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A5.2.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.4/S15.5.4.4_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.5/S15.5.4.5_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.6/S15.5.4.6_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.8/S15.5.4.8_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.9/S15.5.4.9_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.10/S15.5.4.10_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.11/S15.5.4.11_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.12/S15.5.4.12_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.13/S15.5.4.13_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.16/S15.5.4.16_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.17/S15.5.4.17_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.18/S15.5.4.18_A9.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.19/S15.5.4.19_A9.js
test262o/test/suite/ch15/15.9/15.9.4/15.9.4.2/S15.9.4.2_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.4/15.9.4.3/S15.9.4.3_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.1/S15.9.5.1_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.2/S15.9.5.2_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.3/S15.9.5.3_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.4/S15.9.5.4_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.5/S15.9.5.5_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.6/S15.9.5.6_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.7/S15.9.5.7_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.8/S15.9.5.8_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.9/S15.9.5.9_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.10/S15.9.5.10_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.11/S15.9.5.11_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.12/S15.9.5.12_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.13/S15.9.5.13_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.14/S15.9.5.14_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.15/S15.9.5.15_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.16/S15.9.5.16_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.17/S15.9.5.17_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.18/S15.9.5.18_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.19/S15.9.5.19_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.20/S15.9.5.20_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.21/S15.9.5.21_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.22/S15.9.5.22_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.23/S15.9.5.23_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.24/S15.9.5.24_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.25/S15.9.5.25_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.26/S15.9.5.26_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.27/S15.9.5.27_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.28/S15.9.5.28_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.29/S15.9.5.29_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.30/S15.9.5.30_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.31/S15.9.5.31_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.32/S15.9.5.32_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.33/S15.9.5.33_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.34/S15.9.5.34_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.35/S15.9.5.35_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.36/S15.9.5.36_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.37/S15.9.5.37_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.38/S15.9.5.38_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.39/S15.9.5.39_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/S15.9.5.40_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.41/S15.9.5.41_A3_T2.js
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.42/S15.9.5.42_A3_T2.js
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A9.js
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.3/S15.10.6.3_A9.js
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.4/S15.10.6.4_A9.js
# ES6 != ES5: object literals may have duplicates
test262o/test/suite/ch11/11.1/11.1.5/11.1.5-4-4-a-1-s.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-1.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-2.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-1.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-2.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-1.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-2.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-3.js
test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-4.js
# ES6 != ES5: Date.prototype is no longer an instance of Date
test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/15.9.5.40_1.js
# ES6 != ES5: Object.getPrototypeOf converts argument to object
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1.js
# ES6 != ES5: Object.getPrototypeOf(NativeError)
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-12.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-13.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-14.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-15.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-16.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-17.js
# ES6 != ES5: Object.getOwnPropertyDescriptor converts argument to object
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1.js
# ES6 != ES5: Object.getOwnPropertyNames converts argument to object
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-5.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1.js
# ES6 != ES5: Object.seal accepts all types
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-1.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1.js
# ES6 != ES5: Object.freeze accepts all types
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-1.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1.js
# ES6 != ES5: Object.preventExtensions accepts all types
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-1.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1.js
# ES6 != ES5: Object.isSealed accepts all types
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.11/15.2.3.11-1.js
# ES6 != ES5: Object.isFrozen accepts all types
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-1.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1.js
# ES6 != ES5: Object.isExtensible accepts all types
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-1.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-3.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-4.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1.js
# ES6 != ES5: Object.keys converts argument to object
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-1.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-2.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-3.js
# ES6 != ES5: source and other properties of RegExp.prototype are not own properties
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214.js
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215.js
# ES6 != ES5: String numeric object properties are enumerated first
test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-44.js
# ES6: new RegExp(regex, flags) is valid
test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js
test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T2.js
test262o/test/suite/ch15/15.10/15.10.4/15.10.4.1/15.10.4.1-1.js
test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T1.js
test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T2.js
# ES6 != ES5: RegExp.prototype.test behavior
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A5_T3.js
# ES6 != ES5: source, global, ignoreCase, multiline, lastIndex are not data properties
# of RegExp objects and RegExp.prototype is not a RegExp object
test262o/test/suite/ch15/15.10/15.10.6/15.10.6.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-2.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A8.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A9.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A10.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-1.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-2.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A8.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A9.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A10.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-1.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-2.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A8.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A9.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A10.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-1.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-2.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A8.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A9.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A10.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-1.js
test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-2.js
# ES6 != ES5: Error.prototype is a normal object
test262o/test/suite/ch15/15.11/15.11.4/S15.11.4_A2.js
# ES6 different ToLength() semantics
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A4_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A2_T2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T1.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A2_T2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T1.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A3_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A3_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T1.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A4_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T1.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T3.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A3_T2.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-8.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-28.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-29.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-28.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-8.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-29.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-8.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-28.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-29.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-8.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-28.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-29.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-25.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-7.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-12.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-25.js
# ES6 different ToLength() semantics causes near infinite runtime
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-14.js
test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-14.js
# ES6 arguments/caller changes
test262o/test/suite/ch10/10.6/10.6-13-b-1-s.js
test262o/test/suite/ch10/10.6/10.6-13-b-2-s.js
test262o/test/suite/ch10/10.6/10.6-13-b-3-s.js
test262o/test/suite/ch10/10.6/10.6-14-1-s.js
test262o/test/suite/ch10/10.6/10.6-14-b-1-s.js
test262o/test/suite/ch10/10.6/10.6-14-b-4-s.js
test262o/test/suite/ch13/13.2/13.2-29-s.js
test262o/test/suite/ch13/13.2/13.2-30-s.js
test262o/test/suite/ch13/13.2/13.2-31-s.js
test262o/test/suite/ch13/13.2/13.2-32-s.js
test262o/test/suite/ch13/13.2/13.2-33-s.js
test262o/test/suite/ch13/13.2/13.2-34-s.js
test262o/test/suite/ch13/13.2/13.2-35-s.js
test262o/test/suite/ch13/13.2/13.2-36-s.js
test262o/test/suite/ch13/13.2/S13.2.3_A1.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-1.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-4.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-5.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-1.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-4.js
test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-5.js
# u180e is no longer considered as a space
test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A2.js
test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T1.js
test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T2.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A2_T10.js
test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A2_T10.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-2.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-3.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-4.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-5.js
test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-6.js
test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A1_T1.js
test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A2_T1.js
# E6 eval return value is different
test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.js
test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.1.js
# ECMA 2019 optional-catch-binding feature allows try{}catch{}
test262o/test/suite/ch12/12.14/S12.14_A16_T4.js
# Syntax error instead of ReferenceError in ES2020
test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-1.js
test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-2.js
test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-3.js
test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-4.js
[tests]
# list test files or use config.testdir

9
tests.conf Normal file
View file

@ -0,0 +1,9 @@
[config]
local=yes
verbose=yes
testdir=tests
[exclude]
tests/fixture_cyclic_import.js
tests/microbench.js
tests/test_worker_module.js

49
tests/assert.js Normal file
View file

@ -0,0 +1,49 @@
export function assert(actual, expected, message) {
if (arguments.length === 1)
expected = true;
if (typeof actual === typeof expected) {
if (actual === expected) {
if (actual !== 0 || (1 / actual) === (1 / expected))
return;
}
if (typeof actual === 'number') {
if (isNaN(actual) && isNaN(expected))
return;
}
if (typeof actual === 'object') {
if (actual !== null && expected !== null
&& actual.constructor === expected.constructor
&& actual.toString() === expected.toString())
return;
}
}
throw Error("assertion failed: got |" + actual + "|" +
", expected |" + expected + "|" +
(message ? " (" + message + ")" : ""));
}
export function assertThrows(err, func)
{
var ex;
ex = false;
try {
func();
} catch(e) {
ex = true;
assert(e instanceof err);
}
assert(ex, true, "exception expected");
}
export function assertArrayEquals(a, b)
{
if (!Array.isArray(a) || !Array.isArray(b))
return assert(false);
assert(a.length, b.length);
a.forEach((value, idx) => {
assert(b[idx], value);
});
}

View file

@ -1,96 +0,0 @@
/*
* QuickJS: binary JSON module (test only)
*
* Copyright (c) 2017-2019 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "../quickjs-libc.h"
#include "../cutils.h"
static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
uint8_t *buf;
uint64_t pos, len;
JSValue obj;
size_t size;
int flags;
if (JS_ToIndex(ctx, &pos, argv[1]))
return JS_EXCEPTION;
if (JS_ToIndex(ctx, &len, argv[2]))
return JS_EXCEPTION;
buf = JS_GetArrayBuffer(ctx, &size, argv[0]);
if (!buf)
return JS_EXCEPTION;
if (pos + len > size)
return JS_ThrowRangeError(ctx, "array buffer overflow");
flags = 0;
if (JS_ToBool(ctx, argv[3]))
flags |= JS_READ_OBJ_REFERENCE;
obj = JS_ReadObject(ctx, buf + pos, len, flags);
return obj;
}
static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
size_t len;
uint8_t *buf;
JSValue array;
int flags;
flags = 0;
if (JS_ToBool(ctx, argv[1]))
flags |= JS_WRITE_OBJ_REFERENCE;
buf = JS_WriteObject(ctx, &len, argv[0], flags);
if (!buf)
return JS_EXCEPTION;
array = JS_NewArrayBufferCopy(ctx, buf, len);
js_free(ctx, buf);
return array;
}
static const JSCFunctionListEntry js_bjson_funcs[] = {
JS_CFUNC_DEF("read", 4, js_bjson_read ),
JS_CFUNC_DEF("write", 2, js_bjson_write ),
};
static int js_bjson_init(JSContext *ctx, JSModuleDef *m)
{
return JS_SetModuleExportList(ctx, m, js_bjson_funcs,
countof(js_bjson_funcs));
}
#ifdef JS_SHARED_LIBRARY
#define JS_INIT_MODULE js_init_module
#else
#define JS_INIT_MODULE js_init_module_bjson
#endif
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_bjson_init);
if (!m)
return NULL;
JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs));
return m;
}

7
tests/bug633/0.js Normal file
View file

@ -0,0 +1,7 @@
/*---
flags: [qjs:no-detect-module]
negative:
phase: parse
type: SyntaxError
---*/
const undefined = 42 // SyntaxError at global scope

4
tests/bug633/1.js Normal file
View file

@ -0,0 +1,4 @@
/*---
flags: [qjs:no-detect-module, module]
---*/
const undefined = 42 // not a SyntaxError at toplevel module scope

4
tests/bug633/2.js Normal file
View file

@ -0,0 +1,4 @@
/*---
flags: [qjs:no-detect-module]
---*/
{ const undefined = 42 } // not a SyntaxError, not at global scope

4
tests/bug633/3.js Normal file
View file

@ -0,0 +1,4 @@
/*---
flags: [qjs:no-detect-module]
---*/
;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope

Some files were not shown because too many files have changed in this diff Show more