109
quickjs/external/quickjs-rs/.github/workflows/main.yml
vendored
Normal file
109
quickjs/external/quickjs-rs/.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request: {}
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test on ${{ matrix.os }} with features ${{ matrix.features }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- ubuntu-latest
|
||||||
|
- macOS-latest
|
||||||
|
- windows-latest
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
if: matrix.os != 'windows-latest'
|
||||||
|
|
||||||
|
- name: Install stable toolchain (windows)
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
target: x86_64-pc-windows-gnu
|
||||||
|
override: true
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
|
||||||
|
- name: Install `just` command runner
|
||||||
|
uses: extractions/setup-just@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Setup (debian)
|
||||||
|
run: |
|
||||||
|
echo "Install system tools"
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y curl xz-utils build-essential gcc-multilib valgrind
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
|
- name: Setup (windows)
|
||||||
|
run: |
|
||||||
|
$env:PATH = "C:\msys64\mingw64\bin;C:\msys64\usr\bin;$env:PATH"
|
||||||
|
echo "::set-env name=PATH::${env:PATH}"
|
||||||
|
echo "::set-env name=CARGO_BUILD_TARGET::x86_64-pc-windows-gnu"
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
|
||||||
|
- name: Build (default features)
|
||||||
|
env:
|
||||||
|
FEATURES: ""
|
||||||
|
run: |
|
||||||
|
cargo clean
|
||||||
|
just FEATURES="$FEATURES" build
|
||||||
|
|
||||||
|
- name: Test (default features)
|
||||||
|
env:
|
||||||
|
FEATURES: ""
|
||||||
|
run: |
|
||||||
|
just FEATURES="$FEATURES" test
|
||||||
|
|
||||||
|
- name: Build (--no-default-features)
|
||||||
|
env:
|
||||||
|
FEATURES: "--no-default-features"
|
||||||
|
run: |
|
||||||
|
cargo clean
|
||||||
|
just FEATURES="$FEATURES" build
|
||||||
|
|
||||||
|
- name: Test (--no-default-features)
|
||||||
|
env:
|
||||||
|
FEATURES: "--no-default-features"
|
||||||
|
run: |
|
||||||
|
just FEATURES="$FEATURES" test
|
||||||
|
|
||||||
|
- name: Build (--all-features)
|
||||||
|
env:
|
||||||
|
FEATURES: "--all-features"
|
||||||
|
run: |
|
||||||
|
cargo clean
|
||||||
|
just FEATURES="$FEATURES" build
|
||||||
|
|
||||||
|
- name: Test (--all-features)
|
||||||
|
env:
|
||||||
|
FEATURES: "--all-features"
|
||||||
|
run: |
|
||||||
|
just FEATURES="$FEATURES" test
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: just lint
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
|
- name: Check for leaks (Valgrind)
|
||||||
|
run: just valgrind
|
||||||
|
if: matrix.os == 'ubuntu-latest' && matrix.features == '--all-features'
|
||||||
2
quickjs/external/quickjs-rs/.gitignore
vendored
Normal file
2
quickjs/external/quickjs-rs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
/Cargo.lock
|
||||||
63
quickjs/external/quickjs-rs/CHANGELOG.md
vendored
Normal file
63
quickjs/external/quickjs-rs/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# quick-js - Changelog
|
||||||
|
|
||||||
|
## Master branch
|
||||||
|
|
||||||
|
## v0.3.4 - 2020-07-09
|
||||||
|
|
||||||
|
* Bump quickjs to 2020-07-05
|
||||||
|
|
||||||
|
## v0.3.3 - 2020-05-27
|
||||||
|
|
||||||
|
* Add Windows support
|
||||||
|
(only with MSYS2 environment and `x86_64-pc-windows-gnu` target architecture)
|
||||||
|
|
||||||
|
## v0.3.2 - 2020-05-25
|
||||||
|
|
||||||
|
* Updated quickjs to 2020-04-12
|
||||||
|
|
||||||
|
## v0.3.1 - 2020-03-24
|
||||||
|
|
||||||
|
* Update quickjs to 2020-03-16
|
||||||
|
* Add `TryFrom<JsValue>` impl for `HashMap<String, X>`
|
||||||
|
|
||||||
|
## v0.3.0 - 2019-11-02
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Add BigInt integration
|
||||||
|
* Add logging system and optional `log` crate integration
|
||||||
|
* Upgrade quickjs to 2019-10-27
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
* Made `Value` enum non-exhaustive
|
||||||
|
* new Value::BigInt variant (with `bigint` feature)
|
||||||
|
|
||||||
|
## v0.2.3 - 2019-08-30
|
||||||
|
|
||||||
|
* Properly free property keys after enumeration
|
||||||
|
(Fixes memory leak when deserializing objects)
|
||||||
|
|
||||||
|
## v0.2.2 - 2019-08-13
|
||||||
|
|
||||||
|
* Fix invalid millisecond conversion for JsValue::Date
|
||||||
|
|
||||||
|
## v0.2.1 - 2019-08-13
|
||||||
|
|
||||||
|
* Impelemented deserializiation of objects to `JsValue::Object`
|
||||||
|
* Added `chrono` integration via the `chrono` feature
|
||||||
|
Adds a `JsValue::Date(DateTime<Utc>)` variant that allows (de)serializing
|
||||||
|
a JS `Date`
|
||||||
|
* Implemented resolving promises in `eval`/`call_function`
|
||||||
|
* Added `patched` feature for applying quickjs fixes
|
||||||
|
* quickjs upgraded to `2019-08-10` release
|
||||||
|
|
||||||
|
## v0.2.0 - 2019-07-31
|
||||||
|
|
||||||
|
* Added `memory_limit` customization
|
||||||
|
* Added `Context::clear` method for resetting context
|
||||||
|
* Callbacks now support more function signatures
|
||||||
|
( up to 5 arguments, `Result<T, E>` return value)
|
||||||
|
* Updated embedded quickjs bindings to version 2019-07-28.
|
||||||
|
* Fixed a bug in callback logic
|
||||||
|
|
||||||
32
quickjs/external/quickjs-rs/Cargo.toml
vendored
Normal file
32
quickjs/external/quickjs-rs/Cargo.toml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2018"
|
||||||
|
name = "quick-js"
|
||||||
|
description = "QuickJS Javascript engine wrapper"
|
||||||
|
version = "0.3.5-alpha.0"
|
||||||
|
readme = "README.md"
|
||||||
|
documentation = "https://docs.rs/quick-js"
|
||||||
|
repository = "https://github.com/theduke/quickjs-rs"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["Christoph Herzog <chris@theduke.at>"]
|
||||||
|
keywords = ["quickjs", "javascript", "js", "engine", "interpreter"]
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
features = [ "chrono", "bigint", "log" ]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
patched = ["libquickjs-sys/patched"]
|
||||||
|
bigint = ["num-bigint", "num-traits", "libquickjs-sys/patched"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libquickjs-sys = { version = "> 0.3.0, < 0.8.0", path = "./libquickjs-sys" }
|
||||||
|
chrono = { version = "0.4.7", optional = true }
|
||||||
|
num-bigint = { version = "0.2.2", optional = true }
|
||||||
|
num-traits = { version = "0.2.0", optional = true }
|
||||||
|
log = { version = "0.4.8", optional = true }
|
||||||
|
once_cell = "1.2.0"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"libquickjs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
19
quickjs/external/quickjs-rs/LICENSE.txt
vendored
Normal file
19
quickjs/external/quickjs-rs/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2019 Christoph Herzog <christoph.herzog@theduke.at>
|
||||||
|
|
||||||
|
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.
|
||||||
91
quickjs/external/quickjs-rs/README.md
vendored
Normal file
91
quickjs/external/quickjs-rs/README.md
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# quickjs-rs
|
||||||
|
|
||||||
|
[](https://crates.io/crates/quick-js)
|
||||||
|
[](https://docs.rs/quick-js)
|
||||||
|
[
|
||||||
|
|
||||||
|
A Rust wrapper for [QuickJS](https://bellard.org/quickjs/).
|
||||||
|
|
||||||
|
QuickJS is a new, small Javascript engine by Fabrice Bellard and Charlie Gordon.
|
||||||
|
It is fast and supports the full ES2020 specification.
|
||||||
|
|
||||||
|
This crate allows you to easily run and integrate with Javascript code from Rust.
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
quick-js = "0.3.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use quick_js::{Context, JsValue};
|
||||||
|
|
||||||
|
let context = Context::new().unwrap();
|
||||||
|
|
||||||
|
// Eval.
|
||||||
|
|
||||||
|
let value = context.eval("1 + 2").unwrap();
|
||||||
|
assert_eq!(value, JsValue::Int(3));
|
||||||
|
|
||||||
|
let value = context.eval_as::<String>(" var x = 100 + 250; x.toString() ").unwrap();
|
||||||
|
assert_eq!(&value, "350");
|
||||||
|
|
||||||
|
// Callbacks.
|
||||||
|
|
||||||
|
context.add_callback("myCallback", |a: i32, b: i32| a + b).unwrap();
|
||||||
|
|
||||||
|
context.eval(r#"
|
||||||
|
// x will equal 30
|
||||||
|
var x = myCallback(10, 20);
|
||||||
|
"#).unwrap();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optional Features
|
||||||
|
|
||||||
|
The crate supports the following features:
|
||||||
|
|
||||||
|
* `chrono`: chrono integration
|
||||||
|
- adds a `JsValue::Date` variant that can be (de)serialized to/from a JS `Date`
|
||||||
|
* `bigint`: arbitrary precision integer support via [num-bigint](https://github.com/rust-num/num-bigint)
|
||||||
|
* `log`: allows forwarding `console.log` messages to the `log` crate.
|
||||||
|
Note: must be enabled with `ContextBuilder::console(quick_js::console::LogConsole);`
|
||||||
|
|
||||||
|
* `patched`
|
||||||
|
Enabled automatically for some other features, like `bigint`.
|
||||||
|
You should not need to enable this manually.
|
||||||
|
Applies QuickJS patches that can be found in `libquickjs-sys/embed/patches` directory.
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
By default, quickjs is **bundled** with the `libquickjs-sys` crate and
|
||||||
|
automatically compiled, assuming you have the appropriate dependencies.
|
||||||
|
|
||||||
|
### Windows Support
|
||||||
|
|
||||||
|
Windows is only supported with the [MSYS2](https://www.msys2.org/) environment
|
||||||
|
and `x86_64-pc-windows-gnu` target architecture.
|
||||||
|
|
||||||
|
If you have MSYS2 installed and the MSYS `bin` directory in your path, you can
|
||||||
|
compile quickjs with `cargo build --target="x86_64-pc-windows-gnu"`.
|
||||||
|
|
||||||
|
The target can also be configured permanently via a
|
||||||
|
[cargo config file](https://doc.rust-lang.org/cargo/reference/config.html) or
|
||||||
|
the `CARGO_BUILD_TARGET` env var.
|
||||||
|
|
||||||
|
### System installation
|
||||||
|
|
||||||
|
To use the system installation, without the bundled feature, first install the required
|
||||||
|
dependencies, and then compile and install quickjs.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Debian/Ubuntu: apt-get install -y curl xz-utils build-essential gcc-multilib libclang-dev clang
|
||||||
|
mkdir quickjs
|
||||||
|
curl -L https://bellard.org/quickjs/quickjs-2019-07-09.tar.xz | tar xJv -C quickjs --strip-components 1
|
||||||
|
cd quickjs
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
You then need to disable the `bundled` feature in the `libquickjs-sys` crate to
|
||||||
|
force using the system version.
|
||||||
22
quickjs/external/quickjs-rs/examples/eval.rs
vendored
Normal file
22
quickjs/external/quickjs-rs/examples/eval.rs
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use quick_js::Context;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let context = Context::new().unwrap();
|
||||||
|
|
||||||
|
let value = context.eval("1 + 2").unwrap();
|
||||||
|
println!("js: 1 + 2 = {:?}", value);
|
||||||
|
|
||||||
|
context
|
||||||
|
.add_callback("myCallback", |a: i32, b: i32| a + b * b)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let value = context
|
||||||
|
.eval(
|
||||||
|
r#"
|
||||||
|
var x = myCallback(10, 20);
|
||||||
|
x;
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
println!("js: callback = {:?}", value);
|
||||||
|
}
|
||||||
56
quickjs/external/quickjs-rs/justfile
vendored
Normal file
56
quickjs/external/quickjs-rs/justfile
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
embed_dir := "./libquickjs-sys/embed/quickjs"
|
||||||
|
|
||||||
|
DOWNLOAD_URL := "https://bellard.org/quickjs/quickjs-2020-07-05.tar.xz"
|
||||||
|
FEATURES := "--all-features"
|
||||||
|
|
||||||
|
download-new:
|
||||||
|
test -d {{embed_dir}} && rm -r {{embed_dir}} || echo ""
|
||||||
|
mkdir {{embed_dir}} && \
|
||||||
|
curl -L {{DOWNLOAD_URL}} | tar xJv -C {{embed_dir}} --strip-components 1
|
||||||
|
|
||||||
|
download-cleanup:
|
||||||
|
rm -r "{{embed_dir}}/doc" "{{embed_dir}}/examples" "{{embed_dir}}/tests"
|
||||||
|
find "{{embed_dir}}" -type f | grep -E "\.(pdf|html|js|texi|sh)$" | xargs rm
|
||||||
|
find "{{embed_dir}}" -type f | grep test | xargs rm
|
||||||
|
|
||||||
|
generate-bindings:
|
||||||
|
(cd libquickjs-sys; bindgen wrapper.h -o embed/bindings.rs -- -I ./embed)
|
||||||
|
# Update VERSION in README
|
||||||
|
sed -i "s/**Embedded VERSION: .*/**Embedded VERSION: $(cat ./libquickjs-sys/embed/quickjs/VERSION)**/" ./libquickjs-sys/README.md
|
||||||
|
|
||||||
|
update-quickjs: download-new generate-bindings download-cleanup
|
||||||
|
|
||||||
|
|
||||||
|
debian-setup:
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
sudo apt update && sudo apt-get install -y curl xz-utils build-essential gcc-multilib libclang-dev clang valgrind
|
||||||
|
|
||||||
|
build:
|
||||||
|
rustc --version
|
||||||
|
cargo --version
|
||||||
|
|
||||||
|
cargo build --verbose {{FEATURES}}
|
||||||
|
|
||||||
|
test:
|
||||||
|
rustc --version
|
||||||
|
cargo --version
|
||||||
|
|
||||||
|
# Limit test threads to 1 to show test name before execution.
|
||||||
|
RUST_TEST_THREADS=1 cargo test --verbose {{FEATURES}}
|
||||||
|
|
||||||
|
lint:
|
||||||
|
rustc --version
|
||||||
|
cargo --version
|
||||||
|
cargo clippy --version
|
||||||
|
|
||||||
|
echo "Linting!"
|
||||||
|
rustup component add rustfmt clippy
|
||||||
|
|
||||||
|
echo "Checking formatting..."
|
||||||
|
cargo fmt -- --check
|
||||||
|
echo "Checking clippy..."
|
||||||
|
cargo clippy
|
||||||
|
|
||||||
|
valgrind:
|
||||||
|
echo "Checking for memory leaks..."
|
||||||
|
find target/debug -maxdepth 1 -type f -executable | xargs valgrind --leak-check=full --error-exitcode=1
|
||||||
56
quickjs/external/quickjs-rs/libquickjs-sys/CHANGELOG.md
vendored
Normal file
56
quickjs/external/quickjs-rs/libquickjs-sys/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# libquickjs_sys - Changelog
|
||||||
|
|
||||||
|
## v0.7.0 - 2020-07-09
|
||||||
|
|
||||||
|
Upgraded to quickjs version `2020-07-05`.
|
||||||
|
|
||||||
|
* Added
|
||||||
|
- JS_ParseJSON2
|
||||||
|
- JSSharedArrayBufferFunctions
|
||||||
|
- JS_WriteObject2
|
||||||
|
- JS_SetSharedArrayBufferFunctions
|
||||||
|
- JS_WriteObject2
|
||||||
|
- JS_SetSharedArrayBufferFunctions
|
||||||
|
- JS_PARSE_JSON_EXT
|
||||||
|
- JS_WRITE_OBJ_SAB
|
||||||
|
- JS_WRITE_OBJ_REFERENCE
|
||||||
|
- JS_READ_OBJ_SAB
|
||||||
|
- JS_READ_OBJ_REFERENCE
|
||||||
|
|
||||||
|
## v0.6.0 - 2020-05-25
|
||||||
|
|
||||||
|
Upgraded to quickjs version `2020-04-12`.
|
||||||
|
|
||||||
|
* Lot's of changes from `usize` to `size_t`.
|
||||||
|
|
||||||
|
## v0.5.0 - 2020-03-24
|
||||||
|
|
||||||
|
Upgraded to version `2020-03-16`:
|
||||||
|
|
||||||
|
- Added functions `JS_GetRuntimeOpaque`, `JS_SetRuntimeOpaque`
|
||||||
|
- Removed function `JS_NewInt64`, JS_ToInt64Ext
|
||||||
|
|
||||||
|
## v0.4.0 - 2019-11-02
|
||||||
|
|
||||||
|
Upgraded to version `2019-09-18`:
|
||||||
|
|
||||||
|
* Added `JS_ValueToAtom`
|
||||||
|
* Added `JS_SetConstructor`
|
||||||
|
* `JS_GetTypedArrayBuffer`
|
||||||
|
|
||||||
|
Updated bindgen dependency to 0.51.
|
||||||
|
|
||||||
|
## v0.3.0 - 2019-08-13
|
||||||
|
|
||||||
|
* Added `patched` feature for applying patches
|
||||||
|
* Added patch stack-overflow-signed to fix stackoverflow due invalid cast
|
||||||
|
|
||||||
|
* c_int changed to usize in JS_NewAtomLen/JS_NewStringLen
|
||||||
|
* JS_ToCStringLen2 replaces JS_ToCStringLen
|
||||||
|
* Added JS_GetOwnProperty(Names) functions
|
||||||
|
|
||||||
|
## v0.2.0 - 2019-07-31
|
||||||
|
|
||||||
|
* Updated embedded bindings to version 2019-07-28
|
||||||
|
- `JS_EVAL_FLAG_SHEBANG` constant was removed
|
||||||
|
- `JS_NewPromiseCallback` was added
|
||||||
26
quickjs/external/quickjs-rs/libquickjs-sys/Cargo.toml
vendored
Normal file
26
quickjs/external/quickjs-rs/libquickjs-sys/Cargo.toml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2018"
|
||||||
|
name = "libquickjs-sys"
|
||||||
|
description = "QuickJS Javascript Engine FFI bindings"
|
||||||
|
version = "0.7.0"
|
||||||
|
readme = "README.md"
|
||||||
|
documentation = "https://docs.rs/quickjs-sys"
|
||||||
|
repository = "https://github.com/theduke/quickjs-rs"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["Christoph Herzog <chris@theduke.at>"]
|
||||||
|
categories = ["external-ffi-bindings"]
|
||||||
|
keywords = ["quickjs"]
|
||||||
|
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
bundled = ["cc", "copy_dir"]
|
||||||
|
patched = ["bundled"]
|
||||||
|
default = ["bundled"]
|
||||||
|
|
||||||
|
system = ["bindgen"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bindgen = { version = "0.54.0", optional = true }
|
||||||
|
cc = { version = "1.0", optional = true }
|
||||||
|
copy_dir = { version = "0.1.2", optional = true }
|
||||||
19
quickjs/external/quickjs-rs/libquickjs-sys/LICENSE.txt
vendored
Normal file
19
quickjs/external/quickjs-rs/libquickjs-sys/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2019 Christoph Herzog <christoph.herzog@theduke.at>
|
||||||
|
|
||||||
|
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.
|
||||||
32
quickjs/external/quickjs-rs/libquickjs-sys/README.md
vendored
Normal file
32
quickjs/external/quickjs-rs/libquickjs-sys/README.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# libquickjs-sys
|
||||||
|
|
||||||
|
FFI Bindings for [quickjs](https://bellard.org/quickjs/), a Javascript engine.
|
||||||
|
|
||||||
|
See the [quick](https://crates.io/crates/quickjs) crate for a high-level
|
||||||
|
wrapper.
|
||||||
|
|
||||||
|
**Embedded VERSION: 2020-07-05**
|
||||||
|
|
||||||
|
## Embedded vs system
|
||||||
|
|
||||||
|
By default, an embedded version of quickjs is used.
|
||||||
|
|
||||||
|
If you want to use a version installed on your system, use:
|
||||||
|
|
||||||
|
|
||||||
|
```toml
|
||||||
|
libquickjs-sys = { version = "...", default-features = false, features = ["system"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Updating the embedded bindings
|
||||||
|
|
||||||
|
QuickJS sources and a pre-generated `bindings.rs` are included in the repo.
|
||||||
|
|
||||||
|
They are used if the `embedded` feature is enabled.
|
||||||
|
|
||||||
|
To updat the bindings, follow these steps:
|
||||||
|
|
||||||
|
* (Install [just](https://github.com/casey/just))
|
||||||
|
* Update the download URL in ./justfile
|
||||||
|
* run `just quickjs-update`
|
||||||
144
quickjs/external/quickjs-rs/libquickjs-sys/build.rs
vendored
Normal file
144
quickjs/external/quickjs-rs/libquickjs-sys/build.rs
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn exists(path: impl AsRef<Path>) -> bool {
|
||||||
|
PathBuf::from(path.as_ref()).exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
const LIB_NAME: &str = "quickjs";
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "system"), not(feature = "bundled")))]
|
||||||
|
fn main() {
|
||||||
|
panic!("Invalid config for crate libquickjs-sys: must enable either the 'bundled' or the 'system' feature");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
extern crate bindgen;
|
||||||
|
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
fn main() {
|
||||||
|
#[cfg(not(feature = "bindgen"))]
|
||||||
|
panic!("Invalid configuration for libquickjs-sys: Must either enable the bundled or the bindgen feature");
|
||||||
|
|
||||||
|
#[cfg(feature = "patched")]
|
||||||
|
panic!("Invalid configuration for libquickjs-sys: the patched feature is incompatible with the system feature");
|
||||||
|
|
||||||
|
let lib: std::borrow::Cow<str> = if let Ok(lib) = env::var("QUICKJS_LIBRARY_PATH") {
|
||||||
|
lib.into()
|
||||||
|
} else if cfg!(unix) {
|
||||||
|
if exists(format!("/usr/lib/quickjs/{}.a", LIB_NAME)) {
|
||||||
|
"/usr/lib/quickjs".into()
|
||||||
|
} else if exists("/usr/local/lib/quickjs") {
|
||||||
|
"/usr/local/lib/quickjs".into()
|
||||||
|
} else {
|
||||||
|
panic!("quickjs library could not be found. Try setting the QUICKJS_LIBRARY_PATH env variable");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("quickjs error: Windows is not supported yet");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate bindings.
|
||||||
|
let bindings = bindgen::Builder::default()
|
||||||
|
.header("wrapper.h")
|
||||||
|
.generate()
|
||||||
|
.expect("Unable to generate bindings");
|
||||||
|
|
||||||
|
// Write the bindings to the $OUT_DIR/bindings.rs file.
|
||||||
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
bindings
|
||||||
|
.write_to_file(out_path.join("bindings.rs"))
|
||||||
|
.expect("Couldn't write bindings!");
|
||||||
|
|
||||||
|
// Instruct cargo to statically link quickjs.
|
||||||
|
println!("cargo:rustc-link-search=native={}", lib);
|
||||||
|
println!("cargo:rustc-link-lib=static={}", LIB_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bundled")]
|
||||||
|
fn main() {
|
||||||
|
let embed_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("embed");
|
||||||
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
|
||||||
|
let code_dir = out_path.join("quickjs");
|
||||||
|
if exists(&code_dir) {
|
||||||
|
std::fs::remove_dir_all(&code_dir).unwrap();
|
||||||
|
}
|
||||||
|
copy_dir::copy_dir(embed_path.join("quickjs"), &code_dir)
|
||||||
|
.expect("Could not copy quickjs directory");
|
||||||
|
|
||||||
|
#[cfg(feature = "patched")]
|
||||||
|
apply_patches(&code_dir);
|
||||||
|
|
||||||
|
eprintln!("Compiling quickjs...");
|
||||||
|
let quickjs_version =
|
||||||
|
std::fs::read_to_string(code_dir.join("VERSION")).expect("failed to read quickjs version");
|
||||||
|
cc::Build::new()
|
||||||
|
.files(
|
||||||
|
[
|
||||||
|
"cutils.c",
|
||||||
|
"libbf.c",
|
||||||
|
"libregexp.c",
|
||||||
|
"libunicode.c",
|
||||||
|
"quickjs.c",
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.map(|f| code_dir.join(f)),
|
||||||
|
)
|
||||||
|
.define("_GNU_SOURCE", None)
|
||||||
|
.define(
|
||||||
|
"CONFIG_VERSION",
|
||||||
|
format!("\"{}\"", quickjs_version.trim()).as_str(),
|
||||||
|
)
|
||||||
|
.define("CONFIG_BIGNUM", None)
|
||||||
|
// The below flags are used by the official Makefile.
|
||||||
|
.flag_if_supported("-Wchar-subscripts")
|
||||||
|
.flag_if_supported("-Wno-array-bounds")
|
||||||
|
.flag_if_supported("-Wno-format-truncation")
|
||||||
|
.flag_if_supported("-Wno-missing-field-initializers")
|
||||||
|
.flag_if_supported("-Wno-sign-compare")
|
||||||
|
.flag_if_supported("-Wno-unused-parameter")
|
||||||
|
.flag_if_supported("-Wundef")
|
||||||
|
.flag_if_supported("-Wuninitialized")
|
||||||
|
.flag_if_supported("-Wunused")
|
||||||
|
.flag_if_supported("-Wwrite-strings")
|
||||||
|
.flag_if_supported("-funsigned-char")
|
||||||
|
// Below flags are added to supress warnings that appear on some
|
||||||
|
// platforms.
|
||||||
|
.flag_if_supported("-Wno-cast-function-type")
|
||||||
|
.flag_if_supported("-Wno-implicit-fallthrough")
|
||||||
|
// cc uses the OPT_LEVEL env var by default, but we hardcode it to -O2
|
||||||
|
// since release builds use -O3 which might be problematic for quickjs,
|
||||||
|
// and debug builds only happen once anyway so the optimization slowdown
|
||||||
|
// is fine.
|
||||||
|
.opt_level(2)
|
||||||
|
.compile(LIB_NAME);
|
||||||
|
|
||||||
|
std::fs::copy(embed_path.join("bindings.rs"), out_path.join("bindings.rs"))
|
||||||
|
.expect("Could not copy bindings.rs");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "patched")]
|
||||||
|
fn apply_patches(code_dir: &PathBuf) {
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
eprintln!("Applying patches...");
|
||||||
|
let embed_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("embed");
|
||||||
|
let patches_path = embed_path.join("patches");
|
||||||
|
for patch in fs::read_dir(patches_path).expect("Could not open patches directory") {
|
||||||
|
let patch = patch.expect("Could not open patch");
|
||||||
|
eprintln!("Applying {:?}...", patch.file_name());
|
||||||
|
let status = std::process::Command::new("patch")
|
||||||
|
.current_dir(&code_dir)
|
||||||
|
.arg("-i")
|
||||||
|
.arg(fs::canonicalize(patch.path()).expect("Cannot canonicalize patch path"))
|
||||||
|
.spawn()
|
||||||
|
.expect("Could not apply patches")
|
||||||
|
.wait()
|
||||||
|
.expect("Could not apply patches");
|
||||||
|
assert!(
|
||||||
|
status.success(),
|
||||||
|
"Patch command returned non-zero exit code"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
3884
quickjs/external/quickjs-rs/libquickjs-sys/embed/bindings.rs
vendored
Normal file
3884
quickjs/external/quickjs-rs/libquickjs-sys/embed/bindings.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
47
quickjs/external/quickjs-rs/libquickjs-sys/embed/patches/js-tobigint64-overflow.patch
vendored
Normal file
47
quickjs/external/quickjs-rs/libquickjs-sys/embed/patches/js-tobigint64-overflow.patch
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
diff --git libquickjs-sys/embed/quickjs/libbf.c libquickjs-sys/embed/quickjs/libbf.c
|
||||||
|
index cbabf95..f0625f9 100644
|
||||||
|
--- libquickjs-sys/embed/quickjs/libbf.c
|
||||||
|
+++ libquickjs-sys/embed/quickjs/libbf.c
|
||||||
|
@@ -2261,14 +2261,17 @@ int bf_get_int64(int64_t *pres, const bf_t *a, int flags)
|
||||||
|
v = INT64_MAX;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
+ ret = BF_ST_OVERFLOW;
|
||||||
|
slimb_t bit_pos = a->len * LIMB_BITS - a->expn;
|
||||||
|
v = get_bits(a->tab, a->len, bit_pos);
|
||||||
|
#if LIMB_BITS == 32
|
||||||
|
v |= (uint64_t)get_bits(a->tab, a->len, bit_pos + 32) << 32;
|
||||||
|
#endif
|
||||||
|
- if (a->sign)
|
||||||
|
+ if (a->sign) {
|
||||||
|
+ if (a->expn == 64 && v == (uint64_t)INT64_MAX + 1)
|
||||||
|
+ ret = 0; // not overflow, but INT64_MIN
|
||||||
|
v = -v;
|
||||||
|
- ret = 0;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
*pres = v;
|
||||||
|
return ret;
|
||||||
|
diff --git libquickjs-sys/embed/quickjs/quickjs.c libquickjs-sys/embed/quickjs/quickjs.c
|
||||||
|
index 7bb20cb..ad5811c 100644
|
||||||
|
--- libquickjs-sys/embed/quickjs/quickjs.c
|
||||||
|
+++ libquickjs-sys/embed/quickjs/quickjs.c
|
||||||
|
@@ -11244,15 +11244,16 @@ static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf)
|
||||||
|
static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val)
|
||||||
|
{
|
||||||
|
bf_t a_s, *a;
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
a = JS_ToBigIntFree(ctx, &a_s, val);
|
||||||
|
if (!a) {
|
||||||
|
*pres = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
- bf_get_int64(pres, a, BF_GET_INT_MOD);
|
||||||
|
+ ret = bf_get_int64(pres, a, BF_GET_INT_MOD);
|
||||||
|
JS_FreeBigInt(ctx, a, &a_s);
|
||||||
|
- return 0;
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
|
||||||
15
quickjs/external/quickjs-rs/libquickjs-sys/embed/patches/stack-overflow-signed.patch
vendored
Normal file
15
quickjs/external/quickjs-rs/libquickjs-sys/embed/patches/stack-overflow-signed.patch
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
diff -urN quickjs-2019-07-28/quickjs.c quickjs-2019-07-28-stack-overflow-signed/quickjs.c
|
||||||
|
--- quickjs-2019-07-28/quickjs.c 2019-07-28 15:03:03.000000000 +0000
|
||||||
|
+++ quickjs-2019-07-28-stack-overflow-signed/quickjs.c 2019-08-09 20:00:03.666846091 +0000
|
||||||
|
@@ -1732,9 +1732,9 @@
|
||||||
|
|
||||||
|
static inline BOOL js_check_stack_overflow(JSContext *rt, size_t alloca_size)
|
||||||
|
{
|
||||||
|
- size_t size;
|
||||||
|
+ ptrdiff_t size;
|
||||||
|
size = rt->stack_top - js_get_stack_pointer();
|
||||||
|
- return unlikely((size + alloca_size) > rt->stack_size);
|
||||||
|
+ return unlikely((size + (ptrdiff_t)alloca_size) > (ptrdiff_t)rt->stack_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
125
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/Changelog
vendored
Normal file
125
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/Changelog
vendored
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
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
|
||||||
468
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/Makefile
vendored
Normal file
468
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/Makefile
vendored
Normal file
@@ -0,0 +1,468 @@
|
|||||||
|
#
|
||||||
|
# QuickJS Javascript Engine
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017-2020 Fabrice Bellard
|
||||||
|
# Copyright (c) 2017-2020 Charlie Gordon
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
|
||||||
|
ifeq ($(shell uname -s),Darwin)
|
||||||
|
CONFIG_DARWIN=y
|
||||||
|
endif
|
||||||
|
# Windows cross compilation from Linux
|
||||||
|
#CONFIG_WIN32=y
|
||||||
|
# use link time optimization (smaller and faster executables but slower build)
|
||||||
|
CONFIG_LTO=y
|
||||||
|
# consider warnings as errors (for development)
|
||||||
|
#CONFIG_WERROR=y
|
||||||
|
# force 32 bit build for some utilities
|
||||||
|
#CONFIG_M32=y
|
||||||
|
|
||||||
|
ifdef CONFIG_DARWIN
|
||||||
|
# use clang instead of gcc
|
||||||
|
CONFIG_CLANG=y
|
||||||
|
CONFIG_DEFAULT_AR=y
|
||||||
|
endif
|
||||||
|
|
||||||
|
# installation directory
|
||||||
|
prefix=/usr/local
|
||||||
|
|
||||||
|
# use the gprof profiler
|
||||||
|
#CONFIG_PROFILE=y
|
||||||
|
# use address sanitizer
|
||||||
|
#CONFIG_ASAN=y
|
||||||
|
# include the code for BigInt/BigFloat/BigDecimal and math mode
|
||||||
|
CONFIG_BIGNUM=y
|
||||||
|
|
||||||
|
OBJDIR=.obj
|
||||||
|
|
||||||
|
ifdef CONFIG_WIN32
|
||||||
|
CROSS_PREFIX=i686-w64-mingw32-
|
||||||
|
EXE=.exe
|
||||||
|
else
|
||||||
|
CROSS_PREFIX=
|
||||||
|
EXE=
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_CLANG
|
||||||
|
HOST_CC=clang
|
||||||
|
CC=$(CROSS_PREFIX)clang
|
||||||
|
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
CFLAGS += -Wextra
|
||||||
|
CFLAGS += -Wno-sign-compare
|
||||||
|
CFLAGS += -Wno-missing-field-initializers
|
||||||
|
CFLAGS += -Wundef -Wuninitialized
|
||||||
|
CFLAGS += -Wunused -Wno-unused-parameter
|
||||||
|
CFLAGS += -Wwrite-strings
|
||||||
|
CFLAGS += -Wchar-subscripts -funsigned-char
|
||||||
|
CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
ifdef CONFIG_DEFAULT_AR
|
||||||
|
AR=$(CROSS_PREFIX)ar
|
||||||
|
else
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
AR=$(CROSS_PREFIX)llvm-ar
|
||||||
|
else
|
||||||
|
AR=$(CROSS_PREFIX)ar
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
HOST_CC=gcc
|
||||||
|
CC=$(CROSS_PREFIX)gcc
|
||||||
|
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||||
|
CFLAGS += -Wno-array-bounds -Wno-format-truncation
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
AR=$(CROSS_PREFIX)gcc-ar
|
||||||
|
else
|
||||||
|
AR=$(CROSS_PREFIX)ar
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
STRIP=$(CROSS_PREFIX)strip
|
||||||
|
ifdef CONFIG_WERROR
|
||||||
|
CFLAGS+=-Werror
|
||||||
|
endif
|
||||||
|
DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
|
||||||
|
ifdef CONFIG_BIGNUM
|
||||||
|
DEFINES+=-DCONFIG_BIGNUM
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_WIN32
|
||||||
|
DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior
|
||||||
|
endif
|
||||||
|
|
||||||
|
CFLAGS+=$(DEFINES)
|
||||||
|
CFLAGS_DEBUG=$(CFLAGS) -O0
|
||||||
|
CFLAGS_SMALL=$(CFLAGS) -Os
|
||||||
|
CFLAGS_OPT=$(CFLAGS) -O2
|
||||||
|
CFLAGS_NOLTO:=$(CFLAGS_OPT)
|
||||||
|
LDFLAGS=-g
|
||||||
|
ifdef CONFIG_LTO
|
||||||
|
CFLAGS_SMALL+=-flto
|
||||||
|
CFLAGS_OPT+=-flto
|
||||||
|
LDFLAGS+=-flto
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_PROFILE
|
||||||
|
CFLAGS+=-p
|
||||||
|
LDFLAGS+=-p
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_ASAN
|
||||||
|
CFLAGS+=-fsanitize=address -fno-omit-frame-pointer
|
||||||
|
LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_WIN32
|
||||||
|
LDEXPORT=
|
||||||
|
else
|
||||||
|
LDEXPORT=-rdynamic
|
||||||
|
endif
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# examples
|
||||||
|
ifeq ($(CROSS_PREFIX),)
|
||||||
|
ifdef CONFIG_ASAN
|
||||||
|
PROGS+=
|
||||||
|
else
|
||||||
|
PROGS+=examples/hello examples/hello_module examples/test_fib
|
||||||
|
ifndef CONFIG_DARWIN
|
||||||
|
PROGS+=examples/fib.so examples/point.so
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
|
||||||
|
|
||||||
|
QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
|
||||||
|
|
||||||
|
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
|
||||||
|
ifdef CONFIG_BIGNUM
|
||||||
|
QJS_LIB_OBJS+=$(OBJDIR)/libbf.o
|
||||||
|
QJS_OBJS+=$(OBJDIR)/qjscalc.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
HOST_LIBS=-lm -ldl -lpthread
|
||||||
|
LIBS=-lm
|
||||||
|
ifndef CONFIG_WIN32
|
||||||
|
LIBS+=-ldl -lpthread
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(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)
|
||||||
|
|
||||||
|
jscompress: jscompress.c
|
||||||
|
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c
|
||||||
|
|
||||||
|
unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h
|
||||||
|
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f repl.c qjscalc.c out.c
|
||||||
|
rm -f *.a *.o *.d *~ jscompress 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
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# examples
|
||||||
|
|
||||||
|
# example of static JS compilation
|
||||||
|
HELLO_SRCS=examples/hello.js
|
||||||
|
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
|
||||||
|
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
|
||||||
|
-fno-date -fno-module-loader
|
||||||
|
ifdef CONFIG_BIGNUM
|
||||||
|
HELLO_OPTS+=-fno-bigint
|
||||||
|
endif
|
||||||
|
|
||||||
|
hello.c: $(QJSC) $(HELLO_SRCS)
|
||||||
|
$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
|
||||||
|
|
||||||
|
ifdef CONFIG_M32
|
||||||
|
examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
|
||||||
|
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
else
|
||||||
|
examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# example of static JS compilation with modules
|
||||||
|
HELLO_MODULE_SRCS=examples/hello_module.js
|
||||||
|
HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
|
||||||
|
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
|
||||||
|
-fno-date -m
|
||||||
|
examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS)
|
||||||
|
$(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS)
|
||||||
|
|
||||||
|
# use of an external C module (static compilation)
|
||||||
|
|
||||||
|
test_fib.c: $(QJSC) examples/test_fib.js
|
||||||
|
$(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/test_fib.js
|
||||||
|
|
||||||
|
examples/test_fib: $(OBJDIR)/test_fib.o $(OBJDIR)/examples/fib.o libquickjs$(LTOEXT).a
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
examples/fib.so: $(OBJDIR)/examples/fib.pic.o
|
||||||
|
$(CC) $(LDFLAGS) -shared -o $@ $^
|
||||||
|
|
||||||
|
examples/point.so: $(OBJDIR)/examples/point.pic.o
|
||||||
|
$(CC) $(LDFLAGS) -shared -o $@ $^
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# documentation
|
||||||
|
|
||||||
|
DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html
|
||||||
|
|
||||||
|
build_doc: $(DOCS)
|
||||||
|
|
||||||
|
clean_doc:
|
||||||
|
rm -f $(DOCS)
|
||||||
|
|
||||||
|
doc/%.pdf: doc/%.texi
|
||||||
|
texi2pdf --clean -o $@ -q $<
|
||||||
|
|
||||||
|
doc/%.html.pre: doc/%.texi
|
||||||
|
makeinfo --html --no-headers --no-split --number-sections -o $@ $<
|
||||||
|
|
||||||
|
doc/%.html: doc/%.html.pre
|
||||||
|
sed -e 's|</style>|</style>\n<meta name="viewport" content="width=device-width, initial-scale=1.0">|' < $< > $@
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# tests
|
||||||
|
|
||||||
|
ifndef CONFIG_DARWIN
|
||||||
|
test: 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
|
||||||
|
ifndef CONFIG_DARWIN
|
||||||
|
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)
|
||||||
78
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/TODO
vendored
Normal file
78
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/TODO
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
Misc:
|
||||||
|
- use realpath in module name normalizer and put it in quickjs-libc
|
||||||
|
- use custom printf to avoid C library compatibility issues
|
||||||
|
- rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ?
|
||||||
|
- unify coding style and naming conventions
|
||||||
|
- use names from the ECMA spec in library implementation
|
||||||
|
- modules: if no ".", use a well known module loading path ?
|
||||||
|
- use JSHoistedDef only for global variables (JSHoistedDef.var_name != JS_ATOM_NULL)
|
||||||
|
- add index in JSVarDef and is_arg flag to merge args and vars in JSFunctionDef
|
||||||
|
- replace most JSVarDef flags with var_type enumeration
|
||||||
|
- use byte code emitters with typed arguments (for clarity)
|
||||||
|
- use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing
|
||||||
|
and use the same wrappers in all phases
|
||||||
|
- use more generic method for line numbers in resolve_variables and resolve_labels
|
||||||
|
- use custom timezone support to avoid C library compatibility issues
|
||||||
|
|
||||||
|
Memory:
|
||||||
|
- test border cases for max number of atoms, object properties, string length
|
||||||
|
- add emergency malloc mode for out of memory exceptions.
|
||||||
|
- test all DynBuf memory errors
|
||||||
|
- test all js_realloc memory errors
|
||||||
|
- bignum: handle memory errors
|
||||||
|
- use memory pools for objects, etc?
|
||||||
|
- improve JS_ComputeMemoryUsage() with more info
|
||||||
|
|
||||||
|
Optimizations:
|
||||||
|
- 64-bit atoms in 64-bit mode ?
|
||||||
|
- use auto-init properties for more global objects
|
||||||
|
- reuse stack slots for disjoint scopes, if strip
|
||||||
|
- optimize `for of` iterator for built-in array objects
|
||||||
|
- add heuristic to avoid some cycles in closures
|
||||||
|
- small String (0-2 charcodes) with immediate storage
|
||||||
|
- perform static string concatenation at compile time
|
||||||
|
- optimize string concatenation with ropes or miniropes?
|
||||||
|
- add implicit numeric strings for Uint32 numbers?
|
||||||
|
- optimize `s += a + b`, `s += a.b` and similar simple expressions
|
||||||
|
- ensure string canonical representation and optimise comparisons and hashes?
|
||||||
|
- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references
|
||||||
|
- optimize function storage with length and name accessors?
|
||||||
|
- property access optimization on the global object, functions,
|
||||||
|
prototypes and special non extensible objects.
|
||||||
|
- create object literals with the correct length by backpatching length argument
|
||||||
|
- remove redundant set_loc_uninitialized/check_uninitialized opcodes
|
||||||
|
- peephole optim: push_atom_value, to_propkey -> push_atom_value
|
||||||
|
- peephole optim: put_loc x, get_loc_check x -> set_loc x
|
||||||
|
- comparative performance benchmark
|
||||||
|
- use variable name when throwing uninitialized exception if available
|
||||||
|
- convert slow array to fast array when all properties != length are numeric
|
||||||
|
- optimize destructuring assignments for global and local variables
|
||||||
|
- implement some form of tail-call-optimization
|
||||||
|
- optimize OP_apply
|
||||||
|
- optimize f(...b)
|
||||||
|
|
||||||
|
Extensions:
|
||||||
|
- support more features in [features] section
|
||||||
|
- add built-in preprocessor in compiler, get rid of jscompress
|
||||||
|
handle #if, #ifdef, #line, limited support for #define
|
||||||
|
- get rid of __loadScript, use more common name
|
||||||
|
- BSD sockets
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Test262o: 0/11262 errors, 463 excluded
|
||||||
|
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
|
||||||
|
|
||||||
|
Test262: 30/71095 errors, 870 excluded, 549 skipped
|
||||||
|
Test262 commit: 281eb10b2844929a7c0ac04527f5b42ce56509fd
|
||||||
1
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/VERSION
vendored
Normal file
1
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/VERSION
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2020-07-05
|
||||||
620
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/cutils.c
vendored
Normal file
620
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/cutils.c
vendored
Normal file
@@ -0,0 +1,620 @@
|
|||||||
|
/*
|
||||||
|
* C utilities
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Fabrice Bellard
|
||||||
|
* Copyright (c) 2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
void pstrcpy(char *buf, int buf_size, const char *str)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
char *q = buf;
|
||||||
|
|
||||||
|
if (buf_size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
c = *str++;
|
||||||
|
if (c == 0 || q >= buf + buf_size - 1)
|
||||||
|
break;
|
||||||
|
*q++ = c;
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strcat and truncate. */
|
||||||
|
char *pstrcat(char *buf, int buf_size, const char *s)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
len = strlen(buf);
|
||||||
|
if (len < buf_size)
|
||||||
|
pstrcpy(buf + len, buf_size - len, s);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strstart(const char *str, const char *val, const char **ptr)
|
||||||
|
{
|
||||||
|
const char *p, *q;
|
||||||
|
p = str;
|
||||||
|
q = val;
|
||||||
|
while (*q != '\0') {
|
||||||
|
if (*p != *q)
|
||||||
|
return 0;
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
if (ptr)
|
||||||
|
*ptr = p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int has_suffix(const char *str, const char *suffix)
|
||||||
|
{
|
||||||
|
size_t len = strlen(str);
|
||||||
|
size_t slen = strlen(suffix);
|
||||||
|
return (len >= slen && !memcmp(str + len - slen, suffix, slen));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dynamic buffer package */
|
||||||
|
|
||||||
|
static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
|
||||||
|
{
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
if (!realloc_func)
|
||||||
|
realloc_func = dbuf_default_realloc;
|
||||||
|
s->opaque = opaque;
|
||||||
|
s->realloc_func = realloc_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_init(DynBuf *s)
|
||||||
|
{
|
||||||
|
dbuf_init2(s, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return < 0 if error */
|
||||||
|
int dbuf_realloc(DynBuf *s, size_t new_size)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
uint8_t *new_buf;
|
||||||
|
if (new_size > s->allocated_size) {
|
||||||
|
if (s->error)
|
||||||
|
return -1;
|
||||||
|
size = s->allocated_size * 3 / 2;
|
||||||
|
if (size > new_size)
|
||||||
|
new_size = size;
|
||||||
|
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
|
||||||
|
if (!new_buf) {
|
||||||
|
s->error = TRUE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->buf = new_buf;
|
||||||
|
s->allocated_size = new_size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
size_t end;
|
||||||
|
end = offset + len;
|
||||||
|
if (dbuf_realloc(s, end))
|
||||||
|
return -1;
|
||||||
|
memcpy(s->buf + offset, data, len);
|
||||||
|
if (end > s->size)
|
||||||
|
s->size = end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||||
|
if (dbuf_realloc(s, s->size + len))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(s->buf + s->size, data, len);
|
||||||
|
s->size += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
|
||||||
|
{
|
||||||
|
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||||
|
if (dbuf_realloc(s, s->size + len))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(s->buf + s->size, s->buf + offset, len);
|
||||||
|
s->size += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_putc(DynBuf *s, uint8_t c)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbuf_putstr(DynBuf *s, const char *str)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (const uint8_t *)str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buf[128];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (len < sizeof(buf)) {
|
||||||
|
/* fast case */
|
||||||
|
return dbuf_put(s, (uint8_t *)buf, len);
|
||||||
|
} else {
|
||||||
|
if (dbuf_realloc(s, s->size + len + 1))
|
||||||
|
return -1;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
|
||||||
|
fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
s->size += len;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_free(DynBuf *s)
|
||||||
|
{
|
||||||
|
/* we test s->buf as a fail safe to avoid crashing if dbuf_free()
|
||||||
|
is called twice */
|
||||||
|
if (s->buf) {
|
||||||
|
s->realloc_func(s->opaque, s->buf, 0);
|
||||||
|
}
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
|
||||||
|
are output. */
|
||||||
|
int unicode_to_utf8(uint8_t *buf, unsigned int c)
|
||||||
|
{
|
||||||
|
uint8_t *q = buf;
|
||||||
|
|
||||||
|
if (c < 0x80) {
|
||||||
|
*q++ = c;
|
||||||
|
} else {
|
||||||
|
if (c < 0x800) {
|
||||||
|
*q++ = (c >> 6) | 0xc0;
|
||||||
|
} else {
|
||||||
|
if (c < 0x10000) {
|
||||||
|
*q++ = (c >> 12) | 0xe0;
|
||||||
|
} else {
|
||||||
|
if (c < 0x00200000) {
|
||||||
|
*q++ = (c >> 18) | 0xf0;
|
||||||
|
} else {
|
||||||
|
if (c < 0x04000000) {
|
||||||
|
*q++ = (c >> 24) | 0xf8;
|
||||||
|
} else if (c < 0x80000000) {
|
||||||
|
*q++ = (c >> 30) | 0xfc;
|
||||||
|
*q++ = ((c >> 24) & 0x3f) | 0x80;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*q++ = ((c >> 18) & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
*q++ = ((c >> 12) & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
*q++ = ((c >> 6) & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
*q++ = (c & 0x3f) | 0x80;
|
||||||
|
}
|
||||||
|
return q - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned int utf8_min_code[5] = {
|
||||||
|
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char utf8_first_code_mask[5] = {
|
||||||
|
0x1f, 0xf, 0x7, 0x3, 0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* return -1 if error. *pp is not updated in this case. max_len must
|
||||||
|
be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
|
||||||
|
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
|
||||||
|
{
|
||||||
|
int l, c, b, i;
|
||||||
|
|
||||||
|
c = *p++;
|
||||||
|
if (c < 0x80) {
|
||||||
|
*pp = p;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
switch(c) {
|
||||||
|
case 0xc0 ... 0xdf:
|
||||||
|
l = 1;
|
||||||
|
break;
|
||||||
|
case 0xe0 ... 0xef:
|
||||||
|
l = 2;
|
||||||
|
break;
|
||||||
|
case 0xf0 ... 0xf7:
|
||||||
|
l = 3;
|
||||||
|
break;
|
||||||
|
case 0xf8 ... 0xfb:
|
||||||
|
l = 4;
|
||||||
|
break;
|
||||||
|
case 0xfc ... 0xfd:
|
||||||
|
l = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* check that we have enough characters */
|
||||||
|
if (l > (max_len - 1))
|
||||||
|
return -1;
|
||||||
|
c &= utf8_first_code_mask[l - 1];
|
||||||
|
for(i = 0; i < l; i++) {
|
||||||
|
b = *p++;
|
||||||
|
if (b < 0x80 || b >= 0xc0)
|
||||||
|
return -1;
|
||||||
|
c = (c << 6) | (b & 0x3f);
|
||||||
|
}
|
||||||
|
if (c < utf8_min_code[l - 1])
|
||||||
|
return -1;
|
||||||
|
*pp = p;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
|
||||||
|
|
||||||
|
static void *rqsort_arg;
|
||||||
|
static int (*rqsort_cmp)(const void *, const void *, void *);
|
||||||
|
|
||||||
|
static int rqsort_cmp2(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
return rqsort_cmp(p1, p2, rqsort_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not reentrant, but not needed with emscripten */
|
||||||
|
void rqsort(void *base, size_t nmemb, size_t size,
|
||||||
|
int (*cmp)(const void *, const void *, void *),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
rqsort_arg = arg;
|
||||||
|
rqsort_cmp = cmp;
|
||||||
|
qsort(base, nmemb, size, rqsort_cmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef void (*exchange_f)(void *a, void *b, size_t size);
|
||||||
|
typedef int (*cmp_f)(const void *, const void *, void *opaque);
|
||||||
|
|
||||||
|
static void exchange_bytes(void *a, void *b, size_t size) {
|
||||||
|
uint8_t *ap = (uint8_t *)a;
|
||||||
|
uint8_t *bp = (uint8_t *)b;
|
||||||
|
|
||||||
|
while (size-- != 0) {
|
||||||
|
uint8_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_byte(void *a, void *b, size_t size) {
|
||||||
|
uint8_t *ap = (uint8_t *)a;
|
||||||
|
uint8_t *bp = (uint8_t *)b;
|
||||||
|
uint8_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int16s(void *a, void *b, size_t size) {
|
||||||
|
uint16_t *ap = (uint16_t *)a;
|
||||||
|
uint16_t *bp = (uint16_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint16_t); size-- != 0;) {
|
||||||
|
uint16_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int16(void *a, void *b, size_t size) {
|
||||||
|
uint16_t *ap = (uint16_t *)a;
|
||||||
|
uint16_t *bp = (uint16_t *)b;
|
||||||
|
uint16_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int32s(void *a, void *b, size_t size) {
|
||||||
|
uint32_t *ap = (uint32_t *)a;
|
||||||
|
uint32_t *bp = (uint32_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint32_t); size-- != 0;) {
|
||||||
|
uint32_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int32(void *a, void *b, size_t size) {
|
||||||
|
uint32_t *ap = (uint32_t *)a;
|
||||||
|
uint32_t *bp = (uint32_t *)b;
|
||||||
|
uint32_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int64s(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint64_t); size-- != 0;) {
|
||||||
|
uint64_t t = *ap;
|
||||||
|
*ap++ = *bp;
|
||||||
|
*bp++ = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int64(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
uint64_t t = *ap;
|
||||||
|
*ap = *bp;
|
||||||
|
*bp = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_int128s(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
|
||||||
|
for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
|
||||||
|
uint64_t t = ap[0];
|
||||||
|
uint64_t u = ap[1];
|
||||||
|
ap[0] = bp[0];
|
||||||
|
ap[1] = bp[1];
|
||||||
|
bp[0] = t;
|
||||||
|
bp[1] = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exchange_one_int128(void *a, void *b, size_t size) {
|
||||||
|
uint64_t *ap = (uint64_t *)a;
|
||||||
|
uint64_t *bp = (uint64_t *)b;
|
||||||
|
uint64_t t = ap[0];
|
||||||
|
uint64_t u = ap[1];
|
||||||
|
ap[0] = bp[0];
|
||||||
|
ap[1] = bp[1];
|
||||||
|
bp[0] = t;
|
||||||
|
bp[1] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline exchange_f exchange_func(const void *base, size_t size) {
|
||||||
|
switch (((uintptr_t)base | (uintptr_t)size) & 15) {
|
||||||
|
case 0:
|
||||||
|
if (size == sizeof(uint64_t) * 2)
|
||||||
|
return exchange_one_int128;
|
||||||
|
else
|
||||||
|
return exchange_int128s;
|
||||||
|
case 8:
|
||||||
|
if (size == sizeof(uint64_t))
|
||||||
|
return exchange_one_int64;
|
||||||
|
else
|
||||||
|
return exchange_int64s;
|
||||||
|
case 4:
|
||||||
|
case 12:
|
||||||
|
if (size == sizeof(uint32_t))
|
||||||
|
return exchange_one_int32;
|
||||||
|
else
|
||||||
|
return exchange_int32s;
|
||||||
|
case 2:
|
||||||
|
case 6:
|
||||||
|
case 10:
|
||||||
|
case 14:
|
||||||
|
if (size == sizeof(uint16_t))
|
||||||
|
return exchange_one_int16;
|
||||||
|
else
|
||||||
|
return exchange_int16s;
|
||||||
|
default:
|
||||||
|
if (size == 1)
|
||||||
|
return exchange_one_byte;
|
||||||
|
else
|
||||||
|
return exchange_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
|
||||||
|
{
|
||||||
|
uint8_t *basep = (uint8_t *)base;
|
||||||
|
size_t i, n, c, r;
|
||||||
|
exchange_f swap = exchange_func(base, size);
|
||||||
|
|
||||||
|
if (nmemb > 1) {
|
||||||
|
i = (nmemb / 2) * size;
|
||||||
|
n = nmemb * size;
|
||||||
|
|
||||||
|
while (i > 0) {
|
||||||
|
i -= size;
|
||||||
|
for (r = i; (c = r * 2 + size) < n; r = c) {
|
||||||
|
if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
|
||||||
|
c += size;
|
||||||
|
if (cmp(basep + r, basep + c, opaque) > 0)
|
||||||
|
break;
|
||||||
|
swap(basep + r, basep + c, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = n - size; i > 0; i -= size) {
|
||||||
|
swap(basep, basep + i, size);
|
||||||
|
|
||||||
|
for (r = 0; (c = r * 2 + size) < i; r = c) {
|
||||||
|
if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
|
||||||
|
c += size;
|
||||||
|
if (cmp(basep + r, basep + c, opaque) > 0)
|
||||||
|
break;
|
||||||
|
swap(basep + r, basep + c, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
|
||||||
|
{
|
||||||
|
return cmp(a, b, opaque) < 0 ?
|
||||||
|
(cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
|
||||||
|
(cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pointer based version with local stack and insertion sort threshhold */
|
||||||
|
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
|
||||||
|
{
|
||||||
|
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
|
||||||
|
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
|
||||||
|
size_t m4, i, lt, gt, span, span2;
|
||||||
|
int c, depth;
|
||||||
|
exchange_f swap = exchange_func(base, size);
|
||||||
|
exchange_f swap_block = exchange_func(base, size | 128);
|
||||||
|
|
||||||
|
if (nmemb < 2 || size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sp->base = (uint8_t *)base;
|
||||||
|
sp->count = nmemb;
|
||||||
|
sp->depth = 0;
|
||||||
|
sp++;
|
||||||
|
|
||||||
|
while (sp > stack) {
|
||||||
|
sp--;
|
||||||
|
ptr = sp->base;
|
||||||
|
nmemb = sp->count;
|
||||||
|
depth = sp->depth;
|
||||||
|
|
||||||
|
while (nmemb > 6) {
|
||||||
|
if (++depth > 50) {
|
||||||
|
/* depth check to ensure worst case logarithmic time */
|
||||||
|
heapsortx(ptr, nmemb, size, cmp, opaque);
|
||||||
|
nmemb = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* select median of 3 from 1/4, 1/2, 3/4 positions */
|
||||||
|
/* should use median of 5 or 9? */
|
||||||
|
m4 = (nmemb >> 2) * size;
|
||||||
|
m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
|
||||||
|
swap(ptr, m, size); /* move the pivot to the start or the array */
|
||||||
|
i = lt = 1;
|
||||||
|
pi = plt = ptr + size;
|
||||||
|
gt = nmemb;
|
||||||
|
pj = pgt = top = ptr + nmemb * size;
|
||||||
|
for (;;) {
|
||||||
|
while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
|
||||||
|
if (c == 0) {
|
||||||
|
swap(plt, pi, size);
|
||||||
|
lt++;
|
||||||
|
plt += size;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
pi += size;
|
||||||
|
}
|
||||||
|
while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
|
||||||
|
if (c == 0) {
|
||||||
|
gt--;
|
||||||
|
pgt -= size;
|
||||||
|
swap(pgt, pj, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pi >= pj)
|
||||||
|
break;
|
||||||
|
swap(pi, pj, size);
|
||||||
|
i++;
|
||||||
|
pi += size;
|
||||||
|
}
|
||||||
|
/* array has 4 parts:
|
||||||
|
* from 0 to lt excluded: elements identical to pivot
|
||||||
|
* from lt to pi excluded: elements smaller than pivot
|
||||||
|
* from pi to gt excluded: elements greater than pivot
|
||||||
|
* from gt to n excluded: elements identical to pivot
|
||||||
|
*/
|
||||||
|
/* move elements identical to pivot in the middle of the array: */
|
||||||
|
/* swap values in ranges [0..lt[ and [i-lt..i[
|
||||||
|
swapping the smallest span between lt and i-lt is sufficient
|
||||||
|
*/
|
||||||
|
span = plt - ptr;
|
||||||
|
span2 = pi - plt;
|
||||||
|
lt = i - lt;
|
||||||
|
if (span > span2)
|
||||||
|
span = span2;
|
||||||
|
swap_block(ptr, pi - span, span);
|
||||||
|
/* swap values in ranges [gt..top[ and [i..top-(top-gt)[
|
||||||
|
swapping the smallest span between top-gt and gt-i is sufficient
|
||||||
|
*/
|
||||||
|
span = top - pgt;
|
||||||
|
span2 = pgt - pi;
|
||||||
|
pgt = top - span2;
|
||||||
|
gt = nmemb - (gt - i);
|
||||||
|
if (span > span2)
|
||||||
|
span = span2;
|
||||||
|
swap_block(pi, top - span, span);
|
||||||
|
|
||||||
|
/* now array has 3 parts:
|
||||||
|
* from 0 to lt excluded: elements smaller than pivot
|
||||||
|
* from lt to gt excluded: elements identical to pivot
|
||||||
|
* from gt to n excluded: elements greater than pivot
|
||||||
|
*/
|
||||||
|
/* stack the larger segment and keep processing the smaller one
|
||||||
|
to minimize stack use for pathological distributions */
|
||||||
|
if (lt > nmemb - gt) {
|
||||||
|
sp->base = ptr;
|
||||||
|
sp->count = lt;
|
||||||
|
sp->depth = depth;
|
||||||
|
sp++;
|
||||||
|
ptr = pgt;
|
||||||
|
nmemb -= gt;
|
||||||
|
} else {
|
||||||
|
sp->base = pgt;
|
||||||
|
sp->count = nmemb - gt;
|
||||||
|
sp->depth = depth;
|
||||||
|
sp++;
|
||||||
|
nmemb = lt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Use insertion sort for small fragments */
|
||||||
|
for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
|
||||||
|
for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
|
||||||
|
swap(pj, pj - size, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
297
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/cutils.h
vendored
Normal file
297
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/cutils.h
vendored
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
* C utilities
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Fabrice Bellard
|
||||||
|
* Copyright (c) 2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef CUTILS_H
|
||||||
|
#define CUTILS_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
/* set if CPU is big endian */
|
||||||
|
#undef WORDS_BIGENDIAN
|
||||||
|
|
||||||
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#define force_inline inline __attribute__((always_inline))
|
||||||
|
#define no_inline __attribute__((noinline))
|
||||||
|
#define __maybe_unused __attribute__((unused))
|
||||||
|
|
||||||
|
#define xglue(x, y) x ## y
|
||||||
|
#define glue(x, y) xglue(x, y)
|
||||||
|
#define stringify(s) tostring(s)
|
||||||
|
#define tostring(s) #s
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||||
|
#endif
|
||||||
|
#ifndef countof
|
||||||
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
enum {
|
||||||
|
FALSE = 0,
|
||||||
|
TRUE = 1,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void pstrcpy(char *buf, int buf_size, const char *str);
|
||||||
|
char *pstrcat(char *buf, int buf_size, const char *s);
|
||||||
|
int strstart(const char *str, const char *val, const char **ptr);
|
||||||
|
int has_suffix(const char *str, const char *suffix);
|
||||||
|
|
||||||
|
static inline int max_int(int a, int b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int min_int(int a, int b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t max_int64(int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t min_int64(int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int clz32(unsigned int a)
|
||||||
|
{
|
||||||
|
return __builtin_clz(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int clz64(uint64_t a)
|
||||||
|
{
|
||||||
|
return __builtin_clzll(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int ctz32(unsigned int a)
|
||||||
|
{
|
||||||
|
return __builtin_ctz(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WARNING: undefined if a = 0 */
|
||||||
|
static inline int ctz64(uint64_t a)
|
||||||
|
{
|
||||||
|
return __builtin_ctzll(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct __attribute__((packed)) packed_u64 {
|
||||||
|
uint64_t v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((packed)) packed_u32 {
|
||||||
|
uint32_t v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((packed)) packed_u16 {
|
||||||
|
uint16_t v;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint64_t get_u64(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return ((const struct packed_u64 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t get_i64(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int64_t)((const struct packed_u64 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u64(uint8_t *tab, uint64_t val)
|
||||||
|
{
|
||||||
|
((struct packed_u64 *)tab)->v = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_u32(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return ((const struct packed_u32 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t get_i32(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int32_t)((const struct packed_u32 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u32(uint8_t *tab, uint32_t val)
|
||||||
|
{
|
||||||
|
((struct packed_u32 *)tab)->v = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_u16(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return ((const struct packed_u16 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t get_i16(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int16_t)((const struct packed_u16 *)tab)->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u16(uint8_t *tab, uint16_t val)
|
||||||
|
{
|
||||||
|
((struct packed_u16 *)tab)->v = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_u8(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return *tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t get_i8(const uint8_t *tab)
|
||||||
|
{
|
||||||
|
return (int8_t)*tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void put_u8(uint8_t *tab, uint8_t val)
|
||||||
|
{
|
||||||
|
*tab = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t bswap16(uint16_t x)
|
||||||
|
{
|
||||||
|
return (x >> 8) | (x << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t bswap32(uint32_t v)
|
||||||
|
{
|
||||||
|
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
|
||||||
|
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t bswap64(uint64_t v)
|
||||||
|
{
|
||||||
|
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
|
||||||
|
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX: should take an extra argument to pass slack information to the caller */
|
||||||
|
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
|
typedef struct DynBuf {
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t size;
|
||||||
|
size_t allocated_size;
|
||||||
|
BOOL error; /* true if a memory allocation error occurred */
|
||||||
|
DynBufReallocFunc *realloc_func;
|
||||||
|
void *opaque; /* for realloc_func */
|
||||||
|
} DynBuf;
|
||||||
|
|
||||||
|
void dbuf_init(DynBuf *s);
|
||||||
|
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
||||||
|
int dbuf_realloc(DynBuf *s, size_t new_size);
|
||||||
|
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
|
||||||
|
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
|
||||||
|
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
|
||||||
|
int dbuf_putc(DynBuf *s, uint8_t c);
|
||||||
|
int dbuf_putstr(DynBuf *s, const char *str);
|
||||||
|
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (uint8_t *)&val, 2);
|
||||||
|
}
|
||||||
|
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (uint8_t *)&val, 4);
|
||||||
|
}
|
||||||
|
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
|
||||||
|
{
|
||||||
|
return dbuf_put(s, (uint8_t *)&val, 8);
|
||||||
|
}
|
||||||
|
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
|
||||||
|
const char *fmt, ...);
|
||||||
|
void dbuf_free(DynBuf *s);
|
||||||
|
static inline BOOL dbuf_error(DynBuf *s) {
|
||||||
|
return s->error;
|
||||||
|
}
|
||||||
|
static inline void dbuf_set_error(DynBuf *s)
|
||||||
|
{
|
||||||
|
s->error = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UTF8_CHAR_LEN_MAX 6
|
||||||
|
|
||||||
|
int unicode_to_utf8(uint8_t *buf, unsigned int c);
|
||||||
|
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
|
||||||
|
|
||||||
|
static inline int from_hex(int c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
return c - 'A' + 10;
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rqsort(void *base, size_t nmemb, size_t size,
|
||||||
|
int (*cmp)(const void *, const void *, void *),
|
||||||
|
void *arg);
|
||||||
|
|
||||||
|
#endif /* CUTILS_H */
|
||||||
918
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/jscompress.c
vendored
Normal file
918
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/jscompress.c
vendored
Normal file
@@ -0,0 +1,918 @@
|
|||||||
|
/*
|
||||||
|
* Javascript Compressor
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
|
||||||
|
typedef struct JSToken {
|
||||||
|
int tok;
|
||||||
|
char buf[20];
|
||||||
|
char *str;
|
||||||
|
int len;
|
||||||
|
int size;
|
||||||
|
int line_num; /* line number for start of token */
|
||||||
|
int lines; /* number of embedded linefeeds in token */
|
||||||
|
} JSToken;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TOK_EOF = 256,
|
||||||
|
TOK_IDENT,
|
||||||
|
TOK_STR1,
|
||||||
|
TOK_STR2,
|
||||||
|
TOK_STR3,
|
||||||
|
TOK_NUM,
|
||||||
|
TOK_COM,
|
||||||
|
TOK_LCOM,
|
||||||
|
};
|
||||||
|
|
||||||
|
void tok_reset(JSToken *tt)
|
||||||
|
{
|
||||||
|
if (tt->str != tt->buf) {
|
||||||
|
free(tt->str);
|
||||||
|
tt->str = tt->buf;
|
||||||
|
tt->size = sizeof(tt->buf);
|
||||||
|
}
|
||||||
|
tt->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tok_add_ch(JSToken *tt, int c)
|
||||||
|
{
|
||||||
|
if (tt->len + 1 > tt->size) {
|
||||||
|
tt->size *= 2;
|
||||||
|
if (tt->str == tt->buf) {
|
||||||
|
tt->str = malloc(tt->size);
|
||||||
|
memcpy(tt->str, tt->buf, tt->len);
|
||||||
|
} else {
|
||||||
|
tt->str = realloc(tt->str, tt->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tt->str[tt->len++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *infile;
|
||||||
|
const char *filename;
|
||||||
|
int output_line_num;
|
||||||
|
int line_num;
|
||||||
|
int ch;
|
||||||
|
JSToken tokc;
|
||||||
|
|
||||||
|
int skip_mask;
|
||||||
|
#define DEFINE_MAX 20
|
||||||
|
char *define_tab[DEFINE_MAX];
|
||||||
|
int define_len;
|
||||||
|
|
||||||
|
void error(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (filename) {
|
||||||
|
fprintf(stderr, "%s:%d: ", filename, line_num);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "jscompress: ");
|
||||||
|
}
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void define_symbol(const char *def)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < define_len; i++) {
|
||||||
|
if (!strcmp(tokc.str, define_tab[i]))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (define_len >= DEFINE_MAX)
|
||||||
|
error("too many defines");
|
||||||
|
define_tab[define_len++] = strdup(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefine_symbol(const char *def)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = j = 0; i < define_len; i++) {
|
||||||
|
if (!strcmp(tokc.str, define_tab[i])) {
|
||||||
|
free(define_tab[i]);
|
||||||
|
} else {
|
||||||
|
define_tab[j++] = define_tab[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
define_len = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *find_symbol(const char *def)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < define_len; i++) {
|
||||||
|
if (!strcmp(tokc.str, define_tab[i]))
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next(void);
|
||||||
|
|
||||||
|
void nextch(void)
|
||||||
|
{
|
||||||
|
ch = fgetc(infile);
|
||||||
|
if (ch == '\n')
|
||||||
|
line_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skip_blanks(void)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
next();
|
||||||
|
if (tokc.tok != ' ' && tokc.tok != '\t' &&
|
||||||
|
tokc.tok != TOK_COM && tokc.tok != TOK_LCOM)
|
||||||
|
return tokc.tok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_directive(void)
|
||||||
|
{
|
||||||
|
int ifdef, mask = skip_mask;
|
||||||
|
/* simplistic preprocessor:
|
||||||
|
#define / #undef / #ifdef / #ifndef / #else / #endif
|
||||||
|
no symbol substitution.
|
||||||
|
*/
|
||||||
|
skip_mask = 0; /* disable skipping to parse preprocessor line */
|
||||||
|
nextch();
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected preprocessing directive after #");
|
||||||
|
|
||||||
|
if (!strcmp(tokc.str, "define")) {
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected identifier after #define");
|
||||||
|
define_symbol(tokc.str);
|
||||||
|
} else if (!strcmp(tokc.str, "undef")) {
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected identifier after #undef");
|
||||||
|
undefine_symbol(tokc.str);
|
||||||
|
} else if ((ifdef = 1, !strcmp(tokc.str, "ifdef")) ||
|
||||||
|
(ifdef = 0, !strcmp(tokc.str, "ifndef"))) {
|
||||||
|
if (skip_blanks() != TOK_IDENT)
|
||||||
|
error("expected identifier after #ifdef/#ifndef");
|
||||||
|
mask = (mask << 2) | 2 | ifdef;
|
||||||
|
if (find_symbol(tokc.str))
|
||||||
|
mask ^= 1;
|
||||||
|
} else if (!strcmp(tokc.str, "else")) {
|
||||||
|
if (!(mask & 2))
|
||||||
|
error("#else without a #if");
|
||||||
|
mask ^= 1;
|
||||||
|
} else if (!strcmp(tokc.str, "endif")) {
|
||||||
|
if (!(mask & 2))
|
||||||
|
error("#endif without a #if");
|
||||||
|
mask >>= 2;
|
||||||
|
} else {
|
||||||
|
error("unsupported preprocessing directive");
|
||||||
|
}
|
||||||
|
if (skip_blanks() != '\n')
|
||||||
|
error("extra characters on preprocessing line");
|
||||||
|
skip_mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return -1 if invalid char */
|
||||||
|
static int hex_to_num(int ch)
|
||||||
|
{
|
||||||
|
if (ch >= 'a' && ch <= 'f')
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
else if (ch >= 'A' && ch <= 'F')
|
||||||
|
return ch - 'A' + 10;
|
||||||
|
else if (ch >= '0' && ch <= '9')
|
||||||
|
return ch - '0';
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next(void)
|
||||||
|
{
|
||||||
|
again:
|
||||||
|
tok_reset(&tokc);
|
||||||
|
tokc.line_num = line_num;
|
||||||
|
tokc.lines = 0;
|
||||||
|
switch(ch) {
|
||||||
|
case EOF:
|
||||||
|
tokc.tok = TOK_EOF;
|
||||||
|
if (skip_mask)
|
||||||
|
error("missing #endif");
|
||||||
|
break;
|
||||||
|
case 'a' ... 'z':
|
||||||
|
case 'A' ... 'Z':
|
||||||
|
case '_':
|
||||||
|
case '$':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
while ((ch >= 'a' && ch <= 'z') ||
|
||||||
|
(ch >= 'A' && ch <= 'Z') ||
|
||||||
|
(ch >= '0' && ch <= '9') ||
|
||||||
|
(ch == '_' || ch == '$')) {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_IDENT;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
nextch();
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, '.');
|
||||||
|
goto has_dot;
|
||||||
|
}
|
||||||
|
tokc.tok = '.';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
if (ch == 'x' || ch == 'X') {
|
||||||
|
/* hexa */
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
while ((ch >= 'a' && ch <= 'f') ||
|
||||||
|
(ch >= 'A' && ch <= 'F') ||
|
||||||
|
(ch >= '0' && ch <= '9')) {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_NUM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto has_digit;
|
||||||
|
|
||||||
|
case '1' ... '9':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
has_digit:
|
||||||
|
/* decimal */
|
||||||
|
while (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
if (ch == '.') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
has_dot:
|
||||||
|
while (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch == 'e' || ch == 'E') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
if (ch == '+' || ch == '-') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
while (ch >= '0' && ch <= '9') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_NUM;
|
||||||
|
break;
|
||||||
|
case '`':
|
||||||
|
{
|
||||||
|
nextch();
|
||||||
|
while (ch != '`' && ch != EOF) {
|
||||||
|
if (ch == '\\') {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
if (ch == EOF) {
|
||||||
|
error("unexpected char after '\\'");
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
} else {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextch();
|
||||||
|
tok_add_ch(&tokc, 0);
|
||||||
|
tokc.tok = TOK_STR3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
{
|
||||||
|
int n, i, c, hex_digit_count;
|
||||||
|
int quote_ch;
|
||||||
|
quote_ch = ch;
|
||||||
|
nextch();
|
||||||
|
while (ch != quote_ch && ch != EOF) {
|
||||||
|
if (ch == '\\') {
|
||||||
|
nextch();
|
||||||
|
switch(ch) {
|
||||||
|
case 'n':
|
||||||
|
tok_add_ch(&tokc, '\n');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
tok_add_ch(&tokc, '\r');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
tok_add_ch(&tokc, '\t');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
tok_add_ch(&tokc, '\v');
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
case '\\':
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
case '0' ... '7':
|
||||||
|
n = 0;
|
||||||
|
while (ch >= '0' && ch <= '7') {
|
||||||
|
n = n * 8 + (ch - '0');
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, n);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'u':
|
||||||
|
if (ch == 'x')
|
||||||
|
hex_digit_count = 2;
|
||||||
|
else
|
||||||
|
hex_digit_count = 4;
|
||||||
|
nextch();
|
||||||
|
n = 0;
|
||||||
|
for(i = 0; i < hex_digit_count; i++) {
|
||||||
|
c = hex_to_num(ch);
|
||||||
|
if (c < 0)
|
||||||
|
error("unexpected char after '\\x'");
|
||||||
|
n = n * 16 + c;
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
if (n >= 256)
|
||||||
|
error("unicode is currently unsupported");
|
||||||
|
tok_add_ch(&tokc, n);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error("unexpected char after '\\'");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* XXX: should refuse embedded newlines */
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextch();
|
||||||
|
tok_add_ch(&tokc, 0);
|
||||||
|
if (quote_ch == '\'')
|
||||||
|
tokc.tok = TOK_STR1;
|
||||||
|
else
|
||||||
|
tokc.tok = TOK_STR2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
nextch();
|
||||||
|
if (ch == '/') {
|
||||||
|
tok_add_ch(&tokc, '/');
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
while (ch != '\n' && ch != EOF) {
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
nextch();
|
||||||
|
}
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_LCOM;
|
||||||
|
} else if (ch == '*') {
|
||||||
|
int last;
|
||||||
|
tok_add_ch(&tokc, '/');
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
last = 0;
|
||||||
|
for(;;) {
|
||||||
|
nextch();
|
||||||
|
if (ch == EOF)
|
||||||
|
error("unterminated comment");
|
||||||
|
if (ch == '\n')
|
||||||
|
tokc.lines++;
|
||||||
|
tok_add_ch(&tokc, ch);
|
||||||
|
if (last == '*' && ch == '/')
|
||||||
|
break;
|
||||||
|
last = ch;
|
||||||
|
}
|
||||||
|
nextch();
|
||||||
|
tok_add_ch(&tokc, '\0');
|
||||||
|
tokc.tok = TOK_COM;
|
||||||
|
} else {
|
||||||
|
tokc.tok = '/';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
parse_directive();
|
||||||
|
goto again;
|
||||||
|
case '\n':
|
||||||
|
/* adjust line number */
|
||||||
|
tokc.line_num--;
|
||||||
|
tokc.lines++;
|
||||||
|
/* fall thru */
|
||||||
|
default:
|
||||||
|
tokc.tok = ch;
|
||||||
|
nextch();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (skip_mask & 1)
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_tok(FILE *f, JSToken *tt)
|
||||||
|
{
|
||||||
|
/* keep output lines in sync with input lines */
|
||||||
|
while (output_line_num < tt->line_num) {
|
||||||
|
putc('\n', f);
|
||||||
|
output_line_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(tt->tok) {
|
||||||
|
case TOK_IDENT:
|
||||||
|
case TOK_COM:
|
||||||
|
case TOK_LCOM:
|
||||||
|
fprintf(f, "%s", tt->str);
|
||||||
|
break;
|
||||||
|
case TOK_NUM:
|
||||||
|
{
|
||||||
|
unsigned long a;
|
||||||
|
char *p;
|
||||||
|
a = strtoul(tt->str, &p, 0);
|
||||||
|
if (*p == '\0' && a <= 0x7fffffff) {
|
||||||
|
/* must be an integer */
|
||||||
|
fprintf(f, "%d", (int)a);
|
||||||
|
} else {
|
||||||
|
fprintf(f, "%s", tt->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOK_STR3:
|
||||||
|
fprintf(f, "`%s`", tt->str);
|
||||||
|
break;
|
||||||
|
case TOK_STR1:
|
||||||
|
case TOK_STR2:
|
||||||
|
{
|
||||||
|
int i, c, quote_ch;
|
||||||
|
if (tt->tok == TOK_STR1)
|
||||||
|
quote_ch = '\'';
|
||||||
|
else
|
||||||
|
quote_ch = '\"';
|
||||||
|
fprintf(f, "%c", quote_ch);
|
||||||
|
for(i = 0; i < tt->len - 1; i++) {
|
||||||
|
c = (uint8_t)tt->str[i];
|
||||||
|
switch(c) {
|
||||||
|
case '\r':
|
||||||
|
fprintf(f, "\\r");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
fprintf(f, "\\n");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
fprintf(f, "\\t");
|
||||||
|
break;
|
||||||
|
case '\v':
|
||||||
|
fprintf(f, "\\v");
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
if (c == quote_ch)
|
||||||
|
fprintf(f, "\\%c", c);
|
||||||
|
else
|
||||||
|
fprintf(f, "%c", c);
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
fprintf(f, "\\\\");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* XXX: no utf-8 support! */
|
||||||
|
if (c >= 32 && c <= 255) {
|
||||||
|
fprintf(f, "%c", c);
|
||||||
|
} else if (c <= 255)
|
||||||
|
fprintf(f, "\\x%02x", c);
|
||||||
|
else
|
||||||
|
fprintf(f, "\\u%04x", c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f, "%c", quote_ch);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (tokc.tok >= 256)
|
||||||
|
error("unsupported token in print_tok: %d", tt->tok);
|
||||||
|
fprintf(f, "%c", tt->tok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output_line_num += tt->lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if token pasting could occur */
|
||||||
|
static BOOL compat_token(int c1, int c2)
|
||||||
|
{
|
||||||
|
if ((c1 == TOK_IDENT || c1 == TOK_NUM) &&
|
||||||
|
(c2 == TOK_IDENT || c2 == TOK_NUM))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ((c1 == c2 && strchr("+-<>&|=*/.", c1))
|
||||||
|
|| (c2 == '=' && strchr("+-<>&|!*/^%", c1))
|
||||||
|
|| (c1 == '=' && c2 == '>')
|
||||||
|
|| (c1 == '/' && c2 == '*')
|
||||||
|
|| (c1 == '.' && c2 == TOK_NUM)
|
||||||
|
|| (c1 == TOK_NUM && c2 == '.'))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void js_compress(const char *filename, const char *outfilename,
|
||||||
|
BOOL do_strip, BOOL keep_header)
|
||||||
|
{
|
||||||
|
FILE *outfile;
|
||||||
|
int ltok, seen_space;
|
||||||
|
|
||||||
|
line_num = 1;
|
||||||
|
infile = fopen(filename, "rb");
|
||||||
|
if (!infile) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_line_num = 1;
|
||||||
|
outfile = fopen(outfilename, "wb");
|
||||||
|
if (!outfile) {
|
||||||
|
perror(outfilename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nextch();
|
||||||
|
next();
|
||||||
|
ltok = 0;
|
||||||
|
seen_space = 0;
|
||||||
|
if (do_strip) {
|
||||||
|
if (keep_header) {
|
||||||
|
while (tokc.tok == ' ' ||
|
||||||
|
tokc.tok == '\n' ||
|
||||||
|
tokc.tok == '\t' ||
|
||||||
|
tokc.tok == '\v' ||
|
||||||
|
tokc.tok == '\b' ||
|
||||||
|
tokc.tok == '\f') {
|
||||||
|
seen_space = 1;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
if (tokc.tok == TOK_COM) {
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
//fprintf(outfile, "\n");
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if (tokc.tok == TOK_EOF)
|
||||||
|
break;
|
||||||
|
if (tokc.tok == ' ' ||
|
||||||
|
tokc.tok == '\r' ||
|
||||||
|
tokc.tok == '\t' ||
|
||||||
|
tokc.tok == '\v' ||
|
||||||
|
tokc.tok == '\b' ||
|
||||||
|
tokc.tok == '\f' ||
|
||||||
|
tokc.tok == TOK_LCOM ||
|
||||||
|
tokc.tok == TOK_COM) {
|
||||||
|
/* don't print spaces or comments */
|
||||||
|
seen_space = 1;
|
||||||
|
} else if (tokc.tok == TOK_STR3) {
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
} else if (tokc.tok == TOK_STR1 || tokc.tok == TOK_STR2) {
|
||||||
|
int count, i;
|
||||||
|
/* find the optimal quote char */
|
||||||
|
count = 0;
|
||||||
|
for(i = 0; i < tokc.len; i++) {
|
||||||
|
if (tokc.str[i] == '\'')
|
||||||
|
count++;
|
||||||
|
else if (tokc.str[i] == '\"')
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
tokc.tok = TOK_STR2;
|
||||||
|
else if (count < 0)
|
||||||
|
tokc.tok = TOK_STR1;
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
} else {
|
||||||
|
if (seen_space && !compat_token(ltok, tokc.tok)) {
|
||||||
|
fprintf(outfile, " ");
|
||||||
|
}
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
ltok = tokc.tok;
|
||||||
|
seen_space = 0;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* just handle preprocessing */
|
||||||
|
while (tokc.tok != TOK_EOF) {
|
||||||
|
print_tok(outfile, &tokc);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(outfile);
|
||||||
|
fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HASH_SIZE 30011
|
||||||
|
#define MATCH_LEN_MIN 3
|
||||||
|
#define MATCH_LEN_MAX (4 + 63)
|
||||||
|
#define DIST_MAX 65535
|
||||||
|
|
||||||
|
static int find_longest_match(int *pdist, const uint8_t *src, int src_len,
|
||||||
|
const int *hash_next, int cur_pos)
|
||||||
|
{
|
||||||
|
int pos, i, match_len, match_pos, pos_min, len_max;
|
||||||
|
|
||||||
|
len_max = min_int(src_len - cur_pos, MATCH_LEN_MAX);
|
||||||
|
match_len = 0;
|
||||||
|
match_pos = 0;
|
||||||
|
pos_min = max_int(cur_pos - DIST_MAX - 1, 0);
|
||||||
|
pos = hash_next[cur_pos];
|
||||||
|
while (pos >= pos_min) {
|
||||||
|
for(i = 0; i < len_max; i++) {
|
||||||
|
if (src[cur_pos + i] != src[pos + i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i > match_len) {
|
||||||
|
match_len = i;
|
||||||
|
match_pos = pos;
|
||||||
|
}
|
||||||
|
pos = hash_next[pos];
|
||||||
|
}
|
||||||
|
*pdist = cur_pos - match_pos - 1;
|
||||||
|
return match_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lz_compress(uint8_t **pdst, const uint8_t *src, int src_len)
|
||||||
|
{
|
||||||
|
int *hash_table, *hash_next;
|
||||||
|
uint32_t h, v;
|
||||||
|
int i, dist, len, len1, dist1;
|
||||||
|
uint8_t *dst, *q;
|
||||||
|
|
||||||
|
/* build the hash table */
|
||||||
|
|
||||||
|
hash_table = malloc(sizeof(hash_table[0]) * HASH_SIZE);
|
||||||
|
for(i = 0; i < HASH_SIZE; i++)
|
||||||
|
hash_table[i] = -1;
|
||||||
|
hash_next = malloc(sizeof(hash_next[0]) * src_len);
|
||||||
|
for(i = 0; i < src_len; i++)
|
||||||
|
hash_next[i] = -1;
|
||||||
|
|
||||||
|
for(i = 0; i < src_len - MATCH_LEN_MIN + 1; i++) {
|
||||||
|
h = ((src[i] << 16) | (src[i + 1] << 8) | src[i + 2]) % HASH_SIZE;
|
||||||
|
hash_next[i] = hash_table[h];
|
||||||
|
hash_table[h] = i;
|
||||||
|
}
|
||||||
|
for(;i < src_len; i++) {
|
||||||
|
hash_next[i] = -1;
|
||||||
|
}
|
||||||
|
free(hash_table);
|
||||||
|
|
||||||
|
dst = malloc(src_len + 4); /* never larger than the source */
|
||||||
|
q = dst;
|
||||||
|
*q++ = src_len >> 24;
|
||||||
|
*q++ = src_len >> 16;
|
||||||
|
*q++ = src_len >> 8;
|
||||||
|
*q++ = src_len >> 0;
|
||||||
|
/* compress */
|
||||||
|
i = 0;
|
||||||
|
while (i < src_len) {
|
||||||
|
if (src[i] >= 128)
|
||||||
|
return -1;
|
||||||
|
len = find_longest_match(&dist, src, src_len, hash_next, i);
|
||||||
|
if (len >= MATCH_LEN_MIN) {
|
||||||
|
/* heuristic: see if better length just after */
|
||||||
|
len1 = find_longest_match(&dist1, src, src_len, hash_next, i + 1);
|
||||||
|
if (len1 > len)
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
if (len < MATCH_LEN_MIN) {
|
||||||
|
no_match:
|
||||||
|
*q++ = src[i];
|
||||||
|
i++;
|
||||||
|
} else if (len <= (3 + 15) && dist < (1 << 10)) {
|
||||||
|
v = 0x8000 | ((len - 3) << 10) | dist;
|
||||||
|
*q++ = v >> 8;
|
||||||
|
*q++ = v;
|
||||||
|
i += len;
|
||||||
|
} else if (len >= 4 && len <= (4 + 63) && dist < (1 << 16)) {
|
||||||
|
v = 0xc00000 | ((len - 4) << 16) | dist;
|
||||||
|
*q++ = v >> 16;
|
||||||
|
*q++ = v >> 8;
|
||||||
|
*q++ = v;
|
||||||
|
i += len;
|
||||||
|
} else {
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(hash_next);
|
||||||
|
*pdst = dst;
|
||||||
|
return q - dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_file(uint8_t **pbuf, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
uint8_t *buf;
|
||||||
|
int buf_len;
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
buf_len = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
buf = malloc(buf_len + 1);
|
||||||
|
fread(buf, 1, buf_len, f);
|
||||||
|
buf[buf_len] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
*pbuf = buf;
|
||||||
|
return buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_file(const char *filename, const uint8_t *buf, int buf_len)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fwrite(buf, 1, buf_len, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_c_source(const char *filename, const uint8_t *buf, int buf_len,
|
||||||
|
const char *var_name)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fprintf(f, "/* This file is automatically generated - do not edit */\n\n");
|
||||||
|
fprintf(f, "const uint8_t %s[] = {\n", var_name);
|
||||||
|
for(i = 0; i < buf_len; i++) {
|
||||||
|
fprintf(f, " 0x%02x,", buf[i]);
|
||||||
|
if ((i % 8) == 7 || (i == buf_len - 1))
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
fprintf(f, "};\n");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFAULT_OUTPUT_FILENAME "out.js"
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
printf("jscompress version 1.0 Copyright (c) 2008-2018 Fabrice Bellard\n"
|
||||||
|
"usage: jscompress [options] filename\n"
|
||||||
|
"Javascript compressor\n"
|
||||||
|
"\n"
|
||||||
|
"-h print this help\n"
|
||||||
|
"-n do not compress spaces\n"
|
||||||
|
"-H keep the first comment\n"
|
||||||
|
"-c compress to file\n"
|
||||||
|
"-C name compress to C source ('name' is the variable name)\n"
|
||||||
|
"-D symbol define preprocessor symbol\n"
|
||||||
|
"-U symbol undefine preprocessor symbol\n"
|
||||||
|
"-o outfile set the output filename (default=%s)\n",
|
||||||
|
DEFAULT_OUTPUT_FILENAME);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c, do_strip, keep_header, compress;
|
||||||
|
const char *out_filename, *c_var, *fname;
|
||||||
|
char tmpfilename[1024];
|
||||||
|
|
||||||
|
do_strip = 1;
|
||||||
|
keep_header = 0;
|
||||||
|
out_filename = DEFAULT_OUTPUT_FILENAME;
|
||||||
|
compress = 0;
|
||||||
|
c_var = NULL;
|
||||||
|
for(;;) {
|
||||||
|
c = getopt(argc, argv, "hno:HcC:D:U:");
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
switch(c) {
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
do_strip = 0;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
out_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
keep_header = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
compress = 1;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
c_var = optarg;
|
||||||
|
compress = 1;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
define_symbol(optarg);
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
undefine_symbol(optarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optind >= argc)
|
||||||
|
help();
|
||||||
|
|
||||||
|
filename = argv[optind++];
|
||||||
|
|
||||||
|
if (compress) {
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
/* XXX: use another directory ? */
|
||||||
|
snprintf(tmpfilename, sizeof(tmpfilename), "out.%d", getpid());
|
||||||
|
#else
|
||||||
|
snprintf(tmpfilename, sizeof(tmpfilename), "/tmp/out.%d", getpid());
|
||||||
|
#endif
|
||||||
|
fname = tmpfilename;
|
||||||
|
} else {
|
||||||
|
fname = out_filename;
|
||||||
|
}
|
||||||
|
js_compress(filename, fname, do_strip, keep_header);
|
||||||
|
|
||||||
|
if (compress) {
|
||||||
|
uint8_t *buf1, *buf2;
|
||||||
|
int buf1_len, buf2_len;
|
||||||
|
|
||||||
|
buf1_len = load_file(&buf1, fname);
|
||||||
|
unlink(fname);
|
||||||
|
buf2_len = lz_compress(&buf2, buf1, buf1_len);
|
||||||
|
if (buf2_len < 0) {
|
||||||
|
fprintf(stderr, "Could not compress file (UTF8 chars are forbidden)\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c_var) {
|
||||||
|
save_c_source(out_filename, buf2, buf2_len, c_var);
|
||||||
|
} else {
|
||||||
|
save_file(out_filename, buf2, buf2_len);
|
||||||
|
}
|
||||||
|
free(buf1);
|
||||||
|
free(buf2);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8466
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libbf.c
vendored
Normal file
8466
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libbf.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
535
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libbf.h
vendored
Normal file
535
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libbf.h
vendored
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
/*
|
||||||
|
* Tiny arbitrary precision floating point library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2020 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBBF_H
|
||||||
|
#define LIBBF_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define LIMB_LOG2_BITS 6
|
||||||
|
#else
|
||||||
|
#define LIMB_LOG2_BITS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
|
||||||
|
|
||||||
|
#if LIMB_BITS == 64
|
||||||
|
typedef __int128 int128_t;
|
||||||
|
typedef unsigned __int128 uint128_t;
|
||||||
|
typedef int64_t slimb_t;
|
||||||
|
typedef uint64_t limb_t;
|
||||||
|
typedef uint128_t dlimb_t;
|
||||||
|
#define BF_RAW_EXP_MIN INT64_MIN
|
||||||
|
#define BF_RAW_EXP_MAX INT64_MAX
|
||||||
|
|
||||||
|
#define LIMB_DIGITS 19
|
||||||
|
#define BF_DEC_BASE UINT64_C(10000000000000000000)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef int32_t slimb_t;
|
||||||
|
typedef uint32_t limb_t;
|
||||||
|
typedef uint64_t dlimb_t;
|
||||||
|
#define BF_RAW_EXP_MIN INT32_MIN
|
||||||
|
#define BF_RAW_EXP_MAX INT32_MAX
|
||||||
|
|
||||||
|
#define LIMB_DIGITS 9
|
||||||
|
#define BF_DEC_BASE 1000000000U
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* in bits */
|
||||||
|
/* minimum number of bits for the exponent */
|
||||||
|
#define BF_EXP_BITS_MIN 3
|
||||||
|
/* maximum number of bits for the exponent */
|
||||||
|
#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
|
||||||
|
/* extended range for exponent, used internally */
|
||||||
|
#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
|
||||||
|
/* minimum possible precision */
|
||||||
|
#define BF_PREC_MIN 2
|
||||||
|
/* minimum possible precision */
|
||||||
|
#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
|
||||||
|
/* some operations support infinite precision */
|
||||||
|
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
|
||||||
|
|
||||||
|
#if LIMB_BITS == 64
|
||||||
|
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
|
||||||
|
#else
|
||||||
|
#define BF_CHKSUM_MOD 975620677U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BF_EXP_ZERO BF_RAW_EXP_MIN
|
||||||
|
#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
|
||||||
|
#define BF_EXP_NAN BF_RAW_EXP_MAX
|
||||||
|
|
||||||
|
/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
|
||||||
|
+/-infinity is represented with expn = BF_EXP_INF and len = 0,
|
||||||
|
NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
struct bf_context_t *ctx;
|
||||||
|
int sign;
|
||||||
|
slimb_t expn;
|
||||||
|
limb_t len;
|
||||||
|
limb_t *tab;
|
||||||
|
} bf_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* must be kept identical to bf_t */
|
||||||
|
struct bf_context_t *ctx;
|
||||||
|
int sign;
|
||||||
|
slimb_t expn;
|
||||||
|
limb_t len;
|
||||||
|
limb_t *tab;
|
||||||
|
} bfdec_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BF_RNDN, /* round to nearest, ties to even */
|
||||||
|
BF_RNDZ, /* round to zero */
|
||||||
|
BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
|
||||||
|
BF_RNDU, /* round to +inf */
|
||||||
|
BF_RNDNA, /* round to nearest, ties away from zero */
|
||||||
|
BF_RNDA, /* round away from zero */
|
||||||
|
BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
|
||||||
|
inexact flag is always set) */
|
||||||
|
} bf_rnd_t;
|
||||||
|
|
||||||
|
/* allow subnormal numbers. Only available if the number of exponent
|
||||||
|
bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
|
||||||
|
#define BF_FLAG_SUBNORMAL (1 << 3)
|
||||||
|
/* 'prec' is the precision after the radix point instead of the whole
|
||||||
|
mantissa. Can only be used with bf_round() and
|
||||||
|
bfdec_[add|sub|mul|div|sqrt|round](). */
|
||||||
|
#define BF_FLAG_RADPNT_PREC (1 << 4)
|
||||||
|
|
||||||
|
#define BF_RND_MASK 0x7
|
||||||
|
#define BF_EXP_BITS_SHIFT 5
|
||||||
|
#define BF_EXP_BITS_MASK 0x3f
|
||||||
|
|
||||||
|
/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
|
||||||
|
#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
|
||||||
|
|
||||||
|
/* contains the rounding mode and number of exponents bits */
|
||||||
|
typedef uint32_t bf_flags_t;
|
||||||
|
|
||||||
|
typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bf_t val;
|
||||||
|
limb_t prec;
|
||||||
|
} BFConstCache;
|
||||||
|
|
||||||
|
typedef struct bf_context_t {
|
||||||
|
void *realloc_opaque;
|
||||||
|
bf_realloc_func_t *realloc_func;
|
||||||
|
BFConstCache log2_cache;
|
||||||
|
BFConstCache pi_cache;
|
||||||
|
struct BFNTTState *ntt_state;
|
||||||
|
} bf_context_t;
|
||||||
|
|
||||||
|
static inline int bf_get_exp_bits(bf_flags_t flags)
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
|
||||||
|
if (e == BF_EXP_BITS_MASK)
|
||||||
|
return BF_EXP_BITS_MAX + 1;
|
||||||
|
else
|
||||||
|
return BF_EXP_BITS_MAX - e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bf_flags_t bf_set_exp_bits(int n)
|
||||||
|
{
|
||||||
|
return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returned status */
|
||||||
|
#define BF_ST_INVALID_OP (1 << 0)
|
||||||
|
#define BF_ST_DIVIDE_ZERO (1 << 1)
|
||||||
|
#define BF_ST_OVERFLOW (1 << 2)
|
||||||
|
#define BF_ST_UNDERFLOW (1 << 3)
|
||||||
|
#define BF_ST_INEXACT (1 << 4)
|
||||||
|
/* indicate that a memory allocation error occured. NaN is returned */
|
||||||
|
#define BF_ST_MEM_ERROR (1 << 5)
|
||||||
|
|
||||||
|
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
|
||||||
|
|
||||||
|
static inline slimb_t bf_max(slimb_t a, slimb_t b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline slimb_t bf_min(slimb_t a, slimb_t b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
|
||||||
|
void *realloc_opaque);
|
||||||
|
void bf_context_end(bf_context_t *s);
|
||||||
|
/* free memory allocated for the bf cache data */
|
||||||
|
void bf_clear_cache(bf_context_t *s);
|
||||||
|
|
||||||
|
static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
return s->realloc_func(s->realloc_opaque, ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'size' must be != 0 */
|
||||||
|
static inline void *bf_malloc(bf_context_t *s, size_t size)
|
||||||
|
{
|
||||||
|
return bf_realloc(s, NULL, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bf_free(bf_context_t *s, void *ptr)
|
||||||
|
{
|
||||||
|
/* must test ptr otherwise equivalent to malloc(0) */
|
||||||
|
if (ptr)
|
||||||
|
bf_realloc(s, ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bf_init(bf_context_t *s, bf_t *r);
|
||||||
|
|
||||||
|
static inline void bf_delete(bf_t *r)
|
||||||
|
{
|
||||||
|
bf_context_t *s = r->ctx;
|
||||||
|
/* we accept to delete a zeroed bf_t structure */
|
||||||
|
if (s && r->tab) {
|
||||||
|
bf_realloc(s, r->tab, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bf_neg(bf_t *r)
|
||||||
|
{
|
||||||
|
r->sign ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_is_finite(const bf_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn < BF_EXP_INF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_is_nan(const bf_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn == BF_EXP_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_is_zero(const bf_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn == BF_EXP_ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bf_memcpy(bf_t *r, const bf_t *a)
|
||||||
|
{
|
||||||
|
*r = *a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bf_set_ui(bf_t *r, uint64_t a);
|
||||||
|
int bf_set_si(bf_t *r, int64_t a);
|
||||||
|
void bf_set_nan(bf_t *r);
|
||||||
|
void bf_set_zero(bf_t *r, int is_neg);
|
||||||
|
void bf_set_inf(bf_t *r, int is_neg);
|
||||||
|
int bf_set(bf_t *r, const bf_t *a);
|
||||||
|
void bf_move(bf_t *r, bf_t *a);
|
||||||
|
int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
|
||||||
|
int bf_set_float64(bf_t *a, double d);
|
||||||
|
|
||||||
|
int bf_cmpu(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_cmp_full(const bf_t *a, const bf_t *b);
|
||||||
|
int bf_cmp(const bf_t *a, const bf_t *b);
|
||||||
|
static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
|
||||||
|
{
|
||||||
|
return bf_cmp(a, b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
|
||||||
|
{
|
||||||
|
return bf_cmp(a, b) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
|
||||||
|
{
|
||||||
|
return bf_cmp(a, b) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
|
||||||
|
#define BF_DIVREM_EUCLIDIAN BF_RNDF
|
||||||
|
int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
|
||||||
|
limb_t prec, bf_flags_t flags, int rnd_mode);
|
||||||
|
int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags, int rnd_mode);
|
||||||
|
int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags, int rnd_mode);
|
||||||
|
/* round to integer with infinite precision */
|
||||||
|
int bf_rint(bf_t *r, int rnd_mode);
|
||||||
|
int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
|
||||||
|
int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
slimb_t bf_get_exp_min(const bf_t *a);
|
||||||
|
int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
|
||||||
|
int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
|
||||||
|
int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
|
||||||
|
|
||||||
|
/* additional flags for bf_atof */
|
||||||
|
/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
|
||||||
|
#define BF_ATOF_NO_HEX (1 << 16)
|
||||||
|
/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
|
||||||
|
#define BF_ATOF_BIN_OCT (1 << 17)
|
||||||
|
/* Do not parse NaN or Inf */
|
||||||
|
#define BF_ATOF_NO_NAN_INF (1 << 18)
|
||||||
|
/* return the exponent separately */
|
||||||
|
#define BF_ATOF_EXPONENT (1 << 19)
|
||||||
|
|
||||||
|
int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
/* this version accepts prec = BF_PREC_INF and returns the radix
|
||||||
|
exponent */
|
||||||
|
int bf_atof2(bf_t *r, slimb_t *pexponent,
|
||||||
|
const char *str, const char **pnext, int radix,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
|
||||||
|
slimb_t expn, limb_t prec, bf_flags_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/* Conversion of floating point number to string. Return a null
|
||||||
|
terminated string or NULL if memory error. *plen contains its
|
||||||
|
length if plen != NULL. The exponent letter is "e" for base 10,
|
||||||
|
"p" for bases 2, 8, 16 with a binary exponent and "@" for the other
|
||||||
|
bases. */
|
||||||
|
|
||||||
|
#define BF_FTOA_FORMAT_MASK (3 << 16)
|
||||||
|
|
||||||
|
/* fixed format: prec significant digits rounded with (flags &
|
||||||
|
BF_RND_MASK). Exponential notation is used if too many zeros are
|
||||||
|
needed.*/
|
||||||
|
#define BF_FTOA_FORMAT_FIXED (0 << 16)
|
||||||
|
/* fractional format: prec digits after the decimal point rounded with
|
||||||
|
(flags & BF_RND_MASK) */
|
||||||
|
#define BF_FTOA_FORMAT_FRAC (1 << 16)
|
||||||
|
/* free format:
|
||||||
|
|
||||||
|
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
|
||||||
|
configuration of 'flags'. The result is meaningful only if 'a' is
|
||||||
|
already rounded to 'prec' bits. If the subnormal flag is set, the
|
||||||
|
exponent in 'flags' must also be set to the desired exponent range.
|
||||||
|
*/
|
||||||
|
#define BF_FTOA_FORMAT_FREE (2 << 16)
|
||||||
|
/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
|
||||||
|
(takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
|
||||||
|
binary radices with bf_ftoa() and for bfdec_ftoa(). */
|
||||||
|
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
|
||||||
|
|
||||||
|
/* force exponential notation for fixed or free format */
|
||||||
|
#define BF_FTOA_FORCE_EXP (1 << 20)
|
||||||
|
/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
|
||||||
|
base 2 if non zero value */
|
||||||
|
#define BF_FTOA_ADD_PREFIX (1 << 21)
|
||||||
|
/* return "Infinity" instead of "Inf" and add a "+" for positive
|
||||||
|
exponents */
|
||||||
|
#define BF_FTOA_JS_QUIRKS (1 << 22)
|
||||||
|
|
||||||
|
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)
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* the following functions are exported for testing only. */
|
||||||
|
void mp_print_str(const char *str, const limb_t *tab, limb_t n);
|
||||||
|
void bf_print_str(const char *str, const bf_t *a);
|
||||||
|
int bf_resize(bf_t *r, limb_t len);
|
||||||
|
int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
|
||||||
|
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,
|
||||||
|
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 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);
|
||||||
|
int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
|
||||||
|
limb_t bf_isqrt(limb_t a);
|
||||||
|
|
||||||
|
/* transcendental functions */
|
||||||
|
int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
|
||||||
|
int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
|
||||||
|
/* decimal floating point */
|
||||||
|
|
||||||
|
static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
|
||||||
|
{
|
||||||
|
bf_init(s, (bf_t *)r);
|
||||||
|
}
|
||||||
|
static inline void bfdec_delete(bfdec_t *r)
|
||||||
|
{
|
||||||
|
bf_delete((bf_t *)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bfdec_neg(bfdec_t *r)
|
||||||
|
{
|
||||||
|
r->sign ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bfdec_is_finite(const bfdec_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn < BF_EXP_INF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bfdec_is_nan(const bfdec_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn == BF_EXP_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bfdec_is_zero(const bfdec_t *a)
|
||||||
|
{
|
||||||
|
return (a->expn == BF_EXP_ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
|
||||||
|
{
|
||||||
|
bf_memcpy((bf_t *)r, (const bf_t *)a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bfdec_set_ui(bfdec_t *r, uint64_t a);
|
||||||
|
int bfdec_set_si(bfdec_t *r, int64_t a);
|
||||||
|
|
||||||
|
static inline void bfdec_set_nan(bfdec_t *r)
|
||||||
|
{
|
||||||
|
bf_set_nan((bf_t *)r);
|
||||||
|
}
|
||||||
|
static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
|
||||||
|
{
|
||||||
|
bf_set_zero((bf_t *)r, is_neg);
|
||||||
|
}
|
||||||
|
static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
|
||||||
|
{
|
||||||
|
bf_set_inf((bf_t *)r, is_neg);
|
||||||
|
}
|
||||||
|
static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
|
||||||
|
{
|
||||||
|
return bf_set((bf_t *)r, (bf_t *)a);
|
||||||
|
}
|
||||||
|
static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
|
||||||
|
{
|
||||||
|
bf_move((bf_t *)r, (bf_t *)a);
|
||||||
|
}
|
||||||
|
static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
|
||||||
|
{
|
||||||
|
return bf_cmpu((const bf_t *)a, (const bf_t *)b);
|
||||||
|
}
|
||||||
|
static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
|
||||||
|
{
|
||||||
|
return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
|
||||||
|
}
|
||||||
|
static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
|
||||||
|
{
|
||||||
|
return bf_cmp((const bf_t *)a, (const bf_t *)b);
|
||||||
|
}
|
||||||
|
static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
|
||||||
|
{
|
||||||
|
return bfdec_cmp(a, b) == 0;
|
||||||
|
}
|
||||||
|
static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
|
||||||
|
{
|
||||||
|
return bfdec_cmp(a, b) <= 0;
|
||||||
|
}
|
||||||
|
static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
|
||||||
|
{
|
||||||
|
return bfdec_cmp(a, b) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags);
|
||||||
|
int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
|
||||||
|
limb_t prec, bf_flags_t flags, int rnd_mode);
|
||||||
|
int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
|
||||||
|
bf_flags_t flags, int rnd_mode);
|
||||||
|
int bfdec_rint(bfdec_t *r, int rnd_mode);
|
||||||
|
int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
|
||||||
|
int bfdec_get_int32(int *pres, const bfdec_t *a);
|
||||||
|
int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
|
||||||
|
|
||||||
|
char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
|
||||||
|
int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
|
||||||
|
limb_t prec, bf_flags_t flags);
|
||||||
|
|
||||||
|
/* the following functions are exported for testing only. */
|
||||||
|
extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
|
||||||
|
void bfdec_print_str(const char *str, const bfdec_t *a);
|
||||||
|
static inline int bfdec_resize(bfdec_t *r, limb_t len)
|
||||||
|
{
|
||||||
|
return bf_resize((bf_t *)r, len);
|
||||||
|
}
|
||||||
|
int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
|
||||||
|
|
||||||
|
#endif /* LIBBF_H */
|
||||||
58
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libregexp-opcode.h
vendored
Normal file
58
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libregexp-opcode.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Regular Expression Engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEF
|
||||||
|
|
||||||
|
DEF(invalid, 1) /* never used */
|
||||||
|
DEF(char, 3)
|
||||||
|
DEF(char32, 5)
|
||||||
|
DEF(dot, 1)
|
||||||
|
DEF(any, 1) /* same as dot but match any character including line terminator */
|
||||||
|
DEF(line_start, 1)
|
||||||
|
DEF(line_end, 1)
|
||||||
|
DEF(goto, 5)
|
||||||
|
DEF(split_goto_first, 5)
|
||||||
|
DEF(split_next_first, 5)
|
||||||
|
DEF(match, 1)
|
||||||
|
DEF(save_start, 2) /* save start position */
|
||||||
|
DEF(save_end, 2) /* save end position, must come after saved_start */
|
||||||
|
DEF(save_reset, 3) /* reset save positions */
|
||||||
|
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
|
||||||
|
DEF(push_i32, 5) /* push integer on the stack */
|
||||||
|
DEF(drop, 1)
|
||||||
|
DEF(word_boundary, 1)
|
||||||
|
DEF(not_word_boundary, 1)
|
||||||
|
DEF(back_reference, 2)
|
||||||
|
DEF(backward_back_reference, 2) /* must come after back_reference */
|
||||||
|
DEF(range, 3) /* variable length */
|
||||||
|
DEF(range32, 3) /* variable length */
|
||||||
|
DEF(lookahead, 5)
|
||||||
|
DEF(negative_lookahead, 5)
|
||||||
|
DEF(push_char_pos, 1) /* push the character position on the stack */
|
||||||
|
DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character
|
||||||
|
position */
|
||||||
|
DEF(prev, 1) /* go to the previous char */
|
||||||
|
DEF(simple_greedy_quant, 17)
|
||||||
|
|
||||||
|
#endif /* DEF */
|
||||||
2588
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libregexp.c
vendored
Normal file
2588
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libregexp.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
91
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libregexp.h
vendored
Normal file
91
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libregexp.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Regular Expression Engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBREGEXP_H
|
||||||
|
#define LIBREGEXP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "libunicode.h"
|
||||||
|
|
||||||
|
#define LRE_BOOL int /* for documentation purposes */
|
||||||
|
|
||||||
|
#define LRE_FLAG_GLOBAL (1 << 0)
|
||||||
|
#define LRE_FLAG_IGNORECASE (1 << 1)
|
||||||
|
#define LRE_FLAG_MULTILINE (1 << 2)
|
||||||
|
#define LRE_FLAG_DOTALL (1 << 3)
|
||||||
|
#define LRE_FLAG_UTF16 (1 << 4)
|
||||||
|
#define LRE_FLAG_STICKY (1 << 5)
|
||||||
|
|
||||||
|
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
|
||||||
|
|
||||||
|
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
|
||||||
|
const char *buf, size_t buf_len, int re_flags,
|
||||||
|
void *opaque);
|
||||||
|
int lre_get_capture_count(const uint8_t *bc_buf);
|
||||||
|
int lre_get_flags(const uint8_t *bc_buf);
|
||||||
|
int lre_exec(uint8_t **capture,
|
||||||
|
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
|
||||||
|
int cbuf_type, void *opaque);
|
||||||
|
|
||||||
|
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
|
||||||
|
LRE_BOOL lre_is_space(int c);
|
||||||
|
|
||||||
|
/* must be provided by the user */
|
||||||
|
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
||||||
|
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
||||||
|
|
||||||
|
/* JS identifier test */
|
||||||
|
extern uint32_t const lre_id_start_table_ascii[4];
|
||||||
|
extern uint32_t const lre_id_continue_table_ascii[4];
|
||||||
|
|
||||||
|
static inline int lre_js_is_ident_first(int c)
|
||||||
|
{
|
||||||
|
if ((uint32_t)c < 128) {
|
||||||
|
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||||
|
} else {
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
return lre_is_id_start(c);
|
||||||
|
#else
|
||||||
|
return !lre_is_space(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int lre_js_is_ident_next(int c)
|
||||||
|
{
|
||||||
|
if ((uint32_t)c < 128) {
|
||||||
|
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||||
|
} else {
|
||||||
|
/* ZWNJ and ZWJ are accepted in identifiers */
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
|
||||||
|
#else
|
||||||
|
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LRE_BOOL
|
||||||
|
|
||||||
|
#endif /* LIBREGEXP_H */
|
||||||
4368
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libunicode-table.h
vendored
Normal file
4368
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libunicode-table.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1538
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libunicode.c
vendored
Normal file
1538
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libunicode.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
124
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libunicode.h
vendored
Normal file
124
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/libunicode.h
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Unicode utilities
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBUNICODE_H
|
||||||
|
#define LIBUNICODE_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#define LRE_BOOL int /* for documentation purposes */
|
||||||
|
|
||||||
|
/* define it to include all the unicode tables (40KB larger) */
|
||||||
|
#define CONFIG_ALL_UNICODE
|
||||||
|
|
||||||
|
#define LRE_CC_RES_LEN_MAX 3
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UNICODE_NFC,
|
||||||
|
UNICODE_NFD,
|
||||||
|
UNICODE_NFKC,
|
||||||
|
UNICODE_NFKD,
|
||||||
|
} UnicodeNormalizationEnum;
|
||||||
|
|
||||||
|
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
||||||
|
LRE_BOOL lre_is_cased(uint32_t c);
|
||||||
|
LRE_BOOL lre_is_case_ignorable(uint32_t c);
|
||||||
|
|
||||||
|
/* char ranges */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int len; /* in points, always even */
|
||||||
|
int size;
|
||||||
|
uint32_t *points; /* points sorted by increasing value */
|
||||||
|
void *mem_opaque;
|
||||||
|
void *(*realloc_func)(void *opaque, void *ptr, size_t size);
|
||||||
|
} CharRange;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CR_OP_UNION,
|
||||||
|
CR_OP_INTER,
|
||||||
|
CR_OP_XOR,
|
||||||
|
} CharRangeOpEnum;
|
||||||
|
|
||||||
|
void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||||
|
void cr_free(CharRange *cr);
|
||||||
|
int cr_realloc(CharRange *cr, int size);
|
||||||
|
int cr_copy(CharRange *cr, const CharRange *cr1);
|
||||||
|
|
||||||
|
static inline int cr_add_point(CharRange *cr, uint32_t v)
|
||||||
|
{
|
||||||
|
if (cr->len >= cr->size) {
|
||||||
|
if (cr_realloc(cr, cr->len + 1))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cr->points[cr->len++] = v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||||
|
{
|
||||||
|
if ((cr->len + 2) > cr->size) {
|
||||||
|
if (cr_realloc(cr, cr->len + 2))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cr->points[cr->len++] = c1;
|
||||||
|
cr->points[cr->len++] = c2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
|
||||||
|
|
||||||
|
static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||||
|
{
|
||||||
|
uint32_t b_pt[2];
|
||||||
|
b_pt[0] = c1;
|
||||||
|
b_pt[1] = c2 + 1;
|
||||||
|
return cr_union1(cr, b_pt, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
||||||
|
const uint32_t *b_pt, int b_len, int op);
|
||||||
|
|
||||||
|
int cr_invert(CharRange *cr);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ALL_UNICODE
|
||||||
|
|
||||||
|
LRE_BOOL lre_is_id_start(uint32_t c);
|
||||||
|
LRE_BOOL lre_is_id_continue(uint32_t c);
|
||||||
|
|
||||||
|
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
||||||
|
UnicodeNormalizationEnum n_type,
|
||||||
|
void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||||
|
|
||||||
|
/* Unicode character range functions */
|
||||||
|
|
||||||
|
int unicode_script(CharRange *cr,
|
||||||
|
const char *script_name, LRE_BOOL is_ext);
|
||||||
|
int unicode_general_category(CharRange *cr, const char *gc_name);
|
||||||
|
int unicode_prop(CharRange *cr, const char *prop_name);
|
||||||
|
|
||||||
|
#endif /* CONFIG_ALL_UNICODE */
|
||||||
|
|
||||||
|
#undef LRE_BOOL
|
||||||
|
|
||||||
|
#endif /* LIBUNICODE_H */
|
||||||
100
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/list.h
vendored
Normal file
100
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/list.h
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Linux klist like system
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016-2017 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct list_head {
|
||||||
|
struct list_head *prev;
|
||||||
|
struct list_head *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LIST_HEAD_INIT(el) { &(el), &(el) }
|
||||||
|
|
||||||
|
/* return the pointer of type 'type *' containing 'el' as field 'member' */
|
||||||
|
#define list_entry(el, type, member) \
|
||||||
|
((type *)((uint8_t *)(el) - offsetof(type, member)))
|
||||||
|
|
||||||
|
static inline void init_list_head(struct list_head *head)
|
||||||
|
{
|
||||||
|
head->prev = head;
|
||||||
|
head->next = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert 'el' between 'prev' and 'next' */
|
||||||
|
static inline void __list_add(struct list_head *el,
|
||||||
|
struct list_head *prev, struct list_head *next)
|
||||||
|
{
|
||||||
|
prev->next = el;
|
||||||
|
el->prev = prev;
|
||||||
|
el->next = next;
|
||||||
|
next->prev = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add 'el' at the head of the list 'head' (= after element head) */
|
||||||
|
static inline void list_add(struct list_head *el, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(el, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add 'el' at the end of the list 'head' (= before element head) */
|
||||||
|
static inline void list_add_tail(struct list_head *el, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(el, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_del(struct list_head *el)
|
||||||
|
{
|
||||||
|
struct list_head *prev, *next;
|
||||||
|
prev = el->prev;
|
||||||
|
next = el->next;
|
||||||
|
prev->next = next;
|
||||||
|
next->prev = prev;
|
||||||
|
el->prev = NULL; /* fail safe */
|
||||||
|
el->next = NULL; /* fail safe */
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int list_empty(struct list_head *el)
|
||||||
|
{
|
||||||
|
return el->next == el;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define list_for_each(el, head) \
|
||||||
|
for(el = (head)->next; el != (head); el = el->next)
|
||||||
|
|
||||||
|
#define list_for_each_safe(el, el1, head) \
|
||||||
|
for(el = (head)->next, el1 = el->next; el != (head); \
|
||||||
|
el = el1, el1 = el->next)
|
||||||
|
|
||||||
|
#define list_for_each_prev(el, head) \
|
||||||
|
for(el = (head)->prev; el != (head); el = el->prev)
|
||||||
|
|
||||||
|
#define list_for_each_prev_safe(el, el1, head) \
|
||||||
|
for(el = (head)->prev, el1 = el->prev; el != (head); \
|
||||||
|
el = el1, el1 = el->prev)
|
||||||
|
|
||||||
|
#endif /* LIST_H */
|
||||||
551
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/qjs.c
vendored
Normal file
551
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/qjs.c
vendored
Normal file
@@ -0,0 +1,551 @@
|
|||||||
|
/*
|
||||||
|
* QuickJS stand alone interpreter
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2020 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2020 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <malloc/malloc.h>
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
#include "quickjs-libc.h"
|
||||||
|
|
||||||
|
extern const uint8_t qjsc_repl[];
|
||||||
|
extern const uint32_t qjsc_repl_size;
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
extern const uint8_t qjsc_qjscalc[];
|
||||||
|
extern const uint32_t qjsc_qjscalc_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||||
|
const char *filename, int eval_flags)
|
||||||
|
{
|
||||||
|
JSValue val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) {
|
||||||
|
/* for the modules, we compile then run to be able to set
|
||||||
|
import.meta */
|
||||||
|
val = JS_Eval(ctx, buf, buf_len, filename,
|
||||||
|
eval_flags | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||||
|
if (!JS_IsException(val)) {
|
||||||
|
js_module_set_import_meta(ctx, val, TRUE, TRUE);
|
||||||
|
val = JS_EvalFunction(ctx, val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
||||||
|
}
|
||||||
|
if (JS_IsException(val)) {
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
JS_FreeValue(ctx, val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int eval_file(JSContext *ctx, const char *filename, int module)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
int ret, eval_flags;
|
||||||
|
size_t buf_len;
|
||||||
|
|
||||||
|
buf = js_load_file(ctx, &buf_len, filename);
|
||||||
|
if (!buf) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module < 0) {
|
||||||
|
module = (has_suffix(filename, ".mjs") ||
|
||||||
|
JS_DetectModule((const char *)buf, buf_len));
|
||||||
|
}
|
||||||
|
if (module)
|
||||||
|
eval_flags = JS_EVAL_TYPE_MODULE;
|
||||||
|
else
|
||||||
|
eval_flags = JS_EVAL_TYPE_GLOBAL;
|
||||||
|
ret = eval_buf(ctx, buf, buf_len, filename, eval_flags);
|
||||||
|
js_free(ctx, buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define MALLOC_OVERHEAD 0
|
||||||
|
#else
|
||||||
|
#define MALLOC_OVERHEAD 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct trace_malloc_data {
|
||||||
|
uint8_t *base;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
|
||||||
|
struct trace_malloc_data *dp)
|
||||||
|
{
|
||||||
|
return ptr - dp->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default memory allocation functions with memory limitation */
|
||||||
|
static inline size_t js_trace_malloc_usable_size(void *ptr)
|
||||||
|
{
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
return malloc_size(ptr);
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
return _msize(ptr);
|
||||||
|
#elif defined(EMSCRIPTEN)
|
||||||
|
return 0;
|
||||||
|
#elif defined(__linux__)
|
||||||
|
return malloc_usable_size(ptr);
|
||||||
|
#else
|
||||||
|
/* change this to `return 0;` if compilation fails */
|
||||||
|
return malloc_usable_size(ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((format(printf, 2, 3)))
|
||||||
|
js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
while ((c = *fmt++) != '\0') {
|
||||||
|
if (c == '%') {
|
||||||
|
/* only handle %p and %zd */
|
||||||
|
if (*fmt == 'p') {
|
||||||
|
uint8_t *ptr = va_arg(ap, void *);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
printf("NULL");
|
||||||
|
} else {
|
||||||
|
printf("H%+06lld.%zd",
|
||||||
|
js_trace_malloc_ptr_offset(ptr, s->opaque),
|
||||||
|
js_trace_malloc_usable_size(ptr));
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fmt[0] == 'z' && fmt[1] == 'd') {
|
||||||
|
size_t sz = va_arg(ap, size_t);
|
||||||
|
printf("%zd", sz);
|
||||||
|
fmt += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putc(c, stdout);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_trace_malloc_init(struct trace_malloc_data *s)
|
||||||
|
{
|
||||||
|
free(s->base = malloc(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *js_trace_malloc(JSMallocState *s, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
/* Do not allocate zero bytes: behavior is platform dependent */
|
||||||
|
assert(size != 0);
|
||||||
|
|
||||||
|
if (unlikely(s->malloc_size + size > s->malloc_limit))
|
||||||
|
return NULL;
|
||||||
|
ptr = malloc(size);
|
||||||
|
js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr);
|
||||||
|
if (ptr) {
|
||||||
|
s->malloc_count++;
|
||||||
|
s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_trace_free(JSMallocState *s, void *ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
js_trace_malloc_printf(s, "F %p\n", ptr);
|
||||||
|
s->malloc_count--;
|
||||||
|
s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
size_t old_size;
|
||||||
|
|
||||||
|
if (!ptr) {
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
return js_trace_malloc(s, size);
|
||||||
|
}
|
||||||
|
old_size = js_trace_malloc_usable_size(ptr);
|
||||||
|
if (size == 0) {
|
||||||
|
js_trace_malloc_printf(s, "R %zd %p\n", size, ptr);
|
||||||
|
s->malloc_count--;
|
||||||
|
s->malloc_size -= old_size + MALLOC_OVERHEAD;
|
||||||
|
free(ptr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (s->malloc_size + size - old_size > s->malloc_limit)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
js_trace_malloc_printf(s, "R %zd %p", size, ptr);
|
||||||
|
|
||||||
|
ptr = realloc(ptr, size);
|
||||||
|
js_trace_malloc_printf(s, " -> %p\n", ptr);
|
||||||
|
if (ptr) {
|
||||||
|
s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JSMallocFunctions trace_mf = {
|
||||||
|
js_trace_malloc,
|
||||||
|
js_trace_free,
|
||||||
|
js_trace_realloc,
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
malloc_size,
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
(size_t (*)(const void *))_msize,
|
||||||
|
#elif defined(EMSCRIPTEN)
|
||||||
|
NULL,
|
||||||
|
#elif defined(__linux__)
|
||||||
|
(size_t (*)(const void *))malloc_usable_size,
|
||||||
|
#else
|
||||||
|
/* change this to `NULL,` if compilation fails */
|
||||||
|
malloc_usable_size,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PROG_NAME "qjs"
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
printf("QuickJS version " CONFIG_VERSION "\n"
|
||||||
|
"usage: " PROG_NAME " [options] [file [args]]\n"
|
||||||
|
"-h --help list options\n"
|
||||||
|
"-e --eval EXPR evaluate EXPR\n"
|
||||||
|
"-i --interactive go to interactive mode\n"
|
||||||
|
"-m --module load as ES6 module (default=autodetect)\n"
|
||||||
|
" --script load as ES6 script (default=autodetect)\n"
|
||||||
|
"-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
|
||||||
|
"-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"
|
||||||
|
" --unhandled-rejection dump unhandled promise rejections\n"
|
||||||
|
"-q --quit just instantiate the interpreter and quit\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
JSRuntime *rt;
|
||||||
|
JSContext *ctx;
|
||||||
|
struct trace_malloc_data trace_data = { NULL };
|
||||||
|
int optind;
|
||||||
|
char *expr = NULL;
|
||||||
|
int interactive = 0;
|
||||||
|
int dump_memory = 0;
|
||||||
|
int trace_memory = 0;
|
||||||
|
int empty_run = 0;
|
||||||
|
int module = -1;
|
||||||
|
int load_std = 0;
|
||||||
|
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, bignum_ext = 0;
|
||||||
|
#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");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* cannot use getopt because we want to pass the command line to
|
||||||
|
the script */
|
||||||
|
optind = 1;
|
||||||
|
while (optind < argc && *argv[optind] == '-') {
|
||||||
|
char *arg = argv[optind] + 1;
|
||||||
|
const char *longopt = "";
|
||||||
|
/* a single - is not an option, it also stops argument scanning */
|
||||||
|
if (!*arg)
|
||||||
|
break;
|
||||||
|
optind++;
|
||||||
|
if (*arg == '-') {
|
||||||
|
longopt = arg + 1;
|
||||||
|
arg += strlen(arg);
|
||||||
|
/* -- stops argument scanning */
|
||||||
|
if (!*longopt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (; *arg || *longopt; longopt = "") {
|
||||||
|
char opt = *arg;
|
||||||
|
if (opt)
|
||||||
|
arg++;
|
||||||
|
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
|
||||||
|
help();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'e' || !strcmp(longopt, "eval")) {
|
||||||
|
if (*arg) {
|
||||||
|
expr = arg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (optind < argc) {
|
||||||
|
expr = argv[optind++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "qjs: missing expression for -e\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
if (opt == 'I' || !strcmp(longopt, "include")) {
|
||||||
|
if (optind >= argc) {
|
||||||
|
fprintf(stderr, "expecting filename");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (include_count >= countof(include_list)) {
|
||||||
|
fprintf(stderr, "too many included files");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
include_list[include_count++] = argv[optind++];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'i' || !strcmp(longopt, "interactive")) {
|
||||||
|
interactive++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'm' || !strcmp(longopt, "module")) {
|
||||||
|
module = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(longopt, "script")) {
|
||||||
|
module = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'd' || !strcmp(longopt, "dump")) {
|
||||||
|
dump_memory++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 'T' || !strcmp(longopt, "trace")) {
|
||||||
|
trace_memory++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(longopt, "std")) {
|
||||||
|
load_std = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
memory_limit = (size_t)strtod(argv[optind++], NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(longopt, "stack-size")) {
|
||||||
|
if (optind >= argc) {
|
||||||
|
fprintf(stderr, "expecting stack size");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
stack_size = (size_t)strtod(argv[optind++], NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt) {
|
||||||
|
fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "qjs: unknown option '--%s'\n", longopt);
|
||||||
|
}
|
||||||
|
help();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trace_memory) {
|
||||||
|
js_trace_malloc_init(&trace_data);
|
||||||
|
rt = JS_NewRuntime2(&trace_mf, &trace_data);
|
||||||
|
} else {
|
||||||
|
rt = JS_NewRuntime();
|
||||||
|
}
|
||||||
|
if (!rt) {
|
||||||
|
fprintf(stderr, "qjs: cannot allocate JS runtime\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
if (memory_limit != 0)
|
||||||
|
JS_SetMemoryLimit(rt, memory_limit);
|
||||||
|
if (stack_size != 0)
|
||||||
|
JS_SetMaxStackSize(rt, stack_size);
|
||||||
|
js_std_init_handlers(rt);
|
||||||
|
ctx = JS_NewContext(rt);
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "qjs: cannot allocate JS context\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
if (bignum_ext || load_jscalc) {
|
||||||
|
JS_AddIntrinsicBigFloat(ctx);
|
||||||
|
JS_AddIntrinsicBigDecimal(ctx);
|
||||||
|
JS_AddIntrinsicOperators(ctx);
|
||||||
|
JS_EnableBignumExt(ctx, TRUE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* loader for ES6 modules */
|
||||||
|
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||||
|
|
||||||
|
if (dump_unhandled_promise_rejection) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* system modules */
|
||||||
|
js_init_module_std(ctx, "std");
|
||||||
|
js_init_module_os(ctx, "os");
|
||||||
|
|
||||||
|
/* make 'std' and 'os' visible to non module code */
|
||||||
|
if (load_std) {
|
||||||
|
const char *str = "import * as std from 'std';\n"
|
||||||
|
"import * as os from 'os';\n"
|
||||||
|
"globalThis.std = std;\n"
|
||||||
|
"globalThis.os = os;\n";
|
||||||
|
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < include_count; i++) {
|
||||||
|
if (eval_file(ctx, include_list[i], module))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expr) {
|
||||||
|
if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", 0))
|
||||||
|
goto fail;
|
||||||
|
} else
|
||||||
|
if (optind >= argc) {
|
||||||
|
/* interactive mode */
|
||||||
|
interactive = 1;
|
||||||
|
} else {
|
||||||
|
const char *filename;
|
||||||
|
filename = argv[optind];
|
||||||
|
if (eval_file(ctx, filename, module))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (interactive) {
|
||||||
|
js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0);
|
||||||
|
}
|
||||||
|
js_std_loop(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dump_memory) {
|
||||||
|
JSMemoryUsage stats;
|
||||||
|
JS_ComputeMemoryUsage(rt, &stats);
|
||||||
|
JS_DumpMemoryUsage(stdout, &stats, rt);
|
||||||
|
}
|
||||||
|
js_std_free_handlers(rt);
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
|
||||||
|
if (empty_run && dump_memory) {
|
||||||
|
clock_t t[5];
|
||||||
|
double best[5];
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < 100; i++) {
|
||||||
|
t[0] = clock();
|
||||||
|
rt = JS_NewRuntime();
|
||||||
|
t[1] = clock();
|
||||||
|
ctx = JS_NewContext(rt);
|
||||||
|
t[2] = clock();
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
t[3] = clock();
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
t[4] = clock();
|
||||||
|
for (j = 4; j > 0; j--) {
|
||||||
|
double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC;
|
||||||
|
if (i == 0 || best[j] > ms)
|
||||||
|
best[j] = ms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n",
|
||||||
|
best[1] + best[2] + best[3] + best[4],
|
||||||
|
best[1], best[2], best[3], best[4]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
fail:
|
||||||
|
js_std_free_handlers(rt);
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
728
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/qjsc.c
vendored
Normal file
728
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/qjsc.c
vendored
Normal file
@@ -0,0 +1,728 @@
|
|||||||
|
/*
|
||||||
|
* QuickJS command line compiler
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018-2020 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cutils.h"
|
||||||
|
#include "quickjs-libc.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
char *short_name;
|
||||||
|
int flags;
|
||||||
|
} namelist_entry_t;
|
||||||
|
|
||||||
|
typedef struct namelist_t {
|
||||||
|
namelist_entry_t *array;
|
||||||
|
int count;
|
||||||
|
int size;
|
||||||
|
} namelist_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *option_name;
|
||||||
|
const char *init_name;
|
||||||
|
} FeatureEntry;
|
||||||
|
|
||||||
|
static namelist_t cname_list;
|
||||||
|
static namelist_t cmodule_list;
|
||||||
|
static namelist_t init_module_list;
|
||||||
|
static uint64_t feature_bitmap;
|
||||||
|
static FILE *outfile;
|
||||||
|
static BOOL byte_swap;
|
||||||
|
static BOOL dynamic_export;
|
||||||
|
static const char *c_ident_prefix = "qjsc_";
|
||||||
|
|
||||||
|
#define FE_ALL (-1)
|
||||||
|
|
||||||
|
static const FeatureEntry feature_list[] = {
|
||||||
|
{ "date", "Date" },
|
||||||
|
{ "eval", "Eval" },
|
||||||
|
{ "string-normalize", "StringNormalize" },
|
||||||
|
{ "regexp", "RegExp" },
|
||||||
|
{ "json", "JSON" },
|
||||||
|
{ "proxy", "Proxy" },
|
||||||
|
{ "map", "MapSet" },
|
||||||
|
{ "typedarray", "TypedArrays" },
|
||||||
|
{ "promise", "Promise" },
|
||||||
|
#define FE_MODULE_LOADER 9
|
||||||
|
{ "module-loader", NULL },
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
{ "bigint", "BigInt" },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
namelist_entry_t *e;
|
||||||
|
if (lp->count == lp->size) {
|
||||||
|
size_t newsize = lp->size + (lp->size >> 1) + 4;
|
||||||
|
namelist_entry_t *a =
|
||||||
|
realloc(lp->array, sizeof(lp->array[0]) * newsize);
|
||||||
|
/* XXX: check for realloc failure */
|
||||||
|
lp->array = a;
|
||||||
|
lp->size = newsize;
|
||||||
|
}
|
||||||
|
e = &lp->array[lp->count++];
|
||||||
|
e->name = strdup(name);
|
||||||
|
if (short_name)
|
||||||
|
e->short_name = strdup(short_name);
|
||||||
|
else
|
||||||
|
e->short_name = NULL;
|
||||||
|
e->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void namelist_free(namelist_t *lp)
|
||||||
|
{
|
||||||
|
while (lp->count > 0) {
|
||||||
|
namelist_entry_t *e = &lp->array[--lp->count];
|
||||||
|
free(e->name);
|
||||||
|
free(e->short_name);
|
||||||
|
}
|
||||||
|
free(lp->array);
|
||||||
|
lp->array = NULL;
|
||||||
|
lp->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namelist_entry_t *namelist_find(namelist_t *lp, const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < lp->count; i++) {
|
||||||
|
namelist_entry_t *e = &lp->array[i];
|
||||||
|
if (!strcmp(e->name, name))
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_c_name(char *buf, size_t buf_size, const char *file)
|
||||||
|
{
|
||||||
|
const char *p, *r;
|
||||||
|
size_t len, i;
|
||||||
|
int c;
|
||||||
|
char *q;
|
||||||
|
|
||||||
|
p = strrchr(file, '/');
|
||||||
|
if (!p)
|
||||||
|
p = file;
|
||||||
|
else
|
||||||
|
p++;
|
||||||
|
r = strrchr(p, '.');
|
||||||
|
if (!r)
|
||||||
|
len = strlen(p);
|
||||||
|
else
|
||||||
|
len = r - p;
|
||||||
|
pstrcpy(buf, buf_size, c_ident_prefix);
|
||||||
|
q = buf + strlen(buf);
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
c = p[i];
|
||||||
|
if (!((c >= '0' && c <= '9') ||
|
||||||
|
(c >= 'A' && c <= 'Z') ||
|
||||||
|
(c >= 'a' && c <= 'z'))) {
|
||||||
|
c = '_';
|
||||||
|
}
|
||||||
|
if ((q - buf) < buf_size - 1)
|
||||||
|
*q++ = c;
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t i, col;
|
||||||
|
col = 0;
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
fprintf(f, " 0x%02x,", buf[i]);
|
||||||
|
if (++col == 8) {
|
||||||
|
fprintf(f, "\n");
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (col != 0)
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_object_code(JSContext *ctx,
|
||||||
|
FILE *fo, JSValueConst obj, const char *c_name,
|
||||||
|
BOOL load_only)
|
||||||
|
{
|
||||||
|
uint8_t *out_buf;
|
||||||
|
size_t out_buf_len;
|
||||||
|
int flags;
|
||||||
|
flags = JS_WRITE_OBJ_BYTECODE;
|
||||||
|
if (byte_swap)
|
||||||
|
flags |= JS_WRITE_OBJ_BSWAP;
|
||||||
|
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
|
||||||
|
if (!out_buf) {
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
namelist_add(&cname_list, c_name, NULL, load_only);
|
||||||
|
|
||||||
|
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
|
||||||
|
c_name, (unsigned int)out_buf_len);
|
||||||
|
fprintf(fo, "const uint8_t %s[%u] = {\n",
|
||||||
|
c_name, (unsigned int)out_buf_len);
|
||||||
|
dump_hex(fo, out_buf, out_buf_len);
|
||||||
|
fprintf(fo, "};\n\n");
|
||||||
|
|
||||||
|
js_free(ctx, out_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
|
||||||
|
{
|
||||||
|
/* should never be called when compiling JS code */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void find_unique_cname(char *cname, size_t cname_size)
|
||||||
|
{
|
||||||
|
char cname1[1024];
|
||||||
|
int suffix_num;
|
||||||
|
size_t len, max_len;
|
||||||
|
assert(cname_size >= 32);
|
||||||
|
/* find a C name not matching an existing module C name by
|
||||||
|
adding a numeric suffix */
|
||||||
|
len = strlen(cname);
|
||||||
|
max_len = cname_size - 16;
|
||||||
|
if (len > max_len)
|
||||||
|
cname[max_len] = '\0';
|
||||||
|
suffix_num = 1;
|
||||||
|
for(;;) {
|
||||||
|
snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num);
|
||||||
|
if (!namelist_find(&cname_list, cname1))
|
||||||
|
break;
|
||||||
|
suffix_num++;
|
||||||
|
}
|
||||||
|
pstrcpy(cname, cname_size, cname1);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||||
|
const char *module_name, void *opaque)
|
||||||
|
{
|
||||||
|
JSModuleDef *m;
|
||||||
|
namelist_entry_t *e;
|
||||||
|
|
||||||
|
/* check if it is a declared C or system module */
|
||||||
|
e = namelist_find(&cmodule_list, module_name);
|
||||||
|
if (e) {
|
||||||
|
/* add in the static init module list */
|
||||||
|
namelist_add(&init_module_list, e->name, e->short_name, 0);
|
||||||
|
/* create a dummy module */
|
||||||
|
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||||
|
} else if (has_suffix(module_name, ".so")) {
|
||||||
|
fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name);
|
||||||
|
/* create a dummy module */
|
||||||
|
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||||
|
/* the resulting executable will export its symbols for the
|
||||||
|
dynamic library */
|
||||||
|
dynamic_export = TRUE;
|
||||||
|
} else {
|
||||||
|
size_t buf_len;
|
||||||
|
uint8_t *buf;
|
||||||
|
JSValue func_val;
|
||||||
|
char cname[1024];
|
||||||
|
|
||||||
|
buf = js_load_file(ctx, &buf_len, module_name);
|
||||||
|
if (!buf) {
|
||||||
|
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||||
|
module_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compile the module */
|
||||||
|
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
|
||||||
|
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||||
|
js_free(ctx, buf);
|
||||||
|
if (JS_IsException(func_val))
|
||||||
|
return NULL;
|
||||||
|
get_c_name(cname, sizeof(cname), module_name);
|
||||||
|
if (namelist_find(&cname_list, cname)) {
|
||||||
|
find_unique_cname(cname, sizeof(cname));
|
||||||
|
}
|
||||||
|
output_object_code(ctx, outfile, func_val, cname, TRUE);
|
||||||
|
|
||||||
|
/* the module is already referenced, so we must free it */
|
||||||
|
m = JS_VALUE_GET_PTR(func_val);
|
||||||
|
JS_FreeValue(ctx, func_val);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compile_file(JSContext *ctx, FILE *fo,
|
||||||
|
const char *filename,
|
||||||
|
const char *c_name1,
|
||||||
|
int module)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
char c_name[1024];
|
||||||
|
int eval_flags;
|
||||||
|
JSValue obj;
|
||||||
|
size_t buf_len;
|
||||||
|
|
||||||
|
buf = js_load_file(ctx, &buf_len, filename);
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "Could not load '%s'\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
eval_flags = JS_EVAL_FLAG_COMPILE_ONLY;
|
||||||
|
if (module < 0) {
|
||||||
|
module = (has_suffix(filename, ".mjs") ||
|
||||||
|
JS_DetectModule((const char *)buf, buf_len));
|
||||||
|
}
|
||||||
|
if (module)
|
||||||
|
eval_flags |= JS_EVAL_TYPE_MODULE;
|
||||||
|
else
|
||||||
|
eval_flags |= JS_EVAL_TYPE_GLOBAL;
|
||||||
|
obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags);
|
||||||
|
if (JS_IsException(obj)) {
|
||||||
|
js_std_dump_error(ctx);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
js_free(ctx, buf);
|
||||||
|
if (c_name1) {
|
||||||
|
pstrcpy(c_name, sizeof(c_name), c_name1);
|
||||||
|
} else {
|
||||||
|
get_c_name(c_name, sizeof(c_name), filename);
|
||||||
|
}
|
||||||
|
output_object_code(ctx, fo, obj, c_name, FALSE);
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char main_c_template1[] =
|
||||||
|
"int main(int argc, char **argv)\n"
|
||||||
|
"{\n"
|
||||||
|
" JSRuntime *rt;\n"
|
||||||
|
" JSContext *ctx;\n"
|
||||||
|
" rt = JS_NewRuntime();\n"
|
||||||
|
" js_std_init_handlers(rt);\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static const char main_c_template2[] =
|
||||||
|
" js_std_loop(ctx);\n"
|
||||||
|
" JS_FreeContext(ctx);\n"
|
||||||
|
" JS_FreeRuntime(rt);\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
#define PROG_NAME "qjsc"
|
||||||
|
|
||||||
|
void help(void)
|
||||||
|
{
|
||||||
|
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
|
||||||
|
"usage: " PROG_NAME " [options] [files]\n"
|
||||||
|
"\n"
|
||||||
|
"options are:\n"
|
||||||
|
"-c only output bytecode in a C file\n"
|
||||||
|
"-e output main() and bytecode in a C file (default = executable output)\n"
|
||||||
|
"-o output set the output filename\n"
|
||||||
|
"-N cname set the C name of the generated data\n"
|
||||||
|
"-m compile as Javascript module (default=autodetect)\n"
|
||||||
|
"-M module_name[,cname] add initialization code for an external C module\n"
|
||||||
|
"-x byte swapped output\n"
|
||||||
|
"-p prefix set the prefix of the generated C names\n"
|
||||||
|
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
|
||||||
|
out_filename = NULL;
|
||||||
|
output_type = OUTPUT_EXECUTABLE;
|
||||||
|
cname = NULL;
|
||||||
|
feature_bitmap = FE_ALL;
|
||||||
|
module = -1;
|
||||||
|
byte_swap = FALSE;
|
||||||
|
verbose = 0;
|
||||||
|
use_lto = FALSE;
|
||||||
|
stack_size = 0;
|
||||||
|
|
||||||
|
/* add system modules */
|
||||||
|
namelist_add(&cmodule_list, "std", "std", 0);
|
||||||
|
namelist_add(&cmodule_list, "os", "os", 0);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:");
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
switch(c) {
|
||||||
|
case 'h':
|
||||||
|
help();
|
||||||
|
case 'o':
|
||||||
|
out_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
output_type = OUTPUT_C;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
output_type = OUTPUT_C_MAIN;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
cname = optarg;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
p = optarg;
|
||||||
|
if (!strcmp(optarg, "lto")) {
|
||||||
|
use_lto = TRUE;
|
||||||
|
} else if (strstart(p, "no-", &p)) {
|
||||||
|
use_lto = TRUE;
|
||||||
|
for(i = 0; i < countof(feature_list); i++) {
|
||||||
|
if (!strcmp(p, feature_list[i].option_name)) {
|
||||||
|
feature_bitmap &= ~((uint64_t)1 << i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == countof(feature_list))
|
||||||
|
goto bad_feature;
|
||||||
|
} else
|
||||||
|
#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;
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char path[1024];
|
||||||
|
char cname[1024];
|
||||||
|
pstrcpy(path, sizeof(path), optarg);
|
||||||
|
p = strchr(path, ',');
|
||||||
|
if (p) {
|
||||||
|
*p = '\0';
|
||||||
|
pstrcpy(cname, sizeof(cname), p + 1);
|
||||||
|
} else {
|
||||||
|
get_c_name(cname, sizeof(cname), path);
|
||||||
|
}
|
||||||
|
namelist_add(&cmodule_list, path, cname, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
byte_swap = TRUE;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
c_ident_prefix = optarg;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
stack_size = (size_t)strtod(optarg, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc)
|
||||||
|
help();
|
||||||
|
|
||||||
|
if (!out_filename) {
|
||||||
|
if (output_type == OUTPUT_EXECUTABLE) {
|
||||||
|
out_filename = "a.out";
|
||||||
|
} else {
|
||||||
|
out_filename = "out.c";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_type == OUTPUT_EXECUTABLE) {
|
||||||
|
#if defined(_WIN32) || defined(__ANDROID__)
|
||||||
|
/* XXX: find a /tmp directory ? */
|
||||||
|
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
|
||||||
|
#else
|
||||||
|
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
fo = fopen(cfilename, "w");
|
||||||
|
if (!fo) {
|
||||||
|
perror(cfilename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
outfile = fo;
|
||||||
|
|
||||||
|
rt = JS_NewRuntime();
|
||||||
|
ctx = JS_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) {
|
||||||
|
fprintf(fo, "#include \"quickjs-libc.h\"\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fprintf(fo, "#include <inttypes.h>\n"
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = optind; i < argc; i++) {
|
||||||
|
const char *filename = argv[i];
|
||||||
|
compile_file(ctx, fo, filename, cname, module);
|
||||||
|
cname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_type != OUTPUT_C) {
|
||||||
|
fputs(main_c_template1, fo);
|
||||||
|
fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");
|
||||||
|
|
||||||
|
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 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
|
||||||
|
fprintf(fo, " js_std_add_helpers(ctx, argc, argv);\n");
|
||||||
|
|
||||||
|
for(i = 0; i < init_module_list.count; i++) {
|
||||||
|
namelist_entry_t *e = &init_module_list.array[i];
|
||||||
|
/* initialize the static C modules */
|
||||||
|
|
||||||
|
fprintf(fo,
|
||||||
|
" {\n"
|
||||||
|
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
|
||||||
|
" js_init_module_%s(ctx, \"%s\");\n"
|
||||||
|
" }\n",
|
||||||
|
e->short_name, e->short_name, e->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < cname_list.count; i++) {
|
||||||
|
namelist_entry_t *e = &cname_list.array[i];
|
||||||
|
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, %s);\n",
|
||||||
|
e->name, e->name,
|
||||||
|
e->flags ? "1" : "0");
|
||||||
|
}
|
||||||
|
fputs(main_c_template2, fo);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FreeContext(ctx);
|
||||||
|
JS_FreeRuntime(rt);
|
||||||
|
|
||||||
|
fclose(fo);
|
||||||
|
|
||||||
|
if (output_type == OUTPUT_EXECUTABLE) {
|
||||||
|
return output_executable(out_filename, cfilename, use_lto, verbose,
|
||||||
|
argv[0]);
|
||||||
|
}
|
||||||
|
namelist_free(&cname_list);
|
||||||
|
namelist_free(&cmodule_list);
|
||||||
|
namelist_free(&init_module_list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
272
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-atom.h
vendored
Normal file
272
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-atom.h
vendored
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* QuickJS atom definitions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEF
|
||||||
|
|
||||||
|
/* Note: first atoms are considered as keywords in the parser */
|
||||||
|
DEF(null, "null") /* must be first */
|
||||||
|
DEF(false, "false")
|
||||||
|
DEF(true, "true")
|
||||||
|
DEF(if, "if")
|
||||||
|
DEF(else, "else")
|
||||||
|
DEF(return, "return")
|
||||||
|
DEF(var, "var")
|
||||||
|
DEF(this, "this")
|
||||||
|
DEF(delete, "delete")
|
||||||
|
DEF(void, "void")
|
||||||
|
DEF(typeof, "typeof")
|
||||||
|
DEF(new, "new")
|
||||||
|
DEF(in, "in")
|
||||||
|
DEF(instanceof, "instanceof")
|
||||||
|
DEF(do, "do")
|
||||||
|
DEF(while, "while")
|
||||||
|
DEF(for, "for")
|
||||||
|
DEF(break, "break")
|
||||||
|
DEF(continue, "continue")
|
||||||
|
DEF(switch, "switch")
|
||||||
|
DEF(case, "case")
|
||||||
|
DEF(default, "default")
|
||||||
|
DEF(throw, "throw")
|
||||||
|
DEF(try, "try")
|
||||||
|
DEF(catch, "catch")
|
||||||
|
DEF(finally, "finally")
|
||||||
|
DEF(function, "function")
|
||||||
|
DEF(debugger, "debugger")
|
||||||
|
DEF(with, "with")
|
||||||
|
/* FutureReservedWord */
|
||||||
|
DEF(class, "class")
|
||||||
|
DEF(const, "const")
|
||||||
|
DEF(enum, "enum")
|
||||||
|
DEF(export, "export")
|
||||||
|
DEF(extends, "extends")
|
||||||
|
DEF(import, "import")
|
||||||
|
DEF(super, "super")
|
||||||
|
/* FutureReservedWords when parsing strict mode code */
|
||||||
|
DEF(implements, "implements")
|
||||||
|
DEF(interface, "interface")
|
||||||
|
DEF(let, "let")
|
||||||
|
DEF(package, "package")
|
||||||
|
DEF(private, "private")
|
||||||
|
DEF(protected, "protected")
|
||||||
|
DEF(public, "public")
|
||||||
|
DEF(static, "static")
|
||||||
|
DEF(yield, "yield")
|
||||||
|
DEF(await, "await")
|
||||||
|
|
||||||
|
/* empty string */
|
||||||
|
DEF(empty_string, "")
|
||||||
|
/* identifiers */
|
||||||
|
DEF(length, "length")
|
||||||
|
DEF(fileName, "fileName")
|
||||||
|
DEF(lineNumber, "lineNumber")
|
||||||
|
DEF(message, "message")
|
||||||
|
DEF(errors, "errors")
|
||||||
|
DEF(stack, "stack")
|
||||||
|
DEF(name, "name")
|
||||||
|
DEF(toString, "toString")
|
||||||
|
DEF(toLocaleString, "toLocaleString")
|
||||||
|
DEF(valueOf, "valueOf")
|
||||||
|
DEF(eval, "eval")
|
||||||
|
DEF(prototype, "prototype")
|
||||||
|
DEF(constructor, "constructor")
|
||||||
|
DEF(configurable, "configurable")
|
||||||
|
DEF(writable, "writable")
|
||||||
|
DEF(enumerable, "enumerable")
|
||||||
|
DEF(value, "value")
|
||||||
|
DEF(get, "get")
|
||||||
|
DEF(set, "set")
|
||||||
|
DEF(of, "of")
|
||||||
|
DEF(__proto__, "__proto__")
|
||||||
|
DEF(undefined, "undefined")
|
||||||
|
DEF(number, "number")
|
||||||
|
DEF(boolean, "boolean")
|
||||||
|
DEF(string, "string")
|
||||||
|
DEF(object, "object")
|
||||||
|
DEF(symbol, "symbol")
|
||||||
|
DEF(integer, "integer")
|
||||||
|
DEF(unknown, "unknown")
|
||||||
|
DEF(arguments, "arguments")
|
||||||
|
DEF(callee, "callee")
|
||||||
|
DEF(caller, "caller")
|
||||||
|
DEF(_eval_, "<eval>")
|
||||||
|
DEF(_ret_, "<ret>")
|
||||||
|
DEF(_var_, "<var>")
|
||||||
|
DEF(_with_, "<with>")
|
||||||
|
DEF(lastIndex, "lastIndex")
|
||||||
|
DEF(target, "target")
|
||||||
|
DEF(index, "index")
|
||||||
|
DEF(input, "input")
|
||||||
|
DEF(defineProperties, "defineProperties")
|
||||||
|
DEF(apply, "apply")
|
||||||
|
DEF(join, "join")
|
||||||
|
DEF(concat, "concat")
|
||||||
|
DEF(split, "split")
|
||||||
|
DEF(construct, "construct")
|
||||||
|
DEF(getPrototypeOf, "getPrototypeOf")
|
||||||
|
DEF(setPrototypeOf, "setPrototypeOf")
|
||||||
|
DEF(isExtensible, "isExtensible")
|
||||||
|
DEF(preventExtensions, "preventExtensions")
|
||||||
|
DEF(has, "has")
|
||||||
|
DEF(deleteProperty, "deleteProperty")
|
||||||
|
DEF(defineProperty, "defineProperty")
|
||||||
|
DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
|
||||||
|
DEF(ownKeys, "ownKeys")
|
||||||
|
DEF(add, "add")
|
||||||
|
DEF(done, "done")
|
||||||
|
DEF(next, "next")
|
||||||
|
DEF(values, "values")
|
||||||
|
DEF(source, "source")
|
||||||
|
DEF(flags, "flags")
|
||||||
|
DEF(global, "global")
|
||||||
|
DEF(unicode, "unicode")
|
||||||
|
DEF(raw, "raw")
|
||||||
|
DEF(new_target, "new.target")
|
||||||
|
DEF(this_active_func, "this.active_func")
|
||||||
|
DEF(home_object, "<home_object>")
|
||||||
|
DEF(computed_field, "<computed_field>")
|
||||||
|
DEF(static_computed_field, "<static_computed_field>") /* must come after computed_fields */
|
||||||
|
DEF(class_fields_init, "<class_fields_init>")
|
||||||
|
DEF(brand, "<brand>")
|
||||||
|
DEF(hash_constructor, "#constructor")
|
||||||
|
DEF(as, "as")
|
||||||
|
DEF(from, "from")
|
||||||
|
DEF(meta, "meta")
|
||||||
|
DEF(_default_, "*default*")
|
||||||
|
DEF(_star_, "*")
|
||||||
|
DEF(Module, "Module")
|
||||||
|
DEF(then, "then")
|
||||||
|
DEF(resolve, "resolve")
|
||||||
|
DEF(reject, "reject")
|
||||||
|
DEF(promise, "promise")
|
||||||
|
DEF(proxy, "proxy")
|
||||||
|
DEF(revoke, "revoke")
|
||||||
|
DEF(async, "async")
|
||||||
|
DEF(exec, "exec")
|
||||||
|
DEF(groups, "groups")
|
||||||
|
DEF(status, "status")
|
||||||
|
DEF(reason, "reason")
|
||||||
|
DEF(globalThis, "globalThis")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(bigint, "bigint")
|
||||||
|
DEF(bigfloat, "bigfloat")
|
||||||
|
DEF(bigdecimal, "bigdecimal")
|
||||||
|
DEF(roundingMode, "roundingMode")
|
||||||
|
DEF(maximumSignificantDigits, "maximumSignificantDigits")
|
||||||
|
DEF(maximumFractionDigits, "maximumFractionDigits")
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ATOMICS
|
||||||
|
DEF(not_equal, "not-equal")
|
||||||
|
DEF(timed_out, "timed-out")
|
||||||
|
DEF(ok, "ok")
|
||||||
|
#endif
|
||||||
|
DEF(toJSON, "toJSON")
|
||||||
|
/* class names */
|
||||||
|
DEF(Object, "Object")
|
||||||
|
DEF(Array, "Array")
|
||||||
|
DEF(Error, "Error")
|
||||||
|
DEF(Number, "Number")
|
||||||
|
DEF(String, "String")
|
||||||
|
DEF(Boolean, "Boolean")
|
||||||
|
DEF(Symbol, "Symbol")
|
||||||
|
DEF(Arguments, "Arguments")
|
||||||
|
DEF(Math, "Math")
|
||||||
|
DEF(JSON, "JSON")
|
||||||
|
DEF(Date, "Date")
|
||||||
|
DEF(Function, "Function")
|
||||||
|
DEF(GeneratorFunction, "GeneratorFunction")
|
||||||
|
DEF(ForInIterator, "ForInIterator")
|
||||||
|
DEF(RegExp, "RegExp")
|
||||||
|
DEF(ArrayBuffer, "ArrayBuffer")
|
||||||
|
DEF(SharedArrayBuffer, "SharedArrayBuffer")
|
||||||
|
/* must keep same order as class IDs for typed arrays */
|
||||||
|
DEF(Uint8ClampedArray, "Uint8ClampedArray")
|
||||||
|
DEF(Int8Array, "Int8Array")
|
||||||
|
DEF(Uint8Array, "Uint8Array")
|
||||||
|
DEF(Int16Array, "Int16Array")
|
||||||
|
DEF(Uint16Array, "Uint16Array")
|
||||||
|
DEF(Int32Array, "Int32Array")
|
||||||
|
DEF(Uint32Array, "Uint32Array")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(BigInt64Array, "BigInt64Array")
|
||||||
|
DEF(BigUint64Array, "BigUint64Array")
|
||||||
|
#endif
|
||||||
|
DEF(Float32Array, "Float32Array")
|
||||||
|
DEF(Float64Array, "Float64Array")
|
||||||
|
DEF(DataView, "DataView")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(BigInt, "BigInt")
|
||||||
|
DEF(BigFloat, "BigFloat")
|
||||||
|
DEF(BigFloatEnv, "BigFloatEnv")
|
||||||
|
DEF(BigDecimal, "BigDecimal")
|
||||||
|
DEF(OperatorSet, "OperatorSet")
|
||||||
|
DEF(Operators, "Operators")
|
||||||
|
#endif
|
||||||
|
DEF(Map, "Map")
|
||||||
|
DEF(Set, "Set") /* Map + 1 */
|
||||||
|
DEF(WeakMap, "WeakMap") /* Map + 2 */
|
||||||
|
DEF(WeakSet, "WeakSet") /* Map + 3 */
|
||||||
|
DEF(Map_Iterator, "Map Iterator")
|
||||||
|
DEF(Set_Iterator, "Set Iterator")
|
||||||
|
DEF(Array_Iterator, "Array Iterator")
|
||||||
|
DEF(String_Iterator, "String Iterator")
|
||||||
|
DEF(RegExp_String_Iterator, "RegExp String Iterator")
|
||||||
|
DEF(Generator, "Generator")
|
||||||
|
DEF(Proxy, "Proxy")
|
||||||
|
DEF(Promise, "Promise")
|
||||||
|
DEF(PromiseResolveFunction, "PromiseResolveFunction")
|
||||||
|
DEF(PromiseRejectFunction, "PromiseRejectFunction")
|
||||||
|
DEF(AsyncFunction, "AsyncFunction")
|
||||||
|
DEF(AsyncFunctionResolve, "AsyncFunctionResolve")
|
||||||
|
DEF(AsyncFunctionReject, "AsyncFunctionReject")
|
||||||
|
DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction")
|
||||||
|
DEF(AsyncGenerator, "AsyncGenerator")
|
||||||
|
DEF(EvalError, "EvalError")
|
||||||
|
DEF(RangeError, "RangeError")
|
||||||
|
DEF(ReferenceError, "ReferenceError")
|
||||||
|
DEF(SyntaxError, "SyntaxError")
|
||||||
|
DEF(TypeError, "TypeError")
|
||||||
|
DEF(URIError, "URIError")
|
||||||
|
DEF(InternalError, "InternalError")
|
||||||
|
/* private symbols */
|
||||||
|
DEF(Private_brand, "<brand>")
|
||||||
|
/* symbols */
|
||||||
|
DEF(Symbol_toPrimitive, "Symbol.toPrimitive")
|
||||||
|
DEF(Symbol_iterator, "Symbol.iterator")
|
||||||
|
DEF(Symbol_match, "Symbol.match")
|
||||||
|
DEF(Symbol_matchAll, "Symbol.matchAll")
|
||||||
|
DEF(Symbol_replace, "Symbol.replace")
|
||||||
|
DEF(Symbol_search, "Symbol.search")
|
||||||
|
DEF(Symbol_split, "Symbol.split")
|
||||||
|
DEF(Symbol_toStringTag, "Symbol.toStringTag")
|
||||||
|
DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable")
|
||||||
|
DEF(Symbol_hasInstance, "Symbol.hasInstance")
|
||||||
|
DEF(Symbol_species, "Symbol.species")
|
||||||
|
DEF(Symbol_unscopables, "Symbol.unscopables")
|
||||||
|
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
|
||||||
|
#ifdef CONFIG_BIGNUM
|
||||||
|
DEF(Symbol_operatorSet, "Symbol.operatorSet")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEF */
|
||||||
3773
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-libc.c
vendored
Normal file
3773
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-libc.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
58
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-libc.h
vendored
Normal file
58
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-libc.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* QuickJS C library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef QUICKJS_LIBC_H
|
||||||
|
#define QUICKJS_LIBC_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "quickjs.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
|
||||||
|
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
|
||||||
|
void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
|
||||||
|
void js_std_loop(JSContext *ctx);
|
||||||
|
void js_std_init_handlers(JSRuntime *rt);
|
||||||
|
void js_std_free_handlers(JSRuntime *rt);
|
||||||
|
void js_std_dump_error(JSContext *ctx);
|
||||||
|
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
|
||||||
|
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
|
||||||
|
JS_BOOL use_realpath, JS_BOOL is_main);
|
||||||
|
JSModuleDef *js_module_loader(JSContext *ctx,
|
||||||
|
const char *module_name, void *opaque);
|
||||||
|
void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
||||||
|
int flags);
|
||||||
|
void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
|
||||||
|
JSValueConst reason,
|
||||||
|
JS_BOOL is_handled, void *opaque);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" { */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* QUICKJS_LIBC_H */
|
||||||
367
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-opcode.h
vendored
Normal file
367
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs-opcode.h
vendored
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
* QuickJS opcode definitions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||||
|
* Copyright (c) 2017-2018 Charlie Gordon
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef FMT
|
||||||
|
FMT(none)
|
||||||
|
FMT(none_int)
|
||||||
|
FMT(none_loc)
|
||||||
|
FMT(none_arg)
|
||||||
|
FMT(none_var_ref)
|
||||||
|
FMT(u8)
|
||||||
|
FMT(i8)
|
||||||
|
FMT(loc8)
|
||||||
|
FMT(const8)
|
||||||
|
FMT(label8)
|
||||||
|
FMT(u16)
|
||||||
|
FMT(i16)
|
||||||
|
FMT(label16)
|
||||||
|
FMT(npop)
|
||||||
|
FMT(npopx)
|
||||||
|
FMT(npop_u16)
|
||||||
|
FMT(loc)
|
||||||
|
FMT(arg)
|
||||||
|
FMT(var_ref)
|
||||||
|
FMT(u32)
|
||||||
|
FMT(i32)
|
||||||
|
FMT(const)
|
||||||
|
FMT(label)
|
||||||
|
FMT(atom)
|
||||||
|
FMT(atom_u8)
|
||||||
|
FMT(atom_u16)
|
||||||
|
FMT(atom_label_u8)
|
||||||
|
FMT(atom_label_u16)
|
||||||
|
FMT(label_u16)
|
||||||
|
#undef FMT
|
||||||
|
#endif /* FMT */
|
||||||
|
|
||||||
|
#ifdef DEF
|
||||||
|
|
||||||
|
#ifndef def
|
||||||
|
#define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DEF(invalid, 1, 0, 0, none) /* never emitted */
|
||||||
|
|
||||||
|
/* push values */
|
||||||
|
DEF( push_i32, 5, 0, 1, i32)
|
||||||
|
DEF( push_const, 5, 0, 1, const)
|
||||||
|
DEF( fclosure, 5, 0, 1, const) /* must follow push_const */
|
||||||
|
DEF(push_atom_value, 5, 0, 1, atom)
|
||||||
|
DEF( private_symbol, 5, 0, 1, atom)
|
||||||
|
DEF( undefined, 1, 0, 1, none)
|
||||||
|
DEF( null, 1, 0, 1, none)
|
||||||
|
DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */
|
||||||
|
DEF( push_false, 1, 0, 1, none)
|
||||||
|
DEF( push_true, 1, 0, 1, none)
|
||||||
|
DEF( object, 1, 0, 1, none)
|
||||||
|
DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */
|
||||||
|
DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */
|
||||||
|
|
||||||
|
DEF( drop, 1, 1, 0, none) /* a -> */
|
||||||
|
DEF( nip, 1, 2, 1, none) /* a b -> b */
|
||||||
|
DEF( nip1, 1, 3, 2, none) /* a b c -> b c */
|
||||||
|
DEF( dup, 1, 1, 2, none) /* a -> a a */
|
||||||
|
DEF( dup1, 1, 2, 3, none) /* a b -> a a b */
|
||||||
|
DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */
|
||||||
|
DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */
|
||||||
|
DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */
|
||||||
|
DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */
|
||||||
|
DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */
|
||||||
|
DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */
|
||||||
|
DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */
|
||||||
|
DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */
|
||||||
|
DEF( swap, 1, 2, 2, none) /* a b -> b a */
|
||||||
|
DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */
|
||||||
|
DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */
|
||||||
|
DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */
|
||||||
|
DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */
|
||||||
|
DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */
|
||||||
|
|
||||||
|
DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */
|
||||||
|
DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */
|
||||||
|
DEF( apply, 3, 3, 1, u16)
|
||||||
|
DEF( return, 1, 1, 0, none)
|
||||||
|
DEF( return_undef, 1, 0, 0, none)
|
||||||
|
DEF(check_ctor_return, 1, 1, 2, none)
|
||||||
|
DEF( check_ctor, 1, 0, 0, none)
|
||||||
|
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
|
||||||
|
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
|
||||||
|
DEF( return_async, 1, 1, 0, none)
|
||||||
|
DEF( throw, 1, 1, 0, none)
|
||||||
|
DEF( throw_var, 6, 0, 0, atom_u8)
|
||||||
|
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
||||||
|
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
|
||||||
|
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||||
|
bytecode string */
|
||||||
|
DEF( get_super, 1, 1, 1, none)
|
||||||
|
DEF( import, 1, 1, 1, none) /* dynamic module import */
|
||||||
|
|
||||||
|
DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */
|
||||||
|
DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */
|
||||||
|
DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */
|
||||||
|
DEF( put_var, 5, 1, 0, atom) /* must come after get_var */
|
||||||
|
DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */
|
||||||
|
DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */
|
||||||
|
|
||||||
|
DEF( get_ref_value, 1, 2, 3, none)
|
||||||
|
DEF( put_ref_value, 1, 3, 0, none)
|
||||||
|
|
||||||
|
DEF( define_var, 6, 0, 0, atom_u8)
|
||||||
|
DEF(check_define_var, 6, 0, 0, atom_u8)
|
||||||
|
DEF( define_func, 6, 1, 0, atom_u8)
|
||||||
|
DEF( get_field, 5, 1, 1, atom)
|
||||||
|
DEF( get_field2, 5, 1, 2, atom)
|
||||||
|
DEF( put_field, 5, 2, 0, atom)
|
||||||
|
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
|
||||||
|
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
|
||||||
|
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
|
||||||
|
DEF( get_array_el, 1, 2, 1, none)
|
||||||
|
DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */
|
||||||
|
DEF( put_array_el, 1, 3, 0, none)
|
||||||
|
DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */
|
||||||
|
DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */
|
||||||
|
DEF( define_field, 5, 2, 1, atom)
|
||||||
|
DEF( set_name, 5, 1, 1, atom)
|
||||||
|
DEF(set_name_computed, 1, 2, 2, none)
|
||||||
|
DEF( set_proto, 1, 2, 1, none)
|
||||||
|
DEF(set_home_object, 1, 2, 2, none)
|
||||||
|
DEF(define_array_el, 1, 3, 2, none)
|
||||||
|
DEF( append, 1, 3, 2, none) /* append enumerated object, update length */
|
||||||
|
DEF(copy_data_properties, 2, 3, 3, u8)
|
||||||
|
DEF( define_method, 6, 2, 1, atom_u8)
|
||||||
|
DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */
|
||||||
|
DEF( define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */
|
||||||
|
DEF( define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */
|
||||||
|
|
||||||
|
DEF( get_loc, 3, 0, 1, loc)
|
||||||
|
DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */
|
||||||
|
DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
|
||||||
|
DEF( get_arg, 3, 0, 1, arg)
|
||||||
|
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
|
||||||
|
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
|
||||||
|
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||||
|
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
|
||||||
|
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
|
||||||
|
DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||||
|
DEF( get_loc_check, 3, 0, 1, loc)
|
||||||
|
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||||
|
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||||
|
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||||
|
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||||
|
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||||
|
DEF( close_loc, 3, 0, 0, loc)
|
||||||
|
DEF( if_false, 5, 1, 0, label)
|
||||||
|
DEF( if_true, 5, 1, 0, label) /* must come after if_false */
|
||||||
|
DEF( goto, 5, 0, 0, label) /* must come after if_true */
|
||||||
|
DEF( catch, 5, 0, 1, label)
|
||||||
|
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
|
||||||
|
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
|
||||||
|
|
||||||
|
DEF( to_object, 1, 1, 1, none)
|
||||||
|
//DEF( to_string, 1, 1, 1, none)
|
||||||
|
DEF( to_propkey, 1, 1, 1, none)
|
||||||
|
DEF( to_propkey2, 1, 2, 2, none)
|
||||||
|
|
||||||
|
DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||||
|
DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8)
|
||||||
|
|
||||||
|
DEF( make_loc_ref, 7, 0, 2, atom_u16)
|
||||||
|
DEF( make_arg_ref, 7, 0, 2, atom_u16)
|
||||||
|
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
|
||||||
|
DEF( make_var_ref, 5, 0, 2, atom)
|
||||||
|
|
||||||
|
DEF( for_in_start, 1, 1, 1, none)
|
||||||
|
DEF( for_of_start, 1, 1, 3, none)
|
||||||
|
DEF(for_await_of_start, 1, 1, 3, none)
|
||||||
|
DEF( for_in_next, 1, 1, 3, none)
|
||||||
|
DEF( for_of_next, 2, 3, 5, u8)
|
||||||
|
DEF(for_await_of_next, 1, 3, 4, none)
|
||||||
|
DEF(iterator_get_value_done, 1, 1, 2, none)
|
||||||
|
DEF( iterator_close, 1, 3, 0, none)
|
||||||
|
DEF(iterator_close_return, 1, 4, 4, none)
|
||||||
|
DEF(async_iterator_close, 1, 3, 2, none)
|
||||||
|
DEF(async_iterator_next, 1, 4, 4, none)
|
||||||
|
DEF(async_iterator_get, 2, 4, 5, u8)
|
||||||
|
DEF( initial_yield, 1, 0, 0, none)
|
||||||
|
DEF( yield, 1, 1, 2, none)
|
||||||
|
DEF( yield_star, 1, 2, 2, none)
|
||||||
|
DEF(async_yield_star, 1, 1, 2, none)
|
||||||
|
DEF( await, 1, 1, 1, none)
|
||||||
|
|
||||||
|
/* arithmetic/logic operations */
|
||||||
|
DEF( neg, 1, 1, 1, none)
|
||||||
|
DEF( plus, 1, 1, 1, none)
|
||||||
|
DEF( dec, 1, 1, 1, none)
|
||||||
|
DEF( inc, 1, 1, 1, none)
|
||||||
|
DEF( post_dec, 1, 1, 2, none)
|
||||||
|
DEF( post_inc, 1, 1, 2, none)
|
||||||
|
DEF( dec_loc, 2, 0, 0, loc8)
|
||||||
|
DEF( inc_loc, 2, 0, 0, loc8)
|
||||||
|
DEF( add_loc, 2, 1, 0, loc8)
|
||||||
|
DEF( not, 1, 1, 1, none)
|
||||||
|
DEF( lnot, 1, 1, 1, none)
|
||||||
|
DEF( typeof, 1, 1, 1, none)
|
||||||
|
DEF( delete, 1, 2, 1, none)
|
||||||
|
DEF( delete_var, 5, 0, 1, atom)
|
||||||
|
|
||||||
|
DEF( mul, 1, 2, 1, none)
|
||||||
|
DEF( div, 1, 2, 1, none)
|
||||||
|
DEF( mod, 1, 2, 1, none)
|
||||||
|
DEF( add, 1, 2, 1, none)
|
||||||
|
DEF( sub, 1, 2, 1, none)
|
||||||
|
DEF( pow, 1, 2, 1, none)
|
||||||
|
DEF( shl, 1, 2, 1, none)
|
||||||
|
DEF( sar, 1, 2, 1, none)
|
||||||
|
DEF( shr, 1, 2, 1, none)
|
||||||
|
DEF( lt, 1, 2, 1, none)
|
||||||
|
DEF( lte, 1, 2, 1, none)
|
||||||
|
DEF( gt, 1, 2, 1, none)
|
||||||
|
DEF( gte, 1, 2, 1, none)
|
||||||
|
DEF( instanceof, 1, 2, 1, none)
|
||||||
|
DEF( in, 1, 2, 1, none)
|
||||||
|
DEF( eq, 1, 2, 1, none)
|
||||||
|
DEF( neq, 1, 2, 1, none)
|
||||||
|
DEF( strict_eq, 1, 2, 1, none)
|
||||||
|
DEF( strict_neq, 1, 2, 1, none)
|
||||||
|
DEF( and, 1, 2, 1, none)
|
||||||
|
DEF( xor, 1, 2, 1, none)
|
||||||
|
DEF( or, 1, 2, 1, none)
|
||||||
|
DEF(is_undefined_or_null, 1, 1, 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)
|
||||||
|
|
||||||
|
/* temporary opcodes: never emitted in the final bytecode */
|
||||||
|
|
||||||
|
def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
|
def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
|
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
|
||||||
|
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
||||||
|
def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
|
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
||||||
|
|
||||||
|
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
|
||||||
|
|
||||||
|
#if SHORT_OPCODES
|
||||||
|
DEF( push_minus1, 1, 0, 1, none_int)
|
||||||
|
DEF( push_0, 1, 0, 1, none_int)
|
||||||
|
DEF( push_1, 1, 0, 1, none_int)
|
||||||
|
DEF( push_2, 1, 0, 1, none_int)
|
||||||
|
DEF( push_3, 1, 0, 1, none_int)
|
||||||
|
DEF( push_4, 1, 0, 1, none_int)
|
||||||
|
DEF( push_5, 1, 0, 1, none_int)
|
||||||
|
DEF( push_6, 1, 0, 1, none_int)
|
||||||
|
DEF( push_7, 1, 0, 1, none_int)
|
||||||
|
DEF( push_i8, 2, 0, 1, i8)
|
||||||
|
DEF( push_i16, 3, 0, 1, i16)
|
||||||
|
DEF( push_const8, 2, 0, 1, const8)
|
||||||
|
DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */
|
||||||
|
DEF(push_empty_string, 1, 0, 1, none)
|
||||||
|
|
||||||
|
DEF( get_loc8, 2, 0, 1, loc8)
|
||||||
|
DEF( put_loc8, 2, 1, 0, loc8)
|
||||||
|
DEF( set_loc8, 2, 1, 1, loc8)
|
||||||
|
|
||||||
|
DEF( get_loc0, 1, 0, 1, none_loc)
|
||||||
|
DEF( get_loc1, 1, 0, 1, none_loc)
|
||||||
|
DEF( get_loc2, 1, 0, 1, none_loc)
|
||||||
|
DEF( get_loc3, 1, 0, 1, none_loc)
|
||||||
|
DEF( put_loc0, 1, 1, 0, none_loc)
|
||||||
|
DEF( put_loc1, 1, 1, 0, none_loc)
|
||||||
|
DEF( put_loc2, 1, 1, 0, none_loc)
|
||||||
|
DEF( put_loc3, 1, 1, 0, none_loc)
|
||||||
|
DEF( set_loc0, 1, 1, 1, none_loc)
|
||||||
|
DEF( set_loc1, 1, 1, 1, none_loc)
|
||||||
|
DEF( set_loc2, 1, 1, 1, none_loc)
|
||||||
|
DEF( set_loc3, 1, 1, 1, none_loc)
|
||||||
|
DEF( get_arg0, 1, 0, 1, none_arg)
|
||||||
|
DEF( get_arg1, 1, 0, 1, none_arg)
|
||||||
|
DEF( get_arg2, 1, 0, 1, none_arg)
|
||||||
|
DEF( get_arg3, 1, 0, 1, none_arg)
|
||||||
|
DEF( put_arg0, 1, 1, 0, none_arg)
|
||||||
|
DEF( put_arg1, 1, 1, 0, none_arg)
|
||||||
|
DEF( put_arg2, 1, 1, 0, none_arg)
|
||||||
|
DEF( put_arg3, 1, 1, 0, none_arg)
|
||||||
|
DEF( set_arg0, 1, 1, 1, none_arg)
|
||||||
|
DEF( set_arg1, 1, 1, 1, none_arg)
|
||||||
|
DEF( set_arg2, 1, 1, 1, none_arg)
|
||||||
|
DEF( set_arg3, 1, 1, 1, none_arg)
|
||||||
|
DEF( get_var_ref0, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( get_var_ref1, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( get_var_ref2, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( get_var_ref3, 1, 0, 1, none_var_ref)
|
||||||
|
DEF( put_var_ref0, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( put_var_ref1, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( put_var_ref2, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( put_var_ref3, 1, 1, 0, none_var_ref)
|
||||||
|
DEF( set_var_ref0, 1, 1, 1, none_var_ref)
|
||||||
|
DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
||||||
|
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||||
|
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||||
|
|
||||||
|
DEF( get_length, 1, 1, 1, none)
|
||||||
|
|
||||||
|
DEF( if_false8, 2, 1, 0, label8)
|
||||||
|
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||||
|
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
||||||
|
DEF( goto16, 3, 0, 0, label16)
|
||||||
|
|
||||||
|
DEF( call0, 1, 1, 1, npopx)
|
||||||
|
DEF( call1, 1, 1, 1, npopx)
|
||||||
|
DEF( call2, 1, 1, 1, npopx)
|
||||||
|
DEF( call3, 1, 1, 1, npopx)
|
||||||
|
|
||||||
|
DEF( is_undefined, 1, 1, 1, none)
|
||||||
|
DEF( is_null, 1, 1, 1, none)
|
||||||
|
DEF( is_function, 1, 1, 1, none)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef DEF
|
||||||
|
#undef def
|
||||||
|
#endif /* DEF */
|
||||||
53313
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs.c
vendored
Normal file
53313
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1030
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs.h
vendored
Normal file
1030
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/quickjs.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/readme.txt
vendored
Normal file
1
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/readme.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
The main documentation is in doc/quickjs.pdf or doc/quickjs.html.
|
||||||
3057
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/unicode_gen.c
vendored
Normal file
3057
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/unicode_gen.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
284
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/unicode_gen_def.h
vendored
Normal file
284
quickjs/external/quickjs-rs/libquickjs-sys/embed/quickjs/unicode_gen_def.h
vendored
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
#ifdef UNICODE_GENERAL_CATEGORY
|
||||||
|
DEF(Cn, "Unassigned") /* must be zero */
|
||||||
|
DEF(Lu, "Uppercase_Letter")
|
||||||
|
DEF(Ll, "Lowercase_Letter")
|
||||||
|
DEF(Lt, "Titlecase_Letter")
|
||||||
|
DEF(Lm, "Modifier_Letter")
|
||||||
|
DEF(Lo, "Other_Letter")
|
||||||
|
DEF(Mn, "Nonspacing_Mark")
|
||||||
|
DEF(Mc, "Spacing_Mark")
|
||||||
|
DEF(Me, "Enclosing_Mark")
|
||||||
|
DEF(Nd, "Decimal_Number,digit")
|
||||||
|
DEF(Nl, "Letter_Number")
|
||||||
|
DEF(No, "Other_Number")
|
||||||
|
DEF(Sm, "Math_Symbol")
|
||||||
|
DEF(Sc, "Currency_Symbol")
|
||||||
|
DEF(Sk, "Modifier_Symbol")
|
||||||
|
DEF(So, "Other_Symbol")
|
||||||
|
DEF(Pc, "Connector_Punctuation")
|
||||||
|
DEF(Pd, "Dash_Punctuation")
|
||||||
|
DEF(Ps, "Open_Punctuation")
|
||||||
|
DEF(Pe, "Close_Punctuation")
|
||||||
|
DEF(Pi, "Initial_Punctuation")
|
||||||
|
DEF(Pf, "Final_Punctuation")
|
||||||
|
DEF(Po, "Other_Punctuation")
|
||||||
|
DEF(Zs, "Space_Separator")
|
||||||
|
DEF(Zl, "Line_Separator")
|
||||||
|
DEF(Zp, "Paragraph_Separator")
|
||||||
|
DEF(Cc, "Control,cntrl")
|
||||||
|
DEF(Cf, "Format")
|
||||||
|
DEF(Cs, "Surrogate")
|
||||||
|
DEF(Co, "Private_Use")
|
||||||
|
/* synthetic properties */
|
||||||
|
DEF(LC, "Cased_Letter")
|
||||||
|
DEF(L, "Letter")
|
||||||
|
DEF(M, "Mark,Combining_Mark")
|
||||||
|
DEF(N, "Number")
|
||||||
|
DEF(S, "Symbol")
|
||||||
|
DEF(P, "Punctuation,punct")
|
||||||
|
DEF(Z, "Separator")
|
||||||
|
DEF(C, "Other")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE_SCRIPT
|
||||||
|
/* scripts aliases names in PropertyValueAliases.txt */
|
||||||
|
DEF(Unknown, "Zzzz")
|
||||||
|
DEF(Adlam, "Adlm")
|
||||||
|
DEF(Ahom, "Ahom")
|
||||||
|
DEF(Anatolian_Hieroglyphs, "Hluw")
|
||||||
|
DEF(Arabic, "Arab")
|
||||||
|
DEF(Armenian, "Armn")
|
||||||
|
DEF(Avestan, "Avst")
|
||||||
|
DEF(Balinese, "Bali")
|
||||||
|
DEF(Bamum, "Bamu")
|
||||||
|
DEF(Bassa_Vah, "Bass")
|
||||||
|
DEF(Batak, "Batk")
|
||||||
|
DEF(Bengali, "Beng")
|
||||||
|
DEF(Bhaiksuki, "Bhks")
|
||||||
|
DEF(Bopomofo, "Bopo")
|
||||||
|
DEF(Brahmi, "Brah")
|
||||||
|
DEF(Braille, "Brai")
|
||||||
|
DEF(Buginese, "Bugi")
|
||||||
|
DEF(Buhid, "Buhd")
|
||||||
|
DEF(Canadian_Aboriginal, "Cans")
|
||||||
|
DEF(Carian, "Cari")
|
||||||
|
DEF(Caucasian_Albanian, "Aghb")
|
||||||
|
DEF(Chakma, "Cakm")
|
||||||
|
DEF(Cham, "Cham")
|
||||||
|
DEF(Cherokee, "Cher")
|
||||||
|
DEF(Chorasmian, "Chrs")
|
||||||
|
DEF(Common, "Zyyy")
|
||||||
|
DEF(Coptic, "Copt,Qaac")
|
||||||
|
DEF(Cuneiform, "Xsux")
|
||||||
|
DEF(Cypriot, "Cprt")
|
||||||
|
DEF(Cyrillic, "Cyrl")
|
||||||
|
DEF(Deseret, "Dsrt")
|
||||||
|
DEF(Devanagari, "Deva")
|
||||||
|
DEF(Dives_Akuru, "Diak")
|
||||||
|
DEF(Dogra, "Dogr")
|
||||||
|
DEF(Duployan, "Dupl")
|
||||||
|
DEF(Egyptian_Hieroglyphs, "Egyp")
|
||||||
|
DEF(Elbasan, "Elba")
|
||||||
|
DEF(Elymaic, "Elym")
|
||||||
|
DEF(Ethiopic, "Ethi")
|
||||||
|
DEF(Georgian, "Geor")
|
||||||
|
DEF(Glagolitic, "Glag")
|
||||||
|
DEF(Gothic, "Goth")
|
||||||
|
DEF(Grantha, "Gran")
|
||||||
|
DEF(Greek, "Grek")
|
||||||
|
DEF(Gujarati, "Gujr")
|
||||||
|
DEF(Gunjala_Gondi, "Gong")
|
||||||
|
DEF(Gurmukhi, "Guru")
|
||||||
|
DEF(Han, "Hani")
|
||||||
|
DEF(Hangul, "Hang")
|
||||||
|
DEF(Hanifi_Rohingya, "Rohg")
|
||||||
|
DEF(Hanunoo, "Hano")
|
||||||
|
DEF(Hatran, "Hatr")
|
||||||
|
DEF(Hebrew, "Hebr")
|
||||||
|
DEF(Hiragana, "Hira")
|
||||||
|
DEF(Imperial_Aramaic, "Armi")
|
||||||
|
DEF(Inherited, "Zinh,Qaai")
|
||||||
|
DEF(Inscriptional_Pahlavi, "Phli")
|
||||||
|
DEF(Inscriptional_Parthian, "Prti")
|
||||||
|
DEF(Javanese, "Java")
|
||||||
|
DEF(Kaithi, "Kthi")
|
||||||
|
DEF(Kannada, "Knda")
|
||||||
|
DEF(Katakana, "Kana")
|
||||||
|
DEF(Kayah_Li, "Kali")
|
||||||
|
DEF(Kharoshthi, "Khar")
|
||||||
|
DEF(Khmer, "Khmr")
|
||||||
|
DEF(Khojki, "Khoj")
|
||||||
|
DEF(Khitan_Small_Script, "Kits")
|
||||||
|
DEF(Khudawadi, "Sind")
|
||||||
|
DEF(Lao, "Laoo")
|
||||||
|
DEF(Latin, "Latn")
|
||||||
|
DEF(Lepcha, "Lepc")
|
||||||
|
DEF(Limbu, "Limb")
|
||||||
|
DEF(Linear_A, "Lina")
|
||||||
|
DEF(Linear_B, "Linb")
|
||||||
|
DEF(Lisu, "Lisu")
|
||||||
|
DEF(Lycian, "Lyci")
|
||||||
|
DEF(Lydian, "Lydi")
|
||||||
|
DEF(Makasar, "Maka")
|
||||||
|
DEF(Mahajani, "Mahj")
|
||||||
|
DEF(Malayalam, "Mlym")
|
||||||
|
DEF(Mandaic, "Mand")
|
||||||
|
DEF(Manichaean, "Mani")
|
||||||
|
DEF(Marchen, "Marc")
|
||||||
|
DEF(Masaram_Gondi, "Gonm")
|
||||||
|
DEF(Medefaidrin, "Medf")
|
||||||
|
DEF(Meetei_Mayek, "Mtei")
|
||||||
|
DEF(Mende_Kikakui, "Mend")
|
||||||
|
DEF(Meroitic_Cursive, "Merc")
|
||||||
|
DEF(Meroitic_Hieroglyphs, "Mero")
|
||||||
|
DEF(Miao, "Plrd")
|
||||||
|
DEF(Modi, "Modi")
|
||||||
|
DEF(Mongolian, "Mong")
|
||||||
|
DEF(Mro, "Mroo")
|
||||||
|
DEF(Multani, "Mult")
|
||||||
|
DEF(Myanmar, "Mymr")
|
||||||
|
DEF(Nabataean, "Nbat")
|
||||||
|
DEF(Nandinagari, "Nand")
|
||||||
|
DEF(New_Tai_Lue, "Talu")
|
||||||
|
DEF(Newa, "Newa")
|
||||||
|
DEF(Nko, "Nkoo")
|
||||||
|
DEF(Nushu, "Nshu")
|
||||||
|
DEF(Nyiakeng_Puachue_Hmong, "Hmnp")
|
||||||
|
DEF(Ogham, "Ogam")
|
||||||
|
DEF(Ol_Chiki, "Olck")
|
||||||
|
DEF(Old_Hungarian, "Hung")
|
||||||
|
DEF(Old_Italic, "Ital")
|
||||||
|
DEF(Old_North_Arabian, "Narb")
|
||||||
|
DEF(Old_Permic, "Perm")
|
||||||
|
DEF(Old_Persian, "Xpeo")
|
||||||
|
DEF(Old_Sogdian, "Sogo")
|
||||||
|
DEF(Old_South_Arabian, "Sarb")
|
||||||
|
DEF(Old_Turkic, "Orkh")
|
||||||
|
DEF(Oriya, "Orya")
|
||||||
|
DEF(Osage, "Osge")
|
||||||
|
DEF(Osmanya, "Osma")
|
||||||
|
DEF(Pahawh_Hmong, "Hmng")
|
||||||
|
DEF(Palmyrene, "Palm")
|
||||||
|
DEF(Pau_Cin_Hau, "Pauc")
|
||||||
|
DEF(Phags_Pa, "Phag")
|
||||||
|
DEF(Phoenician, "Phnx")
|
||||||
|
DEF(Psalter_Pahlavi, "Phlp")
|
||||||
|
DEF(Rejang, "Rjng")
|
||||||
|
DEF(Runic, "Runr")
|
||||||
|
DEF(Samaritan, "Samr")
|
||||||
|
DEF(Saurashtra, "Saur")
|
||||||
|
DEF(Sharada, "Shrd")
|
||||||
|
DEF(Shavian, "Shaw")
|
||||||
|
DEF(Siddham, "Sidd")
|
||||||
|
DEF(SignWriting, "Sgnw")
|
||||||
|
DEF(Sinhala, "Sinh")
|
||||||
|
DEF(Sogdian, "Sogd")
|
||||||
|
DEF(Sora_Sompeng, "Sora")
|
||||||
|
DEF(Soyombo, "Soyo")
|
||||||
|
DEF(Sundanese, "Sund")
|
||||||
|
DEF(Syloti_Nagri, "Sylo")
|
||||||
|
DEF(Syriac, "Syrc")
|
||||||
|
DEF(Tagalog, "Tglg")
|
||||||
|
DEF(Tagbanwa, "Tagb")
|
||||||
|
DEF(Tai_Le, "Tale")
|
||||||
|
DEF(Tai_Tham, "Lana")
|
||||||
|
DEF(Tai_Viet, "Tavt")
|
||||||
|
DEF(Takri, "Takr")
|
||||||
|
DEF(Tamil, "Taml")
|
||||||
|
DEF(Tangut, "Tang")
|
||||||
|
DEF(Telugu, "Telu")
|
||||||
|
DEF(Thaana, "Thaa")
|
||||||
|
DEF(Thai, "Thai")
|
||||||
|
DEF(Tibetan, "Tibt")
|
||||||
|
DEF(Tifinagh, "Tfng")
|
||||||
|
DEF(Tirhuta, "Tirh")
|
||||||
|
DEF(Ugaritic, "Ugar")
|
||||||
|
DEF(Vai, "Vaii")
|
||||||
|
DEF(Wancho, "Wcho")
|
||||||
|
DEF(Warang_Citi, "Wara")
|
||||||
|
DEF(Yezidi, "Yezi")
|
||||||
|
DEF(Yi, "Yiii")
|
||||||
|
DEF(Zanabazar_Square, "Zanb")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE_PROP_LIST
|
||||||
|
/* Prop list not exported to regexp */
|
||||||
|
DEF(Hyphen, "")
|
||||||
|
DEF(Other_Math, "")
|
||||||
|
DEF(Other_Alphabetic, "")
|
||||||
|
DEF(Other_Lowercase, "")
|
||||||
|
DEF(Other_Uppercase, "")
|
||||||
|
DEF(Other_Grapheme_Extend, "")
|
||||||
|
DEF(Other_Default_Ignorable_Code_Point, "")
|
||||||
|
DEF(Other_ID_Start, "")
|
||||||
|
DEF(Other_ID_Continue, "")
|
||||||
|
DEF(Prepended_Concatenation_Mark, "")
|
||||||
|
/* additional computed properties for smaller tables */
|
||||||
|
DEF(ID_Continue1, "")
|
||||||
|
DEF(XID_Start1, "")
|
||||||
|
DEF(XID_Continue1, "")
|
||||||
|
DEF(Changes_When_Titlecased1, "")
|
||||||
|
DEF(Changes_When_Casefolded1, "")
|
||||||
|
DEF(Changes_When_NFKC_Casefolded1, "")
|
||||||
|
|
||||||
|
/* Prop list exported to JS */
|
||||||
|
DEF(ASCII_Hex_Digit, "AHex")
|
||||||
|
DEF(Bidi_Control, "Bidi_C")
|
||||||
|
DEF(Dash, "")
|
||||||
|
DEF(Deprecated, "Dep")
|
||||||
|
DEF(Diacritic, "Dia")
|
||||||
|
DEF(Extender, "Ext")
|
||||||
|
DEF(Hex_Digit, "Hex")
|
||||||
|
DEF(IDS_Binary_Operator, "IDSB")
|
||||||
|
DEF(IDS_Trinary_Operator, "IDST")
|
||||||
|
DEF(Ideographic, "Ideo")
|
||||||
|
DEF(Join_Control, "Join_C")
|
||||||
|
DEF(Logical_Order_Exception, "LOE")
|
||||||
|
DEF(Noncharacter_Code_Point, "NChar")
|
||||||
|
DEF(Pattern_Syntax, "Pat_Syn")
|
||||||
|
DEF(Pattern_White_Space, "Pat_WS")
|
||||||
|
DEF(Quotation_Mark, "QMark")
|
||||||
|
DEF(Radical, "")
|
||||||
|
DEF(Regional_Indicator, "RI")
|
||||||
|
DEF(Sentence_Terminal, "STerm")
|
||||||
|
DEF(Soft_Dotted, "SD")
|
||||||
|
DEF(Terminal_Punctuation, "Term")
|
||||||
|
DEF(Unified_Ideograph, "UIdeo")
|
||||||
|
DEF(Variation_Selector, "VS")
|
||||||
|
DEF(White_Space, "space")
|
||||||
|
DEF(Bidi_Mirrored, "Bidi_M")
|
||||||
|
DEF(Emoji, "")
|
||||||
|
DEF(Emoji_Component, "EComp")
|
||||||
|
DEF(Emoji_Modifier, "EMod")
|
||||||
|
DEF(Emoji_Modifier_Base, "EBase")
|
||||||
|
DEF(Emoji_Presentation, "EPres")
|
||||||
|
DEF(Extended_Pictographic, "ExtPict")
|
||||||
|
DEF(Default_Ignorable_Code_Point, "DI")
|
||||||
|
DEF(ID_Start, "IDS")
|
||||||
|
DEF(Case_Ignorable, "CI")
|
||||||
|
|
||||||
|
/* other binary properties */
|
||||||
|
DEF(ASCII,"")
|
||||||
|
DEF(Alphabetic, "Alpha")
|
||||||
|
DEF(Any, "")
|
||||||
|
DEF(Assigned,"")
|
||||||
|
DEF(Cased, "")
|
||||||
|
DEF(Changes_When_Casefolded, "CWCF")
|
||||||
|
DEF(Changes_When_Casemapped, "CWCM")
|
||||||
|
DEF(Changes_When_Lowercased, "CWL")
|
||||||
|
DEF(Changes_When_NFKC_Casefolded, "CWKCF")
|
||||||
|
DEF(Changes_When_Titlecased, "CWT")
|
||||||
|
DEF(Changes_When_Uppercased, "CWU")
|
||||||
|
DEF(Grapheme_Base, "Gr_Base")
|
||||||
|
DEF(Grapheme_Extend, "Gr_Ext")
|
||||||
|
DEF(ID_Continue, "IDC")
|
||||||
|
DEF(Lowercase, "Lower")
|
||||||
|
DEF(Math, "")
|
||||||
|
DEF(Uppercase, "Upper")
|
||||||
|
DEF(XID_Continue, "XIDC")
|
||||||
|
DEF(XID_Start, "XIDS")
|
||||||
|
|
||||||
|
/* internal tables with index */
|
||||||
|
DEF(Cased1, "")
|
||||||
|
|
||||||
|
#endif
|
||||||
3
quickjs/external/quickjs-rs/libquickjs-sys/release.toml
vendored
Normal file
3
quickjs/external/quickjs-rs/libquickjs-sys/release.toml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Configuration for the [cargo-release](https://github.com/sunng87/cargo-release) tool.
|
||||||
|
|
||||||
|
tag-prefix = "libquickjs-sys-"
|
||||||
40
quickjs/external/quickjs-rs/libquickjs-sys/src/lib.rs
vendored
Normal file
40
quickjs/external/quickjs-rs/libquickjs-sys/src/lib.rs
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//! FFI Bindings for [quickjs](https://bellard.org/quickjs/),
|
||||||
|
//! a Javascript engine.
|
||||||
|
//! See the [quickjs](https://crates.io/crates/quickjs) crate for a high-level
|
||||||
|
//! wrapper.
|
||||||
|
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Small sanity test that starts the runtime and evaluates code.
|
||||||
|
#[test]
|
||||||
|
fn test_eval() {
|
||||||
|
unsafe {
|
||||||
|
let rt = JS_NewRuntime();
|
||||||
|
let ctx = JS_NewContext(rt);
|
||||||
|
|
||||||
|
let code_str = "1 + 1\0";
|
||||||
|
let code = CStr::from_bytes_with_nul(code_str.as_bytes()).unwrap();
|
||||||
|
let script = CStr::from_bytes_with_nul("script\0".as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let value = JS_Eval(
|
||||||
|
ctx,
|
||||||
|
code.as_ptr(),
|
||||||
|
code_str.len() - 1,
|
||||||
|
script.as_ptr(),
|
||||||
|
JS_EVAL_TYPE_GLOBAL as i32,
|
||||||
|
);
|
||||||
|
assert_eq!(value.tag, 0);
|
||||||
|
assert_eq!(value.u.int32, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
quickjs/external/quickjs-rs/libquickjs-sys/wrapper.h
vendored
Normal file
2
quickjs/external/quickjs-rs/libquickjs-sys/wrapper.h
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
#include <quickjs/quickjs.h>
|
||||||
7
quickjs/external/quickjs-rs/release.toml
vendored
Normal file
7
quickjs/external/quickjs-rs/release.toml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Configuration for the [cargo-release](https://github.com/sunng87/cargo-release) tool.
|
||||||
|
|
||||||
|
pre-release-replacements = [
|
||||||
|
{file="README.md", search="quick-js = .*", replace="{{crate_name}} = \"{{version}}\""},
|
||||||
|
]
|
||||||
|
|
||||||
|
tag-prefix = "quick-js-"
|
||||||
11
quickjs/external/quickjs-rs/shell.nix
vendored
Normal file
11
quickjs/external/quickjs-rs/shell.nix
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
|
||||||
|
pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
gcc
|
||||||
|
just
|
||||||
|
rust-bindgen
|
||||||
|
cargo
|
||||||
|
cargo-release
|
||||||
|
];
|
||||||
|
}
|
||||||
1187
quickjs/external/quickjs-rs/src/bindings.rs
vendored
Normal file
1187
quickjs/external/quickjs-rs/src/bindings.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
297
quickjs/external/quickjs-rs/src/callback.rs
vendored
Normal file
297
quickjs/external/quickjs-rs/src/callback.rs
vendored
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
use std::{convert::TryFrom, marker::PhantomData, panic::RefUnwindSafe};
|
||||||
|
|
||||||
|
use crate::value::{JsValue, ValueError};
|
||||||
|
|
||||||
|
pub trait IntoCallbackResult {
|
||||||
|
fn into_callback_res(self) -> Result<JsValue, String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<JsValue>> IntoCallbackResult for T {
|
||||||
|
fn into_callback_res(self) -> Result<JsValue, String> {
|
||||||
|
Ok(self.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<JsValue>, E: std::fmt::Display> IntoCallbackResult for Result<T, E> {
|
||||||
|
fn into_callback_res(self) -> Result<JsValue, String> {
|
||||||
|
match self {
|
||||||
|
Ok(v) => Ok(v.into()),
|
||||||
|
Err(e) => Err(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Callback trait is implemented for functions/closures that can be
|
||||||
|
/// used as callbacks in the JS runtime.
|
||||||
|
pub trait Callback<F>: RefUnwindSafe {
|
||||||
|
/// The number of JS arguments required.
|
||||||
|
fn argument_count(&self) -> usize;
|
||||||
|
/// Execute the callback.
|
||||||
|
///
|
||||||
|
/// Should return:
|
||||||
|
/// - Err(_) if the JS values could not be converted
|
||||||
|
/// - Ok(Err(_)) if an error ocurred while processing.
|
||||||
|
/// The given error will be raised as a JS exception.
|
||||||
|
/// - Ok(Ok(result)) when execution succeeded.
|
||||||
|
fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_callback {
|
||||||
|
(@call $len:literal $self:ident $args:ident ) => {
|
||||||
|
$self()
|
||||||
|
};
|
||||||
|
|
||||||
|
(@call $len:literal $self:ident $args:ident $( $arg:ident ),* ) => {
|
||||||
|
{
|
||||||
|
let mut iter = $args.into_iter();
|
||||||
|
$self(
|
||||||
|
$(
|
||||||
|
$arg::try_from(iter.next().unwrap())?,
|
||||||
|
)*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[ $( $len:literal : ( $( $arg:ident, )* ), )* ] => {
|
||||||
|
$(
|
||||||
|
|
||||||
|
impl<
|
||||||
|
$( $arg, )*
|
||||||
|
R,
|
||||||
|
F,
|
||||||
|
> Callback<PhantomData<(
|
||||||
|
$( &$arg, )*
|
||||||
|
&R,
|
||||||
|
&F,
|
||||||
|
)>> for F
|
||||||
|
where
|
||||||
|
$( $arg: TryFrom<JsValue, Error = ValueError>, )*
|
||||||
|
R: IntoCallbackResult,
|
||||||
|
F: Fn( $( $arg, )* ) -> R + Sized + RefUnwindSafe,
|
||||||
|
{
|
||||||
|
fn argument_count(&self) -> usize {
|
||||||
|
$len
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
if args.len() != $len {
|
||||||
|
return Ok(Err(format!(
|
||||||
|
"Invalid argument count: Expected {}, got {}",
|
||||||
|
self.argument_count(),
|
||||||
|
args.len()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = impl_callback!(@call $len self args $($arg),* );
|
||||||
|
Ok(res.into_callback_res())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_callback![
|
||||||
|
0: (),
|
||||||
|
1: (A1,),
|
||||||
|
2: (A1, A2,),
|
||||||
|
3: (A1, A2, A3,),
|
||||||
|
4: (A1, A2, A3, A4,),
|
||||||
|
5: (A1, A2, A3, A4, A5,),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// A wrapper around Vec<JsValue>, used for vararg callbacks.
|
||||||
|
///
|
||||||
|
/// To create a callback with a variable number of arguments, a callback closure
|
||||||
|
/// must take a single `Arguments` argument.
|
||||||
|
pub struct Arguments(Vec<JsValue>);
|
||||||
|
|
||||||
|
impl Arguments {
|
||||||
|
/// Unpack the arguments into a Vec.
|
||||||
|
pub fn into_vec(self) -> Vec<JsValue> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> Callback<PhantomData<(&Arguments, &F)>> for F
|
||||||
|
where
|
||||||
|
F: Fn(Arguments) + Sized + RefUnwindSafe,
|
||||||
|
{
|
||||||
|
fn argument_count(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
(self)(Arguments(args));
|
||||||
|
Ok(Ok(JsValue::Null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, R> Callback<PhantomData<(&Arguments, &F, &R)>> for F
|
||||||
|
where
|
||||||
|
R: IntoCallbackResult,
|
||||||
|
F: Fn(Arguments) -> R + Sized + RefUnwindSafe,
|
||||||
|
{
|
||||||
|
fn argument_count(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
let res = (self)(Arguments(args));
|
||||||
|
Ok(res.into_callback_res())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement Callback for Fn() -> R functions.
|
||||||
|
//impl<R, F> Callback<PhantomData<(&R, &F)>> for F
|
||||||
|
//where
|
||||||
|
//R: Into<JsValue>,
|
||||||
|
//F: Fn() -> R + Sized + RefUnwindSafe,
|
||||||
|
//{
|
||||||
|
//fn argument_count(&self) -> usize {
|
||||||
|
//0
|
||||||
|
//}
|
||||||
|
|
||||||
|
//fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
//if !args.is_empty() {
|
||||||
|
//return Ok(Err(format!(
|
||||||
|
//"Invalid argument count: Expected 0, got {}",
|
||||||
|
//args.len()
|
||||||
|
//)));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let res = self().into();
|
||||||
|
//Ok(Ok(res))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Implement Callback for Fn(A) -> R functions.
|
||||||
|
//impl<A1, R, F> Callback<PhantomData<(&A1, &R, &F)>> for F
|
||||||
|
//where
|
||||||
|
//A1: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//R: Into<JsValue>,
|
||||||
|
//F: Fn(A1) -> R + Sized + RefUnwindSafe,
|
||||||
|
//{
|
||||||
|
//fn argument_count(&self) -> usize {
|
||||||
|
//1
|
||||||
|
//}
|
||||||
|
//fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
//if args.len() != 1 {
|
||||||
|
//return Ok(Err(format!(
|
||||||
|
//"Invalid argument count: Expected 1, got {}",
|
||||||
|
//args.len()
|
||||||
|
//)));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let arg_raw = args.into_iter().next().expect("Invalid argument count");
|
||||||
|
//let arg = A1::try_from(arg_raw)?;
|
||||||
|
//let res = self(arg).into();
|
||||||
|
//Ok(Ok(res))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// Implement Callback for Fn(A1, A2) -> R functions.
|
||||||
|
//impl<A1, A2, R, F> Callback<PhantomData<(&A1, &A2, &R, &F)>> for F
|
||||||
|
//where
|
||||||
|
//A1: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//A2: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//R: Into<JsValue>,
|
||||||
|
//F: Fn(A1, A2) -> R + Sized + RefUnwindSafe,
|
||||||
|
//{
|
||||||
|
//fn argument_count(&self) -> usize {
|
||||||
|
//2
|
||||||
|
//}
|
||||||
|
|
||||||
|
//fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
//if args.len() != 2 {
|
||||||
|
//return Ok(Err(format!(
|
||||||
|
//"Invalid argument count: Expected 2, got {}",
|
||||||
|
//args.len()
|
||||||
|
//)));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let mut iter = args.into_iter();
|
||||||
|
//let arg1_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg1 = A1::try_from(arg1_raw)?;
|
||||||
|
|
||||||
|
//let arg2_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg2 = A2::try_from(arg2_raw)?;
|
||||||
|
|
||||||
|
//let res = self(arg1, arg2).into();
|
||||||
|
//Ok(Ok(res))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Implement Callback for Fn(A1, A2, A3) -> R functions.
|
||||||
|
//impl<A1, A2, A3, R, F> Callback<PhantomData<(&A1, &A2, &A3, &R, &F)>> for F
|
||||||
|
//where
|
||||||
|
//A1: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//A2: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//A3: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//R: Into<JsValue>,
|
||||||
|
//F: Fn(A1, A2, A3) -> R + Sized + RefUnwindSafe,
|
||||||
|
//{
|
||||||
|
//fn argument_count(&self) -> usize {
|
||||||
|
//3
|
||||||
|
//}
|
||||||
|
|
||||||
|
//fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
//if args.len() != self.argument_count() {
|
||||||
|
//return Ok(Err(format!(
|
||||||
|
//"Invalid argument count: Expected 3, got {}",
|
||||||
|
//args.len()
|
||||||
|
//)));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let mut iter = args.into_iter();
|
||||||
|
//let arg1_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg1 = A1::try_from(arg1_raw)?;
|
||||||
|
|
||||||
|
//let arg2_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg2 = A2::try_from(arg2_raw)?;
|
||||||
|
|
||||||
|
//let arg3_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg3 = A3::try_from(arg3_raw)?;
|
||||||
|
|
||||||
|
//let res = self(arg1, arg2, arg3).into();
|
||||||
|
//Ok(Ok(res))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// Implement Callback for Fn(A1, A2, A3, A4) -> R functions.
|
||||||
|
//impl<A1, A2, A3, A4, R, F> Callback<PhantomData<(&A1, &A2, &A3, &A4, &R, &F)>> for F
|
||||||
|
//where
|
||||||
|
//A1: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//A2: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//A3: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//A4: TryFrom<JsValue, Error = ValueError>,
|
||||||
|
//R: Into<JsValue>,
|
||||||
|
//F: Fn(A1, A2, A3) -> R + Sized + RefUnwindSafe,
|
||||||
|
//{
|
||||||
|
//fn argument_count(&self) -> usize {
|
||||||
|
//4
|
||||||
|
//}
|
||||||
|
|
||||||
|
//fn call(&self, args: Vec<JsValue>) -> Result<Result<JsValue, String>, ValueError> {
|
||||||
|
//if args.len() != self.argument_count() {
|
||||||
|
//return Ok(Err(format!(
|
||||||
|
//"Invalid argument count: Expected 3, got {}",
|
||||||
|
//args.len()
|
||||||
|
//)));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let mut iter = args.into_iter();
|
||||||
|
//let arg1_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg1 = A1::try_from(arg1_raw)?;
|
||||||
|
|
||||||
|
//let arg2_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg2 = A2::try_from(arg2_raw)?;
|
||||||
|
|
||||||
|
//let arg3_raw = iter.next().expect("Invalid argument count");
|
||||||
|
//let arg3 = A3::try_from(arg3_raw)?;
|
||||||
|
|
||||||
|
//let res = self(arg1, arg2, arg3).into();
|
||||||
|
//Ok(Ok(res))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
// RESULT variants.
|
||||||
137
quickjs/external/quickjs-rs/src/console.rs
vendored
Normal file
137
quickjs/external/quickjs-rs/src/console.rs
vendored
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
//! Javascript console integration.
|
||||||
|
//! See the [ConsoleBackend] trait for more info.
|
||||||
|
|
||||||
|
use super::JsValue;
|
||||||
|
|
||||||
|
/// Log level of a log message sent via the console.
|
||||||
|
/// These levels represent the different functions defined in the spec:
|
||||||
|
/// https://s3.amazonaws.com/temp.michaelfbryan.com/callbacks/index.html
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
pub enum Level {
|
||||||
|
Trace,
|
||||||
|
Debug,
|
||||||
|
Log,
|
||||||
|
Info,
|
||||||
|
Warn,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Level {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
use Level::*;
|
||||||
|
let v = match self {
|
||||||
|
Trace => "trace",
|
||||||
|
Debug => "debug",
|
||||||
|
Log => "log",
|
||||||
|
Info => "info",
|
||||||
|
Warn => "warn",
|
||||||
|
Error => "error",
|
||||||
|
};
|
||||||
|
write!(f, "{}", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A console backend that handles console messages sent from JS via
|
||||||
|
/// console.{log,debug,trace,...} functions.
|
||||||
|
///
|
||||||
|
/// A backend has to be registered via the `ContextBuilder::console` method.
|
||||||
|
///
|
||||||
|
/// A backend that forwads to the `log` crate is available with the `log` feature.
|
||||||
|
///
|
||||||
|
/// Note that any closure of type `Fn(Level, Vec<JsValue>)` implements this trait.
|
||||||
|
///
|
||||||
|
/// A very simple logger that just prints to stderr could look like this:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use quick_js::{Context, JsValue, console::Level};
|
||||||
|
///
|
||||||
|
/// Context::builder()
|
||||||
|
/// .console(|level: Level, args: Vec<JsValue>| {
|
||||||
|
/// eprintln!("{}: {:?}", level, args);
|
||||||
|
/// })
|
||||||
|
/// .build()
|
||||||
|
/// # .unwrap();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub trait ConsoleBackend: std::panic::RefUnwindSafe + 'static {
|
||||||
|
/// Handle a log message.
|
||||||
|
fn log(&self, level: Level, values: Vec<JsValue>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> ConsoleBackend for F
|
||||||
|
where
|
||||||
|
F: Fn(Level, Vec<JsValue>) + std::panic::RefUnwindSafe + 'static,
|
||||||
|
{
|
||||||
|
fn log(&self, level: Level, values: Vec<JsValue>) {
|
||||||
|
(self)(level, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
mod log {
|
||||||
|
use super::{JsValue, Level};
|
||||||
|
|
||||||
|
/// A console implementation that logs messages via the `log` crate.
|
||||||
|
///
|
||||||
|
/// Only available with the `log` feature.
|
||||||
|
pub struct LogConsole;
|
||||||
|
|
||||||
|
fn print_value(value: JsValue) -> String {
|
||||||
|
match value {
|
||||||
|
JsValue::Null => "null".to_string(),
|
||||||
|
JsValue::Bool(v) => v.to_string(),
|
||||||
|
JsValue::Int(v) => v.to_string(),
|
||||||
|
JsValue::Float(v) => v.to_string(),
|
||||||
|
JsValue::String(v) => v,
|
||||||
|
JsValue::Array(values) => {
|
||||||
|
let parts = values
|
||||||
|
.into_iter()
|
||||||
|
.map(print_value)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
format!("[{}]", parts)
|
||||||
|
}
|
||||||
|
JsValue::Object(map) => {
|
||||||
|
let parts = map
|
||||||
|
.into_iter()
|
||||||
|
.map(|(key, value)| format!("{}: {}", key, print_value(value)))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
format!("{{{}}}", parts)
|
||||||
|
}
|
||||||
|
#[cfg(feature = "chrono")]
|
||||||
|
JsValue::Date(v) => v.to_string(),
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
JsValue::BigInt(v) => v.to_string(),
|
||||||
|
JsValue::__NonExhaustive => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl super::ConsoleBackend for LogConsole {
|
||||||
|
fn log(&self, level: Level, values: Vec<JsValue>) {
|
||||||
|
if values.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let log_level = match level {
|
||||||
|
Level::Trace => log::Level::Trace,
|
||||||
|
Level::Debug => log::Level::Debug,
|
||||||
|
Level::Log => log::Level::Info,
|
||||||
|
Level::Info => log::Level::Info,
|
||||||
|
Level::Warn => log::Level::Warn,
|
||||||
|
Level::Error => log::Level::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
let msg = values
|
||||||
|
.into_iter()
|
||||||
|
.map(print_value)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
log::log!(log_level, "{}", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
pub use self::log::LogConsole;
|
||||||
47
quickjs/external/quickjs-rs/src/droppable_value.rs
vendored
Normal file
47
quickjs/external/quickjs-rs/src/droppable_value.rs
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/// A small wrapper that frees resources that have to be freed
|
||||||
|
/// automatically when they go out of scope.
|
||||||
|
pub struct DroppableValue<T, F>
|
||||||
|
where
|
||||||
|
F: FnMut(&mut T),
|
||||||
|
{
|
||||||
|
value: T,
|
||||||
|
drop_fn: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F> DroppableValue<T, F>
|
||||||
|
where
|
||||||
|
F: FnMut(&mut T),
|
||||||
|
{
|
||||||
|
pub fn new(value: T, drop_fn: F) -> Self {
|
||||||
|
Self { value, drop_fn }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F> Drop for DroppableValue<T, F>
|
||||||
|
where
|
||||||
|
F: FnMut(&mut T),
|
||||||
|
{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
(self.drop_fn)(&mut self.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F> std::ops::Deref for DroppableValue<T, F>
|
||||||
|
where
|
||||||
|
F: FnMut(&mut T),
|
||||||
|
{
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F> std::ops::DerefMut for DroppableValue<T, F>
|
||||||
|
where
|
||||||
|
F: FnMut(&mut T),
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
949
quickjs/external/quickjs-rs/src/lib.rs
vendored
Normal file
949
quickjs/external/quickjs-rs/src/lib.rs
vendored
Normal file
@@ -0,0 +1,949 @@
|
|||||||
|
//! quick-js is a a Rust wrapper for [QuickJS](https://bellard.org/quickjs/), a new Javascript
|
||||||
|
//! engine by Fabrice Bellard.
|
||||||
|
//!
|
||||||
|
//! It enables easy and straight-forward execution of modern Javascript from Rust.
|
||||||
|
//!
|
||||||
|
//! ## Limitations
|
||||||
|
//!
|
||||||
|
//! * Windows is not supported yet
|
||||||
|
//!
|
||||||
|
//! ## Quickstart:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use quick_js::{Context, JsValue};
|
||||||
|
//!
|
||||||
|
//! let context = Context::new().unwrap();
|
||||||
|
//!
|
||||||
|
//! // Eval.
|
||||||
|
//!
|
||||||
|
//! let value = context.eval("1 + 2").unwrap();
|
||||||
|
//! assert_eq!(value, JsValue::Int(3));
|
||||||
|
//!
|
||||||
|
//! let value = context.eval_as::<String>(" var x = 100 + 250; x.toString() ").unwrap();
|
||||||
|
//! assert_eq!(&value, "350");
|
||||||
|
//!
|
||||||
|
//! // Callbacks.
|
||||||
|
//!
|
||||||
|
//! context.add_callback("myCallback", |a: i32, b: i32| a + b).unwrap();
|
||||||
|
//!
|
||||||
|
//! context.eval(r#"
|
||||||
|
//! // x will equal 30
|
||||||
|
//! var x = myCallback(10, 20);
|
||||||
|
//! "#).unwrap();
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
mod bindings;
|
||||||
|
mod callback;
|
||||||
|
pub mod console;
|
||||||
|
mod droppable_value;
|
||||||
|
mod value;
|
||||||
|
|
||||||
|
use std::{convert::TryFrom, error, fmt};
|
||||||
|
|
||||||
|
pub use callback::{Arguments, Callback};
|
||||||
|
pub use value::*;
|
||||||
|
|
||||||
|
/// Error on Javascript execution.
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub enum ExecutionError {
|
||||||
|
/// Code to be executed contained zero-bytes.
|
||||||
|
InputWithZeroBytes,
|
||||||
|
/// Value conversion failed. (either input arguments or result value).
|
||||||
|
Conversion(ValueError),
|
||||||
|
/// Internal error.
|
||||||
|
Internal(String),
|
||||||
|
/// JS Exception was thrown.
|
||||||
|
Exception(JsValue),
|
||||||
|
/// JS Runtime exceeded the memory limit.
|
||||||
|
OutOfMemory,
|
||||||
|
#[doc(hidden)]
|
||||||
|
__NonExhaustive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ExecutionError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use ExecutionError::*;
|
||||||
|
match self {
|
||||||
|
InputWithZeroBytes => write!(f, "Invalid script input: code contains zero byte (\\0)"),
|
||||||
|
Conversion(e) => e.fmt(f),
|
||||||
|
Internal(e) => write!(f, "Internal error: {}", e),
|
||||||
|
Exception(e) => write!(f, "{:?}", e),
|
||||||
|
OutOfMemory => write!(f, "Out of memory: runtime memory limit exceeded"),
|
||||||
|
__NonExhaustive => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for ExecutionError {}
|
||||||
|
|
||||||
|
impl From<ValueError> for ExecutionError {
|
||||||
|
fn from(v: ValueError) -> Self {
|
||||||
|
ExecutionError::Conversion(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error on context creation.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ContextError {
|
||||||
|
/// Runtime could not be created.
|
||||||
|
RuntimeCreationFailed,
|
||||||
|
/// Context could not be created.
|
||||||
|
ContextCreationFailed,
|
||||||
|
/// Execution error while building.
|
||||||
|
Execution(ExecutionError),
|
||||||
|
#[doc(hidden)]
|
||||||
|
__NonExhaustive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ContextError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use ContextError::*;
|
||||||
|
match self {
|
||||||
|
RuntimeCreationFailed => write!(f, "Could not create runtime"),
|
||||||
|
ContextCreationFailed => write!(f, "Could not create context"),
|
||||||
|
Execution(e) => e.fmt(f),
|
||||||
|
__NonExhaustive => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for ContextError {}
|
||||||
|
|
||||||
|
/// A builder for [Context](Context).
|
||||||
|
///
|
||||||
|
/// Create with [Context::builder](Context::builder).
|
||||||
|
pub struct ContextBuilder {
|
||||||
|
memory_limit: Option<usize>,
|
||||||
|
console_backend: Option<Box<dyn console::ConsoleBackend>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContextBuilder {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
memory_limit: None,
|
||||||
|
console_backend: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the memory limit of the Javascript runtime (in bytes).
|
||||||
|
///
|
||||||
|
/// If the limit is exceeded, methods like `eval` will return
|
||||||
|
/// a `Err(ExecutionError::Exception(JsValue::Null))`
|
||||||
|
// TODO: investigate why we don't get a proper exception message here.
|
||||||
|
pub fn memory_limit(self, max_bytes: usize) -> Self {
|
||||||
|
let mut s = self;
|
||||||
|
s.memory_limit = Some(max_bytes);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a console handler that will proxy `console.{log,trace,debug,...}`
|
||||||
|
/// calls.
|
||||||
|
///
|
||||||
|
/// The given argument must implement the [ConsoleBackend] trait.
|
||||||
|
///
|
||||||
|
/// A very simple logger could look like this:
|
||||||
|
pub fn console<B>(mut self, backend: B) -> Self
|
||||||
|
where
|
||||||
|
B: console::ConsoleBackend,
|
||||||
|
{
|
||||||
|
self.console_backend = Some(Box::new(backend));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finalize the builder and build a JS Context.
|
||||||
|
pub fn build(self) -> Result<Context, ContextError> {
|
||||||
|
let wrapper = bindings::ContextWrapper::new(self.memory_limit)?;
|
||||||
|
if let Some(be) = self.console_backend {
|
||||||
|
wrapper.set_console(be).map_err(ContextError::Execution)?;
|
||||||
|
}
|
||||||
|
Ok(Context::from_wrapper(wrapper))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Context is a wrapper around a QuickJS Javascript context.
|
||||||
|
/// It is the primary way to interact with the runtime.
|
||||||
|
///
|
||||||
|
/// For each `Context` instance a new instance of QuickJS
|
||||||
|
/// runtime is created. It means that it is safe to use
|
||||||
|
/// different contexts in different threads, but each
|
||||||
|
/// `Context` instance must be used only from a single thread.
|
||||||
|
pub struct Context {
|
||||||
|
wrapper: bindings::ContextWrapper,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
fn from_wrapper(wrapper: bindings::ContextWrapper) -> Self {
|
||||||
|
Self { wrapper }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a `ContextBuilder` that allows customization of JS Runtime settings.
|
||||||
|
///
|
||||||
|
/// For details, see the methods on `ContextBuilder`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let _context = quick_js::Context::builder()
|
||||||
|
/// .memory_limit(100_000)
|
||||||
|
/// .build()
|
||||||
|
/// .unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn builder() -> ContextBuilder {
|
||||||
|
ContextBuilder::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new Javascript context with default settings.
|
||||||
|
pub fn new() -> Result<Self, ContextError> {
|
||||||
|
let wrapper = bindings::ContextWrapper::new(None)?;
|
||||||
|
Ok(Self::from_wrapper(wrapper))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset the Javascript engine.
|
||||||
|
///
|
||||||
|
/// All state and callbacks will be removed.
|
||||||
|
pub fn reset(self) -> Result<Self, ContextError> {
|
||||||
|
let wrapper = self.wrapper.reset()?;
|
||||||
|
Ok(Self { wrapper })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluates Javascript code and returns the value of the final expression.
|
||||||
|
///
|
||||||
|
/// **Promises**:
|
||||||
|
/// If the evaluated code returns a Promise, the event loop
|
||||||
|
/// will be executed until the promise is finished. The final value of
|
||||||
|
/// the promise will be returned, or a `ExecutionError::Exception` if the
|
||||||
|
/// promise failed.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use quick_js::{Context, JsValue};
|
||||||
|
/// let context = Context::new().unwrap();
|
||||||
|
///
|
||||||
|
/// let value = context.eval(" 1 + 2 + 3 ");
|
||||||
|
/// assert_eq!(
|
||||||
|
/// value,
|
||||||
|
/// Ok(JsValue::Int(6)),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// let value = context.eval(r#"
|
||||||
|
/// function f() { return 55 * 3; }
|
||||||
|
/// let y = f();
|
||||||
|
/// var x = y.toString() + "!"
|
||||||
|
/// x
|
||||||
|
/// "#);
|
||||||
|
/// assert_eq!(
|
||||||
|
/// value,
|
||||||
|
/// Ok(JsValue::String("165!".to_string())),
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn eval(&self, code: &str) -> Result<JsValue, ExecutionError> {
|
||||||
|
let value_raw = self.wrapper.eval(code)?;
|
||||||
|
let value = value_raw.to_value()?;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluates Javascript code and returns the value of the final expression
|
||||||
|
/// as a Rust type.
|
||||||
|
///
|
||||||
|
/// **Promises**:
|
||||||
|
/// If the evaluated code returns a Promise, the event loop
|
||||||
|
/// will be executed until the promise is finished. The final value of
|
||||||
|
/// the promise will be returned, or a `ExecutionError::Exception` if the
|
||||||
|
/// promise failed.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use quick_js::{Context};
|
||||||
|
/// let context = Context::new().unwrap();
|
||||||
|
///
|
||||||
|
/// let res = context.eval_as::<bool>(" 100 > 10 ");
|
||||||
|
/// assert_eq!(
|
||||||
|
/// res,
|
||||||
|
/// Ok(true),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// let value: i32 = context.eval_as(" 10 + 10 ").unwrap();
|
||||||
|
/// assert_eq!(
|
||||||
|
/// value,
|
||||||
|
/// 20,
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn eval_as<R>(&self, code: &str) -> Result<R, ExecutionError>
|
||||||
|
where
|
||||||
|
R: TryFrom<JsValue>,
|
||||||
|
R::Error: Into<ValueError>,
|
||||||
|
{
|
||||||
|
let value_raw = self.wrapper.eval(code)?;
|
||||||
|
let value = value_raw.to_value()?;
|
||||||
|
let ret = R::try_from(value).map_err(|e| e.into())?;
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call a global function in the Javascript namespace.
|
||||||
|
///
|
||||||
|
/// **Promises**:
|
||||||
|
/// If the evaluated code returns a Promise, the event loop
|
||||||
|
/// will be executed until the promise is finished. The final value of
|
||||||
|
/// the promise will be returned, or a `ExecutionError::Exception` if the
|
||||||
|
/// promise failed.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use quick_js::{Context, JsValue};
|
||||||
|
/// let context = Context::new().unwrap();
|
||||||
|
///
|
||||||
|
/// let res = context.call_function("encodeURIComponent", vec!["a=b"]);
|
||||||
|
/// assert_eq!(
|
||||||
|
/// res,
|
||||||
|
/// Ok(JsValue::String("a%3Db".to_string())),
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn call_function(
|
||||||
|
&self,
|
||||||
|
function_name: &str,
|
||||||
|
args: impl IntoIterator<Item = impl Into<JsValue>>,
|
||||||
|
) -> Result<JsValue, ExecutionError> {
|
||||||
|
let qargs = args
|
||||||
|
.into_iter()
|
||||||
|
.map(|arg| self.wrapper.serialize_value(arg.into()))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
let global = self.wrapper.global()?;
|
||||||
|
let func_obj = global.property(function_name)?;
|
||||||
|
|
||||||
|
if !func_obj.is_object() {
|
||||||
|
return Err(ExecutionError::Internal(format!(
|
||||||
|
"Could not find function '{}' in global scope: does not exist, or not an object",
|
||||||
|
function_name
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = self.wrapper.call_function(func_obj, qargs)?.to_value()?;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a global JS function that is backed by a Rust function or closure.
|
||||||
|
///
|
||||||
|
/// The callback must satisfy several requirements:
|
||||||
|
/// * accepts 0 - 5 arguments
|
||||||
|
/// * each argument must be convertible from a JsValue
|
||||||
|
/// * must return a value
|
||||||
|
/// * the return value must either:
|
||||||
|
/// - be convertible to JsValue
|
||||||
|
/// - be a Result<T, E> where T is convertible to JsValue
|
||||||
|
/// if Err(e) is returned, a Javascript exception will be raised
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use quick_js::{Context, JsValue};
|
||||||
|
/// let context = Context::new().unwrap();
|
||||||
|
///
|
||||||
|
/// // Register a closue as a callback under the "add" name.
|
||||||
|
/// // The 'add' function can now be called from Javascript code.
|
||||||
|
/// context.add_callback("add", |a: i32, b: i32| { a + b }).unwrap();
|
||||||
|
///
|
||||||
|
/// // Now we try out the 'add' function via eval.
|
||||||
|
/// let output = context.eval_as::<i32>(" add( 3 , 4 ) ").unwrap();
|
||||||
|
/// assert_eq!(
|
||||||
|
/// output,
|
||||||
|
/// 7,
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn add_callback<F>(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
callback: impl Callback<F> + 'static,
|
||||||
|
) -> Result<(), ExecutionError> {
|
||||||
|
self.wrapper.add_callback(name, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_global_properties() {
|
||||||
|
// let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
// assert_eq!(
|
||||||
|
// c.global_property("lala"),
|
||||||
|
// Err(ExecutionError::Exception(
|
||||||
|
// "Global object does not have property 'lala'".into()
|
||||||
|
// ))
|
||||||
|
// );
|
||||||
|
|
||||||
|
// c.set_global_property("testprop", true).unwrap();
|
||||||
|
// assert_eq!(
|
||||||
|
// c.global_property("testprop").unwrap(),
|
||||||
|
// JsValue::Bool(true),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eval_pass() {
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
let cases = vec![
|
||||||
|
("null", Ok(JsValue::Null)),
|
||||||
|
("true", Ok(JsValue::Bool(true))),
|
||||||
|
("2 > 10", Ok(JsValue::Bool(false))),
|
||||||
|
("1", Ok(JsValue::Int(1))),
|
||||||
|
("1 + 1", Ok(JsValue::Int(2))),
|
||||||
|
("1.1", Ok(JsValue::Float(1.1))),
|
||||||
|
("2.2 * 2 + 5", Ok(JsValue::Float(9.4))),
|
||||||
|
("\"abc\"", Ok(JsValue::String("abc".into()))),
|
||||||
|
(
|
||||||
|
"[1,2]",
|
||||||
|
Ok(JsValue::Array(vec![JsValue::Int(1), JsValue::Int(2)])),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (code, res) in cases.into_iter() {
|
||||||
|
assert_eq!(c.eval(code), res,);
|
||||||
|
}
|
||||||
|
|
||||||
|
let obj_cases = vec![
|
||||||
|
(
|
||||||
|
r#" {"a": null} "#,
|
||||||
|
Ok(JsValue::Object(HashMap::from_iter(vec![(
|
||||||
|
"a".to_string(),
|
||||||
|
JsValue::Null,
|
||||||
|
)]))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r#" {a: 1, b: true, c: {c1: false}} "#,
|
||||||
|
Ok(JsValue::Object(HashMap::from_iter(vec![
|
||||||
|
("a".to_string(), JsValue::Int(1)),
|
||||||
|
("b".to_string(), JsValue::Bool(true)),
|
||||||
|
(
|
||||||
|
"c".to_string(),
|
||||||
|
JsValue::Object(HashMap::from_iter(vec![(
|
||||||
|
"c1".to_string(),
|
||||||
|
JsValue::Bool(false),
|
||||||
|
)])),
|
||||||
|
),
|
||||||
|
]))),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (index, (code, res)) in obj_cases.into_iter().enumerate() {
|
||||||
|
let full_code = format!(
|
||||||
|
"var v{index} = {code}; v{index}",
|
||||||
|
index = index,
|
||||||
|
code = code
|
||||||
|
);
|
||||||
|
assert_eq!(c.eval(&full_code), res,);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(c.eval_as::<bool>("true").unwrap(), true,);
|
||||||
|
assert_eq!(c.eval_as::<i32>("1 + 2").unwrap(), 3,);
|
||||||
|
|
||||||
|
let value: String = c.eval_as("var x = 44; x.toString()").unwrap();
|
||||||
|
assert_eq!(&value, "44");
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
assert_eq!(
|
||||||
|
c.eval_as::<num_bigint::BigInt>("1n << 100n").unwrap(),
|
||||||
|
num_bigint::BigInt::from(1i128 << 100)
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
assert_eq!(c.eval_as::<i64>("1 << 30").unwrap(), 1i64 << 30);
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
assert_eq!(c.eval_as::<u128>("1n << 100n").unwrap(), 1u128 << 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eval_syntax_error() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
!!!!
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
Err(ExecutionError::Exception(
|
||||||
|
"SyntaxError: unexpected token in expression: \'\'".into()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eval_exception() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
function f() {
|
||||||
|
throw new Error("My Error");
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
Err(ExecutionError::Exception("Error: My Error".into(),))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_async() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
let value = c
|
||||||
|
.eval(
|
||||||
|
r#"
|
||||||
|
new Promise((resolve, _) => {
|
||||||
|
resolve(33);
|
||||||
|
})
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(value, JsValue::Int(33));
|
||||||
|
|
||||||
|
let res = c.eval(
|
||||||
|
r#"
|
||||||
|
new Promise((_resolve, reject) => {
|
||||||
|
reject("Failed...");
|
||||||
|
})
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
Err(ExecutionError::Exception(JsValue::String(
|
||||||
|
"Failed...".into()
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_call() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
c.call_function("parseInt", vec!["22"]).unwrap(),
|
||||||
|
JsValue::Int(22),
|
||||||
|
);
|
||||||
|
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
function add(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.call_function("add", vec![5, 7]).unwrap(),
|
||||||
|
JsValue::Int(12),
|
||||||
|
);
|
||||||
|
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
function sumArray(arr) {
|
||||||
|
let sum = 0;
|
||||||
|
for (const value of arr) {
|
||||||
|
sum += value;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.call_function("sumArray", vec![vec![1, 2, 3]]).unwrap(),
|
||||||
|
JsValue::Int(6),
|
||||||
|
);
|
||||||
|
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
function addObject(obj) {
|
||||||
|
let sum = 0;
|
||||||
|
for (const key of Object.keys(obj)) {
|
||||||
|
sum += obj[key];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let mut obj = std::collections::HashMap::<String, i32>::new();
|
||||||
|
obj.insert("a".into(), 10);
|
||||||
|
obj.insert("b".into(), 20);
|
||||||
|
obj.insert("c".into(), 30);
|
||||||
|
assert_eq!(
|
||||||
|
c.call_function("addObject", vec![obj]).unwrap(),
|
||||||
|
JsValue::Int(60),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_call_large_string() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
c.eval(" function strLen(s) { return s.length; } ").unwrap();
|
||||||
|
|
||||||
|
let s = " ".repeat(200_000);
|
||||||
|
let v = c.call_function("strLen", vec![s]).unwrap();
|
||||||
|
assert_eq!(v, JsValue::Int(200_000));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn call_async() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
function asyncOk() {
|
||||||
|
return new Promise((resolve, _) => {
|
||||||
|
resolve(33);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function asyncErr() {
|
||||||
|
return new Promise((_resolve, reject) => {
|
||||||
|
reject("Failed...");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let value = c.call_function("asyncOk", vec![true]).unwrap();
|
||||||
|
assert_eq!(value, JsValue::Int(33));
|
||||||
|
|
||||||
|
let res = c.call_function("asyncErr", vec![true]);
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
Err(ExecutionError::Exception(JsValue::String(
|
||||||
|
"Failed...".into()
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_callback() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
c.add_callback("cb1", |flag: bool| !flag).unwrap();
|
||||||
|
assert_eq!(c.eval("cb1(true)").unwrap(), JsValue::Bool(false),);
|
||||||
|
|
||||||
|
c.add_callback("concat2", |a: String, b: String| format!("{}{}", a, b))
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.eval(r#"concat2("abc", "def")"#).unwrap(),
|
||||||
|
JsValue::String("abcdef".into()),
|
||||||
|
);
|
||||||
|
|
||||||
|
c.add_callback("add2", |a: i32, b: i32| -> i32 { a + b })
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(c.eval("add2(5, 11)").unwrap(), JsValue::Int(16),);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_callback_argn_variants() {
|
||||||
|
macro_rules! callback_argn_tests {
|
||||||
|
[
|
||||||
|
$(
|
||||||
|
$len:literal : ( $( $argn:ident : $argv:literal ),* ),
|
||||||
|
)*
|
||||||
|
] => {
|
||||||
|
$(
|
||||||
|
{
|
||||||
|
// Test plain return type.
|
||||||
|
let name = format!("cb{}", $len);
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
c.add_callback(&name, | $( $argn : i32 ),*| -> i32 {
|
||||||
|
$( $argn + )* 0
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let code = format!("{}( {} )", name, "1,".repeat($len));
|
||||||
|
let v = c.eval(&code).unwrap();
|
||||||
|
assert_eq!(v, JsValue::Int($len));
|
||||||
|
|
||||||
|
// Test Result<T, E> return type with OK(_) returns.
|
||||||
|
let name = format!("cbres{}", $len);
|
||||||
|
c.add_callback(&name, | $( $argn : i32 ),*| -> Result<i32, String> {
|
||||||
|
Ok($( $argn + )* 0)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let code = format!("{}( {} )", name, "1,".repeat($len));
|
||||||
|
let v = c.eval(&code).unwrap();
|
||||||
|
assert_eq!(v, JsValue::Int($len));
|
||||||
|
|
||||||
|
// Test Result<T, E> return type with Err(_) returns.
|
||||||
|
let name = format!("cbreserr{}", $len);
|
||||||
|
c.add_callback(&name, #[allow(unused_variables)] | $( $argn : i32 ),*| -> Result<i32, String> {
|
||||||
|
Err("error".into())
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let code = format!("{}( {} )", name, "1,".repeat($len));
|
||||||
|
let res = c.eval(&code);
|
||||||
|
assert_eq!(res, Err(ExecutionError::Exception("error".into())));
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback_argn_tests![
|
||||||
|
1: (a : 1),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_callback_varargs() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
// No return.
|
||||||
|
c.add_callback("cb", |args: Arguments| {
|
||||||
|
let args = args.into_vec();
|
||||||
|
assert_eq!(
|
||||||
|
args,
|
||||||
|
vec![
|
||||||
|
JsValue::String("hello".into()),
|
||||||
|
JsValue::Bool(true),
|
||||||
|
JsValue::from(100),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
c.eval(" cb('hello', true, 100) ").unwrap();
|
||||||
|
|
||||||
|
// With return.
|
||||||
|
c.add_callback("cb2", |args: Arguments| -> u32 {
|
||||||
|
let args = args.into_vec();
|
||||||
|
assert_eq!(
|
||||||
|
args,
|
||||||
|
vec![JsValue::from(1), JsValue::from(10), JsValue::from(100),]
|
||||||
|
);
|
||||||
|
111
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
var x = cb2(1, 10, 100);
|
||||||
|
if (x !== 111) {
|
||||||
|
throw new Error('Expected 111, got ' + x);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_callback_invalid_argcount() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
|
||||||
|
c.add_callback("cb", |a: i32, b: i32| a + b).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
c.eval(" cb(5) "),
|
||||||
|
Err(ExecutionError::Exception(
|
||||||
|
"Invalid argument count: Expected 2, got 1".into()
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn memory_limit_exceeded() {
|
||||||
|
let c = Context::builder().memory_limit(100_000).build().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.eval(" 'abc'.repeat(200_000) "),
|
||||||
|
Err(ExecutionError::OutOfMemory),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn context_reset() {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
c.eval(" var x = 123; ").unwrap();
|
||||||
|
c.add_callback("myCallback", || true).unwrap();
|
||||||
|
|
||||||
|
let c2 = c.reset().unwrap();
|
||||||
|
|
||||||
|
// Check it still works.
|
||||||
|
assert_eq!(
|
||||||
|
c2.eval_as::<String>(" 'abc'.repeat(2) ").unwrap(),
|
||||||
|
"abcabc".to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check old state is gone.
|
||||||
|
let err_msg = c2.eval(" x ").unwrap_err().to_string();
|
||||||
|
assert!(err_msg.contains("ReferenceError"));
|
||||||
|
|
||||||
|
// Check callback is gone.
|
||||||
|
let err_msg = c2.eval(" myCallback() ").unwrap_err().to_string();
|
||||||
|
assert!(err_msg.contains("ReferenceError"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn build_context() -> Context {
|
||||||
|
let ctx = Context::new().unwrap();
|
||||||
|
let name = "cb".to_string();
|
||||||
|
ctx.add_callback(&name, |a: String| a.repeat(2)).unwrap();
|
||||||
|
|
||||||
|
let code = " function f(value) { return cb(value); } ".to_string();
|
||||||
|
ctx.eval(&code).unwrap();
|
||||||
|
|
||||||
|
ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn moved_context() {
|
||||||
|
let c = build_context();
|
||||||
|
let v = c.call_function("f", vec!["test"]).unwrap();
|
||||||
|
assert_eq!(v, "testtest".into());
|
||||||
|
|
||||||
|
let v = c.eval(" f('la') ").unwrap();
|
||||||
|
assert_eq!(v, "lala".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "chrono")]
|
||||||
|
#[test]
|
||||||
|
fn chrono_serialize() {
|
||||||
|
let c = build_context();
|
||||||
|
|
||||||
|
c.eval(
|
||||||
|
"
|
||||||
|
function dateToTimestamp(date) {
|
||||||
|
return date.getTime();
|
||||||
|
}
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let now = chrono::Utc::now();
|
||||||
|
let now_millis = now.timestamp_millis();
|
||||||
|
|
||||||
|
let timestamp = c
|
||||||
|
.call_function("dateToTimestamp", vec![JsValue::Date(now.clone())])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(timestamp, JsValue::Float(now_millis as f64));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "chrono")]
|
||||||
|
#[test]
|
||||||
|
fn chrono_deserialize() {
|
||||||
|
use chrono::offset::TimeZone;
|
||||||
|
|
||||||
|
let c = build_context();
|
||||||
|
|
||||||
|
let value = c.eval(" new Date(1234567555) ").unwrap();
|
||||||
|
let datetime = chrono::Utc.timestamp_millis(1234567555);
|
||||||
|
|
||||||
|
assert_eq!(value, JsValue::Date(datetime));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "chrono")]
|
||||||
|
#[test]
|
||||||
|
fn chrono_roundtrip() {
|
||||||
|
let c = build_context();
|
||||||
|
|
||||||
|
c.eval(" function identity(x) { return x; } ").unwrap();
|
||||||
|
let d = chrono::Utc::now();
|
||||||
|
let td = JsValue::Date(d.clone());
|
||||||
|
let td2 = c.call_function("identity", vec![td.clone()]).unwrap();
|
||||||
|
let d2 = if let JsValue::Date(x) = td2 {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
panic!("expected date")
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(d.timestamp_millis(), d2.timestamp_millis());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_deserialize_i64() {
|
||||||
|
for i in vec![0, std::i64::MAX, std::i64::MIN] {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
let value = c.eval(&format!("{}n", i)).unwrap();
|
||||||
|
assert_eq!(value, JsValue::BigInt(i.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_deserialize_bigint() {
|
||||||
|
for i in vec![
|
||||||
|
std::i64::MAX as i128 + 1,
|
||||||
|
std::i64::MIN as i128 - 1,
|
||||||
|
std::i128::MAX,
|
||||||
|
std::i128::MIN,
|
||||||
|
] {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
let value = c.eval(&format!("{}n", i)).unwrap();
|
||||||
|
let expected = num_bigint::BigInt::from(i);
|
||||||
|
assert_eq!(value, JsValue::BigInt(expected.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_serialize_i64() {
|
||||||
|
for i in vec![0, std::i64::MAX, std::i64::MIN] {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
c.eval(&format!(" function isEqual(x) {{ return x === {}n }} ", i))
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
c.call_function("isEqual", vec![JsValue::BigInt(i.into())])
|
||||||
|
.unwrap(),
|
||||||
|
JsValue::Bool(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_serialize_bigint() {
|
||||||
|
for i in vec![
|
||||||
|
std::i64::MAX as i128 + 1,
|
||||||
|
std::i64::MIN as i128 - 1,
|
||||||
|
std::i128::MAX,
|
||||||
|
std::i128::MIN,
|
||||||
|
] {
|
||||||
|
let c = Context::new().unwrap();
|
||||||
|
c.eval(&format!(" function isEqual(x) {{ return x === {}n }} ", i))
|
||||||
|
.unwrap();
|
||||||
|
let value = JsValue::BigInt(num_bigint::BigInt::from(i).into());
|
||||||
|
assert_eq!(
|
||||||
|
c.call_function("isEqual", vec![value]).unwrap(),
|
||||||
|
JsValue::Bool(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_console() {
|
||||||
|
use console::Level;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
let messages = Arc::new(Mutex::new(Vec::<(Level, Vec<JsValue>)>::new()));
|
||||||
|
|
||||||
|
let m = messages.clone();
|
||||||
|
let c = Context::builder()
|
||||||
|
.console(move |level: Level, args: Vec<JsValue>| {
|
||||||
|
m.lock().unwrap().push((level, args));
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
c.eval(
|
||||||
|
r#"
|
||||||
|
console.log("hi");
|
||||||
|
console.error(false);
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let m = messages.lock().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
*m,
|
||||||
|
vec![
|
||||||
|
(Level::Log, vec![JsValue::from("hi")]),
|
||||||
|
(Level::Error, vec![JsValue::from(false)]),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
107
quickjs/external/quickjs-rs/src/value/bigint.rs
vendored
Normal file
107
quickjs/external/quickjs-rs/src/value/bigint.rs
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use num_traits::cast::ToPrimitive;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum BigIntOrI64 {
|
||||||
|
Int(i64),
|
||||||
|
BigInt(num_bigint::BigInt),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for BigIntOrI64 {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
use BigIntOrI64::*;
|
||||||
|
match (&self, &other) {
|
||||||
|
(Int(i), Int(j)) => i == j,
|
||||||
|
(Int(i), BigInt(b)) | (BigInt(b), Int(i)) => b == &num_bigint::BigInt::from(*i),
|
||||||
|
(BigInt(a), BigInt(b)) => a == b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for BigIntOrI64 {}
|
||||||
|
|
||||||
|
/// A value holding JavaScript
|
||||||
|
/// [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) type
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct BigInt {
|
||||||
|
pub(crate) inner: BigIntOrI64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BigInt {
|
||||||
|
/// Return `Some` if value fits into `i64` and `None` otherwise
|
||||||
|
pub fn as_i64(&self) -> Option<i64> {
|
||||||
|
match &self.inner {
|
||||||
|
BigIntOrI64::Int(int) => Some(*int),
|
||||||
|
BigIntOrI64::BigInt(bigint) => bigint.to_i64(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Convert value into `num_bigint::BigInt`
|
||||||
|
pub fn into_bigint(self) -> num_bigint::BigInt {
|
||||||
|
match self.inner {
|
||||||
|
BigIntOrI64::Int(int) => int.into(),
|
||||||
|
BigIntOrI64::BigInt(bigint) => bigint,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for BigInt {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self.inner {
|
||||||
|
BigIntOrI64::Int(i) => write!(f, "{}", i),
|
||||||
|
BigIntOrI64::BigInt(ref i) => write!(f, "{}", i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for BigInt {
|
||||||
|
fn from(int: i64) -> Self {
|
||||||
|
BigInt {
|
||||||
|
inner: BigIntOrI64::Int(int),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<num_bigint::BigInt> for BigInt {
|
||||||
|
fn from(bigint: num_bigint::BigInt) -> Self {
|
||||||
|
BigInt {
|
||||||
|
inner: BigIntOrI64::BigInt(bigint),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_as_i64() {
|
||||||
|
let value = BigInt {
|
||||||
|
inner: BigIntOrI64::Int(1234i64),
|
||||||
|
};
|
||||||
|
assert_eq!(value.as_i64(), Some(1234i64));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_as_i64_overflow() {
|
||||||
|
let value = BigInt {
|
||||||
|
inner: BigIntOrI64::BigInt(num_bigint::BigInt::from(std::i128::MAX)),
|
||||||
|
};
|
||||||
|
assert_eq!(value.as_i64(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_into_bigint() {
|
||||||
|
for i in vec![
|
||||||
|
0 as i128,
|
||||||
|
std::i64::MAX as i128,
|
||||||
|
std::i64::MIN as i128,
|
||||||
|
std::i128::MAX,
|
||||||
|
std::i128::MIN,
|
||||||
|
] {
|
||||||
|
let value = BigInt {
|
||||||
|
inner: BigIntOrI64::BigInt(num_bigint::BigInt::from(i)),
|
||||||
|
};
|
||||||
|
assert_eq!(value.into_bigint(), num_bigint::BigInt::from(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
320
quickjs/external/quickjs-rs/src/value/mod.rs
vendored
Normal file
320
quickjs/external/quickjs-rs/src/value/mod.rs
vendored
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
pub(crate) mod bigint;
|
||||||
|
|
||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
use std::{collections::HashMap, error, fmt};
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
pub use bigint::BigInt;
|
||||||
|
|
||||||
|
/// A value that can be (de)serialized to/from the quickjs runtime.
|
||||||
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum JsValue {
|
||||||
|
Null,
|
||||||
|
Bool(bool),
|
||||||
|
Int(i32),
|
||||||
|
Float(f64),
|
||||||
|
String(String),
|
||||||
|
Array(Vec<JsValue>),
|
||||||
|
Object(HashMap<String, JsValue>),
|
||||||
|
/// chrono::Datetime<Utc> / JS Date integration.
|
||||||
|
/// Only available with the optional `chrono` feature.
|
||||||
|
#[cfg(feature = "chrono")]
|
||||||
|
Date(chrono::DateTime<chrono::Utc>),
|
||||||
|
/// num_bigint::BigInt / JS BigInt integration
|
||||||
|
/// Only available with the optional `bigint` feature
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
BigInt(crate::BigInt),
|
||||||
|
#[doc(hidden)]
|
||||||
|
__NonExhaustive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsValue {
|
||||||
|
/// Cast value to a str.
|
||||||
|
///
|
||||||
|
/// Returns `Some(&str)` if value is a `JsValue::String`, None otherwise.
|
||||||
|
pub fn as_str(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
JsValue::String(ref s) => Some(s.as_str()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert to `String`.
|
||||||
|
pub fn into_string(self) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
JsValue::String(s) => Some(s),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! value_impl_from {
|
||||||
|
(
|
||||||
|
(
|
||||||
|
$( $t1:ty => $var1:ident, )*
|
||||||
|
)
|
||||||
|
(
|
||||||
|
$( $t2:ty => |$exprname:ident| $expr:expr => $var2:ident, )*
|
||||||
|
)
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
impl From<$t1> for JsValue {
|
||||||
|
fn from(value: $t1) -> Self {
|
||||||
|
JsValue::$var1(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::convert::TryFrom<JsValue> for $t1 {
|
||||||
|
type Error = ValueError;
|
||||||
|
|
||||||
|
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
JsValue::$var1(inner) => Ok(inner),
|
||||||
|
_ => Err(ValueError::UnexpectedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
$(
|
||||||
|
impl From<$t2> for JsValue {
|
||||||
|
fn from(value: $t2) -> Self {
|
||||||
|
let $exprname = value;
|
||||||
|
let inner = $expr;
|
||||||
|
JsValue::$var2(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value_impl_from! {
|
||||||
|
(
|
||||||
|
bool => Bool,
|
||||||
|
i32 => Int,
|
||||||
|
f64 => Float,
|
||||||
|
String => String,
|
||||||
|
)
|
||||||
|
(
|
||||||
|
i8 => |x| i32::from(x) => Int,
|
||||||
|
i16 => |x| i32::from(x) => Int,
|
||||||
|
u8 => |x| i32::from(x) => Int,
|
||||||
|
u16 => |x| i32::from(x) => Int,
|
||||||
|
u32 => |x| f64::from(x) => Float,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
value_impl_from! {
|
||||||
|
()
|
||||||
|
(
|
||||||
|
i64 => |x| x.into() => BigInt,
|
||||||
|
u64 => |x| num_bigint::BigInt::from(x).into() => BigInt,
|
||||||
|
i128 => |x| num_bigint::BigInt::from(x).into() => BigInt,
|
||||||
|
u128 => |x| num_bigint::BigInt::from(x).into() => BigInt,
|
||||||
|
num_bigint::BigInt => |x| x.into() => BigInt,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
impl std::convert::TryFrom<JsValue> for i64 {
|
||||||
|
type Error = ValueError;
|
||||||
|
|
||||||
|
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
JsValue::Int(int) => Ok(int as i64),
|
||||||
|
JsValue::BigInt(bigint) => bigint.as_i64().ok_or(ValueError::UnexpectedType),
|
||||||
|
_ => Err(ValueError::UnexpectedType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
macro_rules! value_bigint_impl_tryfrom {
|
||||||
|
(
|
||||||
|
($($t:ty => $to_type:ident, )*)
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
impl std::convert::TryFrom<JsValue> for $t {
|
||||||
|
type Error = ValueError;
|
||||||
|
|
||||||
|
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
|
||||||
|
use num_traits::ToPrimitive;
|
||||||
|
|
||||||
|
match value {
|
||||||
|
JsValue::Int(int) => Ok(int as $t),
|
||||||
|
JsValue::BigInt(bigint) => bigint
|
||||||
|
.into_bigint()
|
||||||
|
.$to_type()
|
||||||
|
.ok_or(ValueError::UnexpectedType),
|
||||||
|
_ => Err(ValueError::UnexpectedType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
value_bigint_impl_tryfrom! {
|
||||||
|
(
|
||||||
|
u64 => to_u64,
|
||||||
|
i128 => to_i128,
|
||||||
|
u128 => to_u128,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
impl std::convert::TryFrom<JsValue> for num_bigint::BigInt {
|
||||||
|
type Error = ValueError;
|
||||||
|
|
||||||
|
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
JsValue::Int(int) => Ok(num_bigint::BigInt::from(int)),
|
||||||
|
JsValue::BigInt(bigint) => Ok(bigint.into_bigint()),
|
||||||
|
_ => Err(ValueError::UnexpectedType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<Vec<T>> for JsValue
|
||||||
|
where
|
||||||
|
T: Into<JsValue>,
|
||||||
|
{
|
||||||
|
fn from(values: Vec<T>) -> Self {
|
||||||
|
let items = values.into_iter().map(|x| x.into()).collect();
|
||||||
|
JsValue::Array(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for JsValue {
|
||||||
|
fn from(val: &'a str) -> Self {
|
||||||
|
JsValue::String(val.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<Option<T>> for JsValue
|
||||||
|
where
|
||||||
|
T: Into<JsValue>,
|
||||||
|
{
|
||||||
|
fn from(opt: Option<T>) -> Self {
|
||||||
|
if let Some(value) = opt {
|
||||||
|
value.into()
|
||||||
|
} else {
|
||||||
|
JsValue::Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> From<HashMap<K, V>> for JsValue
|
||||||
|
where
|
||||||
|
K: Into<String>,
|
||||||
|
V: Into<JsValue>,
|
||||||
|
{
|
||||||
|
fn from(map: HashMap<K, V>) -> Self {
|
||||||
|
let new_map = map.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
|
||||||
|
JsValue::Object(new_map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V> TryFrom<JsValue> for HashMap<String, V>
|
||||||
|
where
|
||||||
|
V: TryFrom<JsValue>,
|
||||||
|
{
|
||||||
|
type Error = ValueError;
|
||||||
|
|
||||||
|
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
JsValue::Object(object) => object
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| match v.try_into() {
|
||||||
|
Ok(v) => Ok((k, v)),
|
||||||
|
Err(_) => Err(ValueError::UnexpectedType),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
_ => Err(ValueError::UnexpectedType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error during value conversion.
|
||||||
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
|
pub enum ValueError {
|
||||||
|
/// Invalid non-utf8 string.
|
||||||
|
InvalidString(std::str::Utf8Error),
|
||||||
|
/// Encountered string with \0 bytes.
|
||||||
|
StringWithZeroBytes(std::ffi::NulError),
|
||||||
|
/// Internal error.
|
||||||
|
Internal(String),
|
||||||
|
/// Received an unexpected type that could not be converted.
|
||||||
|
UnexpectedType,
|
||||||
|
#[doc(hidden)]
|
||||||
|
__NonExhaustive,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove this once either the Never type get's stabilized or the compiler
|
||||||
|
// can properly handle Infallible.
|
||||||
|
impl From<std::convert::Infallible> for ValueError {
|
||||||
|
fn from(_: std::convert::Infallible) -> Self {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ValueError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use ValueError::*;
|
||||||
|
match self {
|
||||||
|
InvalidString(e) => write!(
|
||||||
|
f,
|
||||||
|
"Value conversion failed - invalid non-utf8 string: {}",
|
||||||
|
e
|
||||||
|
),
|
||||||
|
StringWithZeroBytes(_) => write!(f, "String contains \\0 bytes",),
|
||||||
|
Internal(e) => write!(f, "Value conversion failed - internal error: {}", e),
|
||||||
|
UnexpectedType => write!(f, "Could not convert - received unexpected type"),
|
||||||
|
__NonExhaustive => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for ValueError {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_from_i64() {
|
||||||
|
let int = 1234i64;
|
||||||
|
let value = JsValue::from(int);
|
||||||
|
if let JsValue::BigInt(value) = value {
|
||||||
|
assert_eq!(value.as_i64(), Some(int));
|
||||||
|
} else {
|
||||||
|
panic!("Expected JsValue::BigInt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_from_bigint() {
|
||||||
|
let bigint = num_bigint::BigInt::from(std::i128::MAX);
|
||||||
|
let value = JsValue::from(bigint.clone());
|
||||||
|
if let JsValue::BigInt(value) = value {
|
||||||
|
assert_eq!(value.into_bigint(), bigint);
|
||||||
|
} else {
|
||||||
|
panic!("Expected JsValue::BigInt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bigint")]
|
||||||
|
#[test]
|
||||||
|
fn test_bigint_i64_bigint_eq() {
|
||||||
|
let value_i64 = JsValue::BigInt(1234i64.into());
|
||||||
|
let value_bigint = JsValue::BigInt(num_bigint::BigInt::from(1234i64).into());
|
||||||
|
assert_eq!(value_i64, value_bigint);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user