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
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:
parent
c12360ba55
commit
e18d08e951
136 changed files with 41686 additions and 26124 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
403
CMakeLists.txt
Normal file
403
CMakeLists.txt
Normal 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
175
Changelog
|
@ -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
|
4
LICENSE
4
LICENSE
|
@ -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
|
||||
|
||||
|
|
513
Makefile
513
Makefile
|
@ -1,8 +1,10 @@
|
|||
#
|
||||
# QuickJS Javascript Engine
|
||||
#
|
||||
#
|
||||
# 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)
|
||||
|
|
24
README.md
24
README.md
|
@ -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
67
TODO
|
@ -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
|
1
VERSION
1
VERSION
|
@ -1 +0,0 @@
|
|||
2024-01-13
|
|
@ -1,6 +0,0 @@
|
|||
#include <unistd.h>
|
||||
|
||||
int main(void) {
|
||||
closefrom(3);
|
||||
return 0;
|
||||
}
|
17
ctest.c
Normal file
17
ctest.c
Normal 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;
|
||||
}
|
410
cutils.h
410
cutils.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* C utilities
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017 Fabrice Bellard
|
||||
* Copyright (c) 2018 Charlie Gordon
|
||||
*
|
||||
|
@ -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,28 +313,117 @@ 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)) |
|
||||
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
|
||||
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
|
||||
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
|
||||
}
|
||||
#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
2
cxxtest.cc
Normal 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
1166
dirent_compat.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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 < 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 < 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’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> (“round to nearest with ties to even”)<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><=</code></dt>
|
||||
<dt><code>>=</code></dt>
|
||||
<dt><code><</code></dt>
|
||||
<dt><code>></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>"floor"</code>, <code>"ceiling"</code>, <code>"down"</code>, <code>"up"</code>,
|
||||
<code>"half-even"</code>, <code>"half-up"</code>). Either
|
||||
<code>maximumSignificantDigits</code> or <code>maximumFractionDigits</code> 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).
|
||||
</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 = "half-up")</code></dt>
|
||||
<dt><code>toFixed(p, rnd_mode = "half-up")</code></dt>
|
||||
<dt><code>toExponential(p, rnd_mode = "half-up")</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>"use math"</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 === "bigfloat"</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 === "number "</code>, <code>typeof 1n === "number"</code> but <code>typeof 9007199254740992 === "bigint" </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>
|
BIN
doc/jsbignum.pdf
BIN
doc/jsbignum.pdf
Binary file not shown.
|
@ -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
|
1410
doc/quickjs.html
1410
doc/quickjs.html
File diff suppressed because it is too large
Load diff
BIN
doc/quickjs.pdf
BIN
doc/quickjs.pdf
Binary file not shown.
1120
doc/quickjs.texi
1120
doc/quickjs.texi
File diff suppressed because it is too large
Load diff
20
docs/.gitignore
vendored
Normal file
20
docs/.gitignore
vendored
Normal 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
1
docs/.nvmrc
Normal file
|
@ -0,0 +1 @@
|
|||
18
|
3
docs/babel.config.js
Normal file
3
docs/babel.config.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
53
docs/docs/building.md
Normal file
53
docs/docs/building.md
Normal 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
130
docs/docs/cli.md
Normal 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.
|
||||
:::
|
7
docs/docs/developer-guide/_category_.json
Normal file
7
docs/docs/developer-guide/_category_.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"label": "Developer Guide",
|
||||
"position": 6,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
3
docs/docs/developer-guide/api.md
Normal file
3
docs/docs/developer-guide/api.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# API Reference
|
||||
|
||||
WIP.
|
117
docs/docs/developer-guide/internals.md
Normal file
117
docs/docs/developer-guide/internals.md
Normal 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.
|
113
docs/docs/developer-guide/intro.md
Normal file
113
docs/docs/developer-guide/intro.md
Normal 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
68
docs/docs/diff.md
Normal 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
11
docs/docs/es_features.md
Normal 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
34
docs/docs/installation.md
Normal 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
33
docs/docs/intro.md
Normal 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
28
docs/docs/projects.md
Normal 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
553
docs/docs/stdlib.md
Normal 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.
|
18
docs/docs/supported_platforms.md
Normal file
18
docs/docs/supported_platforms.md
Normal 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
114
docs/docusaurus.config.js
Normal 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
14656
docs/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
42
docs/package.json
Normal file
42
docs/package.json
Normal 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
20
docs/sidebars.js
Normal 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
30
docs/src/css/custom.css
Normal 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);
|
||||
}
|
0
test262o_errors.txt → docs/static/.nojekyll
vendored
0
test262o_errors.txt → docs/static/.nojekyll
vendored
BIN
docs/static/img/favicon.ico
vendored
Normal file
BIN
docs/static/img/favicon.ico
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* QuickJS: Example of C module
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
/* example of JS module */
|
||||
|
||||
const fibModule = require("./fib_require.js");
|
||||
|
||||
console.log("Hello World");
|
||||
console.log("fib(10)=", fib(10));
|
|
@ -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"));
|
||||
})();
|
|
@ -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);
|
||||
})();
|
|
@ -54,7 +54,7 @@ function calc_pi(prec) {
|
|||
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;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* QuickJS: Example of C module with a class
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2019 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -43,13 +43,13 @@ 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;
|
||||
JSValue proto;
|
||||
|
||||
|
||||
s = js_mallocz(ctx, sizeof(*s));
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
|
@ -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)
|
||||
|
@ -112,7 +112,7 @@ static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val,
|
|||
static JSClassDef js_point_class = {
|
||||
"Point",
|
||||
.finalizer = js_point_finalizer,
|
||||
};
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_point_proto_funcs[] = {
|
||||
JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0),
|
||||
|
@ -123,24 +123,33 @@ 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));
|
||||
|
||||
|
||||
point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0);
|
||||
/* set proto.constructor and ctor.prototype */
|
||||
JS_SetConstructor(ctx, point_class, point_proto);
|
||||
JS_SetClassProto(ctx, js_point_class_id, point_proto);
|
||||
|
||||
|
||||
JS_SetModuleExport(ctx, m, "Point", point_class);
|
||||
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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
23
fuzz.c
Normal 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;
|
||||
}
|
27
fuzz/README
27
fuzz/README
|
@ -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).
|
257
fuzz/fuzz.dict
257
fuzz/fuzz.dict
|
@ -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"
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
82
gen/function_source.c
Normal 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
109
gen/hello_module.c
Normal 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
318
gen/standalone.c
Normal 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
83
gen/test_fib.c
Normal 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
653
getopt_compat.h
Normal 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__) */
|
36
libbf.h
36
libbf.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Tiny arbitrary precision floating point library
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2021 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -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;
|
||||
|
@ -171,7 +177,7 @@ static inline bf_flags_t bf_set_exp_bits(int n)
|
|||
#define BF_ST_UNDERFLOW (1 << 3)
|
||||
#define BF_ST_INEXACT (1 << 4)
|
||||
/* indicate that a memory allocation error occured. NaN is returned */
|
||||
#define BF_ST_MEM_ERROR (1 << 5)
|
||||
#define BF_ST_MEM_ERROR (1 << 5)
|
||||
|
||||
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
|
||||
|
||||
|
@ -284,7 +290,7 @@ int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags)
|
|||
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
|
||||
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
|
||||
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
|
||||
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
|
||||
bf_flags_t flags);
|
||||
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
|
||||
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||
|
@ -341,12 +347,12 @@ int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
|
|||
/* fractional format: prec digits after the decimal point rounded with
|
||||
(flags & BF_RND_MASK) */
|
||||
#define BF_FTOA_FORMAT_FRAC (1 << 16)
|
||||
/* free format:
|
||||
|
||||
/* free format:
|
||||
|
||||
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
|
||||
number of digits to represent 'a'. The precision and the rounding
|
||||
mode are ignored.
|
||||
|
||||
|
||||
For the non binary radices with bf_ftoa(): use as many digits as
|
||||
necessary so that bf_atof() return the same number when using
|
||||
precision 'prec', rounding to nearest and the subnormal
|
||||
|
@ -373,7 +379,7 @@ char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
|
|||
bf_flags_t flags);
|
||||
|
||||
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
|
||||
#define BF_GET_INT_MOD (1 << 0)
|
||||
#define BF_GET_INT_MOD (1 << 0)
|
||||
int bf_get_int32(int *pres, const bf_t *a, int flags);
|
||||
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
|
||||
int bf_get_uint64(uint64_t *pres, const bf_t *a);
|
||||
|
@ -387,10 +393,10 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
|
|||
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
|
||||
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
|
||||
int is_ceil1);
|
||||
int mp_mul(bf_context_t *s, limb_t *result,
|
||||
const limb_t *op1, limb_t op1_size,
|
||||
int mp_mul(bf_context_t *s, limb_t *result,
|
||||
const limb_t *op1, limb_t op1_size,
|
||||
const limb_t *op2, limb_t op2_size);
|
||||
limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
|
||||
limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
|
||||
limb_t n, limb_t carry);
|
||||
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
|
||||
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
|
||||
|
@ -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 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Regular Expression Engine
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -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 */
|
||||
|
|
611
libregexp.c
611
libregexp.c
File diff suppressed because it is too large
Load diff
26
libregexp.h
26
libregexp.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Regular Expression Engine
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -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,8 +57,10 @@ 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);
|
||||
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
||||
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
||||
|
||||
/* JS identifier test */
|
||||
|
@ -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 */
|
||||
|
|
3366
libunicode-table.h
3366
libunicode-table.h
File diff suppressed because it is too large
Load diff
118
libunicode.c
118
libunicode.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Unicode utilities
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -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,
|
||||
|
@ -149,9 +150,9 @@ static int lre_case_conv_entry(uint32_t *res, uint32_t c, int conv_type, uint32_
|
|||
}
|
||||
|
||||
/* conv_type:
|
||||
0 = to upper
|
||||
0 = to upper
|
||||
1 = to lower
|
||||
2 = case folding (= to lower with modifications)
|
||||
2 = case folding (= to lower with modifications)
|
||||
*/
|
||||
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
|
||||
{
|
||||
|
@ -168,7 +169,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
|
|||
} else {
|
||||
uint32_t v, code, len;
|
||||
int idx, idx_min, idx_max;
|
||||
|
||||
|
||||
idx_min = 0;
|
||||
idx_max = countof(case_conv_table1) - 1;
|
||||
while (idx_min <= idx_max) {
|
||||
|
@ -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
|
||||
|
@ -311,7 +308,7 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
|
|||
uint32_t code, b, bit;
|
||||
int pos;
|
||||
const uint8_t *p;
|
||||
|
||||
|
||||
pos = get_index_pos(&code, c, index_table, index_table_len);
|
||||
if (pos < 0)
|
||||
return FALSE; /* outside the table */
|
||||
|
@ -344,7 +341,7 @@ BOOL lre_is_cased(uint32_t c)
|
|||
{
|
||||
uint32_t v, code, len;
|
||||
int idx, idx_min, idx_max;
|
||||
|
||||
|
||||
idx_min = 0;
|
||||
idx_max = countof(case_conv_table1) - 1;
|
||||
while (idx_min <= idx_max) {
|
||||
|
@ -403,7 +400,7 @@ int cr_realloc(CharRange *cr, int size)
|
|||
{
|
||||
int new_size;
|
||||
uint32_t *new_buf;
|
||||
|
||||
|
||||
if (size > cr->size) {
|
||||
new_size = max_int(size, cr->size * 3 / 2);
|
||||
new_buf = cr->realloc_func(cr->mem_opaque, cr->points,
|
||||
|
@ -430,7 +427,7 @@ static void cr_compress(CharRange *cr)
|
|||
{
|
||||
int i, j, k, len;
|
||||
uint32_t *pt;
|
||||
|
||||
|
||||
pt = cr->points;
|
||||
len = cr->len;
|
||||
i = 0;
|
||||
|
@ -460,7 +457,7 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
|||
{
|
||||
int a_idx, b_idx, is_in;
|
||||
uint32_t v;
|
||||
|
||||
|
||||
a_idx = 0;
|
||||
b_idx = 0;
|
||||
for(;;) {
|
||||
|
@ -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 {
|
||||
|
@ -761,7 +763,7 @@ static int unicode_decomp_char(uint32_t *res, uint32_t c, BOOL is_compat1)
|
|||
{
|
||||
uint32_t v, type, is_compat, code, len;
|
||||
int idx_min, idx_max, idx;
|
||||
|
||||
|
||||
idx_min = 0;
|
||||
idx_max = countof(unicode_decomp_table1) - 1;
|
||||
while (idx_min <= idx_max) {
|
||||
|
@ -791,7 +793,7 @@ static int unicode_compose_pair(uint32_t c0, uint32_t c1)
|
|||
uint32_t code, len, type, v, idx1, d_idx, d_offset, ch;
|
||||
int idx_min, idx_max, idx, d;
|
||||
uint32_t pair[2];
|
||||
|
||||
|
||||
idx_min = 0;
|
||||
idx_max = countof(unicode_comp_table) - 1;
|
||||
while (idx_min <= idx_max) {
|
||||
|
@ -827,7 +829,7 @@ static int unicode_get_cc(uint32_t c)
|
|||
uint32_t code, n, type, cc, c1, b;
|
||||
int pos;
|
||||
const uint8_t *p;
|
||||
|
||||
|
||||
pos = get_index_pos(&code, c,
|
||||
unicode_cc_index, sizeof(unicode_cc_index) / 3);
|
||||
if (pos < 0)
|
||||
|
@ -876,7 +878,7 @@ static int unicode_get_cc(uint32_t c)
|
|||
static void sort_cc(int *buf, int len)
|
||||
{
|
||||
int i, j, k, cc, cc1, start, ch1;
|
||||
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
cc = unicode_get_cc(buf[i]);
|
||||
if (cc != 0) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -915,7 +910,7 @@ static void to_nfd_rec(DynBuf *dbuf,
|
|||
uint32_t c, v;
|
||||
int i, l;
|
||||
uint32_t res[UNICODE_DECOMP_LEN_MAX];
|
||||
|
||||
|
||||
for(i = 0; i < src_len; i++) {
|
||||
c = src[i];
|
||||
if (c >= 0xac00 && c < 0xd7a4) {
|
||||
|
@ -960,7 +955,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
|||
int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len;
|
||||
BOOL is_compat;
|
||||
DynBuf dbuf_s, *dbuf = &dbuf_s;
|
||||
|
||||
|
||||
is_compat = n_type >> 1;
|
||||
|
||||
dbuf_init2(dbuf, opaque, realloc_func);
|
||||
|
@ -988,15 +983,15 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
|||
}
|
||||
buf = (int *)dbuf->buf;
|
||||
buf_len = dbuf->size / sizeof(int);
|
||||
|
||||
|
||||
sort_cc(buf, buf_len);
|
||||
|
||||
|
||||
if (buf_len <= 1 || (n_type & 1) != 0) {
|
||||
/* NFD / NFKD */
|
||||
*pdst = (uint32_t *)buf;
|
||||
return buf_len;
|
||||
}
|
||||
|
||||
|
||||
i = 1;
|
||||
out_len = 1;
|
||||
while (i < buf_len) {
|
||||
|
@ -1033,7 +1028,7 @@ static int unicode_find_name(const char *name_table, const char *name)
|
|||
const char *p, *r;
|
||||
int pos;
|
||||
size_t name_len, len;
|
||||
|
||||
|
||||
p = name_table;
|
||||
pos = 0;
|
||||
name_len = strlen(name);
|
||||
|
@ -1063,16 +1058,16 @@ 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);
|
||||
if (script_idx < 0)
|
||||
return -2;
|
||||
/* Note: we remove the "Unknown" Script */
|
||||
script_idx += UNICODE_SCRIPT_Unknown + 1;
|
||||
|
||||
|
||||
is_common = (script_idx == UNICODE_SCRIPT_Common ||
|
||||
script_idx == UNICODE_SCRIPT_Inherited);
|
||||
if (is_ext) {
|
||||
|
@ -1350,7 +1345,7 @@ static int point_cmp(const void *p1, const void *p2, void *arg)
|
|||
static void cr_sort_and_remove_overlap(CharRange *cr)
|
||||
{
|
||||
uint32_t start, end, start1, end1, i, j;
|
||||
|
||||
|
||||
/* the resulting ranges are not necessarily sorted and may overlap */
|
||||
rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL);
|
||||
j = 0;
|
||||
|
@ -1389,7 +1384,7 @@ int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode)
|
|||
{
|
||||
CharRange cr_inter, cr_mask, cr_result, cr_sub;
|
||||
uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d;
|
||||
|
||||
|
||||
cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func);
|
||||
cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func);
|
||||
cr_init(&cr_result, cr->mem_opaque, cr->realloc_func);
|
||||
|
@ -1404,7 +1399,7 @@ int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode)
|
|||
goto fail;
|
||||
if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* cr_inter = cr & cr_mask */
|
||||
/* cr_sub = cr & ~cr_mask */
|
||||
|
||||
|
@ -1488,7 +1483,7 @@ static int unicode_prop_ops(CharRange *cr, ...)
|
|||
CharRange stack[POP_STACK_LEN_MAX];
|
||||
int stack_len, op, ret, i;
|
||||
uint32_t a;
|
||||
|
||||
|
||||
va_start(ap, cr);
|
||||
stack_len = 0;
|
||||
for(;;) {
|
||||
|
@ -1574,7 +1569,7 @@ int unicode_general_category(CharRange *cr, const char *gc_name)
|
|||
{
|
||||
int gc_idx;
|
||||
uint32_t gc_mask;
|
||||
|
||||
|
||||
gc_idx = unicode_find_name(unicode_gc_name_table, gc_name);
|
||||
if (gc_idx < 0)
|
||||
return -2;
|
||||
|
@ -1592,7 +1587,7 @@ int unicode_general_category(CharRange *cr, const char *gc_name)
|
|||
int unicode_prop(CharRange *cr, const char *prop_name)
|
||||
{
|
||||
int prop_idx, ret;
|
||||
|
||||
|
||||
prop_idx = unicode_find_name(unicode_prop_name_table, prop_name);
|
||||
if (prop_idx < 0)
|
||||
return -2;
|
||||
|
@ -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 */
|
||||
|
|
20
libunicode.h
20
libunicode.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Unicode utilities
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -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 */
|
||||
|
|
12
list.h
12
list.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Linux klist like system
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2016-2017 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -28,6 +28,10 @@
|
|||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct list_head {
|
||||
struct list_head *prev;
|
||||
struct list_head *next;
|
||||
|
@ -45,7 +49,7 @@ static inline void init_list_head(struct list_head *head)
|
|||
}
|
||||
|
||||
/* insert 'el' between 'prev' and 'next' */
|
||||
static inline void __list_add(struct list_head *el,
|
||||
static inline void __list_add(struct list_head *el,
|
||||
struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
prev->next = el;
|
||||
|
@ -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 */
|
||||
|
|
565
qjs.c
565
qjs.c
|
@ -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);
|
||||
}
|
||||
|
@ -83,7 +138,7 @@ static int eval_file(JSContext *ctx, const char *filename, int module)
|
|||
uint8_t *buf;
|
||||
int ret, eval_flags;
|
||||
size_t buf_len;
|
||||
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
perror(filename);
|
||||
|
@ -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;
|
||||
|
||||
#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");
|
||||
int64_t memory_limit = -1;
|
||||
int64_t stack_size = -1;
|
||||
|
||||
/* 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);
|
||||
|
@ -506,35 +654,58 @@ int main(int argc, char **argv)
|
|||
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
if (!empty_run) {
|
||||
#ifdef CONFIG_BIGNUM
|
||||
if (load_jscalc) {
|
||||
js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0);
|
||||
}
|
||||
#endif
|
||||
js_std_add_helpers(ctx, argc - optind, argv + optind);
|
||||
|
||||
/* 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,10 +744,23 @@ 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) {
|
||||
JSMemoryUsage stats;
|
||||
JS_ComputeMemoryUsage(rt, &stats);
|
||||
|
@ -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();
|
||||
|
|
426
qjsc.c
426
qjsc.c
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* 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)
|
||||
|
@ -129,7 +115,7 @@ static void get_c_name(char *buf, size_t buf_size, const char *file)
|
|||
size_t len, i;
|
||||
int c;
|
||||
char *q;
|
||||
|
||||
|
||||
p = strrchr(file, '/');
|
||||
if (!p)
|
||||
p = file;
|
||||
|
@ -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);
|
||||
|
@ -187,13 +177,17 @@ 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,26 +234,23 @@ 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;
|
||||
JSValue func_val;
|
||||
char cname[1024];
|
||||
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, module_name);
|
||||
if (!buf) {
|
||||
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||
module_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* compile the module */
|
||||
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
|
||||
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
|
@ -270,7 +262,7 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
|
|||
find_unique_cname(cname, sizeof(cname));
|
||||
}
|
||||
output_object_code(ctx, outfile, func_val, cname, TRUE);
|
||||
|
||||
|
||||
/* the module is already referenced, so we must free it */
|
||||
m = JS_VALUE_GET_PTR(func_val);
|
||||
JS_FreeValue(ctx, func_val);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -288,7 +281,7 @@ static void compile_file(JSContext *ctx, FILE *fo,
|
|||
int eval_flags;
|
||||
JSValue obj;
|
||||
size_t buf_len;
|
||||
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Could not load '%s'\n", filename);
|
||||
|
@ -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,55 +456,39 @@ 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";
|
||||
|
||||
js__pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||
|
||||
if (output_type == OUTPUT_RAW)
|
||||
fo = fopen(cfilename, "wb");
|
||||
else
|
||||
fo = fopen(cfilename, "w");
|
||||
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
/* XXX: find a /tmp directory ? */
|
||||
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
|
||||
#else
|
||||
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
|
||||
#endif
|
||||
} else {
|
||||
pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||
}
|
||||
|
||||
fo = fopen(cfilename, "w");
|
||||
if (!fo) {
|
||||
perror(cfilename);
|
||||
exit(1);
|
||||
}
|
||||
outfile = fo;
|
||||
|
||||
|
||||
rt = JS_NewRuntime();
|
||||
ctx = JS_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_C) {
|
||||
if (output_type != OUTPUT_RAW) {
|
||||
fprintf(fo, "/* File generated automatically by the QuickJS-ng compiler. */\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -669,38 +507,20 @@ int main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
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++) {
|
||||
namelist_entry_t *e = &init_module_list.array[i];
|
||||
/* initialize the static C modules */
|
||||
|
||||
|
||||
fprintf(fo,
|
||||
" {\n"
|
||||
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
|
||||
|
@ -718,19 +538,17 @@ int main(int argc, char **argv)
|
|||
fprintf(fo,
|
||||
" return ctx;\n"
|
||||
"}\n\n");
|
||||
|
||||
|
||||
fputs(main_c_template1, fo);
|
||||
|
||||
if (stack_size != 0) {
|
||||
fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
|
||||
(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"
|
||||
" js_std_add_helpers(ctx, argc, argv);\n");
|
||||
|
@ -744,16 +562,12 @@ int main(int argc, char **argv)
|
|||
}
|
||||
fputs(main_c_template2, fo);
|
||||
}
|
||||
|
||||
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
fclose(fo);
|
||||
|
||||
if (output_type == OUTPUT_EXECUTABLE) {
|
||||
return output_executable(out_filename, cfilename, use_lto, verbose,
|
||||
argv[0]);
|
||||
}
|
||||
namelist_free(&cname_list);
|
||||
namelist_free(&cmodule_list);
|
||||
namelist_free(&init_module_list);
|
||||
|
|
2657
qjscalc.js
2657
qjscalc.js
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* QuickJS atom definitions
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
* Copyright (c) 2017-2018 Charlie Gordon
|
||||
*
|
||||
|
@ -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")
|
||||
|
@ -204,7 +196,7 @@ DEF(RegExp, "RegExp")
|
|||
DEF(ArrayBuffer, "ArrayBuffer")
|
||||
DEF(SharedArrayBuffer, "SharedArrayBuffer")
|
||||
/* must keep same order as class IDs for typed arrays */
|
||||
DEF(Uint8ClampedArray, "Uint8ClampedArray")
|
||||
DEF(Uint8ClampedArray, "Uint8ClampedArray")
|
||||
DEF(Int8Array, "Int8Array")
|
||||
DEF(Uint8Array, "Uint8Array")
|
||||
DEF(Int16Array, "Int16Array")
|
||||
|
@ -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
54
quickjs-c-atomics.h
Normal 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
|
1518
quickjs-libc.c
1518
quickjs-libc.c
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* QuickJS C library
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -35,23 +35,26 @@ 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));
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* QuickJS opcode definitions
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
* Copyright (c) 2017-2018 Charlie Gordon
|
||||
*
|
||||
|
@ -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 */
|
||||
|
@ -165,15 +170,14 @@ DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
|
|||
DEF( get_arg, 3, 0, 1, arg)
|
||||
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
|
||||
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
|
||||
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
|
||||
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
|
||||
DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||
DEF( get_loc_check, 3, 0, 1, loc)
|
||||
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||
DEF(get_loc_checkthis, 3, 0, 1, loc)
|
||||
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||
DEF( close_loc, 3, 0, 0, loc)
|
||||
|
@ -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,17 +262,10 @@ 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)
|
||||
DEF( nop, 1, 0, 0, none)
|
||||
|
||||
/* temporary opcodes: never emitted in the final bytecode */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -289,10 +288,9 @@ def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1,
|
|||
def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
|
||||
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
|
||||
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
||||
|
||||
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
||||
|
||||
#if SHORT_OPCODES
|
||||
def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */
|
||||
|
||||
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
|
||||
|
|
180
release.sh
180
release.sh
|
@ -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
|
1052
run-test262.c
1052
run-test262.c
File diff suppressed because it is too large
Load diff
129
standalone.js
Normal file
129
standalone.js
Normal 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
|
||||
});
|
||||
}
|
5
test.js
5
test.js
|
@ -1,5 +0,0 @@
|
|||
function test() {
|
||||
breakFunction();
|
||||
console.warn("lol it works!");
|
||||
}
|
||||
test()
|
132
test262-fast.conf
Normal file
132
test262-fast.conf
Normal 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
|
198
test262.conf
198
test262.conf
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
410
test262o.conf
410
test262o.conf
|
@ -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
9
tests.conf
Normal 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
49
tests/assert.js
Normal 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);
|
||||
});
|
||||
}
|
|
@ -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
7
tests/bug633/0.js
Normal 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
4
tests/bug633/1.js
Normal 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
4
tests/bug633/2.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*---
|
||||
flags: [qjs:no-detect-module]
|
||||
---*/
|
||||
{ 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
Loading…
Reference in a new issue