mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor(ops): Adding op2 macro and implementing in a couple of places (#19534)
This is a new op system that will eventually replace `#[op]`. Features - More maintainable, generally less-coupled code - More modern Rust proc-macro libraries - Enforces correct `fast` labelling for fast ops, allowing for visual scanning of fast ops - Explicit marking of `#[string]`, `#[serde]` and `#[smi]` parameters. This first version of op2 supports integer and Option<integer> parameters only, and allows us to start working on converting ops and adding features.
This commit is contained in:
parent
8d6dbda90e
commit
65d9bfb533
23 changed files with 1798 additions and 112 deletions
2
.github/workflows/ci.generate.ts
vendored
2
.github/workflows/ci.generate.ts
vendored
|
@ -5,7 +5,7 @@ import * as yaml from "https://deno.land/std@0.173.0/encoding/yaml.ts";
|
|||
// Bump this number when you want to purge the cache.
|
||||
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
|
||||
// automatically via regex, so ensure that this line maintains this format.
|
||||
const cacheVersion = 40;
|
||||
const cacheVersion = 41;
|
||||
|
||||
const Runners = (() => {
|
||||
const ubuntuRunner = "ubuntu-22.04";
|
||||
|
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
@ -298,8 +298,8 @@ jobs:
|
|||
path: |-
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
key: '40-cargo-home-${{ matrix.os }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '40-cargo-home-${{ matrix.os }}'
|
||||
key: '41-cargo-home-${{ matrix.os }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '41-cargo-home-${{ matrix.os }}'
|
||||
if: '!(github.event_name == ''pull_request'' && matrix.skip_pr)'
|
||||
- name: Restore cache build output (PR)
|
||||
uses: actions/cache/restore@v3
|
||||
|
@ -311,7 +311,7 @@ jobs:
|
|||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: never_saved
|
||||
restore-keys: '40-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
restore-keys: '41-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
- name: Apply and update mtime cache
|
||||
if: '!(github.event_name == ''pull_request'' && matrix.skip_pr) && (!startsWith(github.ref, ''refs/tags/''))'
|
||||
uses: ./.github/mtime_cache
|
||||
|
@ -592,7 +592,7 @@ jobs:
|
|||
!./target/*/gn_out
|
||||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: '40-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
key: '41-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
publish-canary:
|
||||
name: publish canary
|
||||
runs-on: ubuntu-22.04
|
||||
|
|
259
Cargo.lock
generated
259
Cargo.lock
generated
|
@ -191,8 +191,8 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
@ -203,8 +203,8 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -215,8 +215,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c704e2f6ee1a98223f5a7629a6ef0f3decb3b552ed282889dc957edff98ce1e6"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -266,8 +266,8 @@ version = "0.3.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -277,9 +277,9 @@ version = "0.1.68"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"syn 2.0.13",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -300,8 +300,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -716,7 +716,7 @@ version = "0.1.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
|
||||
dependencies = [
|
||||
"quote 1.0.26",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -871,6 +871,29 @@ dependencies = [
|
|||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno-proc-macro-rules"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c65c2ffdafc1564565200967edc4851c7b55422d3913466688907efd05ea26f"
|
||||
dependencies = [
|
||||
"deno-proc-macro-rules-macros",
|
||||
"proc-macro2 1.0.60",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno-proc-macro-rules-macros"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3047b312b7451e3190865713a4dd6e1f821aed614ada219766ebc3024a690435"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_ast"
|
||||
version = "0.27.0"
|
||||
|
@ -1317,18 +1340,24 @@ dependencies = [
|
|||
name = "deno_ops"
|
||||
version = "0.69.0"
|
||||
dependencies = [
|
||||
"deno-proc-macro-rules",
|
||||
"lazy-regex",
|
||||
"once_cell",
|
||||
"pmutil",
|
||||
"pretty_assertions",
|
||||
"prettyplease",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"regex",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.18",
|
||||
"testing_macros",
|
||||
"thiserror",
|
||||
"trybuild",
|
||||
"v8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1537,8 +1566,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"rustc_version 0.4.0",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -1585,8 +1614,8 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -1727,8 +1756,8 @@ dependencies = [
|
|||
"byteorder",
|
||||
"lazy_static",
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -1848,8 +1877,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -2030,8 +2059,8 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479cde5eb168cf5a056dd98f311cbfab7494c216394e4fb9eba0336827a8db93"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -2078,7 +2107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1d449976075322384507443937df2f1d5577afbf4282f12a5a66ef29fa3e6307"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"proc-macro2 1.0.60",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -2167,9 +2196,9 @@ version = "0.3.28"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"syn 2.0.13",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2646,8 +2675,8 @@ checksum = "8a7d079e129b77477a49c5c4f1cfe9ce6c2c909ef52520693e8e811a714c7b20"
|
|||
dependencies = [
|
||||
"Inflector",
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -2761,8 +2790,8 @@ version = "2.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8edfc11b8f56ce85e207e62ea21557cfa09bb24a8f6b04ae181b086ff8611c22"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"regex",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -3085,8 +3114,8 @@ dependencies = [
|
|||
name = "napi_sym"
|
||||
version = "0.39.0"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 1.0.109",
|
||||
|
@ -3511,8 +3540,8 @@ dependencies = [
|
|||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -3540,8 +3569,8 @@ version = "1.0.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -3601,8 +3630,8 @@ version = "0.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -3648,7 +3677,7 @@ version = "0.1.25"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"proc-macro2 1.0.60",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -3678,8 +3707,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -3690,8 +3719,8 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -3712,9 +3741,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.56"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -3766,11 +3795,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.26"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"proc-macro2 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4117,8 +4146,8 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "107c3d5d7f370ac09efa62a78375f94d94b8a33c61d8c278b96683fb4dbf2d8d"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -4314,9 +4343,9 @@ version = "1.0.157"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78997f4555c22a7971214540c4a661291970619afd56de19f77e0de86296e1e5"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"syn 2.0.13",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4337,8 +4366,8 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -4590,8 +4619,8 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
|
|||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4601,8 +4630,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0090512bdfee4b56d82480d66c0fd8a6f53f0fe0f97e075e949b252acdd482e0"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -4613,6 +4642,28 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"rustversion",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
|
@ -4711,8 +4762,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7dadb9998d4f5fc36ef558ed5a092579441579ee8c6fcce84a5228cca9df4004"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -4760,8 +4811,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bf4ee0caee1018808d94ecd09490cb7affd3d504b19aa11c49238f5fc4b54901"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -4856,8 +4907,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "984d5ac69b681fc5438f9abf82b0fda34fe04e119bc75f8213b7e01128c7c9a2"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -4987,8 +5038,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0c20468634668c2bbab581947bb8c75c97158d5a6959f4ba33df20983b20b4f6"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -5024,8 +5075,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3e582c3e3c2269238524923781df5be49e011dbe29cf7683a2215d600a562ea6"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -5047,8 +5098,8 @@ checksum = "4cfc226380ba54a5feed2c12f3ccd33f1ae8e959160290e5d2d9b4e918b6472a"
|
|||
dependencies = [
|
||||
"Inflector",
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"swc_macros_common",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
@ -5070,19 +5121,19 @@ version = "1.0.109"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.13"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
|
||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
|
@ -5092,8 +5143,8 @@ version = "0.12.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid 0.2.4",
|
||||
]
|
||||
|
@ -5195,8 +5246,8 @@ dependencies = [
|
|||
"glob",
|
||||
"once_cell",
|
||||
"pmutil",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"regex",
|
||||
"relative-path",
|
||||
"syn 1.0.109",
|
||||
|
@ -5232,9 +5283,9 @@ version = "1.0.40"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"syn 2.0.13",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5304,9 +5355,9 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"syn 2.0.13",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5443,8 +5494,8 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ebd99eec668d0a450c177acbc4d05e0d0d13b1f8d3db13cd706c52cbec4ac04"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -5472,8 +5523,8 @@ version = "0.1.23"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
|
@ -5840,8 +5891,8 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5896,8 +5947,8 @@ dependencies = [
|
|||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -5920,7 +5971,7 @@ version = "0.2.84"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote 1.0.26",
|
||||
"quote 1.0.28",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
|
@ -5930,8 +5981,8 @@ version = "0.2.84"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
|
@ -6265,8 +6316,8 @@ version = "1.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.60",
|
||||
"quote 1.0.28",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
|
|
@ -131,6 +131,8 @@ signature = "=1.6.4"
|
|||
slab = "0.4"
|
||||
smallvec = "1.8"
|
||||
socket2 = "0.4.7"
|
||||
strum = { version = "0.24", features = ["derive"] }
|
||||
strum_macros = "0.24"
|
||||
tar = "=0.4.38"
|
||||
tempfile = "3.4.0"
|
||||
thiserror = "1.0.40"
|
||||
|
@ -155,6 +157,9 @@ hkdf = "0.12.3"
|
|||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "1", features = ["full", "extra-traits"] }
|
||||
syn2 = { package = "syn", version = "=2.0.18", features = ["full", "extra-traits"] }
|
||||
# Temporary fork while we wait for a more modern version to be published
|
||||
deno-proc-macro-rules = "0.3.2"
|
||||
|
||||
# unix
|
||||
nix = "=0.24.2"
|
||||
|
|
|
@ -41,6 +41,7 @@ pub use url;
|
|||
pub use v8;
|
||||
|
||||
pub use deno_ops::op;
|
||||
pub use deno_ops::op2;
|
||||
|
||||
pub use crate::async_cancel::CancelFuture;
|
||||
pub use crate::async_cancel::CancelHandle;
|
||||
|
@ -130,6 +131,7 @@ pub fn v8_version() -> &'static str {
|
|||
pub mod _ops {
|
||||
pub use super::error::throw_type_error;
|
||||
pub use super::error_codes::get_error_code;
|
||||
pub use super::extensions::OpDecl;
|
||||
pub use super::ops::to_op_result;
|
||||
pub use super::ops::OpCtx;
|
||||
pub use super::ops::OpResult;
|
||||
|
@ -139,10 +141,17 @@ pub mod _ops {
|
|||
pub use super::runtime::ops::map_async_op4;
|
||||
pub use super::runtime::ops::queue_async_op;
|
||||
pub use super::runtime::ops::queue_fast_async_op;
|
||||
pub use super::runtime::ops::to_i32;
|
||||
pub use super::runtime::ops::to_u32;
|
||||
pub use super::runtime::V8_WRAPPER_OBJECT_INDEX;
|
||||
pub use super::runtime::V8_WRAPPER_TYPE_INDEX;
|
||||
}
|
||||
|
||||
pub(crate) mod deno_core {
|
||||
pub(crate) use crate::_ops;
|
||||
pub(crate) use crate::v8;
|
||||
}
|
||||
|
||||
// TODO(mmastrac): Temporary while we move code around
|
||||
pub mod snapshot_util {
|
||||
pub use crate::runtime::create_snapshot;
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::OpState;
|
|||
use crate::Resource;
|
||||
use anyhow::Error;
|
||||
use deno_ops::op;
|
||||
use deno_ops::op2;
|
||||
use serde_v8::ToJsBuffer;
|
||||
use std::cell::RefCell;
|
||||
use std::io::stderr;
|
||||
|
@ -95,7 +96,7 @@ pub fn op_resources(state: &mut OpState) -> Vec<(ResourceId, String)> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
#[op2(core, fast)]
|
||||
fn op_add(a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
}
|
||||
|
|
|
@ -145,3 +145,140 @@ pub fn queue_async_op<'s>(
|
|||
.spawn(unsafe { crate::task::MaskFutureAsSend::new(pinned) });
|
||||
None
|
||||
}
|
||||
|
||||
macro_rules! try_number {
|
||||
($n:ident $type:ident $is:ident) => {
|
||||
if $n.$is() {
|
||||
// SAFETY: v8 handles can be transmuted
|
||||
let n: &v8::Uint32 = unsafe { std::mem::transmute($n) };
|
||||
return n.value() as _;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn to_u32(number: &v8::Value) -> u32 {
|
||||
try_number!(number Uint32 is_uint32);
|
||||
try_number!(number Int32 is_int32);
|
||||
try_number!(number Number is_number);
|
||||
if number.is_big_int() {
|
||||
// SAFETY: v8 handles can be transmuted
|
||||
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
|
||||
return n.u64_value().0 as _;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub fn to_i32(number: &v8::Value) -> i32 {
|
||||
try_number!(number Uint32 is_uint32);
|
||||
try_number!(number Int32 is_int32);
|
||||
try_number!(number Number is_number);
|
||||
if number.is_big_int() {
|
||||
// SAFETY: v8 handles can be transmuted
|
||||
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
|
||||
return n.i64_value().0 as _;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn to_u64(number: &v8::Value) -> u32 {
|
||||
try_number!(number Uint32 is_uint32);
|
||||
try_number!(number Int32 is_int32);
|
||||
try_number!(number Number is_number);
|
||||
if number.is_big_int() {
|
||||
// SAFETY: v8 handles can be transmuted
|
||||
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
|
||||
return n.u64_value().0 as _;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn to_i64(number: &v8::Value) -> i32 {
|
||||
try_number!(number Uint32 is_uint32);
|
||||
try_number!(number Int32 is_int32);
|
||||
try_number!(number Number is_number);
|
||||
if number.is_big_int() {
|
||||
// SAFETY: v8 handles can be transmuted
|
||||
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
|
||||
return n.i64_value().0 as _;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::FastString;
|
||||
use crate::JsRuntime;
|
||||
use crate::RuntimeOptions;
|
||||
use deno_ops::op2;
|
||||
|
||||
crate::extension!(testing, ops = [op_test_add, op_test_add_option]);
|
||||
|
||||
/// Run a test for a single op.
|
||||
fn run_test(
|
||||
op: &'static str,
|
||||
test: &'static str,
|
||||
f: impl FnOnce(Result<&v8::Value, anyhow::Error>, &mut v8::HandleScope),
|
||||
) {
|
||||
let mut runtime = JsRuntime::new(RuntimeOptions {
|
||||
extensions: vec![testing::init_ops_and_esm()],
|
||||
..Default::default()
|
||||
});
|
||||
let value: Result<v8::Global<v8::Value>, anyhow::Error> = runtime
|
||||
.execute_script(
|
||||
"",
|
||||
FastString::Owned(
|
||||
format!("const {{ {op} }} = Deno.core.ensureFastOps(); {test}")
|
||||
.into(),
|
||||
),
|
||||
);
|
||||
let mut scope: v8::HandleScope =
|
||||
// SAFETY: transmute for test (this lifetime should be safe for this purpose)
|
||||
unsafe { std::mem::transmute(runtime.handle_scope()) };
|
||||
match value {
|
||||
Ok(value) => {
|
||||
let value = value.open(&mut scope);
|
||||
f(Ok(value), &mut scope)
|
||||
}
|
||||
Err(err) => f(Err(err), &mut scope),
|
||||
}
|
||||
}
|
||||
|
||||
#[op2(core, fast)]
|
||||
pub fn op_test_add(a: u32, b: u32) -> u32 {
|
||||
a + b
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_op_add() -> Result<(), Box<dyn std::error::Error>> {
|
||||
run_test("op_test_add", "op_test_add(1, 11)", |value, scope| {
|
||||
assert_eq!(value.unwrap().int32_value(scope), Some(12));
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[op2(core)]
|
||||
pub fn op_test_add_option(a: u32, b: Option<u32>) -> u32 {
|
||||
a + b.unwrap_or(100)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_op_add_option() -> Result<(), Box<dyn std::error::Error>> {
|
||||
run_test(
|
||||
"op_test_add_option",
|
||||
"op_test_add_option(1, 11)",
|
||||
|value, scope| {
|
||||
assert_eq!(value.unwrap().int32_value(scope), Some(12));
|
||||
},
|
||||
);
|
||||
run_test(
|
||||
"op_test_add_option",
|
||||
"op_test_add_option(1, null)",
|
||||
|value, scope| {
|
||||
assert_eq!(value.unwrap().int32_value(scope), Some(101));
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ use cache_control::CacheControl;
|
|||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::TryFutureExt;
|
||||
use deno_core::op;
|
||||
use deno_core::op2;
|
||||
use deno_core::serde_v8;
|
||||
use deno_core::serde_v8::from_v8;
|
||||
use deno_core::task::spawn;
|
||||
|
@ -208,8 +209,8 @@ pub async fn op_http_upgrade_websocket_next(
|
|||
ws_create_server_stream(&mut state.borrow_mut(), stream, bytes)
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_http_set_promise_complete(slab_id: SlabId, status: u16) {
|
||||
#[op2(fast)]
|
||||
pub fn op_http_set_promise_complete(#[smi] slab_id: SlabId, status: u16) {
|
||||
let mut http = slab_get(slab_id);
|
||||
// The Javascript code will never provide a status that is invalid here (see 23_response.js)
|
||||
*http.response().status_mut() = StatusCode::from_u16(status).unwrap();
|
||||
|
|
|
@ -15,6 +15,7 @@ path = "./lib.rs"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
deno-proc-macro-rules.workspace = true
|
||||
lazy-regex.workspace = true
|
||||
once_cell.workspace = true
|
||||
pmutil = "0.5.3"
|
||||
|
@ -22,7 +23,12 @@ proc-macro-crate = "1.1.3"
|
|||
proc-macro2.workspace = true
|
||||
quote.workspace = true
|
||||
regex.workspace = true
|
||||
strum.workspace = true
|
||||
strum_macros.workspace = true
|
||||
syn.workspace = true
|
||||
syn2.workspace = true
|
||||
thiserror.workspace = true
|
||||
v8.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions.workspace = true
|
||||
|
|
22
ops/lib.rs
22
ops/lib.rs
|
@ -8,6 +8,7 @@ use proc_macro2::Span;
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
use std::error::Error;
|
||||
use syn::parse;
|
||||
use syn::parse_macro_input;
|
||||
use syn::punctuated::Punctuated;
|
||||
|
@ -22,6 +23,7 @@ use syn::LifetimeDef;
|
|||
mod attrs;
|
||||
mod deno;
|
||||
mod fast_call;
|
||||
mod op2;
|
||||
mod optimizer;
|
||||
|
||||
const SCOPE_LIFETIME: &str = "'scope";
|
||||
|
@ -235,6 +237,26 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
op.gen().into()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn op2(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
match crate::op2::op2(attr.into(), item.into()) {
|
||||
Ok(output) => output.into(),
|
||||
Err(err) => {
|
||||
let mut err: &dyn Error = &err;
|
||||
let mut output = "Failed to parse #[op2]:\n".to_owned();
|
||||
loop {
|
||||
output += &format!(" - {err}\n");
|
||||
if let Some(source) = err.source() {
|
||||
err = source;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
panic!("{output}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate the body of a v8 func for an async op
|
||||
fn codegen_v8_async(
|
||||
core: &TokenStream2,
|
||||
|
|
193
ops/op2/dispatch_fast.rs
Normal file
193
ops/op2/dispatch_fast.rs
Normal file
|
@ -0,0 +1,193 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
use super::generator_state::GeneratorState;
|
||||
use super::signature::Arg;
|
||||
use super::signature::NumericArg;
|
||||
use super::signature::ParsedSignature;
|
||||
use super::signature::RetVal;
|
||||
use super::V8MappingError;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::quote;
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
pub(crate) enum FastValue {
|
||||
#[default]
|
||||
Void,
|
||||
Bool,
|
||||
U32,
|
||||
I32,
|
||||
U64,
|
||||
I64,
|
||||
F32,
|
||||
F64,
|
||||
Pointer,
|
||||
V8Value,
|
||||
Uint8Array,
|
||||
Uint32Array,
|
||||
Float64Array,
|
||||
SeqOneByteString,
|
||||
}
|
||||
|
||||
impl FastValue {
|
||||
/// Quote fast value type.
|
||||
fn quote_rust_type(&self) -> TokenStream {
|
||||
match self {
|
||||
FastValue::Void => quote!(()),
|
||||
FastValue::Bool => quote!(bool),
|
||||
FastValue::U32 => quote!(u32),
|
||||
FastValue::I32 => quote!(i32),
|
||||
FastValue::U64 => quote!(u64),
|
||||
FastValue::I64 => quote!(i64),
|
||||
FastValue::F32 => quote!(f32),
|
||||
FastValue::F64 => quote!(f64),
|
||||
FastValue::Pointer => quote!(*mut ::std::ffi::c_void),
|
||||
FastValue::V8Value => unimplemented!("v8::Local<v8::Value>"),
|
||||
FastValue::Uint8Array
|
||||
| FastValue::Uint32Array
|
||||
| FastValue::Float64Array
|
||||
| FastValue::SeqOneByteString => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Quote fast value type's variant.
|
||||
fn quote_ctype(&self) -> TokenStream {
|
||||
match &self {
|
||||
FastValue::Void => quote!(CType::Void),
|
||||
FastValue::Bool => quote!(CType::Bool),
|
||||
FastValue::U32 => quote!(CType::Uint32),
|
||||
FastValue::I32 => quote!(CType::Int32),
|
||||
FastValue::U64 => quote!(CType::Uint64),
|
||||
FastValue::I64 => quote!(CType::Int64),
|
||||
FastValue::F32 => quote!(CType::Float32),
|
||||
FastValue::F64 => quote!(CType::Float64),
|
||||
FastValue::Pointer => quote!(CType::Pointer),
|
||||
FastValue::V8Value => quote!(CType::V8Value),
|
||||
FastValue::Uint8Array => unreachable!(),
|
||||
FastValue::Uint32Array => unreachable!(),
|
||||
FastValue::Float64Array => unreachable!(),
|
||||
FastValue::SeqOneByteString => quote!(CType::SeqOneByteString),
|
||||
}
|
||||
}
|
||||
|
||||
/// Quote fast value type's variant.
|
||||
fn quote_type(&self) -> TokenStream {
|
||||
match &self {
|
||||
FastValue::Void => quote!(Type::Void),
|
||||
FastValue::Bool => quote!(Type::Bool),
|
||||
FastValue::U32 => quote!(Type::Uint32),
|
||||
FastValue::I32 => quote!(Type::Int32),
|
||||
FastValue::U64 => quote!(Type::Uint64),
|
||||
FastValue::I64 => quote!(Type::Int64),
|
||||
FastValue::F32 => quote!(Type::Float32),
|
||||
FastValue::F64 => quote!(Type::Float64),
|
||||
FastValue::Pointer => quote!(Type::Pointer),
|
||||
FastValue::V8Value => quote!(Type::V8Value),
|
||||
FastValue::Uint8Array => quote!(Type::TypedArray(CType::Uint8)),
|
||||
FastValue::Uint32Array => quote!(Type::TypedArray(CType::Uint32)),
|
||||
FastValue::Float64Array => quote!(Type::TypedArray(CType::Float64)),
|
||||
FastValue::SeqOneByteString => quote!(Type::SeqOneByteString),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_dispatch_fast(
|
||||
generator_state: &mut GeneratorState,
|
||||
signature: &ParsedSignature,
|
||||
) -> Result<Option<(TokenStream, TokenStream)>, V8MappingError> {
|
||||
let mut inputs = vec![];
|
||||
for arg in &signature.args {
|
||||
let fv = match arg {
|
||||
Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
|
||||
Arg::Numeric(NumericArg::bool) => FastValue::Bool,
|
||||
Arg::Numeric(NumericArg::u32)
|
||||
| Arg::Numeric(NumericArg::u16)
|
||||
| Arg::Numeric(NumericArg::u8) => FastValue::U32,
|
||||
Arg::Numeric(NumericArg::i32)
|
||||
| Arg::Numeric(NumericArg::i16)
|
||||
| Arg::Numeric(NumericArg::i8)
|
||||
| Arg::Numeric(NumericArg::__SMI__) => FastValue::I32,
|
||||
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
|
||||
FastValue::U64
|
||||
}
|
||||
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
|
||||
FastValue::I64
|
||||
}
|
||||
_ => {
|
||||
return Err(V8MappingError::NoMapping("a fast argument", arg.clone()))
|
||||
}
|
||||
};
|
||||
inputs.push(fv);
|
||||
}
|
||||
|
||||
let ret_val = match &signature.ret_val {
|
||||
RetVal::Infallible(arg) => arg,
|
||||
RetVal::Result(arg) => arg,
|
||||
};
|
||||
|
||||
let output = match ret_val {
|
||||
Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
|
||||
Arg::Void => FastValue::Void,
|
||||
Arg::Numeric(NumericArg::bool) => FastValue::Bool,
|
||||
Arg::Numeric(NumericArg::u32)
|
||||
| Arg::Numeric(NumericArg::u16)
|
||||
| Arg::Numeric(NumericArg::u8) => FastValue::U32,
|
||||
Arg::Numeric(NumericArg::i32)
|
||||
| Arg::Numeric(NumericArg::i16)
|
||||
| Arg::Numeric(NumericArg::i8) => FastValue::I32,
|
||||
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
|
||||
FastValue::U64
|
||||
}
|
||||
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
|
||||
FastValue::I64
|
||||
}
|
||||
Arg::Special(_) => return Ok(None),
|
||||
_ => {
|
||||
return Err(V8MappingError::NoMapping(
|
||||
"a fast return value",
|
||||
ret_val.clone(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let GeneratorState {
|
||||
fast_function,
|
||||
deno_core,
|
||||
..
|
||||
} = &generator_state;
|
||||
|
||||
let input_types = inputs.iter().map(|fv| fv.quote_type());
|
||||
let output_type = output.quote_ctype();
|
||||
|
||||
let fast_definition = quote! {
|
||||
use #deno_core::v8::fast_api::Type;
|
||||
use #deno_core::v8::fast_api::CType;
|
||||
#deno_core::v8::fast_api::FastFunction::new(
|
||||
&[ #( #input_types ),* ],
|
||||
#output_type,
|
||||
Self::#fast_function as *const ::std::ffi::c_void
|
||||
)
|
||||
};
|
||||
|
||||
let output_type = output.quote_rust_type();
|
||||
let names = &inputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| format_ident!("arg{i}"))
|
||||
.collect::<Vec<_>>();
|
||||
let types = inputs.iter().map(|rv| rv.quote_rust_type());
|
||||
|
||||
let fast_fn = quote!(
|
||||
fn #fast_function(
|
||||
_: #deno_core::v8::Local<#deno_core::v8::Object>,
|
||||
#( #names: #types, )*
|
||||
) -> #output_type {
|
||||
#(
|
||||
let #names = #names as _;
|
||||
)*
|
||||
Self::call(#(#names),*)
|
||||
}
|
||||
);
|
||||
|
||||
Ok(Some((fast_definition, fast_fn)))
|
||||
}
|
220
ops/op2/dispatch_slow.rs
Normal file
220
ops/op2/dispatch_slow.rs
Normal file
|
@ -0,0 +1,220 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
use super::generator_state::GeneratorState;
|
||||
use super::signature::Arg;
|
||||
use super::signature::NumericArg;
|
||||
use super::signature::ParsedSignature;
|
||||
use super::signature::RetVal;
|
||||
use super::signature::Special;
|
||||
use super::V8MappingError;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub fn generate_dispatch_slow(
|
||||
generator_state: &mut GeneratorState,
|
||||
signature: &ParsedSignature,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
let mut output = TokenStream::new();
|
||||
for (index, arg) in signature.args.iter().enumerate() {
|
||||
output.extend(extract_arg(generator_state, index)?);
|
||||
output.extend(from_arg(generator_state, index, arg)?);
|
||||
}
|
||||
output.extend(call(generator_state));
|
||||
output.extend(return_value(generator_state, &signature.ret_val));
|
||||
|
||||
let GeneratorState {
|
||||
deno_core,
|
||||
scope,
|
||||
fn_args,
|
||||
retval,
|
||||
info,
|
||||
slow_function,
|
||||
..
|
||||
} = &generator_state;
|
||||
|
||||
let with_scope = if generator_state.needs_scope {
|
||||
quote!(let #scope = &mut unsafe { #deno_core::v8::CallbackScope::new(&*#info) };)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
let with_retval = if generator_state.needs_retval {
|
||||
quote!(let mut #retval = #deno_core::v8::ReturnValue::from_function_callback_info(unsafe { &*#info });)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
let with_args = if generator_state.needs_args {
|
||||
quote!(let #fn_args = #deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { &*#info });)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
pub extern "C" fn #slow_function(#info: *const #deno_core::v8::FunctionCallbackInfo) {
|
||||
#with_scope
|
||||
#with_retval
|
||||
#with_args
|
||||
|
||||
#output
|
||||
}})
|
||||
}
|
||||
|
||||
pub fn extract_arg(
|
||||
generator_state: &mut GeneratorState,
|
||||
index: usize,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
let GeneratorState { fn_args, .. } = &generator_state;
|
||||
let arg_ident = generator_state.args.get(index);
|
||||
|
||||
Ok(quote!(
|
||||
let #arg_ident = #fn_args.get(#index as i32);
|
||||
))
|
||||
}
|
||||
|
||||
pub fn from_arg(
|
||||
mut generator_state: &mut GeneratorState,
|
||||
index: usize,
|
||||
arg: &Arg,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
let GeneratorState {
|
||||
deno_core, args, ..
|
||||
} = &mut generator_state;
|
||||
let arg_ident = args.get_mut(index).expect("Argument at index was missing");
|
||||
|
||||
let res = match arg {
|
||||
Arg::Numeric(NumericArg::bool) => quote! {
|
||||
let #arg_ident = #arg_ident.is_true();
|
||||
},
|
||||
Arg::Numeric(NumericArg::u8)
|
||||
| Arg::Numeric(NumericArg::u16)
|
||||
| Arg::Numeric(NumericArg::u32) => {
|
||||
quote! {
|
||||
let #arg_ident = #deno_core::_ops::to_u32(&#arg_ident) as _;
|
||||
}
|
||||
}
|
||||
Arg::Numeric(NumericArg::i8)
|
||||
| Arg::Numeric(NumericArg::i16)
|
||||
| Arg::Numeric(NumericArg::i32)
|
||||
| Arg::Numeric(NumericArg::__SMI__) => {
|
||||
quote! {
|
||||
let #arg_ident = #deno_core::_ops::to_i32(&#arg_ident) as _;
|
||||
}
|
||||
}
|
||||
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
|
||||
quote! {
|
||||
let #arg_ident = #deno_core::_ops::to_u64(&#arg_ident) as _;
|
||||
}
|
||||
}
|
||||
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
|
||||
quote! {
|
||||
let #arg_ident = #deno_core::_ops::to_i64(&#arg_ident) as _;
|
||||
}
|
||||
}
|
||||
Arg::OptionNumeric(numeric) => {
|
||||
// Ends the borrow of generator_state
|
||||
let arg_ident = arg_ident.clone();
|
||||
let some = from_arg(generator_state, index, &Arg::Numeric(*numeric))?;
|
||||
quote! {
|
||||
let #arg_ident = if #arg_ident.is_null_or_undefined() {
|
||||
None
|
||||
} else {
|
||||
#some
|
||||
Some(#arg_ident)
|
||||
};
|
||||
}
|
||||
}
|
||||
Arg::Option(Special::String) => {
|
||||
quote! {
|
||||
let #arg_ident = #arg_ident.to_rust_string_lossy();
|
||||
}
|
||||
}
|
||||
Arg::Special(Special::RefStr) => {
|
||||
quote! {
|
||||
let #arg_ident = #arg_ident.to_rust_string_lossy();
|
||||
}
|
||||
}
|
||||
_ => return Err(V8MappingError::NoMapping("a slow argument", arg.clone())),
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn call(
|
||||
generator_state: &mut GeneratorState,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
let GeneratorState { result, .. } = &generator_state;
|
||||
|
||||
let mut tokens = TokenStream::new();
|
||||
for arg in &generator_state.args {
|
||||
tokens.extend(quote!( #arg , ));
|
||||
}
|
||||
Ok(quote! {
|
||||
let #result = Self::call( #tokens );
|
||||
})
|
||||
}
|
||||
|
||||
pub fn return_value(
|
||||
generator_state: &mut GeneratorState,
|
||||
ret_type: &RetVal,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
match ret_type {
|
||||
RetVal::Infallible(ret_type) => {
|
||||
return_value_infallible(generator_state, ret_type)
|
||||
}
|
||||
RetVal::Result(ret_type) => return_value_result(generator_state, ret_type),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn return_value_infallible(
|
||||
generator_state: &mut GeneratorState,
|
||||
ret_type: &Arg,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
let GeneratorState {
|
||||
result,
|
||||
retval,
|
||||
needs_retval,
|
||||
..
|
||||
} = generator_state;
|
||||
|
||||
let res = match ret_type {
|
||||
Arg::Numeric(NumericArg::u8)
|
||||
| Arg::Numeric(NumericArg::u16)
|
||||
| Arg::Numeric(NumericArg::u32) => {
|
||||
*needs_retval = true;
|
||||
quote!(#retval.set_uint32(#result as u32);)
|
||||
}
|
||||
Arg::Numeric(NumericArg::i8)
|
||||
| Arg::Numeric(NumericArg::i16)
|
||||
| Arg::Numeric(NumericArg::i32) => {
|
||||
*needs_retval = true;
|
||||
quote!(#retval.set_int32(#result as i32);)
|
||||
}
|
||||
_ => {
|
||||
return Err(V8MappingError::NoMapping(
|
||||
"a slow return value",
|
||||
ret_type.clone(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn return_value_result(
|
||||
generator_state: &mut GeneratorState,
|
||||
ret_type: &Arg,
|
||||
) -> Result<TokenStream, V8MappingError> {
|
||||
let infallible = return_value_infallible(generator_state, ret_type)?;
|
||||
let GeneratorState { result, .. } = &generator_state;
|
||||
|
||||
let tokens = quote!(
|
||||
let result = match ret_type {
|
||||
Ok(#result) => {
|
||||
#infallible,
|
||||
}
|
||||
Err(err) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
Ok(tokens)
|
||||
}
|
32
ops/op2/generator_state.rs
Normal file
32
ops/op2/generator_state.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
pub struct GeneratorState {
|
||||
/// The path to the `deno_core` crate (either `deno_core` or `crate`, the latter used if the op is `(core)`).
|
||||
pub deno_core: TokenStream,
|
||||
|
||||
/// Identifiers for each of the arguments of the original function
|
||||
pub args: Vec<Ident>,
|
||||
/// The new identifier for the original function's contents.
|
||||
pub call: Ident,
|
||||
/// The result of the `call` function
|
||||
pub result: Ident,
|
||||
|
||||
/// The `v8::CallbackScope` used if necessary for the function.
|
||||
pub scope: Ident,
|
||||
/// The `v8::FunctionCallbackInfo` used to pass args into the slow function.
|
||||
pub info: Ident,
|
||||
/// The `v8::FunctionCallbackArguments` used to pass args into the slow function.
|
||||
pub fn_args: Ident,
|
||||
/// The `v8::ReturnValue` used in the slow function
|
||||
pub retval: Ident,
|
||||
/// The "slow" function (ie: the one that isn't a fastcall)
|
||||
pub slow_function: Ident,
|
||||
/// The "fast" function (ie: a fastcall)
|
||||
pub fast_function: Ident,
|
||||
|
||||
pub needs_args: bool,
|
||||
pub needs_retval: bool,
|
||||
pub needs_scope: bool,
|
||||
}
|
287
ops/op2/mod.rs
Normal file
287
ops/op2/mod.rs
Normal file
|
@ -0,0 +1,287 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
use deno_proc_macro_rules::rules;
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro2::Span;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
use std::iter::zip;
|
||||
use syn2::parse2;
|
||||
use syn2::FnArg;
|
||||
use syn2::ItemFn;
|
||||
use syn2::Path;
|
||||
use thiserror::Error;
|
||||
|
||||
use self::dispatch_fast::generate_dispatch_fast;
|
||||
use self::dispatch_slow::generate_dispatch_slow;
|
||||
use self::generator_state::GeneratorState;
|
||||
use self::signature::parse_signature;
|
||||
use self::signature::Arg;
|
||||
use self::signature::SignatureError;
|
||||
|
||||
pub mod dispatch_fast;
|
||||
pub mod dispatch_slow;
|
||||
pub mod generator_state;
|
||||
pub mod signature;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Op2Error {
|
||||
#[error("Failed to match a pattern for '{0}': (input was '{1}')")]
|
||||
PatternMatchFailed(&'static str, String),
|
||||
#[error("Invalid attribute: '{0}'")]
|
||||
InvalidAttribute(String),
|
||||
#[error("Failed to parse syntax tree")]
|
||||
ParseError(#[from] syn2::Error),
|
||||
#[error("Failed to map a parsed signature to a V8 call")]
|
||||
V8MappingError(#[from] V8MappingError),
|
||||
#[error("Failed to parse signature")]
|
||||
SignatureError(#[from] SignatureError),
|
||||
#[error("This op is fast-compatible and should be marked as (fast)")]
|
||||
ShouldBeFast,
|
||||
#[error("This op is not fast-compatible and should not be marked as (fast)")]
|
||||
ShouldNotBeFast,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum V8MappingError {
|
||||
#[error("Unable to map {1:?} to {0}")]
|
||||
NoMapping(&'static str, Arg),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct MacroConfig {
|
||||
pub core: bool,
|
||||
pub fast: bool,
|
||||
}
|
||||
|
||||
impl MacroConfig {
|
||||
pub fn from_flags(flags: Vec<Ident>) -> Result<Self, Op2Error> {
|
||||
let mut config: MacroConfig = Self::default();
|
||||
for flag in flags {
|
||||
if flag == "core" {
|
||||
config.core = true;
|
||||
} else if flag == "fast" {
|
||||
config.fast = true;
|
||||
} else {
|
||||
return Err(Op2Error::InvalidAttribute(flag.to_string()));
|
||||
}
|
||||
}
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn from_tokens(tokens: TokenStream) -> Result<Self, Op2Error> {
|
||||
let attr_string = tokens.to_string();
|
||||
let config = std::panic::catch_unwind(|| {
|
||||
rules!(tokens => {
|
||||
() => {
|
||||
Ok(MacroConfig::default())
|
||||
}
|
||||
($($flags:ident),+) => {
|
||||
Self::from_flags(flags)
|
||||
}
|
||||
})
|
||||
})
|
||||
.map_err(|_| Op2Error::PatternMatchFailed("attribute", attr_string))??;
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn op2(
|
||||
attr: TokenStream,
|
||||
item: TokenStream,
|
||||
) -> Result<TokenStream, Op2Error> {
|
||||
let func = parse2::<ItemFn>(item)?;
|
||||
let config = MacroConfig::from_tokens(attr)?;
|
||||
generate_op2(config, func)
|
||||
}
|
||||
|
||||
fn generate_op2(
|
||||
config: MacroConfig,
|
||||
func: ItemFn,
|
||||
) -> Result<TokenStream, Op2Error> {
|
||||
// Create a copy of the original function, named "call"
|
||||
let call = Ident::new("call", Span::call_site());
|
||||
let mut op_fn = func.clone();
|
||||
op_fn.attrs.clear();
|
||||
op_fn.sig.ident = call.clone();
|
||||
|
||||
// Clear inert attributes
|
||||
// TODO(mmastrac): This should limit itself to clearing ours only
|
||||
for arg in op_fn.sig.inputs.iter_mut() {
|
||||
match arg {
|
||||
FnArg::Receiver(slf) => slf.attrs.clear(),
|
||||
FnArg::Typed(ty) => ty.attrs.clear(),
|
||||
}
|
||||
}
|
||||
|
||||
let signature = parse_signature(func.attrs, func.sig.clone())?;
|
||||
let processed_args =
|
||||
zip(signature.args.iter(), &func.sig.inputs).collect::<Vec<_>>();
|
||||
|
||||
let mut args = vec![];
|
||||
let mut needs_args = false;
|
||||
for (index, _) in processed_args.iter().enumerate() {
|
||||
let input = format_ident!("arg{index}");
|
||||
args.push(input);
|
||||
needs_args = true;
|
||||
}
|
||||
|
||||
let retval = Ident::new("rv", Span::call_site());
|
||||
let result = Ident::new("result", Span::call_site());
|
||||
let fn_args = Ident::new("args", Span::call_site());
|
||||
let scope = Ident::new("scope", Span::call_site());
|
||||
let info = Ident::new("info", Span::call_site());
|
||||
let slow_function = Ident::new("slow_function", Span::call_site());
|
||||
let fast_function = Ident::new("fast_function", Span::call_site());
|
||||
|
||||
let deno_core = if config.core {
|
||||
syn2::parse_str::<Path>("crate::deno_core")
|
||||
} else {
|
||||
syn2::parse_str::<Path>("deno_core")
|
||||
}
|
||||
.expect("Parsing crate should not fail")
|
||||
.into_token_stream();
|
||||
|
||||
let mut generator_state = GeneratorState {
|
||||
args,
|
||||
fn_args,
|
||||
call,
|
||||
scope,
|
||||
info,
|
||||
deno_core,
|
||||
result,
|
||||
retval,
|
||||
needs_args,
|
||||
slow_function,
|
||||
fast_function,
|
||||
needs_retval: false,
|
||||
needs_scope: false,
|
||||
};
|
||||
|
||||
let name = func.sig.ident;
|
||||
let slow_fn = generate_dispatch_slow(&mut generator_state, &signature)?;
|
||||
let (fast_definition, fast_fn) =
|
||||
match generate_dispatch_fast(&mut generator_state, &signature)? {
|
||||
Some((fast_definition, fast_fn)) => {
|
||||
if !config.fast {
|
||||
return Err(Op2Error::ShouldBeFast);
|
||||
}
|
||||
(quote!(Some({#fast_definition})), fast_fn)
|
||||
}
|
||||
None => {
|
||||
if config.fast {
|
||||
return Err(Op2Error::ShouldNotBeFast);
|
||||
}
|
||||
(quote!(None), quote!())
|
||||
}
|
||||
};
|
||||
|
||||
let GeneratorState {
|
||||
deno_core,
|
||||
slow_function,
|
||||
..
|
||||
} = &generator_state;
|
||||
|
||||
let arg_count: usize = generator_state.args.len();
|
||||
let vis = func.vis;
|
||||
|
||||
Ok(quote! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#vis struct #name {
|
||||
}
|
||||
|
||||
impl #name {
|
||||
pub const fn name() -> &'static str {
|
||||
stringify!(#name)
|
||||
}
|
||||
|
||||
pub const fn decl() -> #deno_core::_ops::OpDecl {
|
||||
#deno_core::_ops::OpDecl {
|
||||
name: stringify!(#name),
|
||||
v8_fn_ptr: Self::#slow_function as _,
|
||||
enabled: true,
|
||||
fast_fn: #fast_definition,
|
||||
is_async: false,
|
||||
is_unstable: false,
|
||||
is_v8: false,
|
||||
arg_count: #arg_count as u8,
|
||||
}
|
||||
}
|
||||
|
||||
#slow_fn
|
||||
#fast_fn
|
||||
|
||||
#[inline(always)]
|
||||
#op_fn
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::PathBuf;
|
||||
use syn2::parse_str;
|
||||
use syn2::File;
|
||||
use syn2::Item;
|
||||
|
||||
#[testing_macros::fixture("op2/test_cases/**/*.rs")]
|
||||
fn test_signature_parser(input: PathBuf) {
|
||||
let update_expected = std::env::var("UPDATE_EXPECTED").is_ok();
|
||||
|
||||
let source =
|
||||
std::fs::read_to_string(&input).expect("Failed to read test file");
|
||||
let file = parse_str::<File>(&source).expect("Failed to parse Rust file");
|
||||
let mut expected_out = vec![];
|
||||
for item in file.items {
|
||||
if let Item::Fn(mut func) = item {
|
||||
let mut config = None;
|
||||
func.attrs.retain(|attr| {
|
||||
let tokens = attr.into_token_stream();
|
||||
let attr_string = attr.clone().into_token_stream().to_string();
|
||||
println!("{}", attr_string);
|
||||
use syn2 as syn;
|
||||
if let Some(new_config) = rules!(tokens => {
|
||||
(#[op2]) => {
|
||||
Some(MacroConfig::default())
|
||||
}
|
||||
(#[op2( $($x:ident),* )]) => {
|
||||
Some(MacroConfig::from_flags(x).expect("Failed to parse attribute"))
|
||||
}
|
||||
(#[$_attr:meta]) => {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
config = Some(new_config);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
let tokens =
|
||||
generate_op2(config.unwrap(), func).expect("Failed to generate op");
|
||||
println!("======== Raw tokens ========:\n{}", tokens.clone());
|
||||
let tree = syn::parse2(tokens).unwrap();
|
||||
let actual = prettyplease::unparse(&tree);
|
||||
println!("======== Generated ========:\n{}", actual);
|
||||
expected_out.push(actual);
|
||||
}
|
||||
}
|
||||
|
||||
let expected_out = expected_out.join("\n");
|
||||
|
||||
if update_expected {
|
||||
std::fs::write(input.with_extension("out"), expected_out)
|
||||
.expect("Failed to write expectation file");
|
||||
} else {
|
||||
let expected = std::fs::read_to_string(input.with_extension("out"))
|
||||
.expect("Failed to read expectation file");
|
||||
assert_eq!(
|
||||
expected, expected_out,
|
||||
"Failed to match expectation. Use UPDATE_EXPECTED=1."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
516
ops/op2/signature.rs
Normal file
516
ops/op2/signature.rs
Normal file
|
@ -0,0 +1,516 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
use deno_proc_macro_rules::rules;
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use quote::ToTokens;
|
||||
use strum::IntoEnumIterator;
|
||||
use strum::IntoStaticStr;
|
||||
use strum_macros::EnumIter;
|
||||
use strum_macros::EnumString;
|
||||
use syn2::Attribute;
|
||||
use syn2::FnArg;
|
||||
use syn2::Pat;
|
||||
use syn2::ReturnType;
|
||||
use syn2::Signature;
|
||||
use syn2::Type;
|
||||
use syn2::TypePath;
|
||||
use thiserror::Error;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Eq, PartialEq, IntoStaticStr, EnumString, EnumIter,
|
||||
)]
|
||||
pub enum NumericArg {
|
||||
/// A placeholder argument for arguments annotated with #[smi].
|
||||
__SMI__,
|
||||
/// A placeholder argument for void data.
|
||||
__VOID__,
|
||||
bool,
|
||||
i8,
|
||||
u8,
|
||||
i16,
|
||||
u16,
|
||||
i32,
|
||||
u32,
|
||||
i64,
|
||||
u64,
|
||||
f32,
|
||||
f64,
|
||||
isize,
|
||||
usize,
|
||||
}
|
||||
|
||||
impl ToTokens for NumericArg {
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
let ident = Ident::new(self.into(), Span::call_site());
|
||||
tokens.extend(quote! { #ident })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Eq, PartialEq, IntoStaticStr, EnumString, EnumIter,
|
||||
)]
|
||||
pub enum V8Arg {
|
||||
External,
|
||||
Object,
|
||||
Array,
|
||||
ArrayBuffer,
|
||||
ArrayBufferView,
|
||||
DataView,
|
||||
TypedArray,
|
||||
BigInt64Array,
|
||||
BigUint64Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
Int16Array,
|
||||
Int32Array,
|
||||
Int8Array,
|
||||
Uint16Array,
|
||||
Uint32Array,
|
||||
Uint8Array,
|
||||
Uint8ClampedArray,
|
||||
BigIntObject,
|
||||
BooleanObject,
|
||||
Date,
|
||||
Function,
|
||||
Map,
|
||||
NumberObject,
|
||||
Promise,
|
||||
PromiseResolver,
|
||||
Proxy,
|
||||
RegExp,
|
||||
Set,
|
||||
SharedArrayBuffer,
|
||||
StringObject,
|
||||
SymbolObject,
|
||||
WasmMemoryObject,
|
||||
WasmModuleObject,
|
||||
Primitive,
|
||||
BigInt,
|
||||
Boolean,
|
||||
Name,
|
||||
String,
|
||||
Symbol,
|
||||
Number,
|
||||
Integer,
|
||||
Int32,
|
||||
Uint32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Special {
|
||||
HandleScope,
|
||||
OpState,
|
||||
String,
|
||||
RefStr,
|
||||
FastApiCallbackOptions,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum RefType {
|
||||
Ref,
|
||||
Mut,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Arg {
|
||||
Void,
|
||||
Special(Special),
|
||||
Ref(RefType, Special),
|
||||
RcRefCell(Special),
|
||||
Option(Special),
|
||||
OptionNumeric(NumericArg),
|
||||
Slice(RefType, NumericArg),
|
||||
Ptr(RefType, NumericArg),
|
||||
V8Local(V8Arg),
|
||||
Numeric(NumericArg),
|
||||
SerdeV8(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum RetVal {
|
||||
Infallible(Arg),
|
||||
Result(Arg),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ParsedSignature {
|
||||
pub args: Vec<Arg>,
|
||||
pub names: Vec<String>,
|
||||
pub ret_val: RetVal,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
enum AttributeModifier {
|
||||
/// #[serde], for serde_v8 types.
|
||||
Serde,
|
||||
/// #[smi], for small integers
|
||||
Smi,
|
||||
/// #[string], for strings.
|
||||
String,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SignatureError {
|
||||
#[error("Invalid argument: {0}")]
|
||||
ArgError(String, #[source] ArgError),
|
||||
#[error("Invalid return type")]
|
||||
RetError(#[from] ArgError),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ArgError {
|
||||
#[error("Invalid self argument")]
|
||||
InvalidSelf,
|
||||
#[error("Invalid argument type: {0}")]
|
||||
InvalidType(String),
|
||||
#[error(
|
||||
"Invalid argument type path (should this be #[smi] or #[serde]?): {0}"
|
||||
)]
|
||||
InvalidTypePath(String),
|
||||
#[error("Too many attributes")]
|
||||
TooManyAttributes,
|
||||
#[error("Invalid #[serde] type: {0}")]
|
||||
InvalidSerdeType(String),
|
||||
#[error("Cannot use #[serde] for type: {0}")]
|
||||
InvalidSerdeAttributeType(String),
|
||||
#[error("Invalid v8 type: {0}")]
|
||||
InvalidV8Type(String),
|
||||
#[error("Internal error: {0}")]
|
||||
InternalError(String),
|
||||
#[error("Missing a #[string] attribute")]
|
||||
MissingStringAttribute,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
struct Attributes {
|
||||
primary: Option<AttributeModifier>,
|
||||
}
|
||||
|
||||
fn stringify_token(tokens: impl ToTokens) -> String {
|
||||
tokens
|
||||
.into_token_stream()
|
||||
.into_iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
}
|
||||
|
||||
pub fn parse_signature(
|
||||
attributes: Vec<Attribute>,
|
||||
signature: Signature,
|
||||
) -> Result<ParsedSignature, SignatureError> {
|
||||
let mut args = vec![];
|
||||
let mut names = vec![];
|
||||
for input in signature.inputs {
|
||||
let name = match &input {
|
||||
FnArg::Receiver(_) => "self".to_owned(),
|
||||
FnArg::Typed(ty) => match &*ty.pat {
|
||||
Pat::Ident(ident) => ident.ident.to_string(),
|
||||
_ => "(complex)".to_owned(),
|
||||
},
|
||||
};
|
||||
names.push(name.clone());
|
||||
args.push(
|
||||
parse_arg(input).map_err(|err| SignatureError::ArgError(name, err))?,
|
||||
);
|
||||
}
|
||||
Ok(ParsedSignature {
|
||||
args,
|
||||
names,
|
||||
ret_val: parse_return(parse_attributes(&attributes)?, &signature.output)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_attributes(attributes: &[Attribute]) -> Result<Attributes, ArgError> {
|
||||
let attrs = attributes
|
||||
.iter()
|
||||
.filter_map(parse_attribute)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if attrs.is_empty() {
|
||||
return Ok(Attributes::default());
|
||||
}
|
||||
if attrs.len() > 1 {
|
||||
return Err(ArgError::TooManyAttributes);
|
||||
}
|
||||
Ok(Attributes {
|
||||
primary: Some(*attrs.get(0).unwrap()),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_attribute(attr: &Attribute) -> Option<AttributeModifier> {
|
||||
let tokens = attr.into_token_stream();
|
||||
use syn2 as syn;
|
||||
std::panic::catch_unwind(|| {
|
||||
rules!(tokens => {
|
||||
(#[serde]) => Some(AttributeModifier::Serde),
|
||||
(#[smi]) => Some(AttributeModifier::Smi),
|
||||
(#[string]) => Some(AttributeModifier::String),
|
||||
(#[$_attr:meta]) => None,
|
||||
})
|
||||
})
|
||||
.expect("Failed to parse an attribute")
|
||||
}
|
||||
|
||||
fn parse_return(
|
||||
attrs: Attributes,
|
||||
rt: &ReturnType,
|
||||
) -> Result<RetVal, ArgError> {
|
||||
match rt {
|
||||
ReturnType::Default => Ok(RetVal::Infallible(Arg::Void)),
|
||||
ReturnType::Type(_, ty) => {
|
||||
let s = stringify_token(ty);
|
||||
let tokens = ty.into_token_stream();
|
||||
use syn2 as syn;
|
||||
|
||||
std::panic::catch_unwind(|| {
|
||||
rules!(tokens => {
|
||||
// x::y::Result<Value>, like io::Result and other specialty result types
|
||||
($($_package:ident ::)* Result < $ty:ty >) => {
|
||||
Ok(RetVal::Result(parse_type(attrs, &ty)?))
|
||||
}
|
||||
// x::y::Result<Value, Error>
|
||||
($($_package:ident ::)* Result < $ty:ty, $_error:ty >) => {
|
||||
Ok(RetVal::Result(parse_type(attrs, &ty)?))
|
||||
}
|
||||
($ty:ty) => {
|
||||
Ok(RetVal::Infallible(parse_type(attrs, &ty)?))
|
||||
}
|
||||
})
|
||||
})
|
||||
.map_err(|e| {
|
||||
ArgError::InternalError(format!(
|
||||
"parse_return({}) {}",
|
||||
s,
|
||||
e.downcast::<&str>().unwrap_or_default()
|
||||
))
|
||||
})?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type_path(attrs: Attributes, tp: &TypePath) -> Result<Arg, ArgError> {
|
||||
if tp.path.segments.len() == 1 {
|
||||
let segment = tp.path.segments.first().unwrap().ident.to_string();
|
||||
for numeric in NumericArg::iter() {
|
||||
if Into::<&'static str>::into(numeric) == segment.as_str() {
|
||||
return Ok(Arg::Numeric(numeric));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use syn2 as syn;
|
||||
|
||||
let tokens = tp.clone().into_token_stream();
|
||||
std::panic::catch_unwind(|| {
|
||||
rules!(tokens => {
|
||||
( $( std :: str :: )? String ) => {
|
||||
if attrs.primary == Some(AttributeModifier::String) {
|
||||
Ok(Arg::Special(Special::String))
|
||||
} else {
|
||||
Err(ArgError::MissingStringAttribute)
|
||||
}
|
||||
}
|
||||
( $( std :: ffi :: )? c_void ) => Ok(Arg::Numeric(NumericArg::__VOID__)),
|
||||
( OpState ) => Ok(Arg::Special(Special::OpState)),
|
||||
( v8 :: HandleScope ) => Ok(Arg::Special(Special::HandleScope)),
|
||||
( v8 :: FastApiCallbackOptions ) => Ok(Arg::Special(Special::FastApiCallbackOptions)),
|
||||
( v8 :: Local < $( $_scope:lifetime , )? v8 :: $v8:ident >) => Ok(Arg::V8Local(parse_v8_type(&v8)?)),
|
||||
( Rc < RefCell < $ty:ty > > ) => Ok(Arg::RcRefCell(parse_type_special(attrs, &ty)?)),
|
||||
( Option < $ty:ty > ) => {
|
||||
match parse_type(attrs, &ty)? {
|
||||
Arg::Special(special) => Ok(Arg::Option(special)),
|
||||
Arg::Numeric(numeric) => Ok(Arg::OptionNumeric(numeric)),
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty)))
|
||||
}
|
||||
}
|
||||
( $any:ty ) => Err(ArgError::InvalidTypePath(stringify_token(any))),
|
||||
})
|
||||
}).map_err(|e| ArgError::InternalError(format!("parse_type_path {e:?}")))?
|
||||
}
|
||||
|
||||
fn parse_v8_type(v8: &Ident) -> Result<V8Arg, ArgError> {
|
||||
let v8 = v8.to_string();
|
||||
V8Arg::try_from(v8.as_str()).map_err(|_| ArgError::InvalidV8Type(v8))
|
||||
}
|
||||
|
||||
fn parse_type_special(
|
||||
attrs: Attributes,
|
||||
ty: &Type,
|
||||
) -> Result<Special, ArgError> {
|
||||
match parse_type(attrs, ty)? {
|
||||
Arg::Special(special) => Ok(special),
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type(attrs: Attributes, ty: &Type) -> Result<Arg, ArgError> {
|
||||
if let Some(primary) = attrs.primary {
|
||||
match primary {
|
||||
AttributeModifier::Serde => match ty {
|
||||
Type::Path(of) => {
|
||||
// If this type will parse without #[serde], it is illegal to use this type with #[serde]
|
||||
if parse_type_path(Attributes::default(), of).is_ok() {
|
||||
return Err(ArgError::InvalidSerdeAttributeType(stringify_token(
|
||||
ty,
|
||||
)));
|
||||
}
|
||||
return Ok(Arg::SerdeV8(stringify_token(of.path.clone())));
|
||||
}
|
||||
_ => return Err(ArgError::InvalidSerdeType(stringify_token(ty))),
|
||||
},
|
||||
AttributeModifier::String => match ty {
|
||||
Type::Path(of) => {
|
||||
return parse_type_path(attrs, of);
|
||||
}
|
||||
Type::Reference(of) => {
|
||||
let mut_type = if of.mutability.is_some() {
|
||||
RefType::Mut
|
||||
} else {
|
||||
RefType::Ref
|
||||
};
|
||||
let tokens = of.elem.clone().into_token_stream();
|
||||
use syn2 as syn;
|
||||
return rules!(tokens => {
|
||||
(str) => Ok(Arg::Special(Special::RefStr)),
|
||||
($_ty:ty) => Ok(Arg::Ref(mut_type, parse_type_special(attrs, &of.elem)?)),
|
||||
});
|
||||
}
|
||||
_ => return Err(ArgError::InvalidSerdeType(stringify_token(ty))),
|
||||
},
|
||||
AttributeModifier::Smi => {
|
||||
return Ok(Arg::Numeric(NumericArg::__SMI__));
|
||||
}
|
||||
}
|
||||
};
|
||||
match ty {
|
||||
Type::Tuple(of) => {
|
||||
if of.elems.is_empty() {
|
||||
Ok(Arg::Void)
|
||||
} else {
|
||||
Err(ArgError::InvalidType(stringify_token(ty)))
|
||||
}
|
||||
}
|
||||
Type::Reference(of) => {
|
||||
let mut_type = if of.mutability.is_some() {
|
||||
RefType::Mut
|
||||
} else {
|
||||
RefType::Ref
|
||||
};
|
||||
match &*of.elem {
|
||||
Type::Slice(of) => match parse_type(attrs, &of.elem)? {
|
||||
Arg::Numeric(numeric) => Ok(Arg::Slice(mut_type, numeric)),
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
},
|
||||
Type::Path(of) => match parse_type_path(attrs, of)? {
|
||||
Arg::Special(special) => Ok(Arg::Ref(mut_type, special)),
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
},
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
}
|
||||
}
|
||||
Type::Ptr(of) => {
|
||||
let mut_type = if of.mutability.is_some() {
|
||||
RefType::Mut
|
||||
} else {
|
||||
RefType::Ref
|
||||
};
|
||||
match &*of.elem {
|
||||
Type::Path(of) => match parse_type_path(attrs, of)? {
|
||||
Arg::Numeric(numeric) => Ok(Arg::Ptr(mut_type, numeric)),
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
},
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
}
|
||||
}
|
||||
Type::Path(of) => parse_type_path(attrs, of),
|
||||
_ => Err(ArgError::InvalidType(stringify_token(ty))),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_arg(arg: FnArg) -> Result<Arg, ArgError> {
|
||||
let FnArg::Typed(typed) = arg else {
|
||||
return Err(ArgError::InvalidSelf);
|
||||
};
|
||||
parse_type(parse_attributes(&typed.attrs)?, &typed.ty)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::op2::signature::parse_signature;
|
||||
use syn2::parse_str;
|
||||
use syn2::ItemFn;
|
||||
|
||||
// We can't test pattern args :/
|
||||
// https://github.com/rust-lang/rfcs/issues/2688
|
||||
macro_rules! test {
|
||||
( $(# [ $fn_attr:ident ])? fn $name:ident ( $( $(# [ $attr:ident ])? $ident:ident : $ty:ty ),* ) $(-> $(# [ $ret_attr:ident ])? $ret:ty)?, ( $( $arg_res:expr ),* ) -> $ret_res:expr ) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
test(
|
||||
stringify!($( #[$fn_attr] )? fn op( $( $( #[$attr] )? $ident : $ty ),* ) $(-> $( #[$ret_attr] )? $ret)? {}),
|
||||
stringify!($($arg_res),*),
|
||||
stringify!($ret_res)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn test(op: &str, args_expected: &str, return_expected: &str) {
|
||||
let item_fn = parse_str::<ItemFn>(op)
|
||||
.unwrap_or_else(|_| panic!("Failed to parse {op} as a ItemFn"));
|
||||
let attrs = item_fn.attrs;
|
||||
let sig = parse_signature(attrs, item_fn.sig).unwrap_or_else(|_| {
|
||||
panic!("Failed to successfully parse signature from {op}")
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
args_expected,
|
||||
format!("{:?}", sig.args).trim_matches(|c| c == '[' || c == ']')
|
||||
);
|
||||
assert_eq!(return_expected, format!("{:?}", sig.ret_val));
|
||||
}
|
||||
|
||||
test!(
|
||||
fn op_state_and_number(opstate: &mut OpState, a: u32) -> (),
|
||||
(Ref(Mut, OpState), Numeric(u32)) -> Infallible(Void)
|
||||
);
|
||||
test!(
|
||||
fn op_slices(r#in: &[u8], out: &mut [u8]),
|
||||
(Slice(Ref, u8), Slice(Mut, u8)) -> Infallible(Void)
|
||||
);
|
||||
test!(
|
||||
#[serde] fn op_serde(#[serde] input: package::SerdeInputType) -> Result<package::SerdeReturnType, Error>,
|
||||
(SerdeV8("package::SerdeInputType")) -> Result(SerdeV8("package::SerdeReturnType"))
|
||||
);
|
||||
test!(
|
||||
fn op_local(input: v8::Local<v8::String>) -> Result<v8::Local<v8::String>, Error>,
|
||||
(V8Local(String)) -> Result(V8Local(String))
|
||||
);
|
||||
test!(
|
||||
fn op_resource(#[smi] rid: ResourceId, buffer: &[u8]),
|
||||
(Numeric(__SMI__), Slice(Ref, u8)) -> Infallible(Void)
|
||||
);
|
||||
test!(
|
||||
fn op_option_numeric_result(state: &mut OpState) -> Result<Option<u32>, AnyError>,
|
||||
(Ref(Mut, OpState)) -> Result(OptionNumeric(u32))
|
||||
);
|
||||
test!(
|
||||
fn op_ffi_read_f64(state: &mut OpState, ptr: * mut c_void, offset: isize) -> Result <f64, AnyError>,
|
||||
(Ref(Mut, OpState), Ptr(Mut, __VOID__), Numeric(isize)) -> Result(Numeric(f64))
|
||||
);
|
||||
test!(
|
||||
fn op_print(#[string] msg: &str, is_err: bool) -> Result<(), Error>,
|
||||
(Special(RefStr), Numeric(bool)) -> Result(Void)
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn test_parse_result() {
|
||||
let rt = parse_str::<ReturnType>("-> Result < (), Error >")
|
||||
.expect("Failed to parse");
|
||||
println!("{:?}", parse_return(Attributes::default(), &rt));
|
||||
}
|
||||
}
|
54
ops/op2/test_cases/sync/add.out
Normal file
54
ops/op2/test_cases/sync/add.out
Normal file
|
@ -0,0 +1,54 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
struct op_add {}
|
||||
impl op_add {
|
||||
pub const fn name() -> &'static str {
|
||||
stringify!(op_add)
|
||||
}
|
||||
pub const fn decl() -> deno_core::_ops::OpDecl {
|
||||
deno_core::_ops::OpDecl {
|
||||
name: stringify!(op_add),
|
||||
v8_fn_ptr: Self::slow_function as _,
|
||||
enabled: true,
|
||||
fast_fn: Some({
|
||||
use deno_core::v8::fast_api::Type;
|
||||
use deno_core::v8::fast_api::CType;
|
||||
deno_core::v8::fast_api::FastFunction::new(
|
||||
&[Type::Uint32, Type::Uint32],
|
||||
CType::Uint32,
|
||||
Self::fast_function as *const ::std::ffi::c_void,
|
||||
)
|
||||
}),
|
||||
is_async: false,
|
||||
is_unstable: false,
|
||||
is_v8: false,
|
||||
arg_count: 2usize as u8,
|
||||
}
|
||||
}
|
||||
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
|
||||
let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
|
||||
&*info
|
||||
});
|
||||
let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
|
||||
&*info
|
||||
});
|
||||
let arg0 = args.get(0usize as i32);
|
||||
let arg0 = deno_core::_ops::to_u32(&arg0) as _;
|
||||
let arg1 = args.get(1usize as i32);
|
||||
let arg1 = deno_core::_ops::to_u32(&arg1) as _;
|
||||
let result = Self::call(arg0, arg1);
|
||||
rv.set_uint32(result as u32);
|
||||
}
|
||||
fn fast_function(
|
||||
_: deno_core::v8::Local<deno_core::v8::Object>,
|
||||
arg0: u32,
|
||||
arg1: u32,
|
||||
) -> u32 {
|
||||
let arg0 = arg0 as _;
|
||||
let arg1 = arg1 as _;
|
||||
Self::call(arg0, arg1)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn call(a: u32, b: u32) -> u32 {
|
||||
a + b
|
||||
}
|
||||
}
|
6
ops/op2/test_cases/sync/add.rs
Normal file
6
ops/op2/test_cases/sync/add.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
#[op2(fast)]
|
||||
fn op_add(a: u32, b: u32) -> u32 {
|
||||
a + b
|
||||
}
|
44
ops/op2/test_cases/sync/add_options.out
Normal file
44
ops/op2/test_cases/sync/add_options.out
Normal file
|
@ -0,0 +1,44 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
pub struct op_test_add_option {}
|
||||
impl op_test_add_option {
|
||||
pub const fn name() -> &'static str {
|
||||
stringify!(op_test_add_option)
|
||||
}
|
||||
pub const fn decl() -> crate::deno_core::_ops::OpDecl {
|
||||
crate::deno_core::_ops::OpDecl {
|
||||
name: stringify!(op_test_add_option),
|
||||
v8_fn_ptr: Self::slow_function as _,
|
||||
enabled: true,
|
||||
fast_fn: None,
|
||||
is_async: false,
|
||||
is_unstable: false,
|
||||
is_v8: false,
|
||||
arg_count: 2usize as u8,
|
||||
}
|
||||
}
|
||||
pub extern "C" fn slow_function(
|
||||
info: *const crate::deno_core::v8::FunctionCallbackInfo,
|
||||
) {
|
||||
let mut rv = crate::deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
|
||||
&*info
|
||||
});
|
||||
let args = crate::deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
|
||||
&*info
|
||||
});
|
||||
let arg0 = args.get(0usize as i32);
|
||||
let arg0 = crate::deno_core::_ops::to_u32(&arg0) as _;
|
||||
let arg1 = args.get(1usize as i32);
|
||||
let arg1 = if arg1.is_null_or_undefined() {
|
||||
None
|
||||
} else {
|
||||
let arg1 = crate::deno_core::_ops::to_u32(&arg1) as _;
|
||||
Some(arg1)
|
||||
};
|
||||
let result = Self::call(arg0, arg1);
|
||||
rv.set_uint32(result as u32);
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn call(a: u32, b: Option<u32>) -> u32 {
|
||||
a + b.unwrap_or(100)
|
||||
}
|
||||
}
|
6
ops/op2/test_cases/sync/add_options.rs
Normal file
6
ops/op2/test_cases/sync/add_options.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
#[op2(core)]
|
||||
pub fn op_test_add_option(a: u32, b: Option<u32>) -> u32 {
|
||||
a + b.unwrap_or(100)
|
||||
}
|
35
ops/op2/test_cases/sync/doc_comment.out
Normal file
35
ops/op2/test_cases/sync/doc_comment.out
Normal file
|
@ -0,0 +1,35 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
pub struct op_has_doc_comment {}
|
||||
impl op_has_doc_comment {
|
||||
pub const fn name() -> &'static str {
|
||||
stringify!(op_has_doc_comment)
|
||||
}
|
||||
pub const fn decl() -> deno_core::_ops::OpDecl {
|
||||
deno_core::_ops::OpDecl {
|
||||
name: stringify!(op_has_doc_comment),
|
||||
v8_fn_ptr: Self::slow_function as _,
|
||||
enabled: true,
|
||||
fast_fn: Some({
|
||||
use deno_core::v8::fast_api::Type;
|
||||
use deno_core::v8::fast_api::CType;
|
||||
deno_core::v8::fast_api::FastFunction::new(
|
||||
&[],
|
||||
CType::Void,
|
||||
Self::fast_function as *const ::std::ffi::c_void,
|
||||
)
|
||||
}),
|
||||
is_async: false,
|
||||
is_unstable: false,
|
||||
is_v8: false,
|
||||
arg_count: 0usize as u8,
|
||||
}
|
||||
}
|
||||
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
|
||||
let result = Self::call();
|
||||
}
|
||||
fn fast_function(_: deno_core::v8::Local<deno_core::v8::Object>) -> () {
|
||||
Self::call()
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn call() -> () {}
|
||||
}
|
5
ops/op2/test_cases/sync/doc_comment.rs
Normal file
5
ops/op2/test_cases/sync/doc_comment.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/// This is a doc comment.
|
||||
#[op2(fast)]
|
||||
pub fn op_has_doc_comment() -> () {}
|
52
ops/op2/test_cases/sync/smi.out
Normal file
52
ops/op2/test_cases/sync/smi.out
Normal file
|
@ -0,0 +1,52 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
struct op_add {}
|
||||
impl op_add {
|
||||
pub const fn name() -> &'static str {
|
||||
stringify!(op_add)
|
||||
}
|
||||
pub const fn decl() -> deno_core::_ops::OpDecl {
|
||||
deno_core::_ops::OpDecl {
|
||||
name: stringify!(op_add),
|
||||
v8_fn_ptr: Self::slow_function as _,
|
||||
enabled: true,
|
||||
fast_fn: Some({
|
||||
use deno_core::v8::fast_api::Type;
|
||||
use deno_core::v8::fast_api::CType;
|
||||
deno_core::v8::fast_api::FastFunction::new(
|
||||
&[Type::Int32, Type::Uint32],
|
||||
CType::Uint32,
|
||||
Self::fast_function as *const ::std::ffi::c_void,
|
||||
)
|
||||
}),
|
||||
is_async: false,
|
||||
is_unstable: false,
|
||||
is_v8: false,
|
||||
arg_count: 2usize as u8,
|
||||
}
|
||||
}
|
||||
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
|
||||
let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
|
||||
&*info
|
||||
});
|
||||
let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
|
||||
&*info
|
||||
});
|
||||
let arg0 = args.get(0usize as i32);
|
||||
let arg0 = deno_core::_ops::to_i32(&arg0) as _;
|
||||
let arg1 = args.get(1usize as i32);
|
||||
let arg1 = deno_core::_ops::to_u32(&arg1) as _;
|
||||
let result = Self::call(arg0, arg1);
|
||||
rv.set_uint32(result as u32);
|
||||
}
|
||||
fn fast_function(
|
||||
_: deno_core::v8::Local<deno_core::v8::Object>,
|
||||
arg0: i32,
|
||||
arg1: u32,
|
||||
) -> u32 {
|
||||
let arg0 = arg0 as _;
|
||||
let arg1 = arg1 as _;
|
||||
Self::call(arg0, arg1)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn call(id: ResourceId, extra: u16) -> u32 {}
|
||||
}
|
4
ops/op2/test_cases/sync/smi.rs
Normal file
4
ops/op2/test_cases/sync/smi.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
#[op2(fast)]
|
||||
fn op_add(#[smi] id: ResourceId, extra: u16) -> u32 {}
|
Loading…
Reference in a new issue